/*!
 * FAST Core - Core Script
 *
 * Copyright © 2011-2025, Fast Enterprises, LLC.
 * 
 * H: 13388650
 *
 * Scrollbar Width Calculator
 * Copyright (c) 2008 Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * focus-options-polyfill
 * Copyright (c) 2018 Juan Valencia
 * Licensed under the MIT license (https://github.com/calvellido/focus-options-polyfill/blob/master/LICENSE)
 * 
 * Progress/Uploadprogress event handling adapted from:
 * https://github.com/englercj/jquery-ajax-progress
 * https://github.com/englercj/jquery-ajax-progress/blob/ff6bf2580eb19ec9eeb5cf43ca911d190f12b36d/LICENSE
 * 
 * Touch Support for jQuery UI Elements based on jQuery UI Touch-Punch
 * MIT Licensed: https://github.com/furf/jquery-ui-touch-punch/blob/4bc009145202d9c7483ba85f3a236a8f3470354d/README.md
 * Updated Project Site: https://github.com/RWAP/jquery-ui-touch-punch
 * Original Project Site: https://github.com/furf/jquery-ui-touch-punch
 * Original Site: https://touchpunch.furf.com/
 */

/*jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:true, undef:true, unused:vars, curly:true, browser:true, jquery:true, maxerr:50, laxbreak: true */
/*global CKEDITOR:false, CodeMirror:false, google:false, DocumentTouch:false, DetectRTC:false, Fingerprint2:false, signalR:false, base64js:false, Modernizr:false */

window.FWDC = (function (window, jQuery)
{
    "use strict";

    /////////// String Extensions ///////////
    if (!String.prototype.startsWith)
    {
        String.prototype.startsWith = function (str)
        {
            return this.indexOf(str) === 0;
        };
    }

    if (!String.prototype.endsWith)
    {
        String.prototype.endsWith = function (suffix)
        {
            return this.indexOf(suffix, this.length - suffix.length) !== -1;
        };
    }

    if (!String.prototype.toBoolean)
    {
        String.prototype.toBoolean = function ()
        {
            return (this.toLowerCase() === "true");
        };
    }

    if (!Number.prototype.padLeft)
    {
        Number.prototype.padLeft = function (n, str)
        {
            var len = n - String(this).length + 1;
            if (len < 1) { return String(this); }
            return (new Array(len)).join(str || '0') + this;
        };
    }

    if (!String.prototype.trim)
    {
        String.prototype.trim = function ()
        {
            return this.replace(/^\s+|\s+$/gm, '');
        };
    }

    if (!Array.prototype.indexOf)
    {
        Array.prototype.indexOf = function (elt /*, from*/)
        {
            var len = this.length;

            var from = Number(arguments[1]) || 0;
            from = (from < 0) ? Math.ceil(from) : Math.floor(from);

            if (from < 0) { from += len; }

            for (; from < len; from++)
            {
                if (from in this && this[from] === elt)
                {
                    return from;
                }
            }
            return -1;
        };
    }

    if (!RegExp.escape)
    {
        var _regexpEscape = /[-/\\^$*+?.()|[\]{}]/g;

        /**
         * Escapes special characters in the given string so that it can be safely used inside a regular expression.
         * @param {string} s The string that should have its special characters escaped.
         * @returns {string} The escaped string.
         */
        RegExp.escape = function (s)
        {
            return s.replace(_regexpEscape, '\\$&');
        };
    }

    function _default(value, defaultValue)
    {
        return value === undefined ? defaultValue : value;
    }

    /////////// Mask Extensions ///////////
    function MaskCharData()
    {
        this.constant = false;
        this.upper = false;
        this.lower = false;
        this.numeric = false;
        this.alpha = false;
        this.space = false;
        this.hidden = false;
        this.unicode = false;
        this.character = null;
    }

    function MaskData(mask)
    {
        var ii,
            upper = false,
            lower = false,
            unicode = false,
            character,
            charData;

        this.length = 0;
        this.maxLength = 0;

        for (ii = 0; ii < mask.length; ii++)
        {
            character = mask.charAt(ii);
            charData = new MaskCharData();
            switch (character)
            {
                case "#":
                case "9":
                    charData.numeric = true;
                    charData.unicode = unicode;
                    upper = false;
                    lower = false;
                    unicode = false;

                    this[this.length] = charData;
                    this.length++;
                    break;

                case "&": // & and C are technically extended ASCII entries that allow far more than just alpha and numeric values.
                case "C":
                case "c":
                case "?":
                    charData.alpha = true;
                    charData.upper = upper;
                    charData.lower = lower;
                    charData.unicode = unicode;
                    upper = false;
                    lower = false;
                    unicode = false;

                    this[this.length] = charData;
                    this.length++;
                    break;

                case "A":
                    charData.alpha = true;
                    charData.numeric = true;
                    charData.upper = upper;
                    charData.lower = lower;
                    charData.unicode = unicode;
                    upper = false;
                    lower = false;
                    unicode = false;

                    this[this.length] = charData;
                    this.length++;
                    break;

                case "a":
                    charData.alpha = true;
                    charData.numeric = true;
                    charData.space = true;
                    charData.upper = upper;
                    charData.lower = lower;
                    charData.unicode = unicode;
                    upper = false;
                    lower = false;
                    unicode = false;

                    this[this.length] = charData;
                    this.length++;
                    break;

                case "*":
                    charData.alpha = true;
                    charData.numeric = true;
                    charData.hidden = true;
                    charData.upper = upper;
                    charData.lower = lower;
                    charData.unicode = unicode;
                    upper = false;
                    lower = false;
                    unicode = false;

                    this[this.length] = charData;
                    this.length++;
                    break;

                case ">":
                    upper = true;
                    lower = false;
                    break;

                case "<":
                    upper = false;
                    lower = true;
                    break;

                case "@":
                    unicode = true;
                    break;

                case "\\":
                    ii++;
                    character = mask.charAt(ii);
                    charData.constant = true;
                    charData.character = character;
                    upper = false;
                    lower = false;
                    unicode = false;

                    this[this.length] = charData;
                    this.length++;
                    break;

                default:
                    charData.constant = true;
                    charData.character = character;

                    this[this.length] = charData;
                    this.length++;
                    break;
            }
        }

        this.maxLength = this.length;
    }

    /////////// FWDC API ///////////
    function FWDCApi(window, jQuery)
    {
        var FWDC = this;

        FWDC.jQuery = jQuery;
        var $ = jQuery,
            _versionUrlSuffix = "?_=2022734350",
            _lastFieldValue,
            _lastFieldText,
            _currentField,
            _$currentField,
            _currentFieldCell,
            _modalManagerClosed = false,
            _docModalClosing = false,
            _$currentTable,
            _$currentTableCells,
            _currentTableCellIndex,
            _$currentRowCells,
            _currentRowCellIndex,
            _$currentColumnCells,
            _currentColumnCellIndex,
            _$currentEditor,
            _$currentEditCell,
            _$currentEditCellContainer,
            _$currentEditContents,
            _currentCellElement,
            _currentCellType,
            _currentTableId,
            _currentColumnId,
            _currentColumnClass,
            _currentRowClass,
            _currentRowNumber,
            _currentDataRowNumber,
            _currentTableInverted = false,
            _recalcResizeRequired = false,
            _recalcScrollPositions = null,
            _recalcHtmlUpdated = false,
            _recalcDocUpdated = false,
            _recalcTableUpdate = false,
            _recalcVisibleViewsUpdated = false,
            _inRecalc = false,
            _linkSourceInfo,
            _stayBusy = false,
            _openingUrl = false,
            _errorOccurred = false,
            _closing = false,
            _keyEvent,
            _focusBackwards,
            _setFocus,
            _toolTipFields = {},
            _toolTipTargets = {},
            _datepickerRegional,
            _datepickerSettings = { dateFormat: 'yy-mm-dd', defaultDate: null, runDate: null, showAnim: "" },
            _autocompleteOptions = {
                messages: {
                    noResults: "No search results.",
                    oneResult: "@plngResults result is available, use up and down arrow keys to navigate.",
                    multiResult: "@plngResults results are available, use up and down arrow keys to navigate.",
                    results: function (amount)
                    {
                        return amount < 2
                            ? _autocompleteOptions.messages.oneResult.replace("@plngResults", amount + "")
                            : _autocompleteOptions.messages.multiResult.replace("@plngResults", amount + "");
                    }
                }
            },
            _toolTipSettings = {},
            _mobileBrowser = false,
            _tabletBrowser = false,
            _loggedOn = false,
            _allowNewWindow = false,
            _currentFilter,
            _$currentFilter,
            _currentFilterValue,
            _siteHttpHeaders = {},
            _savedScrollPositions = null,
            _scrollPositionVer = 0,
            _pushRequest = null,
            _refreshingWindowContent = false,
            _tipCache = {},
            _googleMapsInitialized = false,
            _mapsInitialized = false,
            _mapsReady = $.Callbacks("once unique memory"),
            _mapOptions = {},
            _maps = {},
            _geocoder,
            _geocoderCache = {},
            _directionsService,
            _directionsCache = {},
            _mapIconSelected = { url: "../Resource/Images/MapMarkerSelected.png" },
            _mapIconUnselected = { url: "../Resource/Images/MapMarkerUnselected.png" },
            _mapInfoWindow = null,
            _mapsShiftModifier = false,
            _pendingFocusChange = false,
            _ignoreFocusScroll = 0,
            _lastScrollFocusIn = null,
            _lastScrollMouseDown = null;

        /////////// Private API ///////////
        function FWDCPrivate(window, jQuery)
        {
            var _fwdc = this,
                $ = jQuery,
                _onInitialize = $.Callbacks('once unique memory'),
                _fastAjaxArgs = {
                    fastRequest: true,
                    type: 'POST',
                    contentType: 'application/x-www-form-urlencoded',
                    dataType: 'json',
                    async: true,
                    busy: true,
                    checkBusy: null,
                    timeout: 3600000,
                    global: false,
                    cache: false,
                    commitEdits: null,
                    trigger: "",
                    sourceId: ""
                },
                _decodes = {},
                _standardDecodes,
                _ajaxId = 0;

            _fwdc._log = function (text) { };
            _fwdc._warn = function (text) { };
            _fwdc._error = function ()
            {
                if (window.console && window.console.error)
                {
                    try
                    {
                        window.console.error(arguments);
                    }
                    catch (ignore)
                    {
                        // Ignored
                    }
                }
                else
                {
                    _fwdc._log("ERROR:");
                    _fwdc._log(arguments);
                }
            };
            _fwdc._trace = function (text) { };
            _fwdc._callStack = function () { };
            _fwdc._printStackTrace = function () { };
            _fwdc._logFunction = function (name, func)
            {
                return function ()
                {
                    //_fwdc._log(name, ": ", arguments, this);
                    _fwdc._trace(name, ": ", arguments, this);
                    return func.apply(this, arguments);
                };
            };
            _fwdc._devToast = function (text) { _fwdc._log(text); };

            _fwdc.jQuery = jQuery;
            _fwdc.window = window;
            _fwdc.browserOptions = {};
            _fwdc.$window = $(window);
            _fwdc.debugFocus = false;
            _fwdc.scriptVersion = 1;
            _fwdc.windowWidth = -1;
            _fwdc.windowHeight = -1;
            _fwdc.$document = $(window.document);
            _fwdc.now = Date.now || (new Date().getTime ? function () { return new Date().getTime(); } : function () { return 0; });
            _fwdc.nowString = function () { return (new Date()).toString(); };
            _fwdc.modalDocCount = 0;
            _fwdc.modalManagerCount = 0;
            _fwdc.fastVerLast = "-1.NotInitialized";
            _fwdc.fastVerLastSource = "js";
            _fwdc.initOptions = {};
            _fwdc.exporting = false;
            _fwdc.simplePage = false;
            _fwdc.fastApp = false;
            _fwdc.ctrlDown = false;
            _fwdc.handleF9 = false;
            _fwdc.language = "ENG";
            _fwdc.languageCode = "en";
            _fwdc.regionCode = "en-US";
            _fwdc.fontSize = 14;
            _fwdc.initializingChat = false;
            _fwdc.settingHistory = false;
            _fwdc.currentHash = 0;
            _fwdc.$chatDialog = null;
            _fwdc.appVersion = 9;
            _fwdc.tap = true;
            _fwdc.touchMode = false;
            _fwdc.rtl = false;
            _fwdc.ltr = true;
            _fwdc.bodyHidden = false;
            _fwdc.autoShowBodyHandle = null;
            _fwdc.autoFocusMode = false;
            _fwdc.datePickerNoFocus = false;
            _fwdc.preventAutoFocus = false;
            _fwdc.captchaType = null;
            _fwdc.sessionTimeouts = {
                from: null,
                expiryTimeout: null,
                expiryWarningTimeout: null,
                idleTimeout: null,
                endTimeout: null,
                keepaliveTimeout: null
            };
            _fwdc.busySource = null;
            _fwdc.busySources = { Assistant: "Assistant" };
            _fwdc.supportsPreventScrollOption = false;
            _fwdc.confirmCallback = null;
            _fwdc.windowFocus = true;
            _fwdc.embedded = false;

            _fwdc.pushActive = false;
            _fwdc.pushToken = null;

            _fwdc.chatConversations = {};

            _fwdc.monitoringConfig = "";
            _fwdc.monitoringConfigJson = {};
            _fwdc.monitoringInputs = [];
            _fwdc.monitoringIntervals = {
                Photo: { Min: 0, Range: 0 },
                Screen: { Min: 0, Range: 0 }
            };

            // Check adapted from https://github.com/calvellido/focus-options-polyfill
            try
            {
                var focusElem = document.createElement('div');
                focusElem.addEventListener('focus', function (event)
                {
                    event.preventDefault();
                    event.stopPropagation();
                }, true);

                // Pass a fake options object with a custom preventScroll property that detects if it gets accessed.
                focusElem.focus(
                    Object.defineProperty({}, 'preventScroll', {
                        get: function ()
                        {
                            _fwdc.supportsPreventScrollOption = true;
                            return false;
                        }
                    })
                );
            } catch (e) { /* Do Nothing */ }

            _fwdc.StatusColors = {
                // Indicates status coloring should be automatic based on the element.
                Auto: 0,
                // Use the default accent color.
                Default: 1,
                // Use a color indicating a good status.
                Good: 2,
                // Use a color indicating a complete status.
                Complete: 3,
                // Use a color indicating a warning.
                Warning: 4,
                // Use a color indicating an error status.
                Error: 5,
                // Use a color indicating an inactive status.
                Inactive: 6,
                // Use a color indicating an incomplete status.
                Incomplete: 7,
                // Use a color indicating a bad status.
                Bad: 8,
                // Use a color indicating an invalid status.
                Invalid: 9
            };

            _fwdc.StatusColorParse = {
                0: "Auto",
                1: "Default",
                2: "Good",
                3: "Complete",
                4: "Warning",
                5: "Error",
                6: "Inactive",
                7: "Incomplete",
                8: "Bad",
                9: "Invalid"
            };

            var _baseScrollContainerSelectors = [
                "html",
                ".ScrollStyleContent.FastApp .ManagerBase .ManagerControlsContainer",
                ".ScrollStyleContent.no-csspositionsticky .ManagerBase .ControlContainer",
                ".PanelScrollContainer",
                ".SidebarScrollContainer",
                ".FastModal .ControlContainer",
                ".ModalDocument > .DocumentForm",
                ".DocViewContextMenu > .DocumentForm",
                ".FastScrollElement",
                ".SnapScrollTop",
                ".ManagerAssistantContainer > .DocumentContainer"
            ];

            var _baseAlwaysPreserveScrollContainerSelectors = [
                ".SidebarScrollContainer",
                ".ManagerAssistantContainer > .DocumentContainer"
            ];

            var _baseScrollableElementSelectors = [
                ".ViewScrollContainer",
                ".PanelScrollContainer",
                ".FastScrollContainer",
                ".ui-dialog-content",
                ".ScrollTogether"
            ];

            _fwdc.selectors = {
                managerContainer: ".ManagerContainer",
                documentContainer: "div[data-document-container]",
                modalContainers: "div.DocModalContainer,div.ManagerModalContainer",
                fullModals: ".ManagerModalDialog,.DocModalDialog",
                specialDialogs: ".ui-dialog:not(div.DocModalDialog,div.ManagerModalDialog,div.FlowMenuDialog,.ContextLog)",
                nonTopDialogs: ".ui-dialog > .ui-dialog-content:visible:not(.TopMostModal)",
                visibleModalDialogs: ".FastModal:visible",
                closingModals: ".ui-dialog-closing,.fast-ui-dialog-closing",
                form: ".FastForm",
                panel: ".FastPanel",
                specialClickElements: ".DocHelpElement,.DocDecodeElement,.UserFieldSelectElement",
                //scrollContainers: "html,.ScrollStyleContent.FastApp .ManagerBase .ManagerContentContainer,.ScrollStyleContent.no-csspositionsticky .ManagerBase .ControlContainer,.PanelScrollContainer,.SidebarMenu,.FastModal .ControlContainer,.ModalDocument > .DocumentForm,.DocViewContextMenu > .DocumentForm,.FastScrollElement",
                scrollContainers: _baseScrollContainerSelectors.join(","),
                scrollElements: _baseScrollContainerSelectors.join(",") + "," + _baseScrollableElementSelectors.join(","),
                scrollElementsAlwaysPreserve: _baseAlwaysPreserveScrollContainerSelectors.join(","),
                scrollTopStickyElements: ".DocTableStickyHeader,.DocTableVirtualScrollbar",
                scrollBottomStickyElements: ".ActionBarBottom"
            };

            _fwdc.toolTipSettings = { verticalSide: 'top', horizontalSide: 'right', noFirstError: false, noFirstRequired: true, noRequired: false };

            _fwdc.EventType = {
                Standard: 0,
                Enter: 1,
                CtrlClick: 2,
                MiddleClick: 3,
                AutoRefresh: 4,

                fromEvent: function (event, checkNormalClick)
                {
                    if (!event)
                    {
                        return _fwdc.EventType.Standard;
                    }

                    if (_fwdc.isCtrlClick(event))
                    {
                        return _fwdc.EventType.CtrlClick;
                    }

                    if (_fwdc.isMiddleClick(event))
                    {
                        return _fwdc.EventType.MiddleClick;
                    }

                    if (!checkNormalClick || _fwdc.isNormalClick(event))
                    {
                        return _fwdc.EventType.Standard;
                    }

                    return null;
                }
            };

            _fwdc.keyCodes = {
                BACKSPACE: 8,
                COMMA: 188,
                DELETE: 46,
                DOWN: 40,
                END: 35,
                ENTER: 13,
                ESCAPE: 27,
                HOME: 36,
                LEFT: 37,
                NUMPAD_ADD: 107,
                NUMPAD_DECIMAL: 110,
                NUMPAD_DIVIDE: 111,
                NUMPAD_ENTER: 108,
                NUMPAD_MULTIPLY: 106,
                NUMPAD_SUBTRACT: 109,
                PAGE_DOWN: 34,
                PAGE_UP: 33,
                PERIOD: 190,
                RIGHT: 39,
                SPACE: 32,
                TAB: 9,
                UP: 38,
                F9: 120,
                SHIFT: 16,
                CTRL: 17,
                CONTROL: 17,
                ALT: 18,
                CAPSLOCK: 20,
                NUMLOCK: 144,
                SCROLLLOCK: 145,
                INSERT: 45,
                WINDOWS_LEFT: 91,
                WINDOWS_RIGHT: 92,
                SELECT: 93,
                NUM0: 48,
                NUM1: 49,
                NUM2: 50,
                NUM3: 51,
                NUM4: 52,
                NUM5: 53,
                NUM6: 54,
                NUM7: 55,
                NUM8: 56,
                NUM9: 57,
                NUMPAD0: 96,
                NUMPAD1: 97,
                NUMPAD2: 98,
                NUMPAD3: 99,
                NUMPAD4: 100,
                NUMPAD5: 101,
                NUMPAD6: 102,
                NUMPAD7: 103,
                NUMPAD8: 104,
                NUMPAD9: 105,
                A: 65,
                B: 66,
                C: 67,
                D: 68,
                E: 69,
                F: 70,
                G: 71,
                H: 72,
                I: 73,
                J: 74,
                K: 75,
                L: 76,
                M: 77,
                N: 78,
                O: 79,
                P: 80,
                Q: 81,
                R: 82,
                S: 83,
                T: 84,
                U: 85,
                V: 86,
                W: 87,
                X: 88,
                Y: 89,
                Z: 90,
                F5: 113,
                SUBTRACT: 189,
                EQUALS: 187,
                SLASH: 191,
                BACKSLASH: 220,
                RIGHT_BRACKET: 221,
                APOSTROPHE: 222
            };

            _fwdc.mouseButtons = {
                left: 1,
                middle: 2,
                right: 3
            };

            _fwdc.ScreenWidths = {
                Small: 0,
                Medium: 1,
                Large: 2,
                Wide: 3
            };

            _fwdc.ScreenWidthSizes = {
                Medium: 0,
                Large: 0,
                Wide: 0
            };

            _fwdc.ModalScreenWidthSizes = {
                Medium: 0,
                Large: 0,
                Wide: 0
            };

            _fwdc.ScreenWidthQueries = {
                Small: 0,
                Medium: 0,
                Large: 0
            };

            _fwdc.calculateScreenSizes = function (recalc)
            {
                if (!_fwdc.ScreenWidthSizes.Wide)
                {
                    var $sizer = $($.parseHTML('<div class="FastScreenMeasurer"></div>')).appendTo(_fwdc.supportElementsContainer());

                    $sizer.addClass("FastScreenMeasurerWide");
                    _fwdc.ModalScreenWidthSizes.Wide = _fwdc.ScreenWidthSizes.Wide = $sizer.width();

                    _fwdc.ScreenWidthQueries.Large = "(max-width:" + (_fwdc.ScreenWidthSizes.Wide - 1) + "px)";

                    $sizer.removeClass("FastScreenMeasurerWide");
                    $sizer.addClass("FastScreenMeasurerLarge");

                    _fwdc.ModalScreenWidthSizes.Large = _fwdc.ScreenWidthSizes.Large = $sizer.width();

                    _fwdc.ScreenWidthQueries.Medium = "(max-width:" + (_fwdc.ScreenWidthSizes.Large - 1) + "px)";

                    $sizer.removeClass("FastScreenMeasurerLarge");
                    $sizer.addClass("FastScreenMeasurerMedium");

                    _fwdc.ModalScreenWidthSizes.Medium = _fwdc.ScreenWidthSizes.Medium = $sizer.width();

                    _fwdc.ScreenWidthQueries.Small = "(max-width:" + (_fwdc.ScreenWidthSizes.Medium - 1) + "px)";

                    $sizer.removeClass("FastScreenMeasurerMedium");
                    $sizer.remove();
                }

                if (recalc)
                {
                    _fwdc.calculateScreenWidth();
                }
            };

            _fwdc.screenWidth = -1;
            _fwdc.screenWidthClass = "Unknown";

            _fwdc.isLargeScreen = function ()
            {
                return _fwdc.screenWidth >= _fwdc.ScreenWidths.Large;
            };

            _fwdc.calculateScreenWidth = function ()
            {
                var priorWidth = _fwdc.screenWidth;

                if (window.matchMedia(_fwdc.ScreenWidthQueries.Small).matches)
                {
                    _fwdc.screenWidth = _fwdc.ScreenWidths.Small;
                    _fwdc.screenWidthClass = "Small";
                }
                else if (window.matchMedia(_fwdc.ScreenWidthQueries.Medium).matches)
                {
                    _fwdc.screenWidth = _fwdc.ScreenWidths.Medium;
                    _fwdc.screenWidthClass = "Medium";
                }
                else if (window.matchMedia(_fwdc.ScreenWidthQueries.Large).matches)
                {
                    _fwdc.screenWidth = _fwdc.ScreenWidths.Large;
                    _fwdc.screenWidthClass = "Large";
                }
                else
                {
                    _fwdc.screenWidth = _fwdc.ScreenWidths.Wide;
                    _fwdc.screenWidthClass = "Wide";
                }

                /*var physicalWidth = _fwdc.$window.outerWidth();
                if (physicalWidth >= _fwdc.ScreenWidthSizes.Wide)
                {
                    _fwdc.screenWidth = _fwdc.ScreenWidths.Wide;
                }
                else if (physicalWidth >= _fwdc.ScreenWidthSizes.Large)
                {
                    _fwdc.screenWidth = _fwdc.ScreenWidths.Large;
                }
                else if (physicalWidth >= _fwdc.ScreenWidthSizes.Medium)
                {
                    _fwdc.screenWidth = _fwdc.ScreenWidths.Medium;
                }
                else
                {
                    _fwdc.screenWidth = _fwdc.ScreenWidths.Small;
                }*/

                if (priorWidth !== _fwdc.screenWidth)
                {
                    $("html")
                        .removeClass("FastScreenSizeSmall FastScreenSizeMedium FastScreenSizeLarge FastScreenSizeWide")
                        .addClass("FastScreenSize" + _fwdc.screenWidthClass);

                    _fwdc.onScreenWidthChanged();
                }
            };

            _fwdc.onScreenWidthChanged = function ()
            {
                _fwdc.hideManagerMenu();
                _fwdc.updateScreenSizeSpecificElements();
            };

            //_fwdc.ready = _fwdc.$document.ready;

            _fwdc.onInitialize = function (callback)
            {
                _onInitialize.add(callback);
            };

            _fwdc.busySpinnerContent = function ()
            {
                //var spinnerHtml = '<div class="la-ball-spin-clockwise"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>';
                //var spinnerHtml = '<div class="la-ball-clip-rotate"><div></div></div>';
                //var spinnerHtml = '<div class="la-ball-clip-rotate"><div><div><div></div></div></div></div>';

                //return '<div class="la-ball-spin-clockwise"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>';

                return '<div class="BusySpinnerElement"></div>';
            };

            _fwdc.onSettingsLoaded = function () { };

            _fwdc.setSettings = function (settings)
            {
                if (settings)
                {
                    _datepickerSettings.dateFormat = settings.dateFormat || _datepickerSettings.dateFormat;
                    _datepickerSettings.runDate = _datepickerSettings.defaultDate = settings.defaultDate || _datepickerSettings.defaultDate;
                    _datepickerSettings.closeText = settings.datepickerCloseText || _datepickerSettings.closeText;
                    if (settings.firstDayOfWeek !== undefined)
                    {
                        _datepickerSettings.firstDay = settings.firstDayOfWeek;
                    }

                    _autocompleteOptions.messages.noResults = settings.comboNoResults;
                    _autocompleteOptions.messages.oneResult = settings.comboOneResult;
                    _autocompleteOptions.messages.multiResult = settings.comboMultiResults;

                    _toolTipSettings.verticalSide = settings.toolTipVerticalSide || _toolTipSettings.verticalSide;
                    _toolTipSettings.horizontalSide = settings.toolTipHorizontalSide || _toolTipSettings.horizontalSide;
                    _toolTipSettings.noFirstError = settings.toolTipNoFirstError || _toolTipSettings.noFirstError;
                    _toolTipSettings.noRequired = settings.toolTipNoRequired || _toolTipSettings.noRequired;
                    _toolTipSettings.noFirstRequired = _toolTipSettings.noRequired || _toolTipSettings.noFirstRequired;
                    if (settings.hideRequiredTip)
                    {
                        _toolTipSettings.noRequired = true;
                        _toolTipSettings.noFirstRequired = true;
                    }
                    _mobileBrowser = settings.mobileBrowser;
                    _tabletBrowser = settings.tabletBrowser;
                    _fwdc.tap = settings.tap;
                    _fwdc.appVersion = settings.version;
                    _loggedOn = settings.loggedOn;
                    _allowNewWindow = settings.allowNewWindow;
                    if (_fwdc.language !== settings.language)
                    {
                        _standardDecodes = null;
                        _datepickerRegional = null;
                    }
                    _fwdc.language = settings.language;
                    _fwdc.languageCode = settings.languageCode;
                    _fwdc.regionCode = settings.regionCode;
                    _fwdc.ltr = !(_fwdc.rtl = settings.rtl || false);
                    _fwdc.fontSize = settings.fontSize;
                    _fwdc.browserOptions.noAutoFocus = (settings.mobileBrowser);
                    _fwdc.autoFocusMode = _default(settings.autoFocusMode, true);
                    _fwdc.datePickerNoFocus = settings.datePickerNoFocus;
                    _fwdc.captchaType = settings.captchaType;
                    _fwdc.embedded = settings.embedded;

                    _fwdc.applyPageClasses(settings.pageClasses);

                    _fwdc.onSettingsLoaded();
                }

                if (!_fwdcInitialized)
                {
                    _fwdcInitialized = true;
                    _onFwdcInitialized();
                }
            };

            _fwdc.applyPageClasses = function (pageClasses)
            {
                if (pageClasses !== undefined)
                {
                    _fwdc.pageClasses = pageClasses;
                }

                if (_fwdc.appliedPageClasses !== _fwdc.pageClasses)
                {
                    if (_fwdc.appliedPageClasses)
                    {
                        _fwdc.$html().removeClass(_fwdc.appliedPageClasses);
                        _fwdc.appliedPageClasses = null;
                    }

                    if (_fwdc.pageClasses)
                    {
                        _fwdc.$html().addClass(_fwdc.pageClasses);
                    }

                    _fwdc.appliedPageClasses = _fwdc.pageClasses;

                    _fwdc.clearTransitionCache();
                }
            };

            var _fingerprintingRequested = false;
            var _fingerprintingRequestedInteractive = false;
            var _fingerprintSuccess = false;
            var _fingerprintFailed = false;
            var _fingerprintRanInteractive = false;
            var _fingerprintData = null;
            var _fingerprintDataJson = null;
            var _fingerprintBackgroundRequested = false;
            var _fingerprintVersion = 0;
            var _submittedFingerprintVersion = 0;
            // Version indicator for identifying fingerprint changes due to FAST software updates
            var _fastFingerprintVersion = "2";

            _fwdc.runFingerprinting = function (interactive)
            {
                if (window.Fingerprint2)
                {
                    // Exit if Fingerprinting is not working
                    if (_fingerprintFailed) { return; }

                    var runFingerprintingInternal = function (interactive)
                    {
                        var options = {
                            preprocessor: function (key, value)
                            {
                                switch (key)
                                {
                                    case "canvas":
                                        // Convert the canvas image data into a hashed value to keep the fingerprint data size down
                                        for (var jj = 0; jj < value.length; jj++)
                                        {
                                            var item = value[jj];
                                            if (item && item.startsWith && item.startsWith("canvas fp:"))
                                            {
                                                value[jj] = "canvas fp hash: " + Fingerprint2.x64hash128(item);
                                            }
                                        }
                                        return value;

                                    case "webgl":
                                        // Convert the webgl image data into a hashed value to keep the fingerprint data size down
                                        for (var jj = 0; jj < value.length; jj++)
                                        {
                                            var item = value[jj];
                                            if (item && item.startsWith && item.startsWith("data:image/png"))
                                            {
                                                value[jj] = "webgl image hash: " + Fingerprint2.x64hash128(item);
                                            }
                                        }
                                        return value;
                                }

                                return value;
                            },
                            extraComponents: [
                                {
                                    key: "webRtc",
                                    getData: function (done, options)
                                    {
                                        if (!DetectRTC)
                                        {
                                            done("N/A");
                                            return;
                                        }

                                        try
                                        {
                                            DetectRTC.load(function ()
                                            {
                                                try
                                                {
                                                    if (!DetectRTC.isWebRTCSupported)
                                                    {
                                                        done({
                                                            "isWebRTCSupported": DetectRTC.isWebRTCSupported
                                                        });
                                                        return;
                                                    }

                                                    done({
                                                        "webRtcSupported": DetectRTC.isWebRTCSupported,
                                                        "hasWebcam": DetectRTC.hasWebcam,
                                                        "hasMicrophone": DetectRTC.hasMicrophone,
                                                        "hasSpeakers": DetectRTC.hasSpeakers,
                                                        "screenCapturingSupported": DetectRTC.isScreenCapturingSupported,
                                                        "sctpDataChannelsSupported": DetectRTC.isSctpDataChannelsSupported,
                                                        "rtpDataChannelsSupported": DetectRTC.isRtpDataChannelsSupported,
                                                        "audioContextSupported": DetectRTC.isAudioContextSupported,
                                                        "desktopCapturingSupported": DetectRTC.isDesktopCapturingSupported,
                                                        "mobileDevice": DetectRTC.isMobileDevice,
                                                        // This can improve web socket detection but it makes external calls:
                                                        // DetectRTC.checkWebSocketsSupport(callback);
                                                        "webSocketsSupported": DetectRTC.isWebSocketsSupported,
                                                        "webSocketsBlocked": DetectRTC.isWebSocketsBlocked,
                                                        "canvasSupportsStreamCapturing": DetectRTC.isCanvasSupportsStreamCapturing,
                                                        "videoSupportsStreamCapturing": DetectRTC.isVideoSupportsStreamCapturing,
                                                        "audioInputDevices": DetectRTC.audioInputDevices && DetectRTC.audioInputDevices.length || 0,
                                                        "audioOutputDevices": DetectRTC.audioOutputDevices && DetectRTC.audioOutputDevices.length || 0,
                                                        "videoInputDevices": DetectRTC.videoInputDevices && DetectRTC.videoInputDevices.length || 0,
                                                        "osName": DetectRTC.osName,
                                                        "osVersion": DetectRTC.osVersion,
                                                        "browserName": DetectRTC.browser.name,
                                                        "browserVersion": DetectRTC.browser.version,
                                                        "privateBrowsing": DetectRTC.browser.isPrivateBrowsing
                                                    });
                                                    // This requires external call access and explicitly calls a google STUN URL
                                                    // DetectRTC.DetectLocalIPAddress(callback);
                                                }
                                                catch (ex)
                                                {
                                                    _fwdc._error(ex);
                                                    done("N/A");
                                                }
                                            });
                                        }
                                        catch (ex)
                                        {
                                            _fwdc._error(ex);
                                            done("N/A");
                                        }
                                    }
                                }
                            ]
                        };

                        window.Fingerprint2.get(options, function (components)
                        {
                            try
                            {
                                if (components)
                                {
                                    _fingerprintSuccess = true;

                                    var storeComponents = [];
                                    //var minifiedComponents = {};

                                    for (var ii = 0; ii < components.length; ii++)
                                    {
                                        var component = components[ii];

                                        switch (component.key)
                                        {
                                            // These components are not useful for later checking
                                            case "plugins": // Full browser plugin list is big
                                            case "canvas": // Canvas has been converted to a hash, we don't need the value later
                                            case "webgl": // WebGL has a ton of extensions and very detailed info that we aren't likely to use
                                            case "fonts": // Font list is big and not likely to be useful
                                                // Skip these components entirely
                                                break;

                                            default:
                                                // Store all other components as-is
                                                storeComponents.push(component);
                                                //minifiedComponents[component.key] = component.value;
                                                break;
                                        }
                                    }

                                    //console.log("Original Fingerprint2 Components size:", JSON.stringify(components).length);
                                    //console.log("Stored Fingerprint2 Components size:", JSON.stringify(storeComponents).length);
                                    //console.log("Minified Fingerprint2 Components size:", JSON.stringify(minifiedComponents).length);

                                    _fingerprintData = {
                                        fingerprintVersion: _fastFingerprintVersion,
                                        fingerprintSuccess: true,
                                        fingerprintData: storeComponents
                                    };

                                    var newDataJson = JSON.stringify(_fingerprintData);

                                    if (newDataJson !== _fingerprintDataJson && (interactive || !_fingerprintRanInteractive))
                                    {
                                        _fingerprintDataJson = newDataJson;
                                        _fingerprintVersion++;
                                        //_fwdc._log((interactive ? "Interactive" : "Background") + " Fingerprint Results (" + _fingerprintVersion + "):");
                                        //_fwdc._log(components);
                                    }

                                    if (interactive)
                                    {
                                        _fingerprintRanInteractive = true;
                                    }
                                }
                                else
                                {
                                    throw "Fingerprint2 returned no data";
                                }
                            }
                            catch (ex)
                            {
                                //_fwdc._warn("Error evaluating fingerprint data:", ex);
                                if (!_fingerprintVersion)
                                {
                                    _fingerprintData = {
                                        fingerprintVersion: _fastFingerprintVersion,
                                        fingerprintSuccess: false
                                    };
                                    _fingerprintDataJson = JSON.stringify(_fingerprintData);
                                    _fingerprintVersion = 1;
                                }
                            }
                        });
                    };

                    if (interactive)
                    {
                        if (_fingerprintingRequestedInteractive) { return; }
                        _fingerprintingRequestedInteractive = true;
                        runFingerprintingInternal(true);
                    }
                    else
                    {
                        if (_fingerprintBackgroundRequested) { return; }

                        _fingerprintBackgroundRequested = true;
                        _fwdc.requestIdleCallback("Fingerprint2", function ()
                        {
                            runFingerprintingInternal(false);
                        }, 500);
                    }
                }
                else if (!_fingerprintingRequested)
                {
                    _fwdc._warn("Fingerprint2 not available.");

                    if (!_fingerprintVersion)
                    {
                        _fingerprintData = {
                            fastVersion: _fastFingerprintVersion,
                            fingerprintSuccess: false
                        };
                        _fingerprintDataJson = JSON.stringify(_fingerprintData);
                        _fingerprintVersion = 1;
                    }
                }

                _fingerprintingRequested = true;
            };

            var _intlDateTimeFormatOptions;

            function _getIntlDateTimeFormatOptions()
            {
                if (_intlDateTimeFormatOptions)
                    return _intlDateTimeFormatOptions;

                var dtf;

                _intlDateTimeFormatOptions =
                    Intl
                    && Intl.DateTimeFormat
                    && (dtf = Intl.DateTimeFormat())
                    && dtf.resolvedOptions
                    && dtf.resolvedOptions()
                    || {};

                return _intlDateTimeFormatOptions;
            }

            function _touchEnabled()
            {
                return "ontouchstart" in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
            }

            var _clientInfoJson;

            _fwdc.getClientInfoJson = function ()
            {
                if (_clientInfoJson)
                    return _clientInfoJson;

                var intlOptions = _getIntlDateTimeFormatOptions();

                _clientInfoJson = JSON.stringify({
                    "browserFeatures":
                    {
                        "navigator":
                        {
                            "mediaDevices": "mediaDevices" in navigator,
                            "geolocation": "geolocation" in navigator,
                            "identity": "identity" in navigator,
                            "credentials": "credentials" in navigator
                        }
                    },
                    "time":
                    {
                        "timeZone": intlOptions.timeZone || null,
                        "timezoneOffset": -(new Date().getTimezoneOffset() / 60)
                    },
                    "screen":
                    {
                        "width": screen.width,
                        "height": screen.height,
                        "availWidth": screen.availWidth,
                        "availHeight": screen.availHeight,
                        "touchEnabled": _touchEnabled(),
                        "devicePixelRatio": window.devicePixelRatio || null
                    },
                    "system":
                    {
                        "language": intlOptions.locale || navigator.language || navigator.userLanguage || navigator.browserLanguage || navigator.systemLanguage || null,
                        "mobile": navigator.userAgentData && navigator.userAgentData.mobile || false
                    }
                });

                return _clientInfoJson;
            };

            _fwdc.busy = (function ()
            {
                var _busy = false,
                    _delayTimeout = 0,
                    _busyTimeout = null,
                    _newWindowTimeout = null,
                    _busyId = 1,
                    _source = "Unknown",
                    b = function (noWarn, event)
                    {
                        if (_busy && !noWarn)
                        {
                            _fwdc._warn("busy!");
                            _fwdc._printStackTrace();

                            if (event)
                            {
                                _fwdc._warn("Busy event:", event);
                            }
                        }
                        return _busy;
                    },
                    _callbacks = null,
                    _finalCallbacks = null,
                    _sourceClass = null,
                    _busySource = null;

                b.log = false;
                b.initialized = false;
                b.initialize = function ()
                {
                    if (!b.initialized)
                    {
                        b.$overlay = $('<div id="FastBusyOverlay" class="FastBusyOverlay" role="presentation"></div>').appendTo(_fwdc.$body());
                        b.$container = $('<div id="FastBusyContainer"></div>').appendTo(b.$overlay);
                        b.$element = $('<div id="FastBusySpinner" class="FastBusySpinner"></div>').html(_fwdc.busySpinnerContent()).appendTo(b.$container);
                        b.initialized = true;
                    }
                };

                function onBusyTimeout()
                {
                    _fwdc.refreshPage("onBusyTimeout");
                }

                function _onBusyDone()
                {
                    var callbacks = _callbacks;
                    if (callbacks)
                    {
                        _callbacks = null;
                        try
                        {
                            callbacks.fire();
                        }
                        catch (ex)
                        {
                            _fwdc._warn("Error in Busy Callback", ex);
                        }
                    }

                    var finalCallbacks = _finalCallbacks;
                    if (finalCallbacks)
                    {
                        _finalCallbacks = null;
                        try
                        {
                            finalCallbacks.fire();
                        }
                        catch (ex)
                        {
                            _fwdc._warn("Error in Busy Final Callback", ex);
                        }
                    }
                }

                b._setupElements = function (options)
                {
                    if (this.$message)
                    {
                        this.$message.remove();
                        delete this.$message;
                    }

                    if (this.$unlock)
                    {
                        this.$unlock.remove();
                        delete this.$unlock;
                    }

                    if (options.message)
                    {
                        this.$message = $($.parseHTML('<div id="FastBusyMessage" class="FastBusyMessage"></div>')).text(options.message).appendTo(this.$container);

                        if (options.unlock)
                        {
                            this.$unlock = $($.parseHTML('<a id="FastUnlockSessionLink" class="UnlockSessionLink" href="#"></a>')).text(options.unlock).appendTo(this.$message);
                        }
                    }

                    if (this.$progressBar)
                    {
                        //this.$progressBar.remove();
                        delete this.$progressBar;
                    }

                    if (this.$progressLabel)
                    {
                        //this.$progressLabel.remove();
                        delete this.$progressLabel;
                    }

                    if (this.$progress)
                    {
                        this.$progress.remove();
                        delete this.$progress;
                    }

                    //if (options.showProgress)
                    {
                        this.$progress = $($.parseHTML('<div class="BusyProgress Hidden"></div>'));
                        this.$progressBar = $($.parseHTML('<div id="BusyProgressBar" class="BusyProgressBar Hidden"></div>')).progressbar().appendTo(this.$progress);
                        this.$progressLabel = $($.parseHTML('<div id="BusyProgressLabel" class="BusyProgressLabel Hidden"></div>')).appendTo(this.$progress);
                        this.$progress.appendTo(this.$container);
                    }

                    if (this.$newWindow)
                    {
                        this.$newWindow.remove();
                        delete this.$newWindow;
                    }

                    if (_allowNewWindow && _default(options.allowNewWindow, true))
                    {
                        var $newWindow = this.$newWindow = $($.parseHTML('<div id="FastBusyNewWindow" class="FastBusyNewWindow" style="visibility:hidden;"></div>'));
                        $($.parseHTML('<a href="./?NewWindow=1" target="_blank" class="FastBusyNewWindowLink"></a>')).text(_fwdc.getDecode("BusyNewWindow")).appendTo(this.$newWindow);
                        this.$newWindow.appendTo(this.$container);
                        _newWindowTimeout = setTimeout(function ()
                        {
                            if ($newWindow)
                            {
                                $newWindow.hide().css("visibility", "").fadeIn(250);
                            }
                            _newWindowTimeout = null;
                        }, 1000);
                    }
                };

                function _showBusyOverlay(options /*source, delay, sync, unlock, message, timeout*/)
                {
                    _fwdc.$body().addClass("Busy").attr("aria-busy", "true");

                    _busySource = options.busySource;
                    if (options.busySource !== undefined)
                    {
                        if (options.busySource)
                        {
                            _sourceClass = "Busy" + options.busySource;
                        }
                        else
                        {
                            _sourceClass = null;
                        }
                    }

                    if (_sourceClass)
                    {
                        _fwdc.$body().addClass(_sourceClass);
                    }

                    options = options || {};

                    _source = options.source || "Unknown";

                    b._setupElements(options);

                    b.$container.removeClass("Immediate");

                    if (options.sync)
                    {
                        b.$container.addClass("Immediate");
                    }
                    /*else if (options.delay !== undefined && !options.delay)
                    {
                        b.$container.stop().fadeIn(100);
                    }*/
                    /*else if (!_delayTimeout)
                    {
                        _delayTimeout = setTimeout(function ()
                        {
                            //b.$container.stop().fadeIn(100);
                            _delayTimeout = null;
                        }, options.delay || 300);
                    }*/

                    if (options.message)
                    {
                        b.$container.addClass("HasMessage");
                        //b.$container.stop().show();
                    }
                    else
                    {
                        b.$container.removeClass("HasMessage");
                        //b.$container.stop().fadeIn(100);
                    }

                    //b.$overlay.show();
                    _busyTimeout = setTimeout(onBusyTimeout, options.timeout || 3600000);
                }

                b.tryShow = function (source, options /*sync, check, delay*/)
                {
                    options = options || {};

                    if (options.check && _busy)
                    {
                        _fwdc._trace("[" + _source + "] Already Busy @ [" + (source || "Unknown") + "]");
                        return false;
                    }

                    options.source = source;

                    _busy = true;
                    _busyId++;


                    if (b.log)
                    {
                        _fwdc._trace("busy.tryShow: " + source);
                    }

                    //_fwdc._log("++TRYBUSY: " + source + "(" + _busyId + ")");
                    //_fwdc._printStackTrace();

                    _showBusyOverlay(options);

                    return _busyId;
                };

                b.show = function (source, options /*delay, sync, unlock, message, timeout*/)
                {
                    if (b.log)
                    {
                        _fwdc._log("busy.show: " + source);
                    }

                    _busyId++;

                    options = options || {};
                    options.source = source;

                    if (!_busy || options.message)
                    {
                        _busy = true;
                        _showBusyOverlay(options);
                        //_fwdc._log("++BUSY: " + source + "(" + _busyId + ")");
                        //_fwdc._printStackTrace();
                    }
                    return _busyId;
                };

                b.showUnloading = function ()
                {
                    var unloadingId = b.tryShow("ShowUnloading", { sync: true, check: true });
                    if (unloadingId)
                    {
                        b.unloading = unloadingId;
                    }

                    return b.unloading;
                };

                b.hideUnloading = function ()
                {
                    if (b.unloading)
                    {
                        b.hide(b.unloading);
                        b.unloading = null;
                    }
                };

                b.hide = function (lockedBusyId)
                {
                    if (b.log)
                    {
                        _fwdc._log("busy.hide: " + _source);
                    }

                    if (_busy)
                    {
                        if (lockedBusyId && lockedBusyId !== _busyId)
                        {
                            //_fwdc._warn("[" + _source + "] Busy ID mismatch: " + lockedBusyId + " vs. " + _busyId);
                            //_fwdc._printStackTrace();
                            return false;
                        }

                        //_fwdc._log("--BUSY (" + lockedBusyId + ")");
                        //_fwdc._printStackTrace();

                        if (_delayTimeout)
                        {
                            clearTimeout(_delayTimeout);
                            _delayTimeout = null;
                        }
                        if (_busyTimeout)
                        {
                            clearTimeout(_busyTimeout);
                            _busyTimeout = null;
                        }
                        if (_newWindowTimeout)
                        {
                            clearTimeout(_newWindowTimeout);
                            _newWindowTimeout = null;
                        }

                        _fwdc.$body().removeClass("Busy").attr("aria-busy", "false");
                        if (_sourceClass)
                        {
                            _fwdc.$body().removeClass(_sourceClass);
                        }
                        b.$container.removeClass("Immediate");

                        //b.$container.stop().hide();
                        //b.$overlay.hide();
                        _busy = false;

                        _onBusyDone();

                        if (!_busy)
                        {
                            _sourceClass = null;
                        }

                        return true;
                    }

                    return false;
                };

                b.done = function (callback, defer, final)
                {
                    var deferred = $.Deferred();

                    var runCallback = function ()
                    {
                        //callback();
                        //deferred.resolve();

                        if (_busy)
                        {
                            _fwdc.busy.done(callback, defer, final, deferred);
                        }
                        else
                        {
                            callback();
                            deferred.resolve();
                        }
                    };

                    if (_busy)
                    {
                        if (final)
                        {
                            if (!_finalCallbacks)
                            {
                                _finalCallbacks = $.Callbacks();
                            }
                            _finalCallbacks.add(runCallback);
                        }
                        else
                        {
                            if (!_callbacks)
                            {
                                _callbacks = $.Callbacks();
                            }
                            _callbacks.add(runCallback);
                        }
                    }
                    else if (defer)
                    {
                        _fwdc.setTimeout("busy.done Deferred", runCallback, 0);
                    }
                    else
                    {
                        runCallback();
                    }

                    return deferred.promise();
                };

                b.promise = function (defer)
                {
                    var deferred = $.Deferred();

                    if (_busy)
                    {
                        if (!_callbacks)
                        {
                            _callbacks = $.Callbacks();
                        }

                        _callbacks.add(function ()
                        {
                            deferred.resolve();
                        });

                        return deferred.promise();
                    }

                    if (defer)
                    {
                        _fwdc.setTimeout("busy.done Deferred", deferred.resolve, 0);
                        return deferred.promise();
                    }

                    return Promise.resolve();
                };

                b.isBusy = function ()
                {
                    return _busy;
                };

                b.setProgress = function (value, max, message)
                {
                    if (!this.$progress) { return false; }

                    this.$progress.removeClass("Hidden");

                    if (value !== undefined)
                    {
                        if (value < 0)
                        {
                            value = false;
                        }

                        this.$progressBar.removeClass("Hidden").progressbar({ "value": value, "max": max });
                    }
                    else
                    {
                        this.$progressBar.addClass("Hidden");
                    }

                    if (message !== undefined)
                    {
                        this.$progressLabel.text(message);
                        if (!message)
                        {
                            this.$progressLabel.addClass("Hidden");
                        }
                        else
                        {
                            this.$progressLabel.removeClass("Hidden");
                        }
                    }

                    return true;
                };

                b.setMessage = function (message)
                {
                    return b.setProgress(undefined, undefined, message);
                };

                b.getBusySource = function ()
                {
                    return _busySource;
                };

                return b;
            }());

            _fwdc.uiBusy = function (noWarn, event)
            {
                return _fwdc.busy(noWarn, event) || _fwdc.transitioning(noWarn);
            };

            /*function _onScriptError(ex)
            {
                try
                {
                    var errorText;
                    if (ex instanceof Error)
                    {
                        if (ex.stack)
                        {
                            errorText = ex.stack;
                        }
                        else
                        {
                            errorText = ex.toString();
                        }
                    }
                    else
                    {
                        errorText = ex + '';
                    }
    
                    _fwdc._warn(errorText);
    
                    $.ajax({
                        url: 'ClientScriptError',
                        method: 'POST',
                        async: true,
                        data: { ERROR__: errorText },
                        dataType: "json",
                        error: function (request, statusText, error)
                        {
                            _fwdc._warn("Error submitting client script error.");
                            _fwdc._warn(error);
                        },
                        success: function (data, status, request)
                        {
                            _fwdc._warn("Submitted client script error: " + data.referenceId);
                        }
                    });
                }
                catch (ignore)
                {
                }
            }*/

            function _fwdcAjaxBeforeSend(request, options)
            {
                /*jshint validthis: true */
                if (options.fastBeforeSend)
                {
                    if (options.fastBeforeSend.call(this, request, options) === false)
                    {
                        if (options.busy && !_stayBusy) { _busy.hide(); }
                        return false;
                    }
                }

                if (options && options.fastRequest)
                {
                    if (!options.ignoreActivityCheck)
                    {
                        _fwdc.pauseActivityCheck();
                    }
                    _fwdc.pauseSessionCheck();

                    if (!options.ignoreSessionData && options.type !== "GET" && options.contentType === "application/x-www-form-urlencoded")
                    {
                        if (options.data)
                        {
                            options.data += "&FAST_SCRIPT_VER__=" + encodeURIComponent(_fwdc.scriptVersion);
                        }
                        else
                        {
                            options.data = "FAST_SCRIPT_VER__=" + encodeURIComponent(_fwdc.scriptVersion);
                        }

                        options.data += "&FAST_VERLAST__=" + encodeURIComponent(_fwdc.fastVerLast);
                        options.data += "&FAST_VERLAST_SOURCE__=" + encodeURIComponent(_fwdc.fastVerLastSource);

                        if (_fwdc.lastNotification)
                        {
                            options.data += "&FAST_LASTNOTIFICATION__=" + encodeURIComponent(_fwdc.lastNotification);
                        }

                        options.data += "&FAST_CLIENT_WHEN__=" + encodeURIComponent(_fwdc.now());
                        options.data += "&FAST_CLIENT_WINDOW__=" + encodeURIComponent(_fwdc.getFastWindowName());
                        options.data += "&FAST_CLIENT_AJAX_ID__=" + encodeURIComponent(++_ajaxId);
                        options.data += "&FAST_CLIENT_TRIGGER__=" + encodeURIComponent(options.trigger || "");

                        // ' TODO: Remove this check.
                        /*if (options.sourceId === undefined)
                        {
                            _fwdc._log("AJAX Call Missing Source ID: " + options.url);
                            _fwdc._printStackTrace();
                        }*/
                        options.data += "&FAST_CLIENT_SOURCE_ID__=" + encodeURIComponent(options.sourceId || "");

                        if (_fingerprintVersion > _submittedFingerprintVersion)
                        {
                            options.data += "&FAST_FINGERPRINT__=" + encodeURIComponent(_fingerprintDataJson);
                            options._submittedFingerprintVersion = _fingerprintVersion;
                        }
                    }
                    if (_fwdc.stopAutoRefresh && !options.ignoreAutoRefresh) { _fwdc.stopAutoRefresh(); }

                    options.sendWhen = _fwdc.now();
                }

                if (options.sending)
                {
                    options.sending.call(this, request, options);
                }
            }

            //function _logTimeout(name, timeout)
            //{
            //    if (_fwdc.development && timeout)
            //    {
            //        _fwdc._log(name + ": " + Math.round(timeout / 60000) + "min");
            //    }
            //}

            // The custom argument may come from ajaxForm.
            _fwdc.fwdcAjaxSuccess = function (response, status, request, custom)
            {
                /*jshint validthis: true */
                try
                {
                    var options = this;

                    this.fastOk = true;

                    if (options.fastRequest)
                    {
                        options.received = _fwdc.now();
                        if (request.getResponseHeader("Fast-Ver-Last"))
                        {
                            FWDC.setVerLast(request.getResponseHeader("Fast-Ver-Last"), request.getResponseHeader("Fast-Ver-Source") || "fwdcAjaxSuccessHeader", options.forceVerLast);
                        }
                        else if (response && response.fastverlast)
                        {
                            FWDC.setVerLast(response.fastverlast, response.fastverlastsource || "fwdcAjaxSuccess");
                        }

                        var updateFrom;

                        var expiryTimeout = request.getResponseHeader("Fast-Session-Idle");
                        if (expiryTimeout !== null)
                        {
                            updateFrom = true;
                            expiryTimeout = parseInt(expiryTimeout, 10);
                            _fwdc.sessionTimeouts.expiryTimeout = isNaN(expiryTimeout) ? null : expiryTimeout;
                            if (_fwdc.sessionTimeouts.expiryTimeout)
                            {
                                _fwdc.sessionTimeouts.expiryWarningTimeout = Math.max(_fwdc.sessionTimeouts.expiryTimeout - 305000, 0);

                                //_logTimeout("Expiry", _fwdc.sessionTimeouts.expiryTimeout);
                            }
                            else
                            {
                                _fwdc.sessionTimeouts.expiryWarningTimeout = null;
                            }
                            //_fwdc.startExpiryTimer(expiryTimeout);
                        }

                        var idleTimeout = request.getResponseHeader("Fast-Session-Lock");
                        if (idleTimeout !== null)
                        {
                            updateFrom = true;
                            idleTimeout = parseInt(idleTimeout, 10);
                            _fwdc.sessionTimeouts.idleTimeout = isNaN(idleTimeout) ? null : idleTimeout;
                            //_fwdc.startActivityCheck(idleTimeout);
                            //_logTimeout("Lock", _fwdc.sessionTimeouts.idleTimeout);
                        }

                        var endTimeout = request.getResponseHeader("Fast-Session-End");
                        if (endTimeout !== null)
                        {
                            updateFrom = true;
                            endTimeout = parseInt(endTimeout, 10);
                            _fwdc.sessionTimeouts.endTimeout = isNaN(endTimeout) ? null : endTimeout;
                            //_logTimeout("End", _fwdc.sessionTimeouts.endTimeout);
                            //_fwdc.setupEndTimer(endTimeout);
                        }

                        var keepaliveTimeout = request.getResponseHeader("Fast-Keepalive-Timeout");
                        if (keepaliveTimeout !== null)
                        {
                            updateFrom = true;
                            keepaliveTimeout = parseInt(keepaliveTimeout, 10);
                            _fwdc.sessionTimeouts.keepaliveTimeout = isNaN(keepaliveTimeout) ? null : keepaliveTimeout;
                            //_logTimeout("Keepalive", _fwdc.sessionTimeouts.keepaliveTimeout);
                        }
                        else if (_fwdc.sessionTimeouts.keepaliveTimeout)
                        {
                            _fwdc.sessionTimeouts.keepaliveTimeout = null;
                            updateFrom = true;
                        }

                        if (updateFrom)
                        {
                            _fwdc.sessionTimeouts.from = _fwdc.now();
                        }

                        if (request.responseJSON)
                        {
                            _fwdc.runResponseFunctions(request.responseJSON, false);
                        }

                        if (options._submittedFingerprintVersion && options._submittedFingerprintVersion > _submittedFingerprintVersion)
                        {
                            _submittedFingerprintVersion = options._submittedFingerprintVersion;
                            //_fwdc._log("Submitted fingerprint version " + _submittedFingerprintVersion);
                        }
                    }

                    if (options.fastSuccess)
                    {
                        if (options.fastSuccess.call(this, response, status, request, custom) === false)
                        {
                            _fwdc.refreshPage("fastSuccess Failed");
                            return;
                        }
                    }

                    if (options.fastRequest && request.responseJSON)
                    {
                        _fwdc.runResponseFunctions(request.responseJSON, true);
                    }
                }
                catch (ex)
                {
                    _fwdc.onAjaxError("Success.Exception", ex);
                }
            }

            _fwdc.fwdcAjaxError = function (request, status, error)
            {
                /*jshint validthis: true */
                try
                {
                    var options = this;

                    if (options.fastRequest && !options.ignoreSessionError && request.getResponseHeader("Fast-Session-Expired"))
                    {
                        var location = request.getResponseHeader("location");
                        if (location)
                        {
                            window.location = location;
                            return false;
                        }

                        FWDC.openUrl("../LogOff/?Expired=1");
                        return;
                    }

                    if (options.fastRequest)
                    {
                        options.received = _fwdc.now();
                        if (request.getResponseHeader("Fast-Ver-Last"))
                        {
                            FWDC.setVerLast(request.getResponseHeader("Fast-Ver-Last"), request.getResponseHeader("Fast-Ver-Source") || "fwdcAjaxErrorHeader");
                        }
                    }

                    if (options.fastError)
                    {
                        if (options.fastError.call(this, request, status, error) === false) { return; }
                    }

                    if (options.fastRequest && (request.status !== 422 && request.status !== 401))
                    {
                        var isHtml = request.getResponseHeader("Content-Type");
                        isHtml = (isHtml && isHtml.indexOf("text/html") > -1);
                        _fwdc.onAjaxError("Error.General", request.responseText, isHtml);
                    }
                }
                catch (ex)
                {
                    _fwdc.onAjaxError("Error.Exception", ex);
                }
            }

            _fwdc.fwdcAjaxComplete = function (response, status, request)
            {
                /*jshint validthis: true */
                try
                {
                    var options = this;

                    if (!this.fastOk)
                    {
                        request = response;
                    }

                    if (options.fastRequest)
                    {
                        if (request.status === 401)
                        {
                            _fwdc.refreshPage("ajaxComplete.401");
                            return;
                        }

                        if (request.status === 422 && !options.ignoreSessionError)
                        {
                            _fwdc._warn("Received Desync Status");

                            var location = request.getResponseHeader("location");
                            if (location)
                            {
                                window.location = location;
                                return false;
                            }

                            if (request.getResponseHeader("Fast-Session-Expired"))
                            {
                                FWDC.openUrl("../LogOff/?Expired=1");
                                return;
                            }

                            if (request.getResponseHeader("Fast-Session-Locked"))
                            {
                                _fwdc.refreshPage("ajaxComplete.SessionLock");
                                return;
                            }

                            if (!options.hideErrors)
                            {
                                if ((request.getResponseHeader("content-type") || "").startsWith("text/html") && request.responseText)
                                {
                                    _fwdc.destroyRichElements(true);

                                    var $newContents = $(request.responseText).filter(":NOT(script,title,meta,link)");
                                    if (_fwdc.$body()) { _fwdc.$body().empty().append($newContents); _fwdc.updateScreenReader(); }

                                    _errorOccurred = false;
                                }
                                else
                                {
                                    _fwdc.refreshPage("ajaxComplete.UnknownContent", true);
                                }
                            }
                            else
                            {
                                _errorOccurred = false;
                            }
                        }

                        if (_fwdc._showLastRequest && options.requestWhen && options.fastLog !== false)
                        {
                            var now = _fwdc.now();

                            var difference = now - options.requestWhen;

                            var serverTime;

                            if (options.sendWhen && options.received)
                            {
                                serverTime = options.received - options.sendWhen;
                            }

                            _fwdc._showLastRequest(
                                options.displayOperation || options.url,
                                difference,
                                serverTime,
                                options.trigger,
                                options.sender,
                                request.status,
                                request.getResponseHeader("Server-Timing"),
                                request.getResponseHeader("Fast-Dev-Counter"));
                        }

                        _fwdc.resumeActivityCheck();

                        if (options.busy && !_stayBusy)
                        {
                            _busy.hide(options.busyId);
                        }

                        _openingUrl = false;

                        /*if (options.finally)
                        {
                            options.finally.call(this, request, status);
                        }*/

                        _fwdc.resumeSessionCheck();
                    }

                    if (options.fastComplete)
                    {
                        options.fastComplete.call(this, request, status);
                    }
                }
                catch (ex)
                {
                    _fwdc.onAjaxError("Complete.Exception", ex);
                }
            }

            _fwdc.setTimeout = function (name, callback, timeout, arg1, arg2, arg3, arg4)
            {
                //_fwdc._log("setTimeout: " + name + " (" + timeout + ")");
                if (timeout < 0)
                {
                    return callback(arg1, arg2, arg3, arg4);
                }
                return window.setTimeout(callback, timeout || 0, arg1, arg2, arg3, arg4);
            };

            _fwdc.requestIdleCallback = function (name, callback, timeout, arg1, arg2, arg3, arg4)
            {
                //_fwdc._log("setTimeout: " + name + " (" + timeout + ")");

                if (window.requestIdleCallback)
                {
                    return window.requestIdleCallback(callback, { "timeout": timeout || 0 }, arg1, arg2, arg3, arg4);
                }
                else
                {
                    return window.setTimeout(callback, timeout || 0, arg1, arg2, arg3, arg4);
                }
            };

            _fwdc.clearTimeout = function (name, handle)
            {
                if (handle)
                {
                    //_fwdc._log("clearTimeout: " + name);
                    return window.clearTimeout(handle);
                }
            };

            _fwdc.focusDatepickerHeaderChanged = function ($container, element)
            {
                var $over = $container.querySelectorAll(".ui-datepicker-" + element);
                if ($over.length)
                {
                    $over.focus();
                    return true;
                }

                return _fwdc.focusDatepickerSelected($container);
            };

            _fwdc.focusDatepickerSelected = function ($container)
            {
                var $day = _fwdc.getDatepickerDayFocusTarget($container, true);
                if ($day)
                {
                    $day.focus();
                    return true;
                }

                return false;
            };

            _fwdc.getDatepickerDayFocusTarget = function ($container, active)
            {
                var $over = $container.find(".ui-datepicker-days-cell-over > button:enabled");
                if ($over.length)
                {
                    return $over;
                }

                if (active)
                {
                    // Only look for the active day if we are still directly interacting with datepicker (i.e. keydown handler)
                    // Otherwise, the active day may be hidden and we should focus the current day instead.
                    var $active = $container.find(".ui-state-active > button:enabled");
                    if ($active.length)
                    {
                        return $active;
                    }
                }

                var $current = $container.find(".ui-datepicker-current-day > button:enabled");
                if ($current.length)
                {
                    return $current;
                }

                var $today = $container.find(".ui-datepicker-today > button:enabled");
                if ($today.length)
                {
                    return $today;
                }

                var $first = $container.find(".FastDatepickerDayContainer > button:enabled");
                if ($first.length)
                {
                    return $first.first();
                }

                //Can't focus on a day - focus on change buttons
                var $prev = $container.find(".FastDatepickerChangeMonth .ui-datepicker-prev");
                if ($prev.length)
                {
                    return $prev;
                }

                var $next = $container.find(".FastDatepickerChangeMonth .ui-datepicker-next");
                if ($next.length)
                {
                    return $next;
                }

                return null;
            };

            _fwdc.datepickerHasFocus = function (inst)
            {
                return !!$(document.activeElement).closest(inst.dpDiv).length;
            };

            _fwdc.focus = function (trigger, $field, options)
            {
                if (trigger && typeof trigger !== "string")
                {
                    options = $field;
                    $field = trigger;
                    trigger = undefined;
                }

                options = options || {};

                var checkTabIndex = options.checkTabIndex;
                var defaultFocus = options.defaultFocus;
                var focused = false;
                var preventScroll = options.preventScroll;

                try
                {
                    var $focusTarget = $field;
                    var $visibleElement = $field;

                    if ($field && !$field.inDom())
                    {
                        // The field isn't currently in the DOM.  Attempt to find the new version of it based on its ID.
                        if ($field.attr("id"))
                        {
                            $field = _fwdc.formField($field.attr("id"));
                            // Couldn't find the new version - bail out.
                            if (!$field)
                            {
                                return null;
                            }
                        }
                        else
                        {
                            // The field has no ID, so we can't look for a new  version.
                            return null;
                        }
                    }

                    if (!$field || !$field.length)
                    {
                        // No field to focus.
                        return null;
                    }

                    if ($field.closest(".fast-ui-selectable").length)
                    {
                        // Prevent focusing fields that are in selectable elements.
                        return false;
                    }

                    if (checkTabIndex)
                    {
                        // If we're checking the tabindex, prevent focusing an element with a negative tabindex.
                        var tabindex = $field.attr("tabindex");
                        if (tabindex !== undefined && tabindex < 0)
                        {
                            return false;
                        }
                    }

                    if (($field.hasClass("ui-checkboxradio") || $field.hasClass("FastComboButtonRadio")) && !$field.is(":checked"))
                    {
                        // If we're focusing a checkbox radio control, focus the current one instead of the provided one.
                        var $checked = $field.parent().children("input:checked");
                        if ($checked.length)
                        {
                            $focusTarget = $checked;
                        }
                    }
                    else if ($field.hasClass("FastCodeMirrorBox"))
                    {
                        // For CodeMirror boxes, use the editor container as the visible element instead of the focused textarea.
                        $visibleElement = $field.next(".CodeMirror");
                    }
                    else if ($field.hasClass("FastCameraInputImage"))
                    {
                        // For camera fields, focus the capture button directly.
                        $focusTarget = $field.find("button").first();
                    }
                    else if ($field.hasClass("FastCaptchaField"))
                    {
                        $focusTarget = $field.find("iframe");
                    }
                    else if ($field.hasClass("FastInlineDatepicker"))
                    {
                        $focusTarget = _fwdc.getDatepickerDayFocusTarget($field, false);
                    }

                    if ($focusTarget && $focusTarget.length && $visibleElement.isVisible())
                    {
                        // For table bodies, do not try to check the full size as they may scroll.  Disable this check outside of auto focus mode for simplicity.
                        if (defaultFocus && _fwdc.autoFocusMode && !_fwdc.isElementVisible($visibleElement, null, $visibleElement.tagIs("tbody")))
                        {
                            // Do not force focus onto a default element if it isn't currently visible so we don't scroll unnecessarily.
                            return false;
                        }

                        var $dialog = $focusTarget.closest(".FastModal");
                        var $topDialog = _fwdc.currentDialogContainer(true);
                        var $link;
                        if ($dialog.equals($topDialog))
                        {
                            var $focusParent;
                            if ($focusTarget.hasClass("FastCodeMirrorBox"))
                            {
                                // CodeMirror requires an explicit focus call through its API.
                                $focusTarget.data("fast-code-mirror-editor").focus();
                                focused = true;
                            }
                            else if ($focusTarget.hasClass("HasCKEditor"))
                            {
                                // CKEditor requires an explicit focus call through its API.
                                var richTextBox = $focusTarget.ckeditorGet();
                                if (richTextBox)
                                {
                                    var $container = $(richTextBox.container.$);
                                    if ($container && $container.length && $container.is(":visible"))
                                    {
                                        richTextBox.focus();
                                        focused = true;
                                    }
                                }
                            }
                            else
                            {
                                if ($focusTarget.tagIs("tbody"))
                                {
                                    if ($focusTarget.attr("tabindex") !== undefined)
                                    {
                                        _setFocus = true;
                                        $focusTarget.focusScroll(!preventScroll);
                                        _setFocus = false;
                                        if ($focusTarget.is(".DocEditableTable tbody"))
                                        {
                                            focused = true;
                                            return true;
                                        }
                                        else
                                        {
                                            focused = true;
                                        }
                                    }
                                }
                                else if ($focusTarget.hasClass("ui-autocomplete-input"))
                                {
                                    // Workaround for IE10/11 focus + placeholder bug that opens the dropdown on programmatic focus if a watermark is present:
                                    _suppressComboboxInput($focusTarget);
                                    $focusTarget.focusScroll(!preventScroll);
                                    $focusTarget.select();
                                    focused = true;
                                }
                                else if ($focusTarget.is(":enabled"))
                                {
                                    $focusTarget.focusScroll(!preventScroll);
                                    $focusTarget.select();
                                    focused = true;
                                }
                                else if ($focusTarget.tagIs("a"))
                                {
                                    if (!$focusTarget.attr("href"))
                                    {
                                        // Links without an href are not focusable, so skip them.
                                        return false;
                                    }
                                    $focusTarget.focusScroll(!preventScroll);
                                    focused = true;
                                }
                                else if ($focusTarget.is("td.TDC,td.TDS,td.VICell"))
                                {
                                    $link = $focusTarget.find("a");
                                    if ($link && $link.length)
                                    {
                                        if (!$link.attr("href"))
                                        {
                                            // Links without an href are not focusable, so skip them.
                                            return false;
                                        }

                                        $link.focusScroll(!preventScroll);
                                        focused = true;
                                    }
                                    else if ($focusTarget.hasClass("FieldEnabled"))
                                    {
                                        focused = _fwdc.beginEditCell($focusTarget, true);
                                    }
                                }
                                else if ($focusTarget.tagIs("li"))
                                {
                                    $link = $focusTarget.find("a");
                                    if ($link && $link.length)
                                    {
                                        $link.focusScroll(!preventScroll);
                                        focused = true;
                                    }
                                }
                                else if ($focusTarget.hasClass("FastFocusable"))
                                {
                                    $focusTarget.focusScroll(!preventScroll);
                                    focused = true;
                                }
                                else if ($focusTarget.tagIs("iframe"))
                                {
                                    // This is imperfect, as the focus doesn't move into the frame and hit the first real focusable, it sticks to the frame/body itself.
                                    $focusTarget[0].contentWindow.focus();
                                    focused = true;
                                }
                                else if (($focusParent = $focusTarget.parent(".FastFocusable")) && $focusParent.length)
                                {
                                    $focusParent.focusScroll(!preventScroll);
                                    focused = true;
                                }
                            }

                            if (focused && _fwdc.debugFocus)
                            {
                                _fwdc._trace("Focused: ", $focusTarget);
                            }

                            return focused;
                        }
                    }

                    return null;
                }
                finally
                {
                    //if (focused)
                    //{
                    //    //_fwdc._trace("Focused: ", $focusTarget);

                    //}
                    //else
                    //{
                    //    //_fwdc._trace("Skipped Focus: ", document.activeElement);
                    //}
                }
            };

            // Sets up FAST ajax args with standard handlers before function specific handlers.
            _fwdc.setupAjaxArgs = function (args)
            {
                var origArgs = args;
                args = $.extend({}, _fastAjaxArgs, args, {
                    beforeSend: _fwdcAjaxBeforeSend,
                    fastBeforeSend: args.beforeSend,
                    error: null,
                    fastError: args.error,
                    success: null,
                    fastSuccess: args.success,
                    complete: null,
                    fastComplete: args.complete,
                    headers: _siteHttpHeaders,
                    requestWhen: _fwdc.now(),
                    origArgs: args
                });

                return args;
            };

            // Prepares to run an AJAX call, checking busy status and pending edits as necessary.
            // Returns false if the request should not be started.
            _fwdc.startAjaxArgs = function (args)
            {
                if (args.fastRequest)
                {
                    if (_fwdc.ajax.log)
                    {
                        _fwdc._trace("Starting AJAX Call: ", args.displayOperation || args.url);
                    }

                    if (_errorOccurred)
                    {
                        _fwdc._trace("Skipping call on errored window.");
                        return false;
                    }

                    if (_closing)
                    {
                        _fwdc._trace("Skipping call on closing window.");
                        return false;
                    }

                    if (!FWDC.fastReady && !args.ignoreReady)
                    {
                        _fwdc._trace("Skipping call on uninitialized manager.");
                        return false;
                    }

                    // Add the Browser-URL and Fast-XHR headers to every AJAX call
                    if (args.headers)
                    {
                        args.headers["Fast-Browser-Url"] = window.location.href;
                        args.headers["Fast-XHR"] = "true";
                    }
                    else
                    {
                        args.headers = { "Fast-Browser-Url": window.location.href, "Fast-XHR": "true" };
                    }

                    // If the args didn't specify a busy checking mode, default it to the same as the busy flag
                    if (args.checkBusy === null) { args.checkBusy = args.busy; }

                    // Capture the HTTP method
                    var method = args.method || args.type;

                    // Do not allow jQuery's internal contentType to be provided on GET/HEAD requests
                    if (method === "GET" || method === "HEAD")
                    {
                        args.contentType = "";
                    }

                    // We'll want to commit any pending edits before sending this if the request isn't GET
                    if (args.commitEdits === null || args.commitEdits === undefined) { args.commitEdits = (method !== "GET"); }

                    // If edits need to be commited, send them out.  If it fails, we need to cancel this request
                    if (args.commitEdits && (_fwdc.commitEdits("ajax:" + args.url) === false) && args.checkBusy)
                    {
                        return false;
                    }

                    if (args.busy)
                    {
                        // Check the busy options on the args to detect if we need to do anything special with the busy screen
                        var busyOptions = { sync: !args.async, check: args.checkBusy, busySource: args.busySource };
                        if (args.busyOptions)
                        {
                            busyOptions = $.extend(busyOptions, args.busyOptions);
                        }

                        if ((args.busyId = _busy.tryShow("AJAX: " + args.url, busyOptions)) === false)
                        {
                            if (args.event)
                            {
                                _fwdc._warn("Busy event: ", args.event);
                            }
                            return false;
                        }
                    }
                    else if (args.checkBusy && _busy())
                    {
                        // If we're already busy, cancel the request
                        return false;
                    }

                    // Give the arguments one last chance to do custom validation before the request is sent
                    if (args.beforeRequest && (args.beforeRequest(args) === false))
                    {
                        return false;
                    }

                    // Add the client info header to every AJAX call
                    args.headers["Fast-Client-Info"] = _fwdc.getClientInfoJson();

                    //_fwdc._log("==> AJAX: " + args.url);
                    //_fwdc._printStackTrace_printStackTrace();

                    // If the data is a function, call it to gather data at the last minute
                    if (typeof args.data === "function")
                    {
                        args.data = args.data(args.origArgs);
                    }
                }

                return args;
            };

            /**
             * Executes an AJAX call using jQuery.
             * @param {any} args - The configuration for the AJAX call.
             * @returns A jQuery AJAX call tracking object.
             */
            _fwdc.ajax = function (args)
            {
                args = _fwdc.startAjaxArgs(_fwdc.setupAjaxArgs(args));

                if (!args)
                    return false;

                return $.ajax(args).done(_fwdc.fwdcAjaxSuccess).fail(_fwdc.fwdcAjaxError).always(_fwdc.fwdcAjaxComplete);
            };

            _fwdc.throttle = function (func, delay)
            {
                delay = _default(delay, 100);

                var timeoutHandle;
                var lastCall;

                return function ()
                {
                    var that = this;
                    var originalArguments = arguments;
                    var call;

                    var now = _fwdc.now();
                    //var nextDelay = delay;

                    if (!lastCall || now - lastCall > delay)
                    {
                        call = true;
                    }

                    if (!timeoutHandle)
                    {
                        if (call)
                        {
                            func.apply(that, originalArguments);
                            lastCall = _fwdc.now();
                        }
                        else
                        {
                            timeoutHandle = setTimeout(function ()
                            {
                                timeoutHandle = null;
                                func.apply(that, originalArguments);
                                lastCall = _fwdc.now();
                            }, delay);
                        }
                    }
                };
            };

            _fwdc.debounce = function (func, delay, immediate)
            {
                var timeoutHandle;
                return function ()
                {
                    var that = this;
                    var originalArguments = arguments;

                    var callNow = immediate && !timeoutHandle;
                    clearTimeout(timeoutHandle);
                    timeoutHandle = setTimeout(function ()
                    {
                        timeoutHandle = null;
                        if (!immediate)
                        {
                            func.apply(that, originalArguments);
                        }
                    }, delay);

                    if (callNow)
                    {
                        func.apply(that, originalArguments);
                    }
                };
            };

            _fwdc.setConfirmCallback = function (callback)
            {
                _fwdc.confirmCallback = { target: FWDC, func: callback };
            };

            var _jsonCookies = {};
            _fwdc.getJsonCookie = function (name, initCallback)
            {
                if (_jsonCookies[name])
                {
                    return _jsonCookies[name];
                }
                else
                {
                    var stringData = document.cookie.match("fset-" + name + "=([^;]+)(;|$)");
                    if (stringData && stringData.length > 1 && (stringData = stringData[1]))
                    {
                        try
                        {
                            return (_jsonCookies[name] = JSON.parse(stringData));
                        }
                        catch (ignore)
                        {
                        }
                    }

                    return (_jsonCookies[name] = initCallback ? initCallback() : {});
                }
            };

            _fwdc.setJsonCookie = function (name, data)
            {
                _jsonCookies[name] = data;
                try
                {
                    document.cookie = "fset-" + name + "=" + JSON.stringify(data)
                        + "; expires=Fri, 31 Dec 9999 23:59:59 GMT; path="
                        + _fwdc.getBasePath() + "; SameSite="
                        + (_fwdc.embedded ? "None; Partitioned;" : "Lax;")
                        + (window.location.protocol === "https:" ? " Secure;" : "");
                }
                catch (ex)
                {
                }
            };

            _fwdc.clearJsonCookie = function (name)
            {
                if (document.cookie.match("fset-" + name + "=([^;]+)(;|$)"))
                {
                    document.cookie = "fset-" + name
                        + "=; expires=Fri, 31 Dec 1900 23:59:59 GMT; path="
                        + _fwdc.getBasePath() + "; SameSite="
                        + (_fwdc.embedded ? "None; Partitioned;" : "Lax;")
                        + (window.location.protocol === "https:" ? " Secure;" : "");
                }
            };

            _fwdc.editJsonCookie = function (name, callback)
            {
                var cookie = _fwdc.getJsonCookie(name);
                callback(cookie);
                _fwdc.setJsonCookie(name, cookie);
            };

            _fwdc.persistOption = function (data, ignoreError, callback)
            {
                return _fwdc.busy.done(function ()
                {
                    _fwdc.ajax({
                        url: 'PersistOption',
                        busy: true,
                        data: data,
                        ignoreSessionData: true,
                        hideErrors: true,
                        success: function ()
                        {
                            if (callback) { callback(); }
                        },
                        error: function (request)
                        {
                            if (!ignoreError)
                            {
                                _fwdc._error("PersistOption failed");
                            }
                        }
                    });
                });
            };

            _fwdc.setHistoryStep = function (step)
            {
                _fwdc.settingHistory = true;
                _fwdc.currentHash = step;
                location.hash = step;

                // Remove and re-insert the favicon link tags for Firefox.
                $('link[rel*="icon"]').detach().prependTo("head");
                _fwdc.settingHistory = false;
            };

            _fwdc.initHistoryHash = function ()
            {
                _fwdc.setHistoryStep(1);

                _fwdc.setTimeout("initHistoryHash", function ()
                {
                    _fwdc.incrementHistory();
                }, 100);
            };

            _fwdc.incrementHistory = function ()
            {
                if (!_fwdc.currentHash)
                {
                    _fwdc.initHistoryHash();
                }
                else
                {
                    _fwdc.setHistoryStep(_fwdc.currentHash + 1);
                }
            };

            _fwdc.formatSeconds = function (seconds, showSeconds)
            {
                showSeconds = showSeconds === undefined ? true : showSeconds;
                seconds = isFinite(seconds) ? Math.floor(seconds || 0) : 0;

                var display = "";

                var hours = Math.floor(seconds / 3600);
                if (hours > 0)
                {
                    display = hours.padLeft(2) + ":";
                    seconds = seconds % 3600;
                }

                return display + Math.floor(seconds / 60).padLeft(2) + ":" + (seconds % 60).padLeft(2);
            };

            _fwdc.formatTimestamp = function (date)
            {
                return date.getHours().padLeft(2) + ":" + date.getMinutes().padLeft(2) + ":" + date.getSeconds().padLeft(2);
            };

            function _clickWhichMatch(eventWhich, which)
            {
                which = which || _fwdc.mouseButtons.left;
                // Special case 0 === 1 for IE8.
                return eventWhich === which || (which === _fwdc.mouseButtons.left && eventWhich === 0);
            }

            _fwdc.isNormalClick = function (event, which)
            {
                return event && ((which === undefined && event.isTrigger) || (_clickWhichMatch(event.which, which) && !(event.ctrlKey || event.shiftKey || event.altKey || event.metaKey)));
            };

            _fwdc.isCtrlClick = function (event, which)
            {
                return event && ((event.isTrigger && event.ctrlKey) || (_clickWhichMatch(event.which, which) && event.ctrlKey && !(event.shiftKey || event.altKey || event.metaKey)));
            };

            _fwdc.isShiftClick = function (event, which)
            {
                return event && ((event.isTrigger && event.shiftKey) || (_clickWhichMatch(event.which, which) && event.shiftKey && !(event.ctrlKey || event.altKey || event.metaKey)));
            };

            _fwdc.isMiddleClick = function (event)
            {
                return _fwdc.isNormalClick(event, _fwdc.mouseButtons.middle);
            };

            _fwdc.isNewWindowClick = function (event)
            {
                return event && (_fwdc.isCtrlClick(event) || _fwdc.isMiddleClick(event));
            };

            _fwdc.hasModifiers = function (event)
            {
                return event.shiftKey || event.ctrlKey || event.altKey || event.metaKey;
            };

            _fwdc.noModifiers = function (event)
            {
                return !_fwdc.hasModifiers(event);
            };

            _fwdc.getCanonDateString = function (date)
            {
                if (date === null)
                {
                    return "";
                }

                return date.getFullYear() + "-" + (date.getMonth() + 1).padLeft(2, "0") + "-" + date.getDate().padLeft(2, "0") + " 00:00:00.0000";
            };

            var _remSize;
            _fwdc.remSize = function (rem)
            {
                if (!_remSize)
                {
                    _remSize = parseInt($($("html")).css("font-size"), 10);
                    if (isNaN(_remSize))
                    {
                        _remSize = 16;
                    }
                }
                return rem * _remSize;
            };

            _fwdc.elementEmSize = function (element, em)
            {
                var fontSize = $(element).css("font-size");
                if (fontSize.endsWith("px"))
                {
                    fontSize = parseInt(fontSize, 10);
                }
                else
                {
                    fontSize = NaN;
                }

                if (isNaN(fontSize))
                {
                    fontSize = 16;
                }

                return em * fontSize;
            };

            var _$supportElements;
            _fwdc.supportElementsContainer = function ()
            {
                if (!_$supportElements)
                {
                    _$supportElements = $($.parseHTML('<div id="FastHiddenElements"></div>')).appendTo(_fwdc.$body());
                }

                return _$supportElements;
            };

            // http://stackoverflow.com/questions/13949059/persisting-the-changes-of-range-objects-after-selection-in-html/13950376#13950376
            _fwdc.saveSelection = function (containerEl)
            {
                var m_Document = containerEl.ownerDocument;
                var rv = { start: 0, end: 0 };

                if (m_Document.getSelection && m_Document.createRange)
                {
                    try
                    {
                        var range = m_Document.getSelection().getRangeAt(0);
                        var preSelectionRange = range.cloneRange();
                        preSelectionRange.selectNodeContents(containerEl);
                        preSelectionRange.setEnd(range.startContainer, range.startOffset);
                        rv.start = preSelectionRange.toString().length;
                        rv.end = rv.start + range.toString().length;
                    }
                    catch (ignore)
                    { }
                }
                else if (m_Document.selection && m_Document.body.createTextRange)
                {
                    var selectedTextRange = m_Document.selection.createRange();
                    var preSelectionTextRange = m_Document.body.createTextRange();
                    preSelectionTextRange.moveToElementText(containerEl);
                    preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange);
                    rv.start = preSelectionTextRange.text.length;
                    rv.end = rv.start + selectedTextRange.text.length;
                }

                return rv;
            };

            _fwdc.restoreSelection = function (containerEl, savedSel)
            {
                if (savedSel === null || savedSel === undefined) { return false; }

                var m_Document = containerEl.ownerDocument;
                var m_Window = 'defaultView' in m_Document ? m_Document.defaultView : m_Document.parentWindow;

                if (m_Window.getSelection && m_Document.createRange)
                {
                    var charIndex = 0, range = m_Document.createRange();
                    range.setStart(containerEl, 0);
                    range.collapse(true);
                    var nodeStack = [containerEl], node, foundStart = false, stop = false;

                    while (!stop && (node = nodeStack.pop()))
                    {
                        if (node.nodeType === Node.TEXT_NODE)
                        {
                            var nextCharIndex = charIndex + node.length;
                            if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex)
                            {
                                range.setStart(node, savedSel.start - charIndex);
                                foundStart = true;
                            }
                            if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex)
                            {
                                range.setEnd(node, savedSel.end - charIndex);
                                stop = true;
                            }
                            charIndex = nextCharIndex;
                        }
                        else
                        {
                            var i = node.childNodes.length;
                            while (i--)
                            {
                                nodeStack.push(node.childNodes[i]);
                            }
                        }
                    }

                    var sel = m_Window.getSelection();
                    sel.removeAllRanges();
                    sel.addRange(range);
                }
                else if (m_Document.selection && m_Document.body.createTextRange)
                {
                    var textRange = m_Document.body.createTextRange();
                    textRange.moveToElementText(containerEl);
                    textRange.collapse(true);
                    textRange.moveEnd("character", savedSel.end);
                    textRange.moveStart("character", savedSel.start);
                    textRange.select();
                }
            };

            // http://stackoverflow.com/questions/1335252/how-can-i-get-the-dom-element-which-contains-the-current-selection
            _fwdc.getSelectionBoundaryElement = function (start)
            {
                var range, sel, container;
                if (document.selection)
                {
                    range = document.selection.createRange();
                    range.collapse(start);
                    return range.parentElement();
                }
                else
                {
                    sel = window.getSelection();
                    if (sel.getRangeAt)
                    {
                        if (sel.rangeCount > 0)
                        {
                            range = sel.getRangeAt(0);
                        }
                    }
                    else
                    {
                        // Old WebKit
                        range = document.createRange();
                        range.setStart(sel.anchorNode, sel.anchorOffset);
                        range.setEnd(sel.focusNode, sel.focusOffset);

                        // Handle the case when the selection was selected backwards (from the end to the start in the document)
                        if (range.collapsed !== sel.isCollapsed)
                        {
                            range.setStart(sel.focusNode, sel.focusOffset);
                            range.setEnd(sel.anchorNode, sel.anchorOffset);
                        }
                    }

                    if (range)
                    {
                        container = range[start ? "startContainer" : "endContainer"];

                        // Check if the container is a text node and return its parent if so
                        return container.nodeType === Node.TEXT_NODE ? container.parentNode : container;
                    }
                }
            };

            _fwdc.getSelectionText = function ()
            {
                if (window.getSelection)
                {
                    return window.getSelection().toString() || "";
                }
                else if (document.selection && document.selection.type !== "Control")
                {
                    return document.selection.createRange().text || "";
                }

                return "";
            };

            _fwdc.findScrollableParent = function ($element)
            {
                var $parent = $element.parent();
                // TODO: Better check for document element.

                // Stop when we don't have a parent, or the element is the document, or we're at a dialog.
                while ($parent && $parent.length && !$parent.hasClass("ui-dialog") && !!$parent.prop("tagName"))
                {
                    var overflowY = $parent.css("overflow-y");
                    if (overflowY === "auto" || overflowY === "scroll")
                    {
                        return $parent;
                    }

                    $parent = $parent.parent();
                }

                return null;
            };

            _fwdc.hideToolTips = function (immediate)
            {
                var $qTips = $(".FastFieldQTip,.RowTipQTip");

                if (immediate)
                {
                    $qTips.qtip("destroy");
                }
                else
                {
                    $qTips.qtip("hide");
                }

                _destroyTemporaryQtips(immediate);

                _fwdc.hideManagerMenu();
            };

            _fwdc.closeComboboxes = function ($container)
            {
                var $elements;
                if ($container)
                {
                    $elements = $.findElementsByClassName("ui-autocomplete-input", $container); //.autocomplete("close");
                }
                else
                {
                    $elements = $.findElementsByClassName("ui-autocomplete-input"); //.autocomplete("close");
                }

                try
                {
                    $elements.autocomplete("close");
                }
                catch (ex)
                {
                    _fwdc._error(ex);
                }
            };

            _fwdc.setupModalOverlay = function ($modal, contextMenu)
            {
                var uiDialog = $modal.data("uiDialog");
                var $overlay = uiDialog.overlay;
                if ($overlay && $overlay.length)
                {
                    if (contextMenu)
                    {
                        $overlay.addClass("ContextMenuOverlay");
                    }
                    else
                    {
                        $overlay.addClass("ModalOverlay");
                    }
                }

                _fwdc.setTimeout("setupModalOverlay", function ()
                {
                    jQuery(document)
                        .unbind('mousedown.dialog-overlay')
                        .unbind('mouseup.dialog-overlay');

                    if (contextMenu && $overlay && $overlay.length)
                    {
                        $overlay.click(function () { $modal.dialog("close"); });
                    }
                });
            };

            _fwdc.sizeContentModals = function ($dialog)
            {
                var $dialogs = ($dialog || $(_fwdc.selectors.modalContainers));

                $dialogs.addClass("ModalRendered"); //.dialog("reposition");

                return $dialogs;
            };

            _fwdc.docModalId = function ($documentContainer)
            {
                var docModalId = parseInt($documentContainer.attr("data-doc-modal"), 10);

                return isNaN(docModalId) ? -1 : docModalId;
            };

            _fwdc.currentModalId = function ()
            {
                return _fwdc.docModalId(_fwdc.currentDocumentContainer());
            };

            _fwdc.fieldModalId = function ($field)
            {
                return _fwdc.docModalId($field.closest(_fwdc.selectors.documentContainer));
            };

            _fwdc.formField = function (fieldId, currentDocument, $root)
            {
                if (!fieldId) { return null; }

                if (currentDocument === undefined) { currentDocument = false; }

                var $container = $root || (currentDocument ? _fwdc.currentDocumentContainer() : null);

                var $field = $.findElementById(fieldId, $container);
                if ($field && $field.length > 0)
                {
                    return $field;
                }
                else
                {
                    $field = $("[data-id='" + fieldId + "']", $root);
                    if ($field && $field.length > 0)
                    {
                        return $field;
                    }
                }

                return null;
            };

            _fwdc.onManagerHtmlUpdated = function ($manager)
            {
            };

            var _transitionTypes = {};
            var _transitionCheckProperties = {};
            function _classTransitionInfo(transitionType, $element, $replacing, $container, transitionClass, newClass)
            {
                var transitionInfo = _transitionTypes[transitionType];

                if (transitionInfo === undefined)
                {
                    var $newTest = $element.clone().empty();

                    if ($replacing)
                    {
                        $newTest.insertAfter($replacing);
                    }
                    else if ($container)
                    {
                        $newTest.appendTo($container);
                    }
                    else
                    {
                        $newTest.insertAfter($element);
                    }

                    if (newClass)
                    {
                        $newTest.addClass(newClass);
                    }

                    var transitionPropertyList = _transitionTypes[transitionType] = ($newTest.css("transition-property") || false);

                    if (transitionPropertyList)
                    {
                        var transitionDurations = $newTest.css("transition-duration");
                        var minLength = null;

                        if (transitionDurations)
                        {
                            transitionPropertyList = transitionPropertyList.split(",");
                            transitionDurations = transitionDurations.split(",");

                            for (var ii = 0; ii < transitionDurations.length; ++ii)
                            {
                                var duration = transitionDurations[ii].match(/(\d+(?:\.\d+)?)(ms|s)/i);

                                if (duration)
                                {
                                    var durationMs = parseFloat(duration[1]);
                                    if (!isNaN(durationMs))
                                    {
                                        if (duration[2].toLowerCase() === "s")
                                        {
                                            durationMs *= 1000;
                                        }

                                        if (durationMs > 0 && (minLength === null || durationMs > minLength))
                                        {
                                            minLength = durationMs;
                                        }
                                    }
                                }
                            }
                        }

                        if (!minLength)
                        {
                            _transitionTypes[transitionType] = false;
                        }
                        else
                        {
                            var transitionPropertyValues = {};
                            var transitionProperty;
                            var transitionProperties = {};

                            for (var jj = 0; jj < transitionPropertyList.length; ++jj)
                            {
                                transitionProperty = transitionPropertyList[jj].trim();
                                transitionPropertyValues[transitionProperty] = $newTest.css(transitionProperty);
                            }

                            $newTest
                                .css("transition", "none")
                                .css("animation", "none")
                                .addClass(transitionClass + " FastTransitionTest");

                            var foundTransition = false;
                            for (var kk = 0; kk < transitionPropertyList.length; ++kk)
                            {
                                transitionProperty = transitionPropertyList[kk].trim();

                                if (transitionPropertyValues[transitionProperty] !== $newTest.css(transitionProperty))
                                {
                                    if (!foundTransition)
                                    {
                                        _transitionCheckProperties[transitionType] = transitionProperty;
                                        foundTransition = true;
                                    }
                                    transitionProperties[transitionProperty] = true;
                                    break;
                                }
                            }

                            _transitionTypes[transitionType] = foundTransition ? { "duration": minLength, "properties": transitionProperties } : false;
                        }
                    }
                    else
                    {
                        _transitionTypes[transitionType] = false;
                    }

                    $newTest.remove();
                    transitionInfo = _transitionTypes[transitionType];
                }

                return transitionInfo;
            }

            function _classTransitionDuration(transitionType, $element, $replacing, $container, transitionClass, newClass)
            {
                var info = _classTransitionInfo(transitionType, $element, $replacing, $container, transitionClass, newClass);
                return info && info.duration;
            }

            function _triggerTransitionCalc(transitionType, $element)
            {
                return $element.css(_transitionCheckProperties[transitionType]);
            }

            _fwdc.clearTransitionCache = function ()
            {
                _transitionTypes = {};
                _transitionCheckProperties = {};
            };

            var _transitioningCount = 0;

            _fwdc.transitioning = function (noWarn, event)
            {
                if (_transitioningCount)
                {
                    if (!noWarn)
                    {
                        _fwdc._warn("Transition Active");
                        _fwdc._printStackTrace();

                        if (event)
                        {
                            _fwdc._warn("Event: ", event);
                        }
                    }
                    return true;
                }

                return false;
            };

            _fwdc.incrementTransitioning = function ()
            {
                _transitioningCount++;
                if (_transitioningCount === 1)
                {
                    _fwdc.$body().addClass("Transitioning");
                }
            };

            _fwdc.decrementTransitioning = function ()
            {
                if (_transitioningCount > 0)
                {
                    _transitioningCount--;

                    if (_transitioningCount === 0)
                    {
                        _fwdc.$body().removeClass("Transitioning");
                    }
                }
            };

            _fwdc.onTransition = function (name, $element, transitionClass, callback, addTransitioning)
            {
                if (!$element || !$element.length)
                {
                    return null;
                }

                var transitionType = "onTransition." + name;
                var transitionInfo = _classTransitionInfo(transitionType, $element, null, null, transitionClass);
                if (!transitionInfo || !transitionInfo.duration)
                {
                    if (callback) { callback($element, null); }
                    return false;
                }

                if (addTransitioning === undefined)
                {
                    addTransitioning = true;
                }

                _triggerTransitionCalc(transitionType, $element);

                if (transitionClass)
                {
                    $element.addClass(transitionClass);
                }

                if (addTransitioning)
                {
                    $element.addClass("FastTransitioning");
                    _fwdc.incrementTransitioning();
                }

                var element = $element[0];

                var timeoutHandle;
                var transitionDataName = "fast-on-transition-" + name;
                var finishTransition = function ()
                {
                    if (timeoutHandle)
                    {
                        _fwdc.clearTimeout("onTransition.timeout." + name, timeoutHandle);
                        timeoutHandle = null;
                    }

                    $element
                        .removeData(transitionDataName)
                        .off("transitionend", onTransitionEnd)
                        .removeClass("FastTransitioning");

                    if (addTransitioning)
                    {
                        _fwdc.decrementTransitioning();
                    }
                };

                var onTransitionEnd = function (event)
                {
                    if (event === false || event.target === element)
                    {
                        var transitionProperty = event ? event.originalEvent && event.originalEvent.propertyName : false;

                        if (!transitionProperty || transitionInfo.properties[transitionProperty])
                        {
                            finishTransition();

                            if (callback) { callback($element, event); }
                        }
                    }
                };

                $element
                    .data(transitionDataName, { onTransitionEnd: onTransitionEnd, finishTransition: finishTransition })
                    .on("transitionend", onTransitionEnd);

                timeoutHandle = _fwdc.setTimeout("onTransition.timeout." + name, function ()
                {
                    onTransitionEnd(false);
                }, transitionInfo.duration * 3);

                return true;
            };

            _fwdc.cancelOnTransition = function (name, $element)
            {
                var transitionDataName = "fast-on-transition-" + name;
                var transitionData = $element.data(transitionDataName);
                if (transitionData)
                {
                    transitionData.finishTransition();
                    return true;
                }
                return false;
            };

            _fwdc.invalidateTransitionScroll = false;

            var _crossTransitionCallbacks;
            var _crossTransitionCallbackId = 0;
            _fwdc.afterCrossTransition = function (callback)
            {
                if (_crossTransitionCallbacks)
                {
                    _crossTransitionCallbacks.add(callback);
                    return callback;
                }
                else
                {
                    callback();
                }
                return null;
            };

            _fwdc.cancelAfterCrossTransition = function (callback)
            {
                if (_crossTransitionCallbacks && callback)
                {
                    _crossTransitionCallbacks.remove(callback);
                }
            };

            _fwdc.cancelCrossTransition = function ($newElement)
            {
                var transitionData = $newElement.data("fast-cross-transition");
                if (!transitionData)
                {
                    return false;
                }

                transitionData.cancel();
                return true;
            };

            _fwdc.onCrossTransitionStarting = function ()
            {
                var oldCallbacks = _crossTransitionCallbacks;

                _crossTransitionCallbacks = $.Callbacks("once");

                if (oldCallbacks && oldCallbacks.has())
                {
                    _crossTransitionCallbacks.add(oldCallbacks);
                }

                return ++_crossTransitionCallbackId;
            }

            _fwdc.onCrossTransitionFinished = function (transitionCallbackId)
            {
                if (_crossTransitionCallbackId === transitionCallbackId)
                {
                    if (_crossTransitionCallbacks)
                    {
                        _crossTransitionCallbacks.fire();
                        _crossTransitionCallbacks = null;
                    }

                    _repositionCellEditor();
                }
            }

            _fwdc.crossTransition = function ($old, $new, $container, transitionType, options)
            {
                _fwdc.invalidateTransitionScroll = false;

                FWDC.hideViewMenus();
                _fwdc.hideToolTips();
                _fwdc.closeComboboxes($container || $old);

                if (!$old || !$old.length) { $old = null; }

                var allowTransition = true;
                if ($old && ($old.length > 1 || $old.hasClass("FastTransitioning")))
                {
                    allowTransition = false;
                    _fwdc._warn("Preventing transition due to overlap.");
                }

                options = options || {};

                //var ensureOverlayWidth = options.ensureOverlayWidth || (options.ensureOverlayWidth === undefined);

                var scrollPositions = _fwdc.saveScrollPositions(false, !!options.ignoreScroll);

                var $modal = $old && $old.closest(".ui-dialog-content");
                if (!$modal || !$modal.length)
                {
                    $modal = null;
                }

                var transitionDuration = 0;

                if (transitionType === false || !$old)
                {
                    transitionDuration = 0;
                }
                else
                {
                    transitionType = (transitionType || "?");
                    var transitionTestClass = "FastTransitionNew";
                    if (options.newClass)
                    {
                        transitionType = transitionType + "+" + options.newClass;
                    }

                    transitionDuration = allowTransition && _classTransitionDuration(transitionType, $new, $old, $container, transitionTestClass, options.newClass);
                }

                var oldHeight = 0;
                if (transitionDuration)
                {
                    if ($old)
                    {
                        oldHeight = $old.outerHeight();
                        var width = $old.outerWidth();

                        // nativeOffset should give us the proper absolute offset to use based on the offset parent.
                        var scrollOffset = $old.nativeOffset().top;

                        // This logic doesn't affect standard doc or manager modals, and incorrectly caused jumping in the context log.
                        //var parentScroll = $old.parent().css("overflow-y");
                        //if (parentScroll === "auto" || parentScroll === "scroll")
                        //{
                        //    // Calculate the top offset for modals where the scroll position means absolute positioning will be wrong.
                        //    var offsetToParent = $old.relativeContentOffset($old.parent());
                        //    scrollOffset = (offsetToParent && offsetToParent.top) || 0;
                        //}

                        /*if (!$modal)
                        {
                            minHeight = height;
                        }*/
                        $old
                            //.outerHeight(height)
                            .outerWidth(width)
                            .css({
                                "position": "absolute",
                                "top": scrollOffset + "px"
                            })
                            .addClass("FastTransitionOld FastTransitioning" + (options.newClass ? " " + options.newClass : ""));
                    }

                    $new.addClass("FastTransitionNew FastLoading FastTransitioning" + (options.newClass ? " " + options.newClass : ""));

                    _fwdc.incrementTransitioning();
                }
                else
                {
                    $new.removeClass("FastTransitionNew");
                }

                if ($old)
                {
                    /*$old
                        .removeAttr("id")
                        .find("[id]")
                        .removeAttr("id");*/

                    $old.attr("data-xid", $old.attr("id")).removeAttr("id");

                    $old.find("[id]").each(function ()
                    {
                        // If the ID belongs to something in an SVG, we can't change it.
                        // This used to break some FusionCharts elements where a gradient or other <defs> element lost its ID.
                        if (this.ownerSVGElement)
                        {
                            return;
                        }

                        var $this = $(this);
                        $this.attr("data-xid", $this.attr("id")).removeAttr("id");
                    });

                    _fwdc.disableAccessKeys($old, true);

                    $new.insertAfter($old.last());
                }
                else
                {
                    $new.appendTo($container);
                }

                if (transitionDuration)
                {
                    var transitionId = _fwdc.onCrossTransitionStarting();

                    if (options.setup)
                    {
                        options.setup(!!$old, $new);
                    }

                    if ($modal)
                    {
                        _fwdc.evaluateDialogScreenSize($modal);
                        $modal.dialog("reposition");
                    }

                    if ($old)
                    {
                        var newHeight = $new.outerHeight();
                        var $scrollContainer = _fwdc.findScrollableParent($old || $container);
                        var minHeight = oldHeight;
                        var oldMaxHeight = 0;

                        if ($scrollContainer)
                        {
                            var relativeOffset = $new.relativeContentOffset($scrollContainer);
                            if (relativeOffset)
                            {
                                var viewportHeight = $scrollContainer.viewportHeight();

                                // Why require the new content to be at least as tall as the viewport?
                                //minHeight = relativeOffset.top + viewportHeight;
                                oldMaxHeight = Math.max(newHeight, viewportHeight);
                                //var scrollTop = $scrollContainer.scrollTop();
                                //var scrollHeight = $scrollContainer.scrollHeight();
                                //var scrollBottom = scrollTop + scrollHeight;
                            }
                        }

                        // This is only necessary if we require the viewport height to be the minimum.
                        //if (minHeight)
                        //{
                        //    minHeight = Math.max(minHeight, oldHeight);
                        //}

                        // Cap the height of the old content FIRST so the window can scroll up if needed.
                        if (oldMaxHeight)
                        {
                            $old.css({
                                "max-height": oldMaxHeight + "px",
                                "overflow": "hidden",
                                "margin-bottom": "-" + oldMaxHeight + "px"
                            });
                        }

                        // Attempt to restore the scroll position BEFORE expanding the new content so the screen doesn't scroll too far down.
                        //if (!_fwdc.invalidateTransitionScroll && scrollPositions) // SQR 68871 - Don't ignore positions, we probably grabbed only the Always values, which we want regardless.
                        if (scrollPositions)
                        {
                            _fwdc.restoreScrollPositions(scrollPositions);
                        }

                        // Apply a temporary minimum height to the new content to allow it to cover the old content if it was shorter.
                        if (minHeight)
                        {
                            $new.css("min-height", minHeight + "px");
                        }

                        // Clear overflow that causes sticky elements to not position correctly during transition.
                        // This overflow was only set to hidden to force the screen to scroll up if the new content is smaller.
                        $old.css("overflow", "");
                    }

                    var timeoutHandle;
                    var onTransitionEnd = function (transitionEvent)
                    {
                        if (transitionEvent === false || (transitionEvent && transitionEvent.target === $new[0]))
                        {
                            if (timeoutHandle) { _fwdc.clearTimeout("crossTransition.timeout", timeoutHandle); }

                            if ($old)
                            {
                                _fwdc.destroyRichElements(false, $old);
                                $old.remove();
                            }

                            $new
                                .removeClass("FastLoading FastTransitioning " + (options.newClass || ""))
                                .off(".fastCrossTransition")
                                .css("min-height", "")
                                .data("fast-transition", null);

                            _fwdc.decrementTransitioning();

                            if (options.teardown)
                            {
                                options.teardown($old, $new, true);
                            }

                            _fwdc.onCrossTransitionFinished(transitionId);
                        }
                    };

                    $new
                        .on("transitionend.fastCrossTransition", onTransitionEnd);

                    $new.data("fast-cross-transition", {
                        "$old": $old,
                        "$new": $new,
                        "cancel": function ()
                        {
                            $new.css("transition", "none");
                            onTransitionEnd(false);
                            $new.css("transition", "");
                        }
                    });

                    // Delay triggering the transition to prevent issues with recalc transitions being immediately cancelled.
                    _fwdc.setTimeout("crossTransition.delay", function ()
                    {
                        // Trigger the transition by removing the New class.
                        $new.removeClass("FastTransitionNew");
                        timeoutHandle = _fwdc.setTimeout("crossTransition.timeout", function ()
                        {
                            onTransitionEnd(false);
                        }, transitionDuration * 3);
                    });
                }
                else
                {
                    if ($old)
                    {
                        _fwdc.destroyRichElements(false, $old);
                        $old.remove();
                    }

                    if (options.teardown) { options.teardown($old, $new, false); }

                    if (options.setup)
                    {
                        options.setup(!!$old, $new);
                    }

                    if ($modal)
                    {
                        $modal.dialog("reposition");
                    }
                }

                if (!_fwdc.invalidateTransitionScroll && scrollPositions)
                {
                    _fwdc.restoreScrollPositions(scrollPositions);
                }
            };

            _fwdc.setCurrentManagerHtml = function (html, forceSwitching, switchingBack, skipFocus, immediate)
            {
                // Clear any existing client button handlers - they should be replaced when the new content loads if necessary.
                _onClientButtonClickedHandler = null;

                var $newManager = $($.parseHTML(html, document, true));

                var settings = $newManager.attr("data-app-settings");
                if (settings)
                {
                    $newManager.removeAttr("data-app-settings");
                    _fwdc.setSettings(JSON.parse(settings));
                }

                var id = _fwdc.getManagerContainerId($newManager);
                var $oldManager = _fwdc.currentManagerContainer(id);
                var $container;

                if ($oldManager && $oldManager.length)
                {
                    $container = $oldManager.parent();
                    _fwdc.stopAutoRefresh(null, true);
                }
                else if (!id)
                {
                    $container = $("#FAST_ROOT_MANAGER__");
                }

                var switching = forceSwitching || $newManager.hasClass("FastManagerNewControl");
                var switchingClass = "";

                if (switching)
                {
                    if (switchingBack)
                    {
                        switchingClass = "FastManagerNewControl FastTransitionBack";
                    }
                    else
                    {
                        switchingClass = "FastManagerNewControl";
                    }
                    _fwdc.minimizeChatDialog();
                }

                if ($oldManager.hasClass("ManagerAppHomepage") && !$newManager.hasClass("ManagerAppHomepage"))
                {
                    if (switchingClass)
                    {
                        switchingClass += " FastManagerLeavingHomepage";
                    }
                    else
                    {
                        switchingClass = "FastManagerLeavingHomepage";
                    }
                }

                _fwdc.crossTransition($oldManager, $newManager, $container, immediate ? false : "manager", {
                    newClass: switchingClass,
                    ignoreScroll: switching,
                    setup: function (transition, $new)
                    {
                        _fwdc.setManagerContainer($new, id);
                        _fwdc.setupControls($new);
                        //_fwdc.isSinglePanelContent($new, true);
                        _fwdc.resizeElements($new, true);
                        _fwdc.sizeContentModals();
                        //_fwdc.applyVerLast($new);
                        _fwdc.updateScreenReader();
                        _fwdc.onManagerHtmlUpdated($new);
                        _fwdc.handleManagerBusy($newManager);
                        _fwdc.setupSkipToMain();
                        /*if (focus)
                        {
                            _fwdc.focusCurrentField();
                        }*/
                        _fwdc.showCurrentFieldTip();
                        _fwdc.updateLastScrollFocusIn();
                    },
                    teardown: function ()
                    {

                    }
                });

                var colorClass = _fwdc.getColorClass($newManager);
                _fwdc.setColorClass(_fwdc.supportElementsContainer(), colorClass);

                var dataMonitoring = $newManager.attr("data-monitoring");
                if (dataMonitoring != _fwdc.monitoringConfig)
                {
                    window.clearTimeout(_monitoringPhotoHandle);
                    _monitoringPhotoHandle = null;

                    window.clearTimeout(_monitoringScreenHandle);
                    _monitoringScreenHandle = null;

                    _fwdc.endMonitoringBrowser();

                    _fwdc.monitoringIntervals.Photo.Min = 0;
                    _fwdc.monitoringIntervals.Photo.Range = 0;
                    _fwdc.monitoringIntervals.Screen.Min = 0;
                    _fwdc.monitoringIntervals.Screen.Range = 0;

                    if (dataMonitoring)
                    {
                        var config = JSON.parse(dataMonitoring);
                        _fwdc.monitoringConfigJson = config;
                        if (config)
                        {
                            if (config.Photo && config.Photo.Enabled === true)
                            {
                                var minInterval = config.Photo.MinInterval;
                                if (!minInterval || minInterval < 0) minInterval = 0;
                                var maxInterval = config.Photo.MaxInterval;
                                if (!maxInterval || maxInterval < 0) maxInterval = 0;

                                _fwdc.monitoringIntervals.Photo.Min = minInterval;
                                _fwdc.monitoringIntervals.Photo.Range = maxInterval - minInterval;
                                if (_fwdc.monitoringIntervals.Photo.Range < 0) _fwdc.monitoringIntervals.Photo.Range = 0;

                                _startMonitoringImages("mp_vid", "Photo", config.Photo, _captureMonitoringPhoto);
                            }
                            else
                            {
                                _fwdc.endImageMonitoring("mp_vid");
                            }

                            if (config.Screen && config.Screen.Enabled === true)
                            {
                                var minInterval = config.Screen.MinInterval;
                                if (!minInterval || minInterval < 0) minInterval = 0;
                                var maxInterval = config.Screen.MaxInterval;
                                if (!maxInterval || maxInterval < 0) maxInterval = 0;

                                _fwdc.monitoringIntervals.Screen.Min = minInterval;
                                _fwdc.monitoringIntervals.Screen.Range = maxInterval - minInterval;
                                if (_fwdc.monitoringIntervals.Screen.Range < 0) _fwdc.monitoringIntervals.Screen.Range = 0;

                                _startMonitoringImages("ms_vid", "Screen", config.Screen, _captureMonitoringScreen);
                            }
                            else
                            {
                                _fwdc.endImageMonitoring("ms_vid");
                            }

                            if (config.Browser && config.Browser.Enabled === true)
                            {
                                document.addEventListener("visibilitychange", _monitorVisibilityChange);
                                window.addEventListener("focus", _monitorFocusChange);
                                window.addEventListener("blur", _monitorFocusChange);
                            }
                        }
                        else
                        {
                            _fwdc._warn("Monitoring config not available.");
                        }
                    }
                    else
                    {
                        _fwdc.endImageMonitoring("mp_vid");
                        _fwdc.endImageMonitoring("ms_vid");
                    }

                    _fwdc.monitoringConfig = dataMonitoring;
                }

                var pushConfig = $newManager.attr("data-push-config");
                var chatsActive = $newManager.attr("update-chats-active");

                if (pushConfig)
                {
                    $newManager.removeAttr("data-push-config");
                    _fwdc.connectPush(JSON.parse(pushConfig));
                }
                else if (chatsActive)
                {
                    window.setTimeout(_chatUpdateLastActivity, 1000);
                    _chatUpdateLastActivityHandle = window.setInterval(_chatUpdateLastActivity, 120000);
                }

                return $newManager;
            };

            _fwdc.setCurrentDocHtml = function (html, focus, immediate)
            {
                var $newDoc = $($.parseHTML(html, document, true));
                var id = _fwdc.getDocContainerId($newDoc);
                var $oldDoc = _fwdc.currentDocumentContainer(id);

                _fwdc.stopAutoRefresh(null, true);

                _fwdc.crossTransition($oldDoc, $newDoc, null, immediate ? false : "doc", {
                    setup: function (transition, $new)
                    {
                        _fwdc.setDocContainer($new, id);
                        _fwdc.setupControls($new);
                        //_fwdc.isSinglePanelContent($new, true);
                        _fwdc.resizeElements($new, true);
                        _fwdc.sizeContentModals();
                        //_fwdc.applyVerLast($new);
                        _fwdc.updateScreenReader();
                        _checkSnapScrolling($new, true);
                        /*if (focus)
                        {
                            _fwdc.focusCurrentField();
                        }*/
                        _fwdc.showCurrentFieldTip();
                        _fwdc.updateLastScrollFocusIn();
                    }
                });

                return $newDoc;
            };

            _fwdc.handleManagerBusy = function ($manager)
            {
                $manager = $manager || _fwdc.currentManagerContainer();
                var busyData = $manager.data("manager-busy");
                if (busyData)
                {
                    var data = $.extend({}, busyData);
                    _busy.done(function ()
                    {
                        _busy.show(busyData.source || "ManagerBusy", data);
                    });

                    $manager.removeAttr("data-manager-busy", null);
                }
            };

            _fwdc.setActionResponseHtml = function (response, selectedFields)
            {
                var result = false;
                if (response.html)
                {
                    _fwdc.setCurrentManagerHtml(response.html);
                    result = true;
                }

                if (response.dochtml)
                {
                    var $doc = _fwdc.setCurrentDocHtml(response.dochtml);
                    result = true;

                    if (response.hasProtectedData !== undefined)
                    {
                        var $manager = $doc.closest(".ManagerContainer");
                        if ($manager && $manager.length)
                        {
                            if (response.hasProtectedData)
                            {
                                $manager.addClass("HasProtectedDataSource");
                            }
                            else
                            {
                                $manager.removeClass("HasProtectedDataSource");
                            }
                        }
                    }
                }

                if (selectedFields)
                {
                    _fwdc.setSelectable(selectedFields);
                }

                /*var $currentManager = _fwdc.currentManagerContainer();
                var busyData = $currentManager.data("manager-busy");
                if (busyData)
                {
                    var data = $.extend({}, busyData);
                    _busy.done(function ()
                    {
                        _busy.show(busyData.source || "ManagerBusy", data);
                    });
    
                    $currentManager.removeAttr("data-manager-busy", null);
                }*/

                _fwdc.handleManagerBusy();

                return result;
            };

            _fwdc.handleActionResult = function (response, options)
            {
                //_fwdc.preventAutoFocus = false;

                if (response) { _fwdc.runResponseFunctions(response, false); }

                FWDC.hideViewMenus();
                _fwdc.hideToolTips();
                _fwdc.closeComboboxes();

                if (!options) { options = {}; }

                if (typeof options.sourceInfo === "string")
                {
                    options.sourceInfo = { field: options.sourceInfo };
                }

                var incrementHistory = (options.incrementHistory !== false);

                var result = FWDC.ActionResult.NoAction;
                if (response)
                {
                    _closing = response.closingManager;
                    switch (response.result)
                    {
                        case FWDC.ActionResult.OK:
                            _fwdc.setActionResponseHtml(response);
                            if (!response.skipFocus && !_fwdc.preventAutoFocus) { setTimeout(_fwdc.focusCurrentField, 1); }
                            if (incrementHistory) { _fwdc.incrementHistory(); }
                            break;

                        case FWDC.ActionResult.Modal:
                            _fwdc.openModalManager(response.modalid);
                            break;

                        case FWDC.ActionResult.ConfirmationRequired:
                            var captchas;

                            _fwdc.showStandardDialog(null, {
                                checkBusy: false,
                                dialog: "Confirmation",
                                height: "auto",
                                width: 500,
                                data: ((options.actionId !== null && options.actionId !== undefined) ?
                                    { ACTION_ID__: options.actionId, TYPE__: options.type } :
                                    { FIELD__: options.sourceInfo ? options.sourceInfo.field : "" }),
                                autoCreate: false,
                                setupCallback: function ($modal, $content, dialogOptions, createDialogCallback)
                                {
                                    if (options.confirmedCallback)
                                    {
                                        var $form = $content.is("#ConfirmationForm") ? $content : $content.find("#ConfirmationForm");
                                        $form.data("fast-confirmed-callback", options.confirmedCallback);
                                    }

                                    var setBusy = true;
                                    var busyId = null;

                                    /** If Captchas need to be setup, delay the creation of the modal until they are ready. **/
                                    var captchasSetup = function (newCaptchas)
                                    {
                                        setBusy = false;
                                        captchas = newCaptchas;
                                        createDialogCallback();
                                        if (busyId !== null)
                                        {
                                            _fwdc.busy.hide(busyId);
                                        }
                                    };

                                    _fwdc.initElements($modal);

                                    if (_fwdc.setupCaptchas($modal, null, captchasSetup))
                                    {
                                        if (setBusy)
                                        {
                                            busyId = _fwdc.busy.show("SetupCaptchas", { delay: 0 });
                                        }
                                    }
                                    else
                                    {
                                        createDialogCallback();
                                    }
                                },
                                open: function ($modal, $content, options)
                                {
                                    if (captchas && captchas.length)
                                    {
                                        var $form = $content.is("#ConfirmationForm") ? $content : $content.find("#ConfirmationForm");
                                        $form.data("fast-captcha-id", captchas[0]);
                                    }

                                    var $confirm = $modal.findElementById("ConfirmMessage");
                                    if ($confirm && $confirm.length > 0)
                                    {
                                        $modal.parent().attr("aria-describedby", "ConfirmMessage");
                                    }
                                }
                            });
                            break;

                        case FWDC.ActionResult.ConfirmationFailure:
                            _fwdc.setActionResponseHtml(response);

                            function focusCurrentConfirmationField()
                            {
                                var $form = $.findElementById("ConfirmationForm");
                                if ($form.length)
                                {
                                    var $activeElement = $(document.activeElement);
                                    if ($activeElement.closest($form).length)
                                        return;
                                }

                                _fwdc.focusCurrentField();
                            }

                            setTimeout(focusCurrentConfirmationField, 1);

                            break;

                        case FWDC.ActionResult.NoAction:
                            _fwdc.setActionResponseHtml(response);
                            if (!response.skipFocus && !_fwdc.preventAutoFocus) { setTimeout(_fwdc.focusCurrentField, 1); }
                            _fwdc.incrementHistory();
                            break;

                        case FWDC.ActionResult.CallFunction:
                            _fwdc.setActionResponseHtml(response);
                            break;

                        case FWDC.ActionResult.CloseWindow:
                            window.close();
                            break;

                        case FWDC.ActionResult.Closed:
                        case FWDC.ActionResult.Navigated:
                            break;

                        default:
                            FWDC.messageBox({
                                message: "Unhandled action response: " + response.result,
                                icon: FWDC.MessageBoxIcon.Error,
                                buttons: FWDC.MessageBoxButton.Ok
                            });
                    }

                    if (response.pagetitle)
                    {
                        _fwdc.setPageTitle(response.pagetitle);
                    }

                    _fwdc.runResponseFunctions(response, true);

                    if (options.successCallback)
                    {
                        options.successCallback();
                    }

                    if (response.message)
                    {
                        setTimeout(function () { FWDC.messageBox(response.message); }, 1);
                    }

                    result = response.result;
                }

                if (options.confirmResultCallback)
                {
                    options.confirmResultCallback(result);
                }

                _fwdc.preventAutoFocus = false;

                return result;
            };

            _fwdc.checkFlexGridRowVisibility = function ($container)
            {
                var $grids;

                if ($container && $container.hasClass("FlexGridContainer"))
                {
                    $grids = $container;
                }
                else if (!$grids || !$grids.length)
                {
                    $grids = ($container || _fwdc.currentDocumentContainer()).find(".FlexGridContainer");
                }

                $grids.each(function ()
                {
                    var $grid = $(this);

                    var designMode = $grid.hasClass("FGDesigning");

                    /*if (designMode)
                    {
                        $grid.find(".FGCW").css("height", "");
                    }*/

                    $grid.find(designMode ? ".FGLR,.FGBR" : ".FGLR").each(function ()
                    {
                        var $row = $(this).removeClass("FGPadRow");

                        // Make the row visible based on having visible fields.
                        if ($row.find(".FGFC,.FGDesignerPlaceholder").not(".Hidden,.FGDragging").length)
                        {
                            if (designMode)
                            {
                                $row.removeClass("FGBR").addClass("FGLR");
                            }
                            $row.removeClass("Hidden").addClass("Visible");
                        }
                        else if (designMode)
                        {
                            $row.addClass("FGBR").removeClass("FLGR");
                        }
                        else
                        {
                            $row.addClass("Hidden").removeClass("Visible");
                        }

                        // Find all cells.
                        var $cells = $row.children(".FGLC").removeClass("Visible");

                        $cells.each(function ()
                        {
                            var $cell = $(this);

                            // Find the visible fields in the cell.
                            var $fields = $cell.children(".FGFC,.FGDesignerPlaceholder").removeClass("FGPadCellField").not(".Hidden");

                            if ($fields.length > 1)
                            {
                                // Add a Padding class to subsequent visible cells.
                                var pad = false;
                                $fields.each(function ()
                                {
                                    if (pad)
                                    {
                                        $(this).addClass("FGPadCellField");
                                    }
                                    else
                                    {
                                        pad = true;
                                    }
                                });
                            }

                            // Mark the cell as being hidden in stacked views if it has no visible fields.
                            if ($fields.length)
                            {
                                $cell.removeClass("FGStackHidden").addClass("Visible");
                            }
                            else
                            {
                                $cell.removeClass("Visible").addClass("FGStackHidden");
                            }
                        });
                    });

                    // Hide Blank Rows that have no visible layout rows after them.
                    $grid.find(".FGBR").each(function ()
                    {
                        var $blankRow = $(this).removeClass("FGPadRow");

                        // Check if this is a top padding row (i.e. no real layout rows before it)
                        var $aboveLayoutRows = $blankRow.prevAll(".FGLR");
                        var isTop = !$aboveLayoutRows.length;
                        var showFromTop;
                        if (isTop)
                        {
                            showFromTop = true;
                        }
                        else
                        {
                            showFromTop = $aboveLayoutRows.filterHasClassName("Visible").length > 0;
                        }

                        // Skip subsequent blank rows if we have multiple in a row.
                        var $skipRows = $blankRow.nextUntil(".FGLR");

                        var $searchFromRow = $skipRows.length ? $skipRows.last() : $blankRow;

                        // Find all subsequent blank rows until we find a visible layout row.
                        var $laterRows = $searchFromRow.nextUntil(".FGBR", ".Visible");

                        if (designMode || (showFromTop && $laterRows.length))
                        {
                            $blankRow.removeClass("Hidden").addClass("Visible");
                        }
                        else
                        {
                            $blankRow.addClass("Hidden").removeClass("Visible");
                        }
                    });

                    // Scan visible rows and add a padding class for each subsequent non-blank row.
                    var pad = false;
                    $grid.find("tr.Visible").not(".FGSR").each(function ()
                    {
                        var $row = $(this);
                        if ($row.is(".FGBR"))
                        {
                            pad = false;
                        }
                        else if (pad)
                        {
                            $row.addClass("FGPadRow");
                        }
                        else
                        {
                            pad = true;
                        }

                        var firstCell = true;
                        $row.children(".FGLC.Visible").each(function ()
                        {
                            var $cell = $(this);

                            if (firstCell)
                            {
                                firstCell = false;
                            }
                            else
                            {
                                $cell.addClass("FGPadStackedCell");
                            }
                        });
                    });

                    //if (designMode)
                    //{
                    //    /*$grid.find(".FGCW").css("min-height", "").each(function ()
                    //    {
                    //        $(this).css("min-height", $(this).parent().height() + "px");
                    //    });*/
                    //}
                });
            };

            function _setupViewStackContainer($views, autoMargin, autoMarginClass, addTopMargin)
            {
                var visible = false;

                $views
                    .each(function ()
                    {
                        var $view = $(this);
                        if (visible && addTopMargin)
                        {
                            if (autoMarginClass)
                            {
                                $view.addClass(autoMarginClass);
                            }
                            else
                            {
                                $view.addClass("VSAutoTopMargin");
                            }
                        }
                        else if (!$view.hasClass("Hidden") && !$view.hasClass("DisplayHidden"))
                        {
                            visible = true;
                            if (autoMargin)
                            {
                                if (addTopMargin)
                                {
                                    if (autoMarginClass)
                                    {
                                        $view.addClass(autoMarginClass);
                                    }
                                    else
                                    {
                                        $view.addClass("VSAutoTopMargin");
                                    }
                                }
                                else
                                {
                                    addTopMargin = true;
                                }
                            }
                            else
                            {
                                return false;
                            }
                        }
                    });

                return visible;
            }

            _fwdc.setupViewStacks = function ($container)
            {
                $container = $container || _fwdc.currentDocumentContainer();

                // Process view stacks backwards so hidden statuses ripple upwards.
                var $stacks = $container.find(".ViewStackLayout").reverse();

                $stacks.each(function ()
                {
                    var $stack = $(this);
                    var stackVisible = false;
                    var addRowTopMargin = false;
                    var autoMargin = $stack.attr("data-automargin-class");
                    var autoMarginClass = autoMargin ? autoMargin + "Top" : "VSAutoTopMargin";
                    var autoMarginStackedClass = autoMargin ? autoMargin + "StackedTop" : "VSStackedAutoTopMargin";

                    if ($stack.hasClass("VSWrap"))
                    {
                        $stack.children(".VSWrapper").children(".VSWrapView").each(function ()
                        {
                            var $wrapper = $(this);
                            if (!$wrapper.hasClass("VSWrapFiller"))
                            {
                                var $stackRow = $wrapper.children(".VSWrapContainer").children(".VSViewRow");
                                if (!$stackRow.hasClass("DisplayHidden") && !$stackRow.hasClass("Hidden") && $stackRow.children().not(".Hidden,.DisplayHidden").length)
                                {
                                    $wrapper.removeClass("DisplayHidden");
                                    stackVisible = true;
                                }
                                else
                                {
                                    $wrapper.addClass("DisplayHidden");
                                }
                            }
                        });
                    }
                    else
                    {

                        if ($stack.hasClass("DocViewLayoutDoubleWide"))
                        {
                            $stack.parents(".DocViewLayout,.DocTabWrapper,.FastPanel").addClass("DocViewLayoutDoubleWide");
                        }

                        $stack
                            .children(".VSViewRow,.VSTableWrapper")
                            .removeClass(autoMarginClass)
                            .each(function ()
                            {
                                var $stackRow = $(this).removeClass("DisplayHidden");
                                var stackRowVisible = false;
                                var stackCells = false;

                                if ($stackRow.is(".VSTableWrapper"))
                                {
                                    $stackRow
                                        .children(".VSTableContainer")
                                        .children("tbody")
                                        .children("tr")
                                        .each(function ()
                                        {
                                            var $stackTableRow = $(this);
                                            var stackTableRowVisible = false;

                                            $stackTableRow
                                                .removeClass("DisplayHidden")
                                                .children()
                                                .each(function ()
                                                {
                                                    var $stackTableCell = $(this).removeClass("DisplayHidden");
                                                    var $stackTableCellViews = $stackTableCell.children(".VSView");
                                                    var stackTableCellVisible = _setupViewStackContainer($stackTableCellViews, autoMargin, autoMarginClass, false);

                                                    if (stackTableCellVisible)
                                                    {
                                                        if (stackCells)
                                                        {
                                                            $stackTableCell.addClass(autoMarginStackedClass);
                                                        }
                                                        else
                                                        {
                                                            stackCells = true;
                                                        }
                                                        stackTableRowVisible = true;
                                                        $stackTableCell.removeClass("DisplayHidden");
                                                    }
                                                    else
                                                    {
                                                        $stackTableCell.addClass("DisplayHidden");
                                                    }
                                                });

                                            if (stackTableRowVisible)
                                            {
                                                stackRowVisible = true;
                                                $stackTableRow.removeClass("DisplayHidden");
                                            }
                                            else
                                            {
                                                $stackTableRow.addClass("DisplayHidden");
                                            }
                                        });
                                }
                                else
                                {
                                    //stackRowVisible = _setupViewStackContainer($stackRow, autoMargin, addRowTopMargin);

                                    if (!stackRowVisible)
                                    {
                                        stackRowVisible = !$stackRow.hasClass("DisplayHidden") && !$stackRow.hasClass("Hidden") && $stackRow.children().not(".Hidden,.DisplayHidden").length;
                                    }
                                }

                                if (addRowTopMargin)
                                {
                                    $stackRow.addClass(autoMarginClass);
                                }

                                if (stackRowVisible)
                                {
                                    stackVisible = true;
                                    addRowTopMargin = autoMargin;
                                    $stackRow.removeClass("DisplayHidden");
                                }
                                else
                                {
                                    $stackRow.addClass("DisplayHidden");
                                }
                            });
                    }

                    if (stackVisible)
                    {
                        $stack.removeClass("DisplayHidden");
                    }
                    else
                    {
                        $stack.addClass("DisplayHidden");
                    }
                });
            };

            _fwdc.setupPanels = function ($container)
            {
                $container = $container || _fwdc.currentDocumentContainer();
                var $statusPanels = $container.find(".FastStatusPanel");

                if ($statusPanels.length)
                {
                    $statusPanels.each(function ()
                    {
                        var $panel = $(this);
                        var $parent = $panel.parent();

                        if ($parent.is(".ViewContainer"))
                        {
                            $parent = $parent.parent();
                        }

                        if ($parent.is(".DocLayout"))
                        {
                            $parent = $parent.parent();
                        }

                        var parentSingleChild = $parent.children().length === 1;

                        if (parentSingleChild && $parent.hasClass("VSView"))
                        {
                            var $grandParent = $parent.parent(".VSViewCell");
                            if ($grandParent.length)
                            {
                                $parent = $grandParent;
                                parentSingleChild = $parent.children().length === 1;
                            }
                        }

                        if (parentSingleChild && ($parent.is(".FastPanel,.FastSubPanel,.FastPanelCell,.FastSubPanelCell")))
                        {
                            var statusClass = /FastStatusColor\w+/.exec($panel.attr("class"))[0];
                            if (statusClass)
                            {
                                $parent
                                    .removeClass("FastPanel FastForcedPanel FastSubPanel FastForcedSubPanel FastPanelCell FastSubPanelCell")
                                    .addClass("FastStatusPanel")
                                    .addClass(statusClass);

                                if ($panel.hasClass("LightStatusPanel"))
                                {
                                    $parent.addClass("LightStatusPanel");
                                }
                            }
                        }
                    });
                }
            };

            _fwdc.refreshRichControls = function ($container)
            {
                $container = $container || _fwdc.currentDocumentContainer();
                if ($container)
                {
                    $container.findElementsByClassName("FastCodeMirrorBox").each(function (index, cmField)
                    {
                        var cm = $(cmField).data("fast-code-mirror-editor");
                        if (cm)
                        {
                            cm.fast_refresh();
                        }
                    });

                    $container.findElementsByClassName("HasCKEditor").each(function (index, rtField)
                    {
                        var richTextBox = $(rtField).ckeditorGet();
                        richTextBox.fwdc_resetSize();
                    });

                    $container.findElementsByClassName("FastCameraInputVideoPlaying").each(function ()
                    {
                        _fwdc.sizeCameraInputVideo($(this));
                    });
                }
            };

            _fwdc.refreshPreviewMonitoring = function ()
            {
                if (_fwdc.monitoringConfigJson)
                {
                    if (_fwdc.monitoringConfigJson.Photo && _fwdc.monitoringConfigJson.Photo.Enabled === true)
                    {
                        _previewMonitoringVideo("mp_vid");
                    }

                    if (_fwdc.monitoringConfigJson.Screen && _fwdc.monitoringConfigJson.Screen.Enabled === true)
                    {
                        _previewMonitoringVideo("ms_vid");
                    }
                }
                else
                {
                    _fwdc._warn("Monitoring config not available.");
                }

            };

            _fwdc.refreshTableScrollbars = function ($container, immediate)
            {
                var $scrollbars = $.findElementsByClassName("DocTableVirtualScrollbar", $container);
                if ($scrollbars.length)
                {
                    $scrollbars.each(function ()
                    {
                        _fwdc.Init.tablevirtualscrollbar($(this), null, immediate);
                    });
                }
            };

            _fwdc.autoScaleText = function ($container)
            {
                var $elements = $container ? $container.find(".AutoScaleLabel") : $(".AutoScaleLabel");

                $elements.filter(":visible").each(function ()
                {
                    var $element = $(this);

                    var $content = $element.find(".CaptionLabel,.CaptionLinkText");
                    if (!$content.length)
                    {
                        $content = $element;
                    }

                    var size = _fwdc.getElementContentSize($content);

                    var scale = 1;

                    if (size.cellWidth && size.cellHeight)
                    {
                        var scaleX = size.cellWidth / size.contentWidth;
                        var scaleY = size.cellHeight / size.contentHeight;

                        scale = Math.min(scaleX, scaleY);
                    }

                    if (scale >= 1)
                    {
                        $content.css("transform", "").parent().removeClass("AutoScaleLabelContainer");
                    }
                    else
                    {
                        $content.css("transform", "scale(" + scale + ")").parent().addClass("AutoScaleLabelContainer");
                    }
                });
            };

            _fwdc.resizeAssistant = function ()
            {
                var $container = $.findElementById("MANAGER_ASSISTANT__0");
                if ($container.length)
                {
                    var $controlsContainer = $container.closest(".ManagerControlsContainer");
                    if ($controlsContainer.length)
                    {
                        var top = $controlsContainer.offset().top;
                        var height = _fwdc.windowHeight - (_fwdc.fontSize * 2) - top;
                        $container.outerHeight(height);
                    }
                }
            };

            _fwdc.resizeElements = function ($container, init)
            {
                _resizeControlGrids($container);
                _fwdc.checkFlexGridRowVisibility($container);
                _fwdc.setupViewStacks($container);
                _fwdc.setupPanels($container);
                _fwdc.refreshRichControls($container);
                _fwdc.refreshPreviewMonitoring();
                _fwdc.autoScaleText($container);
                _fwdc.resizeVirtualHeaderRows($container);
                _fwdc.refreshTableScrollbars($container, !init);
                _fwdc.resizeAssistant();
                _checkSnapScrolling($container, true);
                _evaluateBaseManagerAboveFold();
                _fwdc.setTimeout("resizeElements.Delay", function ()
                {
                    _fwdc.updateScrollPanels($container);
                    _fwdc.updateSelectorUnderlines($container);
                    _setupStepLists($container);
                });
            };

            _fwdc.getFastModalClass = function ()
            {
                return "FastModal";
            };

            _fwdc.showComboboxMenu = function (field, $field, type)
            {
                if (typeof field !== "string") { field = field.attr("id"); }

                var $accessKeyElements = _fwdc.disableAccessKeys();

                var $menu = $($.parseHTML(_getFieldProperty(field, type || "combomenu", "html")));
                var $modal = $($.parseHTML("<div class='FastComboMenu'></div>"));
                $modal.attr("title", $menu.attr("title"));
                $menu.attr("title", "");
                $modal.append($menu);
                _fwdc.$body().append($modal);

                $modal.dialog({
                    modal: true,
                    draggable: true,
                    resizable: false,
                    width: 640,
                    height: 480,
                    dialogClass: "FastComboMenuDialog FastPanelDialog FastComboMenuDialogModal " + _fwdc.getFastModalClass(),
                    closeOnEscape: true,
                    position: { my: "center", at: "center", collision: "none" },
                    closeText: _fwdc.getCloseText(),
                    open: function (event, ui)
                    {
                        FWDC.hideViewMenus();
                        _fwdc.hideToolTips();
                        _fwdc.closeComboboxes();
                        _fwdc.updateScreenReader();
                        _fwdc.showCurrentFieldTip();
                    },
                    close: function ()
                    {
                        FWDC.hideViewMenus();
                        _fwdc.hideToolTips();
                        _fwdc.closeComboboxes();
                        $modal.remove();
                        $menu.remove();
                        if ($field) { $field.focus(); }
                        _fwdc.showCurrentFieldTip();
                        _fwdc.restoreAccessKeys($accessKeyElements);
                    }
                });

                var $filter = FWDC.setTableFilterBox("COMBO_FILTER_INPUT", $menu);
                $filter.blur();
                $filter.focus();
            };

            _fwdc.onAjaxError = function (source, error, isHtml)
            {
                _errorOccurred = true;

                _fwdc._warn(source, error);

                // Remove scrolling style classes so standard page scrolling can take place.
                $("html").removeClass("ScrollStylePage ScrollStyleContent");

                _fwdc.revealBody();

                try
                {
                    _fwdc.pauseActivityCheck();
                    _closeModals();
                    FWDC.hideViewMenus();
                    _fwdc.hideToolTips();
                    _fwdc.closeComboboxes();
                    _fwdc.destroyRichElements(true);
                }
                catch (ignore) { }

                if (!error)
                {
                    _fwdc.refreshPage("onAjaxError.BlankError", true);
                }
                else
                {
                    if (isHtml)
                    {
                        $("body")
                            .css("font-size", "1em")
                            .css("padding", "0")
                            .removeClass("FastCentered FastMaximized")
                            .html(error);
                    }
                    else
                    {
                        _fwdc.busy.hide();
                        if (_fwdc.development && error.stack)
                        {
                            error = error.stack;
                        }
                        FWDC.messageBox({
                            caption: _fwdc.getDecode("ClientError", "Error"),
                            message: error,
                            icon: FWDC.MessageBoxIcon.Error,
                            callback: function ()
                            {
                                _fwdc.refreshPage("onAjaxError.Message");
                            }
                        });

                    }
                    window.location.hash = "error";
                    _fwdc.updateScreenReader();
                }
            };

            _fwdc.handleResponse = function (request, options, response)
            {
                if (request.status === 200 || !request.status)
                {
                    if (options.dataType === "json")
                    {
                        if (!response)
                        {
                            return false;
                        }
                    }

                    return true;
                }
                else
                {
                    return false;
                }
            };

            _fwdc.getData = function (controlOrOptions, type, target, dataType, busy, data, callback, errorCallback)
            {
                var returnData;

                var managerModalId = -1;
                var docModalId = _fwdc.currentModalId();

                var control;
                var ignoreAutoRefresh = !busy;
                var ignoreSessionData = false;
                if (controlOrOptions && controlOrOptions.type && !type)
                {
                    control = controlOrOptions.control;
                    type = controlOrOptions.type;
                    target = controlOrOptions.target;
                    dataType = controlOrOptions.dataType;
                    busy = controlOrOptions.busy;
                    data = controlOrOptions.data;
                    callback = controlOrOptions.callback;
                    errorCallback = controlOrOptions.errorCallback;
                    ignoreAutoRefresh = _default(controlOrOptions.ignoreAutoRefresh, !busy);
                    ignoreSessionData = _default(controlOrOptions.ignoreSessionData, ignoreSessionData);

                    if (controlOrOptions.$source)
                    {
                        var $document = _fwdc.parentDocumentContainer(controlOrOptions.$source);
                        if ($document)
                        {
                            managerModalId = $document.attr("data-manager-modal");
                            docModalId = $document.attr("data-doc-modal");
                        }
                    }
                    if (controlOrOptions.managerModalId !== undefined) { managerModalId = controlOrOptions.managerModalId; }
                    if (controlOrOptions.docModalId !== undefined) { docModalId = controlOrOptions.docModalId; }
                }
                else
                {
                    control = controlOrOptions;
                }

                var async = !!callback;

                var result = _fwdc.ajax({
                    url: 'GetData',
                    async: !!callback,
                    busy: !!busy,
                    ignoreReady: !busy,
                    ignoreAutoRefresh: ignoreAutoRefresh,
                    commitEdits: false,
                    ignoreSessionData: ignoreSessionData,
                    data: {
                        MANAGER_MODAL_ID__: managerModalId,
                        DOC_MODAL_ID__: docModalId,
                        CONTROL__: control,
                        TYPE__: type,
                        TARGET__: target,
                        VALUES: data
                    },
                    dataType: dataType || "json",
                    error: function (request)
                    {
                        if (errorCallback)
                        {
                            if (errorCallback === true)
                            {
                                _fwdc._warn("getData returned nothing: " + type + ": " + target);
                                return false;
                            }
                            else
                            {
                                return errorCallback(request);
                            }
                        }
                        else
                        {
                            _fwdc.onAjaxError("getData", request.responseText);
                        }
                    },
                    success: function (data, status, request)
                    {
                        if (!callback)
                        {
                            returnData = data;
                        }
                        else
                        {
                            callback(data);
                        }
                    },
                    complete: function ()
                    {
                        FWDC.resumeAutoRefresh();
                    }
                });


                return (async || result === false) ? result : returnData;
            };

            _fwdc.allowDialogInteraction = function (event)
            {
                return !!$(event.target).closest("#CONTEXT_LOG_CONTAINER__,.FastFieldQTip").length;
            };

            _fwdc.getElementsTotalOffset = function ($elements)
            {
                var top = 1000000000;
                var bottom = 0;
                var left = 1000000000;
                var right = 0;

                $elements.each(function ()
                {
                    var $element = $(this);
                    var offset = $element.offset();

                    var height = $element.outerHeight();
                    var width = $element.outerWidth();

                    top = Math.min(top, offset.top);
                    bottom = Math.max(bottom, offset.top + height);
                    left = Math.min(left, offset.left);
                    right = Math.max(right, offset.left + width);
                });

                return {
                    top: top,
                    right: right,
                    bottom: bottom,
                    left: left,
                    height: bottom - top,
                    width: right - left
                };
            };

            _fwdc.baseViewportElement = function ($element)
            {

            };

            _fwdc.parentViewportElement = function ($element)
            {

            };

            _fwdc.getViewport = function ($element)
            {
                var scrollTop;
                var scrollLeft;
                var width;
                var height;

                if (!$element || $element.is("html,body") || $element.equals(_fwdc.$window))
                {
                    scrollTop = _fwdc.$window.scrollTop();
                    scrollLeft = _fwdc.$window.scrollLeft();
                    width = _fwdc.windowWidth;
                    height = _fwdc.windowHeight;

                    return {
                        top: scrollTop,
                        right: scrollLeft + width,
                        bottom: scrollTop + height,
                        left: scrollLeft,
                        height: height,
                        width: width
                    };
                }

                //var windowOffset = _fwdc.getViewport();

                var offset = $element.offset();

                scrollTop = $element.scrollTop();
                scrollLeft = $element.scrollLeft();
                width = $element.outerWidth();
                height = $element.outerHeight();

                return {
                    top: offset.top + scrollTop,
                    right: offset.left + scrollLeft + width,
                    bottom: offset.top + scrollTop + height,
                    left: offset.left + scrollLeft,
                    height: height,
                    width: width
                };
            };

            _fwdc.isElementVisible = function ($elements, $scrollElement, startOnly)
            {
                if (!$elements || !$elements.length) { return false; }

                $scrollElement = $scrollElement || _fwdc.baseScrollContainer($elements, _fwdc.currentDocumentContainer() || _fwdc.$window);

                var isWindow = _fwdc.$window.equals($scrollElement);

                if (!isWindow && !$scrollElement.length)
                {
                    return _fwdc.isElementVisible($elements, _fwdc.$window);
                }

                var offset = _fwdc.getElementsTotalOffset($elements);

                var scrollViewport = _fwdc.getViewport($scrollElement);

                if (isWindow)
                {
                    // Ignore width/right on the window to prevent small horizontal scrolling concerns.
                    scrollViewport.right = 99999999;
                    scrollViewport.width = 99999999;
                }

                if (startOnly)
                {
                    // Only check if the element starts in the viewport
                    return offset.top >= scrollViewport.top
                        && offset.left <= scrollViewport.right
                        && offset.top <= scrollViewport.bottom
                        && offset.left >= scrollViewport.left
                        && (isWindow || _fwdc.isElementVisible($elements, _fwdc.$window, true));
                }

                // Check if the element is completely within the viewport
                return offset.top >= scrollViewport.top
                    && offset.right <= scrollViewport.right
                    && offset.bottom <= scrollViewport.bottom
                    && offset.left >= scrollViewport.left
                    && (isWindow || _fwdc.isElementVisible($elements, _fwdc.$window));
            };

            _fwdc.scrollIntoView = function (elements, options)
            {
                var $elements;
                if (typeof elements === "string")
                {
                    $elements = $("#" + elements);
                }
                else if (!($elements instanceof jQuery))
                {
                    $elements = $(elements);
                }
                else
                {
                    $elements = elements;
                }

                if (!$elements || !$elements.length)
                {
                    return $elements;
                }

                $elements = $elements.map(function ()
                {
                    var $element = $(this);
                    if ($element.hasClass("FastCodeMirrorBox"))
                    {
                        return $element.next(".CodeMirror").get(0);
                    }
                    else if ($element.css("position") === "fixed")
                    {
                        return null;
                    }

                    return this;
                });

                if (!$elements.length)
                {
                    return $elements;
                }

                options = options || {};

                var $parentsUntil = options.$parentsUntil;
                var minVSpace = _default(options.minVSpace, 20);
                var minHSpace = _default(options.minHSpace, 20);
                var preferTop = !!options.preferTop;

                var handledStickyElements = {};

                var $parents;
                if ($parentsUntil)
                {
                    $parents = $elements.parentsUntil($parentsUntil.parent(), _fwdc.selectors.scrollElements);
                }
                else
                {
                    $parents = $elements.parents(_fwdc.selectors.scrollElements);
                }

                var isTopSticky;
                var isBottomSticky;

                var $stickyParent = $elements.closest(_fwdc.selectors.scrollTopStickyElements);
                if ($stickyParent.length)
                {
                    isTopSticky = true;
                }
                else
                {
                    $stickyParent = $elements.closest(_fwdc.selectors.scrollBottomStickyElements);
                    if ($stickyParent.length)
                    {
                        isBottomSticky = true;
                    }
                }

                if ($parents && $parents.length)
                {
                    $parents.each(function ()
                    {
                        var elementBox = $elements.displayBoundingBox();
                        if (!elementBox)
                        {
                            return;
                        }

                        var $container = $(this);
                        if ($container.tag() === "HTML")
                        {
                            // The HTML element's display bounding box moves as we scroll the window, so just use the document's bounds instead.
                            $container = _fwdc.$document;
                        }

                        var containerBox = $container.displayBoundingBox();
                        if (!containerBox)
                        {
                            return;
                        }

                        var scrollVertical = true;
                        var scrollHorizontal = true;

                        // Panel scroll containers are horizontal only.
                        if ($container.hasClass("PanelScrollContainer"))
                        {
                            scrollVertical = false;
                        }

                        if (scrollVertical)
                        {
                            var topSpace = 0;
                            var bottomSpace = 0;

                            if (!isTopSticky)
                            {
                                var $topStickies = $container.querySelectorAll(_fwdc.selectors.scrollTopStickyElements);
                                $topStickies.each(function ()
                                {
                                    var stickyId = $(this).uniqueId().attr("id");

                                    if (!handledStickyElements[stickyId])
                                    {
                                        handledStickyElements[stickyId] = true;

                                        var height = this.offsetHeight;
                                        if (height)
                                        {
                                            topSpace = Math.max(topSpace, height);
                                        }
                                    }
                                });

                                topSpace += minVSpace;
                            }

                            if (!isBottomSticky)
                            {
                                var $bottomStickies = $container.querySelectorAll(_fwdc.selectors.scrollBottomStickyElements);
                                $bottomStickies.each(function ()
                                {
                                    var stickyId = $(this).uniqueId().attr("id");

                                    if (!handledStickyElements[stickyId])
                                    {
                                        handledStickyElements[stickyId] = true;

                                        var height = this.offsetHeight;
                                        if (height)
                                        {
                                            bottomSpace = Math.max(bottomSpace, height);
                                        }
                                    }
                                });

                                bottomSpace += minVSpace;
                            }

                            var dV = 0;
                            topSpace = Math.min(topSpace, containerBox.height / 2);
                            bottomSpace = Math.min(bottomSpace, containerBox.height / 2);

                            elementBox.top -= topSpace;
                            elementBox.bottom += bottomSpace;

                            if (preferTop)
                            {
                                dV = elementBox.top - containerBox.top;
                                preferTop = false;
                            }
                            else
                            {
                                if (elementBox.top < containerBox.top)
                                {
                                    dV = elementBox.top - containerBox.top;
                                }
                                else if (elementBox.bottom > containerBox.bottom)
                                {
                                    dV = elementBox.bottom - containerBox.bottom;

                                    // If the new top would be out of view, snap to top instead of bottom.
                                    if (elementBox.top - dV < containerBox.top)
                                    {
                                        dV = elementBox.top - containerBox.top;
                                    }
                                }
                            }

                            if (dV)
                            {
                                $container.scrollTop($container.scrollTop() + dV);
                            }
                        }

                        if (scrollHorizontal)
                        {
                            var dH = 0;
                            var horizontalSpace = minHSpace;
                            horizontalSpace = Math.min(horizontalSpace, containerBox.width / 2);

                            elementBox.left -= horizontalSpace;
                            elementBox.right += horizontalSpace;

                            if (elementBox.left < containerBox.left)
                            {
                                dH = elementBox.left - containerBox.left;
                            }
                            else if (elementBox.right > containerBox.right)
                            {
                                dH = elementBox.right - containerBox.right;
                            }

                            if (dH)
                            {
                                $container.scrollLeft($container.scrollLeft() + dH);
                            }
                        }
                    });
                }

                return $elements;
            };

            _fwdc.detectScrollContainers = function ($elements)
            {
                var scrollContainers = [];

                var $parent = $elements.first().parent();

                while ($parent && $parent.length && $parent.isElement())
                {
                    var overflow = $parent.css("overflow");
                    if (overflow.match(/scroll|auto/))
                    {
                        scrollContainers.push($parent[0]);
                    }
                    $parent = $parent.parent();
                }

                return $(scrollContainers);
            };

            _fwdc.ensureElementVisible = function ($elements, scrollToVertical, $scrollElement, vpadding, scrollParents)
            {
                if (!$scrollElement)
                {
                    $scrollElement = _fwdc.$window;
                }
                else if (!$scrollElement.length)
                {
                    return false;
                }

                if (typeof $elements === "string")
                {
                    $elements = $("#" + $elements);
                }
                else if (!($elements instanceof jQuery))
                {
                    $elements = $($elements);
                }

                if (!($elements && $elements.length) || !$elements.isVisible()) { return false; }

                _fwdc.invalidateSavedScrollPositions();

                var elementsOffset = _fwdc.getElementsTotalOffset($elements);
                var top = elementsOffset.top;
                var right = elementsOffset.right;
                var bottom = elementsOffset.bottom;
                var left = elementsOffset.left;
                var height = elementsOffset.height;
                var width = elementsOffset.width;

                var leftConstraint;
                var topConstraint;
                var rightConstraint;
                var bottomConstraint;

                if (vpadding === undefined) { vpadding = 10; }
                var hpadding = 10;

                var scrolled = false;
                var $scrollBase = null;

                var $docContainer;

                if ($scrollElement && !$scrollElement.equals(_fwdc.$window))
                {
                    if (!$scrollElement.length) { return false; }

                    if ($scrollElement.equals(_fwdc.$window))
                    {
                        leftConstraint = 0;
                        topConstraint = 0;
                    }
                    else
                    {
                        leftConstraint = $scrollElement.offset().left;
                        topConstraint = $scrollElement.offset().top;

                        if (scrollParents)
                        {
                            $docContainer = _fwdc.parentDocumentContainer($scrollElement);
                            $scrollBase = $docContainer.closest(_fwdc.selectors.modalContainers);
                            if (!$scrollBase.length)
                            {
                                $scrollBase = _fwdc.$window;
                            }
                        }
                    }

                    rightConstraint = leftConstraint + $scrollElement.outerWidth();
                    bottomConstraint = topConstraint + $scrollElement.outerHeight();
                }
                else
                {
                    $docContainer = _fwdc.parentDocumentContainer($elements);
                    var $modalContainer = $docContainer.closest(_fwdc.selectors.modalContainers);
                    if ($modalContainer.length)
                    {
                        var $sourceScrollElement = $scrollElement;
                        $scrollElement = $docContainer.find(".DocumentForm");
                        leftConstraint = $scrollElement.offset().left;
                        rightConstraint = leftConstraint + $scrollElement.outerWidth();
                        topConstraint = $scrollElement.offset().top;
                        bottomConstraint = topConstraint + $scrollElement.outerHeight();
                        $scrollBase = scrollParents && (!$sourceScrollElement || !$sourceScrollElement.equals(_fwdc.$window)) && _fwdc.$window;
                    }
                    else
                    {
                        var $sidebar = $(".Sidebar").first();
                        if ($sidebar && $sidebar.length && $sidebar.css("position") === "fixed")
                        {
                            leftConstraint = $sidebar.offset().left + $sidebar.width();
                        }
                        else
                        {
                            leftConstraint = 0;
                        }

                        $scrollElement = _fwdc.$window;
                        //var offset = $scrollElement.offset() || { left: 0, top: 0 };
                        var offset = { left: 0, top: 0 };
                        rightConstraint = offset.left + $scrollElement.outerWidth() + $scrollElement.scrollLeft();
                        topConstraint = offset.top + $scrollElement.scrollTop();
                        bottomConstraint = topConstraint + $scrollElement.outerHeight();
                    }
                }

                if ($scrollElement && $scrollElement.length)
                {
                    if (left < (leftConstraint + hpadding))
                    {
                        $scrollElement.scrollLeft($scrollElement.scrollLeft() - (leftConstraint - left) - hpadding);
                        scrolled = true;
                    }
                    else if (right > (rightConstraint - hpadding))
                    {
                        if (width < $scrollElement.width())
                        {
                            $scrollElement.scrollLeft($scrollElement.scrollLeft() - (rightConstraint - right) + hpadding);
                        }
                        else
                        {
                            $scrollElement.scrollLeft($scrollElement.scrollLeft() - (leftConstraint - left) - hpadding);
                        }
                        scrolled = true;
                    }
                }

                if (scrollToVertical)
                {
                    // Window does not support .offset in jQuery 3.
                    var containerTop;
                    if ($scrollElement.length && $scrollElement[0] === window)
                    {
                        containerTop = 0;
                    }
                    else
                    {
                        containerTop = $scrollElement.offset().top;
                    }
                    $scrollElement.scrollTop(top - containerTop + $scrollElement.scrollTop() - vpadding);
                    scrolled = true;
                }
                else if ($scrollElement && $scrollElement.length)
                {
                    if (top < topConstraint)
                    {
                        $scrollElement.scrollTop($scrollElement.scrollTop() - (topConstraint - top) - vpadding);
                        scrolled = true;
                    }
                    else if (bottom > bottomConstraint)
                    {
                        if (height < $scrollElement.height())
                        {
                            $scrollElement.scrollTop($scrollElement.scrollTop() - (bottomConstraint - bottom) + vpadding);
                        }
                        else
                        {
                            $scrollElement.scrollTop($scrollElement.scrollTop() - (topConstraint - top) - vpadding);
                        }
                        scrolled = true;
                    }
                }

                if ($scrollBase)
                {
                    _fwdc.ensureElementVisible($elements, scrollToVertical, $scrollBase, vpadding, scrollParents);
                }

                return scrolled;
            };

            _fwdc.updateScreenReader = function ()
            {
                var $input = $("#virtualbufferupdate");
                if ($input && $input.length)
                {
                    $input.val($input.val() === '0' ? '1' : '0');
                }
            };

            // Run on any page refresh or initial load.
            _fwdc.runInitialScreenSetup = function ()
            {
                _fwdc.busy.done(_fwdc.WebAuthN.startConditionalMediation);
            };

            /**
             * Invokes WDC's SetProperties function.  By default, the response is handled as an Action response, updating the user interface as a normal action update.
             * @param {any} event - The source browser event that is triggering the function.
             * @param {any} options - The configuration and parameters to send for the SetProperties call.
             * @returns {jqXHR} The AJAX call tracking object.
             */
            _fwdc.setProperties = function (event, options)
            {
                var data = {
                    DOC_MODAL_ID__: _fwdc.currentModalId(),
                    EVENT_TYPE__: _fwdc.EventType.fromEvent(event),
                    CONTROL__: options.control || "",
                    TYPE__: options.type,
                    TARGET__: options.target,
                    VALUES: options.properties
                };

                if (options.extraData)
                {
                    data = $.extend(data, options.extraData);
                }

                if (options.confirmedData)
                {
                    data = $.extend(data, options.confirmedData);
                }

                var busy = options.busy === undefined || !!options.busy;
                var callback = options.callback;
                var errorCallback = options.errorCallback;
                var action = options.action !== false;
                var confirmedCallback = options.confirmedCallback;
                var commitEdits = _default(options.commitEdits, true);
                var trigger = options.trigger || "";
                var busySource = _default(options.busySource, _fwdc.eventBusySource(event));

                return _fwdc.ajax({
                    url: 'SetProperties',
                    trigger: trigger,
                    async: _default(options.async, true),
                    busy: busy,
                    busySource: busySource,
                    data: data,
                    hideErrors: !!errorCallback,
                    commitEdits: commitEdits,
                    error: function (request)
                    {
                        //_fwdc.onAjaxError("setProperties", request.responseText);
                        _fwdc._warn("Error in _fwdc.setProperties: ", request);
                        if (errorCallback)
                        {
                            errorCallback(request, options);
                        }
                    },
                    success: function (data, status, request)
                    {
                        if (action)
                        {
                            _fwdc.handleActionResult(data, {
                                type: "SetProperties",
                                confirmedCallback: function (confirmedArgs, confirmResultCallback)
                                {
                                    options.confirmedData = confirmedArgs;
                                    options.confirmedCallback = confirmResultCallback;
                                    _fwdc.setProperties(event, options);
                                },
                                confirmResultCallback: confirmedCallback
                            });
                        }

                        if (callback)
                        {
                            callback(data, status, request, options);
                        }
                    },
                    complete: function ()
                    {
                        if (options.completeCallback)
                        {
                            options.completeCallback(options);
                        }
                        FWDC.resumeAutoRefresh();
                    }
                });
            };

            _fwdc.setPropertiesNoAction = function (control, type, target, busy, properties, callback)
            {
                /*return _fwdc.ajax({
                    url: 'SetProperties',
                    busy: !!busy,
                    data: { DOC_MODAL_ID__: _fwdc.currentModalId(), CONTROL__: control, TYPE__: type, TARGET__: target, VALUES: properties },
                    success: function (data, status, request)
                    {
                        if (callback) { callback(data); }
                    }
                });*/

                return _fwdc.setProperties(null, {
                    control: control,
                    type: type,
                    target: target,
                    busy: busy,
                    properties: properties,
                    callback: callback,
                    action: false
                });
            };

            _fwdc.setPropertiesInternal = function (event, control, type, target, busy, properties, callback, progress, uploadprogress)
            {
                var data = {
                    DOC_MODAL_ID__: _fwdc.currentModalId(),
                    EVENT_TYPE__: _fwdc.EventType.fromEvent(event),
                    CONTROL__: control,
                    TYPE__: type,
                    TARGET__: target,
                    LASTFOCUSFIELD__: _fwdc.getLastFocusField(),
                    VALUES: properties
                };

                return _fwdc.ajax({
                    url: 'SetProperties',
                    busy: ((busy === undefined) || !!busy),
                    data: data,
                    hideErrors: false,
                    error: function (request)
                    {
                        //_fwdc.onAjaxError("setProperties", request.responseText);
                    },
                    success: function (data, status, request)
                    {
                        _fwdc.handleActionResult(data);
                    },
                    complete: function ()
                    {
                        if (callback) { callback(); }
                        FWDC.resumeAutoRefresh();
                    },
                    progress: progress,
                    uploadprogress: uploadprogress
                });
            };

            _fwdc.setPropertiesInternalJson = function (control, type, target, busy, properties, callback, errorCallback)
            {
                return _fwdc.ajax({
                    url: 'SetProperties',
                    async: false,
                    busy: !!busy,
                    data: { DOC_MODAL_ID__: _fwdc.currentModalId(), CONTROL__: control, TYPE__: type, TARGET__: target, VALUES: properties },
                    hideErrors: !!errorCallback,
                    dataType: "json",
                    success: function (data, status, request)
                    {
                        if (callback) { callback(data); }
                    },
                    error: function (request, status, error)
                    {
                        if (errorCallback) { errorCallback(request, status, error); }
                    },
                    complete: function ()
                    {
                        FWDC.resumeAutoRefresh(true);
                    }
                });
            };

            _fwdc.setBackgroundProperties = function (trigger, control, type, target, busy, properties, callback, callbackError)
            {
                return _fwdc.ajax({
                    url: 'SetProperties',
                    trigger: trigger,
                    async: false,
                    busy: !!busy,
                    data: { DOC_MODAL_ID__: _fwdc.currentModalId(), CONTROL__: control, TYPE__: type, TARGET__: target, VALUES: properties },
                    hideErrors: true,
                    commitEdits: false,
                    dataType: "json",
                    error: function (request, status, error)
                    {
                        if (request && request.status === 422)
                        {
                            _fwdc.refreshPage("SetProperties.422");
                            return false;
                        }

                        if (callbackError) { callbackError(); }
                        return false;
                    },
                    success: function (data, status, request)
                    {
                        if (callback) { callback(data); }
                    },
                    complete: function ()
                    {
                        FWDC.resumeAutoRefresh(true);
                    }
                });
            };

            _fwdc.correctField = function (fieldId)
            {
                return _fwdc.ajax({
                    url: 'CorrectField',
                    async: false,
                    busy: false,
                    checkBusy: true,
                    data: function ()
                    {
                        return _fwdc.getDocPostParameters({ FIELD__: fieldId }, "input[type='hidden']");
                    },
                    success: function (data, status, request)
                    {
                        _destroyTemporaryQtips(true);
                        var $field = _fwdc.formField(fieldId);
                        _handleRecalcUpdates(data);
                        if ($field && !$field.is('td')) { $field.focus(); }
                    }
                });
            };

            _fwdc.maxRowsDialog = function (doc)
            {
                _fwdc.showStandardDialog(null, {
                    dialog: "MaxRows",
                    data: { DOC__: doc }
                });
            };

            function _invertTipSide(side)
            {
                switch (side)
                {
                    case "top": return "bottom";
                    case "bottom": return "top";
                    case "left": return "right";
                    case "right": return "left";
                }

                return side;
            }

            _fwdc.showFieldQTip = function (tipId, $field, $target, updateContent)
            {
                var $currentTipField = _toolTipFields[tipId];
                var qtipData = $currentTipField && $currentTipField.data("qtip");
                if ($currentTipField && (!qtipData || qtipData.destroyed))
                {
                    $currentTipField = null;
                }

                var $focusTarget = $target;
                if ($focusTarget && $focusTarget.is(".FastToggleDisplay"))
                {
                    $focusTarget = $focusTarget.prev();
                }
                var focused = $field && $field.isActiveElement() || $focusTarget && $focusTarget.isActiveElement();

                var statusClass;
                if ($field.hasClass('FieldReview'))
                {
                    statusClass = 'Review';
                }
                else if ($field.hasClass('FieldCheck'))
                {
                    statusClass = 'Check';
                }
                else if ($field.hasClass('FieldReviewed'))
                {
                    statusClass = 'Reviewed';
                }
                else if ($field.hasClass('FieldCorrected'))
                {
                    statusClass = 'Corrected';
                }
                else if ($field.hasClass('FieldRequired'))
                {
                    // Combo radio buttons don't have a great way to apply a field tip - do not show required bubbles on them.
                    if (_toolTipSettings.noRequired || $field.hasClass("FCBRBS"))
                    {
                        return null;
                    }

                    statusClass = 'Required';
                }
                else if ($field.hasClass('FieldError'))
                {
                    statusClass = 'Error';
                }

                if (qtipData
                    && qtipData.tooltip
                    && $currentTipField
                    && $currentTipField.equals($field)
                    && !updateContent)
                {
                    qtipData.tooltip.removeClass("ReviewTip CheckTip ReviewedTip CorrectedTip RequiredTip ErrorTip").addClass(statusClass + "Tip");

                    var $contents = qtipData.elements.content.children(".FastQTipContent");
                    if ($contents.length)
                    {
                        $contents.removeClass("FastQTipContent-Review FastQTipContent-Check FastQTipContent-Reviewed FastQTipContent-Corrected FastQTipContent-Required FastQTipContent-Error").addClass("FastQTipContent-" + statusClass);
                    }

                    if (focused)
                    {
                        qtipData.tooltip.addClass("FastFieldQTip-focused");
                    }
                    else
                    {
                        qtipData.tooltip.removeClass("FastFieldQTip-focused");
                    }

                    return $field;
                }

                var text = $field.attr("title");

                if ($field.hasClass('TipDismissed'))
                {
                    if (text !== $field.data("fastDismissedTip"))
                    {
                        $field.removeClass("TipDismissed");
                    }
                    else
                    {
                        statusClass = statusClass + ' TipDismissed';
                    }
                }

                var tableField = $field.hasClass("CellEditor") || !!$field.closest('.TDS,.TDC').length;

                $target = $target || $field;

                var forceLeft = $target.closest('.FastLeftToolTip').length;
                var horizontalSide = forceLeft ? 'left' : _toolTipSettings.horizontalSide;

                var $viewport = _fwdc.closestScrollContainer($target, _fwdc.$window);

                var bigField = $field.width() > (_fwdc.windowWidth * 0.5);

                var vertical =
                    tableField
                    || !_fwdc.isLargeScreen() // Always use vertical position on smaller screens
                    || $field.closest(".ui-dialog").length // Use vertical position on modals
                    || !$(".ManagerBase").hasClass("SidebarPinned") // Use vertical positions if the sidebar is hidden
                    || bigField; // Use vertical positions if the field is very wide to prevent issues with qTip2's positioning (SQR 58860)

                var tip;

                //$viewport = _fwdc.$window;
                var position = {
                    target: $target,
                    viewport: $viewport,
                    //container: _fwdc.closestScrollContainer($target, _fwdc.supportElementsContainer()),
                    // Using the Window instead of the modal causes tips to float in empty space outside the modal if it scrolls.
                    //viewport: _fwdc.$window,
                    //container: _fwdc.supportElementsContainer(),
                    //container: _fwdc.closestScrollContainer($target, _fwdc.$window),
                    container: _fwdc.closestScrollContainer($target, null) || _fwdc.supportElementsContainer(),
                    adjust: { method: vertical ? "shift" : (forceLeft ? 'none shift' : 'flip shift') },
                    my: vertical ? (_invertTipSide(_toolTipSettings.verticalSide) + ' left') : (_invertTipSide(horizontalSide) + ' top'),
                    at: vertical ? (_toolTipSettings.verticalSide + ' right') : ('bottom ' + horizontalSide)
                };

                if (bigField)
                {
                    position.my = "top right";
                    position.at = "bottom right";
                }

                //position.adjust.method = "none";

                if (_fwdc.tap)
                {
                    //position.my = _invertTipSide(_toolTipSettings.verticalSide) + " right";
                    //position.at = _toolTipSettings.verticalSide + " right";
                    if ($field.hasClass("FCBRadioSet"))
                    {
                        // Radio button fieldsets need to left-align so we don't have the error floating way off to the right
                        position.my = "top left";
                        position.at = "bottom left";
                    }
                    else
                    {
                        position.my = "top right";
                        position.at = "bottom right";
                    }

                    tip = { corner: false };
                }
                else if (!vertical)
                {
                    position.adjust.y = position.my.y === 'top' ? 5 : -5;
                }

                var $content = $('<span class="FastQTipContent"></span>').text(text).addClass('FastQTipContent-' + tipId).addClass('FastQTipContent-' + statusClass);
                if (!_fwdc.tap && ($field.hasClass('FieldReview') || $field.hasClass('FieldCheck') || $field.hasClass('FieldCorrectableError')) && _fieldViewEnabled($field))
                {
                    $content.addClass('FastQTipContent-Correctable');
                    var $cell;
                    var fieldId;

                    if ($field.hasClass("TDC") || $field.hasClass("TDS"))
                    {
                        $cell = $field;
                        fieldId = $cell.attr("id");
                    }
                    else if ($field.hasClass("CellEditor"))
                    {
                        $cell = $field.data("fastEditingCell");
                        fieldId = $cell.attr("id");
                    }
                    else
                    {
                        fieldId = $field.attr("data-name") || $field.attr('name') || $field.attr('id');
                    }

                    var acceptText = _fwdc.getDecode($field.hasClass("FieldReview") ? "MarkReviewed" : "CorrectField", "Accept");

                    var $link = $('<a class="FieldTipIcon" href="#"></a>')
                        .text(acceptText)
                        .attr("title", acceptText)
                        .click(function (event)
                        {
                            var correctField = _fwdc.correctField(fieldId);

                            if ($cell)
                            {
                                correctField.done(function ()
                                {
                                    _fwdc.beginEditCell($cell, true);
                                });
                            }

                            return _fwdc.stopEvent(event);
                        })
                    // This mousedown cancel caused focus to stick to other fields when interacting with the tip.
                    /*.mousedown(function (event)
                    {
                        return _fwdc.stopEvent(event);
                    })*/;

                    $content.append($link);
                }

                var mistakeTip = $target.closest(".DocViewMistake").length ? " FastFieldMistakeTip" : "";
                qtipData = $field.data('qtip');

                if (qtipData && $field.equals(_toolTipFields[tipId]) && $target.equals(_toolTipTargets[tipId]))
                {
                    $field.qtip("option", "content.text", $content);

                    if (qtipData && qtipData.tooltip)
                    {
                        qtipData.tooltip.removeClass("ReviewTip CheckTip ReviewedTip CorrectedTip RequiredTip ErrorTip").addClass(statusClass + "Tip");

                        var $updateContents = qtipData.elements.content.children(".FastQTipContent");
                        if ($updateContents.length)
                        {
                            $updateContents.removeClass("FastQTipContent-Review FastQTipContent-Check FastQTipContent-Reviewed FastQTipContent-Corrected FastQTipContent-Required FastQTipContent-Error").addClass("FastQTipContent-" + statusClass);
                        }

                        if (focused)
                        {
                            qtipData.tooltip.addClass("FastFieldQTip-focused");
                        }
                        else
                        {
                            qtipData.tooltip.removeClass("FastFieldQTip-focused");
                        }
                    }
                }
                else
                {
                    $field.off(".fastToolTip");

                    var $newTip = $field.qtip({
                        content: {
                            attr: false,
                            text: $content,
                            title: { button: false }
                        },
                        //suppress: !$field.is("select"),
                        suppress: false,
                        role: "generic",
                        live: "off",
                        cosmeticOnly: true,
                        position: position,
                        show:
                        {
                            event: false,
                            ready: true,
                            effect: !$field.data('qtip') && function (offset)
                            {
                                $(this).fadeIn(100);
                            },
                            delay: 0,
                            solo: false
                        },
                        hide:
                        {
                            event: false,
                            effect: function (offset)
                            {
                                $(this).fadeOut(100);
                            }
                        },
                        style:
                        {
                            classes: 'FastFieldQTip FastFieldQTip-' + tipId + (statusClass ? ' ' + statusClass + 'Tip' : '') + mistakeTip + (focused ? " FastFieldQTip-focused" : ""),
                            tip: tip
                        },
                        events:
                        {
                            render: function (event, api)
                            {
                                api.elements.tooltip.attr('role', 'tooltip');
                                $(this).mousedown(function (event)
                                {
                                    if (event.target && $(event.target).closest("a").length) { return; }

                                    if (event.which === _fwdc.mouseButtons.left)
                                    {
                                        if (vertical)
                                        {
                                            api.set('position.my.y', _invertTipSide(api.get('position.my.y')));
                                            api.set('position.at.y', _invertTipSide(api.get('position.at.y')));
                                            _toolTipSettings.verticalSide = _invertTipSide(_toolTipSettings.verticalSide);
                                        }
                                        else
                                        {
                                            api.set('position.my.x', _invertTipSide(api.get('position.my.x')));
                                            api.set('position.at.x', _invertTipSide(api.get('position.at.x')));
                                            _toolTipSettings.horizontalSide = _invertTipSide(_toolTipSettings.horizontalSide);
                                        }

                                        // Stopping this event prevented standard field focus logic from occurring.
                                        // We want to stop the event from blurring the field if it's the existing tip's field.
                                        if ($($.ui.safeActiveElement(document)).equals($field))
                                        {
                                            event.preventDefault();
                                            event.stopPropagation();
                                            event.stopImmediatePropagation();

                                            return false;
                                        }
                                    }
                                });
                            },
                            hide: function (event, api)
                            {
                                if ($field.equals(_toolTipFields[tipId]))
                                {
                                    _toolTipFields[tipId] = null;
                                    _toolTipTargets[tipId] = null;
                                }
                                api.destroy(true);
                            }
                        }
                    });

                    qtipData = $field.data("qtip");

                    _toolTipFields[tipId] = $newTip;
                    _toolTipTargets[tipId] = $target;

                    $field.one("remove.fastToolTip", function (event)
                    {
                        if ($field.data("qtip"))
                        {
                            // Performan immediate destroy to prevent a pending render from getting stuck when closing a modal.
                            $field.qtip("destroy", true);
                        }
                        if ($field.equals(_toolTipFields[tipId]))
                        {
                            _toolTipFields[tipId] = null;
                            _toolTipTargets[tipId] = null;
                        }
                    });
                }

                qtipData.fastIsTableField = tableField;
                qtipData.fastTipId = tipId;

                return _toolTipFields[tipId];
            };

            _fwdc.hideFieldQTips = function ()
            {
                $(".FastFieldQTip").each(function ()
                {
                    var api = $(this).data("qtip");
                    if (api) { api.hide(); }
                });
            };

            /*_fwdc.currentInteractionContainer = function ()
            {
                return $(".ui-dialog-modal,body").last();
            };*/

            _fwdc.currentDialogContainer = function (noBody)
            {
                var $containers = noBody ? $(".ui-dialog-modal") : $(".ui-dialog-modal,body");

                // Exclude closing dialogs from current.
                return $containers.not(_fwdc.selectors.closingModals).last();
            };

            _fwdc.getModalState = function ()
            {
                return _fwdc.getDocPrefixFieldValue("MODAL_STATE__");
            };

            _fwdc.setModalState = function (state)
            {
                _fwdc.setDocPrefixFieldValue("MODAL_STATE__", state);
            };

            _fwdc.getDocPrefixField = function (id)
            {
                var $doc = _fwdc.currentDocumentContainer();
                var $field = $doc ? $doc.find("#" + $doc.attr("data-idprefix") + id) : null;
                if ($field && $field.length)
                {
                    return $field;
                }
                return null;
            };

            _fwdc.getDocPrefixFieldValue = function (id)
            {
                var $field = _fwdc.getDocPrefixField(id);
                if ($field)
                {
                    return $field.val();
                }

                return null;
            };

            _fwdc.setDocPrefixFieldValue = function (id, value)
            {
                var $field = _fwdc.getDocPrefixField(id);
                if ($field)
                {
                    return $field.val(value);
                }

                return null;
            };

            _fwdc.getLastFocusField = function ()
            {
                return _fwdc.getDocPrefixFieldValue("LASTFOCUSFIELD__");
            };

            _fwdc.setLastFocusField = function (fieldId)
            {
                _fwdc.setDocPrefixFieldValue("LASTFOCUSFIELD__", fieldId);
            };

            _fwdc.setLastFocusClick = function (event)
            {
                if (!_fwdc.autoFocusMode)
                {
                    var $target = $(event.currentTarget);
                    var $clicked = $target.closest("a,button,input");
                    var id = $clicked.attr("id");

                    if (id)
                    {
                        //_fwdc._log("Setting Auto-Focus from Click: ", id, $clicked)
                        _fwdc.setLastFocusField(id);
                    }
                }
            };

            _fwdc.setLastFocusOnClick = function (nativeEvent)
            {
                _fwdc.setLastFocusClick($.event.fix(nativeEvent));
            };

            _fwdc.clearLastFocusField = function (fieldId)
            {
                if (fieldId)
                {
                    var currentId = _fwdc.getLastFocusField();
                    if (currentId === fieldId)
                    {
                        return;
                    }
                }

                _fwdc.setLastFocusField("");
            };

            _fwdc.resetChatFocus = function ()
            {
                _fwdc.setLastFocusField("ChatEntryField");
            };

            var _pendingFocusField;

            _fwdc.focusCurrentField = function (allowScroll)
            {
                if (_closing
                    || _fwdc.exporting
                    || _fwdc.browserOptions.noAutoFocus
                    || _editingCell()
                    || _pendingFocusChange
                    || _fwdc.messageBoxOpen()) { return; }

                if (_pendingFocusField)
                {
                    _fwdc.cancelAfterCrossTransition(_pendingFocusField);
                }

                var doFocus = (function ()
                {
                    var lastFocusField = _fwdc.getLastFocusField();

                    _fwdc.saveScrollPositions();

                    if (lastFocusField)
                    {
                        var $field = _fwdc.formField(lastFocusField);
                        //console.log("FocusCurrentField: ", $field[0]);
                        //console.log("Transitioning: ", $field.closest(".FastTransitioning").attr("class"));
                        //console.log("window.scrollTop1: ", _fwdc.$window.scrollTop());
                        if ($field && $field.length && _fwdc.focus("focusCurrentField", $field, { preventScroll: true }))
                        {
                            //console.log("window.scrollTop2: ", _fwdc.$window.scrollTop());
                            _lastScrollFocusIn = $field[0];

                            _fwdc.restoreScrollPositions();
                            //console.log("window.scrollTop3: ", _fwdc.$window.scrollTop());

                            // Scroll Into View here causes screen jumping back up to inputs when clicking links or other items further down the screen.
                            if (allowScroll)
                            {
                                _fwdc.scrollIntoView($field);
                            }
                            return;
                        }
                    }

                    if (_inRecalc) { return; }

                    var $activeElement = $(document.activeElement);

                    // Start with dialogs.
                    var $dialog = _fwdc.currentDialogContainer(true);

                    if (!$dialog.length)
                    {
                        $dialog = null;
                    }

                    if (!_fwdc.autoFocusMode)
                    {
                        // Non-auto focus mode will still auto focus on dialogs to improve the interactive experience.  
                        if (!$dialog)
                        {
                            _fwdc.$body().focus();
                            return;
                        }

                        //// Ensure focus is within any open modal dialogs.
                        //if ($dialog && !$activeElement.closest($dialog).length)
                        //{
                        //    $dialog.findElementsByClassName("ui-dialog-content").dialog("focusDialog");
                        //    return;
                        //}

                        ////_fwdc._trace("Skipped AUTO Focus: ", document.activeElement);

                        //if ($dialog)
                        //{
                        //    if ($activeElement && $activeElement.closest($dialog).length)
                        //    {
                        //        // We're already focused correctly on the dialog content.
                        //        return;
                        //    }
                        //    else
                        //    {
                        //        // Force focus the dialog itself
                        //        $dialog.findElementsByClassName("ui-dialog-content").dialog("focusDialog");
                        //    }
                        //}
                        //else
                        //{
                        //    // Force focus the body element so we can ensure the first tab would go to the Skip to Content link.
                        //    _fwdc.$body().focus();
                        //}

                        //return;
                    }

                    if ($dialog)
                    {
                        // Check for a doc container inside the current dialog.
                        var $dialogDoc = $dialog.find(_fwdc.selectors.documentContainer);
                        if (_fwdc.autoFocusMode)
                        {
                            if ($dialogDoc.length && _tryFocusContainer($dialogDoc, true, true) || _tryFocusContainer($dialogDoc, false, true))
                            {
                                return;
                            }

                            if (!_tryFocusContainer($dialog, true, true) && _tryFocusContainer($dialog, false, true))
                            {
                                return;
                            }

                        }
                        else
                        {
                            // In non-auto-focus mode, we will allow links or buttons to focus before fields if they're first in tab order.
                            if ($dialogDoc.length && _tryFocusContainer($dialogDoc, false, true))
                            {
                                return;
                            }

                            var $content = $dialog.children(".ui-dialog-content");

                            if (_tryFocusContainer($content) || _tryFocusContainer($dialog, false, true))
                            {
                                return;
                            }
                        }

                        // Focus the dialog element.
                        $dialog.findElementsByClassName("ui-dialog-content").dialog("focusDialog");
                        return;
                    }

                    // Next, check the current document container to prevent selection of manager header links.
                    var $container = _fwdc.currentDocumentContainer();

                    if ($container && $container.length && _tryFocusContainer($container, true, true) || _tryFocusContainer($container, false, true))
                    {
                        _fwdc.restoreScrollPositions();
                        return;
                    }

                    // Next, use whatever the current dialog container is.
                    $container = _fwdc.currentDialogContainer(true);

                    if ($container && $container.length && _tryFocusContainer($container, true, true) || _tryFocusContainer($container, false, true))
                    {
                        _fwdc.restoreScrollPositions();
                        return;
                    }

                    // Next, try the current manager container.
                    $container = _fwdc.currentManagerContainer();

                    if ($container && $container.length && _tryFocusContainer($container, true, true) || _tryFocusContainer($container, false, true))
                    {
                        _fwdc.restoreScrollPositions();
                        return;
                    }
                });

                //doFocus();

                _pendingFocusField = _fwdc.afterCrossTransition(doFocus);
            };

            _fwdc.cancelPendingFocus = function ()
            {
                if (_pendingFocusField)
                {
                    _fwdc.cancelAfterCrossTransition(_pendingFocusField);
                    _pendingFocusField = null;
                }
            };

            _fwdc.updateLastScrollFocusIn = function ()
            {
                var lastScrollFocusIn = _lastScrollFocusIn;
                _lastScrollFocusIn = null;
                if (lastScrollFocusIn)
                {
                    var $lastScrollFocusIn = $(lastScrollFocusIn);
                    var id = $lastScrollFocusIn.attr("data-xid") || $lastScrollFocusIn.attr("id");
                    if (id)
                    {
                        var $new = _fwdc.formField(id, true);
                        if ($new && $new.length)
                        {
                            _lastScrollFocusIn = $new[0];
                        }
                    }
                }
            };

            _fwdc.focusId = function (field, fallback)
            {
                if (_fwdc.exporting) { return false; }

                if (_fwdc.focus(_fwdc.formField(field))) { return true; }

                if (fallback)
                {
                    if (fallback === true)
                    {
                        return _fwdc.focusCurrentField();
                    }
                    else if (typeof fallback === "function")
                    {
                        return fallback(field);
                    }
                    else if (typeof fallback === "string")
                    {
                        return _fwdc.focus(_fwdc.formField(fallback));
                    }
                    else if (fallback instanceof $)
                    {
                        return _fwdc.focus(fallback);
                    }
                }

                return false;
            };

            _fwdc.focusContainer = function (containerId, inputsOnly, defaultFocus)
            {
                if (_fwdc.exporting) { return false; }

                var $container = _fwdc.currentManagerContainer().findElementById(containerId);
                if ($container && $container.length)
                {
                    _fwdc.scrollIntoView($container);

                    if (_tryFocusContainer($container, inputsOnly, defaultFocus))
                    {
                        return true;
                    }
                }
                return _fwdc.focusCurrentField();
            };

            _fwdc.setSelectable = function (selectedFields)
            {
                if (_fwdc.exporting) { return; }

                var $container = _fwdc.currentDocumentContainer();
                var $selectable = $container.find(".fast-ui-selectable");
                if ($selectable.length)
                {
                    var $layouts = $selectable.closest(".ControlGridContainer,.ViewLayout,.FlexGridContainer");
                    if ($layouts && $layouts.length)
                    {
                        $layouts.selectable({
                            filter: ".fast-ui-selectable",
                            cancel: ".ViewSelector,.GroupSelector,.TableContainer a,.fast-ui-prevent-selection,.FGCT,.FGFT,.FGCRG,.FGSCT,.FGCSZ",
                            autoRefresh: false,
                            unselected: function (e, ui)
                            {
                                var $unselected = $(ui.unselected);

                                if ($unselected.data("uiDraggable")) { $unselected.draggable("destroy"); }
                                if ($unselected.data("uiResizable")) { $unselected.resizable("destroy"); }

                                $unselected.find("a,button").each(_fwdc.enableClick);
                            },
                            start: function (e, ui)
                            {
                                if (!e.ctrlKey)
                                {
                                    _fwdc.clearSelected();
                                }
                            },
                            stop: function (e, ui)
                            {
                                _fwdc.raiseSelected();
                            }
                        }).find("img.DocControlImage").one("load", function (event)
                        {
                            var $container = $(this).closest(".ControlGridContainer,.ViewLayout,.FlexGridContainer").data("fast-refresh-selectable", true);
                            _fwdc.setTimeout("SelectableRefresh", function ()
                            {
                                if ($container.data("fast-refresh-selectable"))
                                {
                                    $container.data("fast-refresh-selectable", null).selectable("refresh");
                                }
                            }, 100);
                        });
                        /*.each(function(index, layout)
                        {
                            var $layout = $(layout);
                            var $selectedMenu = $layout.data("FastSelectionMenu");
                            if (!$selectedMenu)
                            {
                                $layout.data("FastSelectionMenu", $selectedMenu = $('<div></div>').addClass("FastSelectionMenu").text("SELECTED?"));
                            }
                        });*/
                    }
                }

                var $resizeOnly = $container.find(".fast-ui-resizable:not(.fast-ui-selectable)");
                $resizeOnly.each(function () { _setResizable(this, true); });

                _setDraggable($container.find(".fast-ui-draggable"));

                var $regionSelectable = $container.find(".fast-ui-regionselectable");
                if ($regionSelectable && $regionSelectable.length)
                {
                    $regionSelectable.selectable({
                        filter: "> *",
                        start: function (e, ui)
                        {
                            var $this = $(this);
                            var offset = $this.offset();
                            this.fastStartPositionX = e.originalEvent.pageX - offset.left;
                            this.fastStartPositionY = e.originalEvent.pageY - offset.top;
                        },
                        stop: function (e, ui)
                        {
                            var $this = $(this);
                            var offset = $this.offset();
                            var left = this.fastStartPositionX;
                            var top = this.fastStartPositionY;
                            var width = e.originalEvent.pageX - left - offset.left;
                            var height = e.originalEvent.pageY - top - offset.top;
                            if (width < 0)
                            {
                                left += width;
                                width *= -1;
                            }

                            if (height < 0)
                            {
                                top += height;
                                height *= -1;
                            }

                            width = width < 0 ? -width : width;
                            height = height < 0 ? -height : height;

                            var $img = $this.find("img.DocControlImage");

                            var imgWidth = 0;
                            var imgHeight = 0;
                            if ($img.length === 1)
                            {
                                imgWidth = $img.width();
                                imgHeight = $img.height();
                            }

                            if ($this.hasClass("fast-ui-zeroregionselectable") || (width > 5 && height > 5))
                            {
                                var $scrollContainer = $this.closest(".SnapScrollTop");
                                if ($scrollContainer && $scrollContainer.length)
                                {
                                    $scrollContainer.scrollTop(0).scrollLeft(0);
                                }

                                _fwdc.ajax({
                                    url: 'RegionSelected',
                                    async: false,
                                    data: {
                                        DOC_MODAL_ID__: _fwdc.currentModalId(),
                                        FIELD__: _findElementName(this),
                                        LEFT__: left,
                                        TOP__: top,
                                        WIDTH__: width,
                                        HEIGHT__: height,
                                        IMG_WIDTH__: imgWidth,
                                        IMG_HEIGHT__: imgHeight
                                    },
                                    error: function (request, status, error)
                                    {
                                        _fwdc.onAjaxError("RegionSelected", request.responseText);
                                    },
                                    success: function (data, status, request)
                                    {
                                        _handleRecalcUpdates(data);
                                    }
                                });
                            }
                        }
                    });
                }

                _setupSortableTables($container);

                if (selectedFields) { _setSelectedFields(selectedFields); }
            };

            _fwdc.runResponseFunctions = function (response, post)
            {
                var propertyName = post ? "postFunctions" : "preFunctions";

                var functions = response[propertyName];
                if (functions)
                {
                    if (functions !== "HANDLED")
                    {
                        $.each(functions, function (index, value)
                        {
                            try
                            {
                                _fwdc.runClientFunction(value);
                            }
                            catch (ex)
                            {
                                _fwdc._warn(ex);
                            }
                        });

                        response[propertyName] = "HANDLED";
                    }
                }
            };

            function _notifyAsyncEvent(func)
            {
                var busySource = _fwdc.busy.getBusySource();
                _fwdc.busy.done(function notifyAsyncEventBusy()
                {
                    var busyId = _fwdc.busy.show("NotifyAsyncEvent", { busySource: busySource });

                    _fwdc.afterCrossTransition(function notifyAsyncEventInternal()
                    {
                        _fwdc.setProperties(null, {
                            trigger: "NotifyAsyncEvent",
                            control: func.parameters[0],
                            type: "NotifyAsyncEvent", target: func.parameters[1],
                            busy: false,
                            busySource: busySource,
                            extraData:
                            {
                                LASTFOCUSFIELD__: _fwdc.getLastFocusField()
                            }
                        }).always(function notifyAsyncEventComplete()
                        {
                            _fwdc.busy.hide(busyId);
                        });
                    });
                });
            }

            _fwdc.runClientFunction = function (func)
            {
                if (func.parameters && func.parameters.length && !func.parameter)
                {
                    func.parameter = func.parameters[0];
                }

                switch (func.name)
                {
                    case "SkipFocus":
                        _fwdc.preventAutoFocus = true;
                        break;
                    case "ImportDialog":
                        _fwdc.busy.done(function ()
                        {
                            _fwdc.importDialog(null);
                        });
                        break;
                    case "AttachmentDialog":
                        _fwdc.busy.done(function ()
                        {
                            if (func.parameters && func.parameters.length === 3)
                            {
                                _fwdc.attachmentDialog(null, { control: func.parameters[0], type: func.parameters[1], target: func.parameters[2] }, true);
                            }
                            else if (func.parameters && func.parameters.length === 2)
                            {
                                _fwdc.attachmentDialog(null, { control: func.parameters[0], type: func.parameters[1] }, true);
                            }
                            else
                            {
                                _fwdc.attachmentDialog(null, func.parameter, true);
                            }
                        });
                        break;
                    case "HiddenAttachmentDialog":
                        _fwdc.busy.done(function ()
                        {
                            _fwdc.attachmentDialog(null, func.parameter, true, true);
                        });
                        break;
                    case "LogOff":
                        _fwdc.logOff(null, true);
                        break;
                    case "PromptLogOff":
                        _fwdc.busy.done(function ()
                        {
                            _fwdc.logOff(null);
                        });
                        break;
                    case "AcceptModal":
                        _fwdc.acceptModal(null, true);
                        break;
                    case "CancelModal":
                        _fwdc.cancelModal(null, true);
                        break;
                    case "CloseDocModal":
                        try
                        {
                            _docModalClosing = true;
                            _destroyDocModal();
                        }
                        finally
                        {
                            _docModalClosing = false;
                        }
                        break;
                    case "FocusId":
                        _fwdc.busy.done(function () { _fwdc.focusId(func.parameter, true); });
                        break;
                    case "FocusContainer":
                        _fwdc.busy.done(function () { _fwdc.focusContainer(func.parameter); });
                        break;
                    case "FocusCurrentField":
                        _fwdc.busy.done(function () { _fwdc.focusCurrentField(); });
                        break;
                    case "ViewLinkClicked":
                        _fwdc.viewLinkClicked({
                            fieldId: func.parameter,
                            trigger: "ClientFunction.ViewLinkClicked",
                            force: true,
                            server: true
                        });
                        break;
                    case "ShowModalView":
                        _fwdc.busy.done(function () { _showModalView(func.parameter); });
                        break;
                    case "MaxRowsDialog":
                        _fwdc.busy.done(function ()
                        {
                            _fwdc.maxRowsDialog(func.parameter);
                        });
                        break;
                    case "CloseModalManager":
                        FWDC.hideViewMenus();
                        _modalManagerClosed = true;
                        var $currentModal = $("#MODAL_MANAGER_" + _fwdc.modalManagerCount);
                        $currentModal.dialog("close");
                        _fwdc.incrementHistory();
                        break;
                    case "OpenUrl":
                        FWDC.openUrl(null, func.parameter);
                        break;
                    case "OpenWindow":
                        FWDC.openWindow(null, func.parameter);
                        break;
                    case "OpenTemporaryUrl":
                        FWDC.openTemporaryUrl(null, func.parameter);
                        break;
                    case "ReferUrl":
                        _fwdc.referUrl(func.parameters[0], func.parameters[1]);
                        break;
                    case "FastMessageBox":
                        FWDC.messageBox(func.parameters);
                        break;
                    case "ScrollToTop":
                        _fwdc.scrollToTop(func.parameters[0]);
                        break;
                    case "ScrollContextToTop":
                        _getContextScrollContainer().scrollTop(0).scrollLeft(0);
                        break;
                    case "SetSelectable":
                        _fwdc.busy.done(function () { _fwdc.setSelectable(func.parameters); });
                        break;
                    case "ShowSidebar":
                        _fwdc.busy.done(function () { _fwdc.showManagerMenu(); });
                        break;
                    case "OpenModalManager":
                        _fwdc.busy.done(function () { _fwdc.openModalManager(func.parameter); });
                        break;
                    case "BeginEditValue":
                        _fwdc.beginEditValue(func.parameters[0], func.parameters[1]);
                        break;
                    case "SetContextLog":
                        _fwdc.setContextLog(func.parameter);
                        break;
                    case "PromptToggleLog":
                        _fastPrompt(func.parameters[0], "password", function (authCode)
                        {
                            _fwdc.toggleLog(authCode);
                        });
                        break;
                    case "RefreshPage":
                        _fwdc.refreshPage(func.parameter || "ClientFunction");
                        break;
                    case "RefreshWindowContent":
                        _fwdc.refreshWindowContent(func.parameters[0], func.parameters[1]);
                        break;
                    case "SwitchManager":
                        _fwdc.switchManager(func.parameters[0], func.parameters[1], func.parameters[2]);
                        break;
                    case "StartChat":
                        FWDC.startChat(func.parameters[0]);
                        break;
                    case "ViewSupportId":
                        _fwdc.busy.done(function () { FWDC.viewSupportId(); });
                        break;
                    case "SelectFieldText":
                        _fwdc.busy.done(function ()
                        {
                            _fwdc.afterCrossTransition(function ()
                            {
                                _fwdc.selectFieldText(func.parameters[0], parseInt(func.parameters[1], 10), parseInt(func.parameters[2], 10));
                            });
                        });
                        break;
                    case "PrintDialog":
                        window.print();
                        break;
                    case "EnsureVisible":
                        //_fwdc.ensureElementVisible(func.parameters[0]);
                        _fwdc.scrollIntoView(func.parameters[0]);
                        break;
                    case "PostAppMessage":
                        _fwdc.postAppMessage(func.parameters[0], func.parameters[1], func.parameters[2] === "true");
                        break;
                    case "NotifyAsyncEvent":
                        _notifyAsyncEvent(func);
                        break;
                    case "RequestUserLocation":
                        _fwdc.busy.done(function ()
                        {
                            _fwdc.afterCrossTransition(function ()
                            {
                                _fwdc.requestUserLocation(func.parameter);
                            });
                        });
                        break;
                    case "PersistOption":
                        _fwdc.persistOption({ "Option": func.parameters[0], "Value": func.parameters[1] }, true);
                        break;
                    case "AccessibilityAnnounce":
                        _fwdc.busy.done(function ()
                        {
                            _fwdc.afterCrossTransition(function ()
                            {
                                _fwdc.liveRegionSay(func.parameters[0]);
                            });
                        });
                        break;
                    case "RequestIdentityCredential":
                        _fwdc.busy.done(function ()
                        {
                            _fwdc.afterCrossTransition(function ()
                            {
                                _fwdc.requestIdentityCredential(func.parameters[0], func.parameters[1], func.parameters[2]);
                            });
                        });
                        break;
                    case "ShowIFrame":
                        _fwdc.busy.done(function ()
                        {
                            _fwdc.afterCrossTransition(function ()
                            {
                                _fwdc.showIFrame.apply(_fwdc, func.parameters);
                            });
                        });
                        break;
                    case "VerifyMonitoring":
                        _verifyMonitoring();
                        break;
                    case "CaptureMonitoring":
                        _manualCaptureMonitoring();
                        break;
                    case "EndMonitoringPhoto":
                        _fwdc.endMonitoringPhoto();
                        break;
                    case "EndMonitoringBrowser":
                        _fwdc.endMonitoringBrowser();
                        break;
                }
            };

            _fwdc.getDecode = function (code, defaultDecode)
            {
                var decode = _decodes[code];
                if (decode) { return decode; }

                if (_standardDecodes)
                {
                    decode = _standardDecodes[code];
                    if (decode) { return decode; }
                }

                decode = code;

                _fwdc.ajax({
                    url: '../StandardDecode/' + encodeURIComponent(code) + '?Language=' + encodeURIComponent(_fwdc.language),
                    async: false,
                    busy: false,
                    checkBusy: false,
                    type: 'GET',
                    success: function (response, status, request)
                    {
                        decode = (response && response.caption) || (defaultDecode === undefined ? code : defaultDecode);
                    }
                });

                _decodes[code] = decode;

                return decode;
            };

            _fwdc.standardDecodes = function (decodes)
            {
                if (!_standardDecodes)
                {
                    if (decodes)
                    {
                        _standardDecodes = decodes;
                    }
                    else
                    {
                        _fwdc.ajax({
                            url: '../StandardDecodes?Language=' + encodeURIComponent(_fwdc.language),
                            async: false,
                            type: 'GET',
                            fastRequest: false,
                            success: function (response, status, request)
                            {
                                _standardDecodes = response;
                            }
                        });
                    }
                }

                return _standardDecodes || {
                    "CapsLockOn": "Caps Lock is on",
                    "LogPassword": "Password for log:",
                    "MsgBoxOk": "OK",
                    "MsgBoxCancel": "Cancel",
                    "MsgBoxYes": "Yes",
                    "MsgBoxNo": "No",
                    "DialogClose": "Close",
                    "NotifyReply": "Reply",
                    "NotifyDismiss": "Dismiss",
                    "NotifyHide": "Hide",
                    "StopAutoRefresh": "Stop",
                    "LogOffPrompt": "Are you sure you want to log off?  Any unsaved data will be lost.",
                    "ReplayTitle": "REPLAY",
                    "LoggedOff": "Logged Off",
                    "SessionExpiring": "Your session will expire in 5 minutes unless you click OK.",
                    "BusyNewWindow": "Open New Window",
                    "AttachmentError": "An unknown error occurred trying to upload this file.",
                    "ImportError": "An unknown error occurred trying to import this file.",
                    "MediaToggleFullscreen": "Toggle Fullscreen",
                    "MediaPlay": "Play",
                    "MediaPause": "Pause",
                    "MediaError": "An error occurred while loading the media file.",
                    "MediaLoading": "Loading",
                    "PopupBlocked": "It looks like your browser has blocked us from opening a window for you.  Please make sure you allow popups from this site and try again.",
                    "Chat": "Chat",
                    "NewConversation": "New Conversation",
                    "ChatJoined": "@pstrWho joined.",
                    "ChatLeft": "@pstrWho left.",
                    "ChatBox": "Type your message here",
                    "ChatSend": "Send",
                    "ChatAttach": "Attach File",
                    "ChatShare": "Share Session",
                    "ChatConfirmShare": "Do you want to share your session with the members of the conversation?\n\nThis will allow them to see what you are seeing in this application.",
                    "ChatInvite": "Invite User",
                    "ChatAddNote": "Add Support Note",
                    "ChatSendLibrary": "Send Library Message",
                    "ChatYou": "You",
                    "ChatAttachmentAdded": "Added attachment: @pstrFilename",
                    "ChatRequestForm": "Request Form",
                    "ChatFormRequested": "@pstrFrom would like you to fill out this form: @pstrForm.",
                    "ChatFormSubmitted": "@pstrFrom submitted: @pstrForm.",
                    "ChatSharedScreen": "Shared their session.",
                    "ChatYouSharedScreen": "Shared your session.",
                    "ChatView": "Click to View",
                    "ChatConfirmClose": "Are you sure you want to leave the conversation?",
                    "ChatInsertLibrary": "Select Library Message",
                    "ChatNote": "Support Note",
                    "ClientError": "An Error Occurred",
                    "ChatViewSupportVisit": "View Support Visit",
                    "MonitoringPhotoTitle": "Monitoring Photo",
                    "MonitoringScreenTitle": "Monitoring Screen",
                    "MonitoringInputs": "Select Camera",
                    "Close": "Close",
                    "CommandBarBestMatches": "Best Matches"
                };
            };

            _fwdc.standardDecode = function (decode)
            {
                return _fwdc.standardDecodes()[decode] || decode;
            };

            _fwdc.getCloseText = function ()
            {
                return _fwdc.standardDecodes().DialogClose || "Close";
            };

            _fwdc.cancelAutoRefresh = function (fieldId, force)
            {
                if (force)
                {
                    _fwdc.setPropertiesInternal(null, "", "CancelAutoRefresh", fieldId, false);
                    return true;
                }

                // TODO: Change this to internal?
                return FWDC.setProperties("", "CancelAutoRefresh", fieldId) !== false;
            };

            _fwdc.disableAccessKeys = function ($container, permanent)
            {
                var $keyElements = $container ? $container.find("[accesskey]") : $("[accesskey]");

                if (!$keyElements.length) { return null; }

                $keyElements.each(function ()
                {
                    var $this = $(this);
                    if (permanent)
                    {
                        $this.removeAttr("accesskey").addClass("AccessKeyRemoved");
                    }
                    else
                    {
                        $this
                            .data("fast-accesskey", $this.attr("accesskey"))
                            .removeAttr("accesskey")
                            .addClass("AccessKeyRemoved");
                    }
                });

                //_fwdc._log("Disabling access keys: ", $keyElements);

                return $keyElements;
            };

            _fwdc.restoreAccessKeys = function ($elements)
            {
                if ($elements && $elements.length)
                {
                    $elements.each(function ()
                    {
                        var $this = $(this);

                        var key;
                        if ((key = $this.data("fast-accesskey")) && key)
                        {
                            $this.removeData("fast-accesskey").attr("accesskey", key).removeClass("AccessKeyRemoved");
                        }
                    });
                }
            };

            _fwdc.blockAccessKeys = function ()
            {
                var $keyElements = $("[accesskey]");

                if (!$keyElements.length) { return null; }

                $keyElements.each(function ()
                {
                    var $this = $(this);
                    if (!$this.hasClass("DisabledAccessKey"))
                    {
                        $this.addClass("DisabledAccessKey");

                        if ($this.attr("onclick"))
                        {
                            $this.data("fast-onclick", $this.attr("onclick")).removeAttr("onclick");
                        }
                    }
                });

                return $keyElements;
            };

            _fwdc.unblockAccessKeys = function ($elements)
            {
                if ($elements && $elements.length)
                {
                    $elements.each(function ()
                    {
                        var $this = $(this).removeClass("DisabledAccessKey");

                        var onclick;
                        if ((onclick = $this.data("fast-onclick")) && onclick)
                        {
                            $this.removeData("fast-onclick").attr("onclick", onclick);
                        }
                    });
                }
            };

            var _lastUserActivity = null;
            function _checkUserActivity()
            {
                var $currentManager = _fwdc.currentManagerContainer();
                if (_lastUserActivity && $currentManager && $currentManager.length)
                {
                    var lastUserActivity = _lastUserActivity;
                    var options = _lastUserActivity === true ? null : _lastUserActivity;
                    if (options && options.getValue)
                    {
                        options.value = options.getValue();
                        delete options.getValue;
                    }
                    _lastUserActivity = null;

                    _fwdc.busy.done(function ()
                    {
                        _fwdc.setBackgroundProperties(
                            "CheckUserActivity:" + (options && options.event ? options.event : "?"),
                            "",
                            "UserActivity",
                            "",
                            true,
                            options,
                            function () { },
                            function ()
                            {
                                _lastUserActivity = _lastUserActivity || lastUserActivity;
                            });
                    });
                }
            }

            var _lastActivity;
            _fwdc.startActivityCheck = function (time)
            {
                _lastActivity = _fwdc.now();
                _fwdc.pauseActivityCheck();
                _fwdc.resumeActivityCheck();
            };

            var _userActivityHandle = null;

            _fwdc.pauseActivityCheck = function ()
            {
                _lastActivity = 0;
                if (_userActivityHandle)
                {
                    clearInterval(_userActivityHandle);
                    _userActivityHandle = null;
                    _lastUserActivity = null;
                }
            };

            _fwdc.resumeActivityCheck = function ()
            {
                _lastActivity = _fwdc.now();
                if (!_userActivityHandle)
                {
                    _lastUserActivity = null;
                    _userActivityHandle = window.setInterval(_checkUserActivity, 60000);
                }
            };

            _fwdc.onUserActivity = function (options)
            {
                /*if (!options || !options.async)
                {
                    _fwdc.runFingerprinting(true);
                }*/
                _lastUserActivity = options || _lastUserActivity || true;
            };

            function _onSessionEnded()
            {
                FWDC.openUrl("../LogOff/?Ended=1");
            }

            function _onSessionLocked()
            {
                if (!_busy())
                {
                    _fwdc.refreshPage("_onSessionIdle");
                }
            }

            function _onSessionExpired()
            {
                FWDC.openUrl("../LogOff/?Ended=1");
            }

            var _expireWarning;
            function _onSessionExpireWarning()
            {
                if (!_expireWarning)
                {
                    _expireWarning = true;

                    var prompt = _fwdc.getDecode("SessionExpiring");
                    if (prompt)
                    {
                        FWDC.messageBox({
                            message: prompt,
                            icon: FWDC.MessageBoxIcon.Warning,
                            callback: function ()
                            {
                                _expireWarning = false;
                                _fwdc.setPropertiesInternal(null, "MANAGER__", "PreventExpiry", "", true);
                            }
                        });
                    }
                }
            }

            var _sessionCheckHandle = null;
            var _disableSessionCheck = false;
            _fwdc.resumeSessionCheck = function ()
            {
                if (_sessionCheckHandle)
                {
                    _fwdc.clearTimeout("Session Check", _sessionCheckHandle);
                    _sessionCheckHandle = null;
                }

                if (_disableSessionCheck)
                {
                    return;
                }

                var timeout = 5184000000;

                var lowestTimeout;

                if (_fwdc.sessionTimeouts.endTimeout === 0)
                {
                    _onSessionEnded();
                }
                else if (_fwdc.sessionTimeouts.endTimeout && _fwdc.sessionTimeouts.endTimeout > 0 && _fwdc.sessionTimeouts.endTimeout < timeout)
                {
                    timeout = _fwdc.sessionTimeouts.endTimeout;
                    lowestTimeout = "End";
                }

                if (_fwdc.sessionTimeouts.idleTimeout === 0)
                {
                    _onSessionLocked();
                }
                else if (_fwdc.sessionTimeouts.idleTimeout && _fwdc.sessionTimeouts.idleTimeout > 0 && _fwdc.sessionTimeouts.idleTimeout < timeout)
                {
                    timeout = _fwdc.sessionTimeouts.idleTimeout;
                    lowestTimeout = "Idle";
                }

                if (_fwdc.sessionTimeouts.expiryTimeout === 0)
                {
                    _onSessionExpired();
                }
                else if (_fwdc.sessionTimeouts.expiryTimeout && _fwdc.sessionTimeouts.expiryTimeout > 0 && _fwdc.sessionTimeouts.expiryTimeout < timeout)
                {
                    timeout = _fwdc.sessionTimeouts.expiryTimeout;
                    lowestTimeout = "Expire";
                }

                if (_fwdc.sessionTimeouts.expiryWarningTimeout === 0)
                {
                    _onSessionExpireWarning();
                }
                else if (_fwdc.sessionTimeouts.expiryWarningTimeout && _fwdc.sessionTimeouts.expiryWarningTimeout > 0 && _fwdc.sessionTimeouts.expiryWarningTimeout < timeout)
                {
                    timeout = _fwdc.sessionTimeouts.expiryWarningTimeout;
                    lowestTimeout = "ExpireWarning";
                }

                if (_fwdc.sessionTimeouts.keepaliveTimeout === 0)
                {
                    //_onSessionExpired();
                    // Immediately fire keepalive?  This should never happen due to server-side logic.
                }
                else if (_fwdc.sessionTimeouts.keepaliveTimeout && _fwdc.sessionTimeouts.keepaliveTimeout > 0 && _fwdc.sessionTimeouts.keepaliveTimeout < timeout)
                {
                    timeout = _fwdc.sessionTimeouts.keepaliveTimeout;
                    lowestTimeout = "Keepalive";
                }

                if (timeout && timeout < 5184000000)
                {
                    if (!_fwdc.sessionTimeouts.from) { _fwdc.sessionTimeouts.from = _fwdc.now(); }
                    var adjustedTimeout = Math.max(timeout - (_fwdc.now() - _fwdc.sessionTimeouts.from), 0);
                    _sessionCheckHandle = _fwdc.setTimeout("Check Session Status", _checkSessionStatus, adjustedTimeout);
                }
            };

            _fwdc.pauseSessionCheck = function ()
            {
                if (_sessionCheckHandle)
                {
                    _fwdc.clearTimeout("Session Check", _sessionCheckHandle);
                    _sessionCheckHandle = null;
                }
            };

            function _checkSessionStatus(error)
            {
                _fwdc.ajax({
                    url: 'GetData',
                    async: true,
                    busy: false,
                    ignoreReady: true,
                    commitEdits: false,
                    ignoreSessionError: true,
                    data: {
                        CONTROL__: "SESSION__",
                        TYPE__: "CheckSession",
                        FAST_CLIENT_TRIGGER__: "Timer"
                    },
                    dataType: "json",
                    error: function (request)
                    {
                        if (request.getResponseHeader("Fast-Session-Locked"))
                        {
                            _onSessionLocked();
                            return false;
                        }

                        if (request.getResponseHeader("Fast-Session-Expired"))
                        {
                            _disableSessionCheck = true;
                            _onSessionExpired();
                            return false;
                        }

                        var isHtml = request.getResponseHeader("Content-Type");
                        isHtml = (isHtml && isHtml.indexOf("text/html") > -1);
                        _fwdc.onAjaxError("Error.General", request.responseText, isHtml);
                    },
                    success: function (data, status, request)
                    {
                    }
                });
            }

            _fwdc.beginEditValue = function (fieldId, value)
            {
                _fwdc.busy.done(function ()
                {
                    _fwdc.afterCrossTransition(function onBeginEditValue()
                    {
                        // Prevent any pending focusCurrentField calls from executing.
                        _fwdc.cancelPendingFocus();

                        var $field = _fwdc.formField(fieldId, true);
                        if ($field)
                        {
                            var cm = $field.data("fast-code-mirror-editor");
                            if (cm)
                            {
                                _clearCurrentField();
                                _fwdc.Events.Field.focus(cm.getTextArea());
                                cm.setValue(value);
                                cm.save();
                                cm.focus();
                            }
                            else if ($field.tagIs("input"))
                            {
                                _fwdc.Events.Field.focus($field.get(0));
                                $field.val(value);
                            }
                            else if ($field.tagIs("textarea"))
                            {
                                if ($field.hasClass("FastCodeMirrorInit"))
                                {
                                    // If the field is an uninitialized code mirror field, delay a focus call.
                                    $field.one("fastcmready", function ()
                                    {
                                        var $field = $(this);
                                        var cm = $field.data("fast-code-mirror-editor");
                                        if (cm)
                                        {
                                            _clearCurrentField();
                                            _fwdc.Events.Field.focus(cm.getTextArea());
                                            cm.save();
                                            cm.focus();
                                            //$field.val(value);
                                            cm.fastSetValue(value);
                                        }
                                    });
                                    //_fwdc.setTimeout("beginEditValue.CodeMirrorInit", function ($field)
                                    //{
                                    //    var cm = $field.data("fast-code-mirror-editor");
                                    //    if (cm)
                                    //    {
                                    //        _clearCurrentField();
                                    //        _fwdc.Events.Field.focus(cm.getTextArea());
                                    //        cm.save();
                                    //        cm.focus();
                                    //    }
                                    //}, 0, $field);
                                }
                                else
                                {
                                    _fwdc.Events.Field.focus($field.get(0));
                                    $field.val(value);
                                }
                            }
                            else if ($field.is("td.FieldEnabled"))
                            {
                                _fwdc.beginEditCell($field, true);
                                _$currentEditor.val(value);
                            }
                        }
                    });
                });
            };

            _fwdc.getBasePath = function ()
            {
                return window.location.pathname.split("/").slice(0, -2).join("/") + "/";
            };

            _fwdc.applyVerLast = function ($container)
            {
                $container = ($container && $container.length) ? $container : _fwdc.currentDocumentContainer();
                if ($container.findElementById("FAST_VERLAST__").val(_fwdc.fastVerLast).length)
                {
                    $container.findElementById("FAST_VERLAST_SOURCE__").val(_fwdc.fastVerLastSource);
                }
            };

            _fwdc.clientActionMissing = function ()
            {
                alert("This client action has not been setup.");
            };

            _fwdc.refreshPage = function (source, force)
            {
                _busy.show("refreshPage");
                window.location.reload(force);
            };

            function _refreshWindowContent(trigger, targetVerLast, targetVerLastSource, busy, switchingBack, noRefresh, lightRefresh)
            {
                if (targetVerLast)
                {
                    FWDC.setVerLast(targetVerLast, targetVerLastSource, true);
                }

                _fwdc.loadManager(trigger, {
                    noRefresh: noRefresh,
                    copy: false,
                    prepareCallback: function ()
                    {
                        try
                        {
                            _refreshingWindowContent = true;
                            _fwdc.pauseActivityCheck();
                            // Calling this here causes early destruction of elements that might stay on screen.
                            //_fwdc.destroyRichElements(true);
                            _closeModals();
                            FWDC.hideViewMenus();
                            _fwdc.hideToolTips();
                            _fwdc.closeComboboxes();
                        }
                        catch (ignore) { }
                        finally
                        {
                            _refreshingWindowContent = false;
                        }
                    },
                    busy: busy,
                    switchingBack: switchingBack,
                    lightRefresh: lightRefresh
                });
            }

            _fwdc.refreshWindowContent = function (targetVerLast, targetVerLastSource, busy, trigger, lightRefresh)
            {
                _refreshWindowContent(trigger || "RefreshWindowContent", targetVerLast, targetVerLastSource, busy, false, false, lightRefresh);
            };

            _fwdc.switchManager = function (targetVerLast, targetVerLastSource, switchingBack)
            {
                _refreshWindowContent("SwitchManager", targetVerLast, targetVerLastSource, true, switchingBack === "true");
            };

            _fwdc.redirectHome = function ()
            {
                window.location = "../";
            };

            _fwdc.blockTransitionClick = function (event)
            {
                _fwdc._warn("Blocked Transition Click:", event);
                return _fwdc.stopEvent(event);
            };

            _fwdc.onMnemonicKeyDown = function (event, target)
            {
                if (event.altKey && event.which >= 65 && event.which <= 90)
                {
                    var result;
                    var $clickTarget;

                    var $accessKeys;

                    $(_fwdc.topDialog() || target || event.currentTarget || event.target).find("span.Mnemonic").each(function ()
                    {
                        var $this = $(this);
                        if ($this.is(":visible"))
                        {
                            var chr = $this.text().toLowerCase();
                            if (chr === String.fromCharCode(event.which).toLowerCase())
                            {
                                var $link = $this.closest("a,button,.FastClickable");
                                if ($link && $link.length && !$link.hasClass("AccessKeyRemoved"))
                                {
                                    $clickTarget = $link;
                                    result = $clickTarget;

                                    // Disable accesskeys to prevent browsers from continuing to execute them in the background.
                                    // Use block access mode instead of disabling so the accesskey attribute is preserved.
                                    $accessKeys = _fwdc.blockAccessKeys(true);
                                }
                                return false;
                            }
                        }
                    });

                    if (result)
                    {
                        //_fwdc._log("onMnemonicKeyDown: ", _fwdc.now(), event, $clickTarget, "Dialog:", $clickTarget.closest(".ui-dialog"), "Class: " + $clickTarget.closest(".ui-dialog").attr("class"));

                        _fwdc.stopEvent(event);
                        event.preventDefault();
                        event.stopPropagation();
                        event.stopImmediatePropagation();
                        if (event.originalEvent && event.originalEvent.cancelBubble)
                        {
                            event.originalEvent.cancelBubble = true;
                        }

                        _fwdc.commitEdits("onMnemonicKeyDown");
                        $clickTarget.focus();

                        _fwdc.busy.done(function ()
                        {
                            _fwdc.unblockAccessKeys($accessKeys);
                            if ($clickTarget.inDom())
                            {
                                $clickTarget.click();
                            }
                        }, true);

                        return true;
                    }
                }
            };

            _fwdc.onBlockedMnemonicClick = function (event)
            {
                _fwdc.stopEvent(event);
                event.preventDefault();
                event.stopPropagation();
                event.stopImmediatePropagation();
                if (event.originalEvent && event.originalEvent.cancelBubble)
                {
                    event.originalEvent.cancelBubble = true;
                }
                return false;
            };

            _fwdc.stopEvent = function (event)
            {
                if (event)
                {
                    event = $.event.fix(event);

                    event.preventDefault();
                    event.stopPropagation();
                    event.stopImmediatePropagation();
                }
            };

            _fwdc.transitionStopEvent = function (event)
            {
                if ($(event.target).closest(".FastTransitioning").length)
                {
                    _fwdc._warn("Blocked Transition Event:", event);
                    _fwdc.stopEvent(event);
                    return true;
                }

                return false;
            };

            var _textConverter;

            _fwdc.textToHtml = function (text)
            {
                _textConverter = _textConverter || $("<div></div>");
                return _textConverter.text(text).html();
            };

            _fwdc.htmlToText = function (html)
            {
                _textConverter = _textConverter || $("<div></div>");
                return _textConverter.html(html).text();
            };

            _fwdc.destroyRichElements = function (all, $container)
            {
                _fwdc.stopAutoRefresh(null, all || $container);

                $container = $container || (all ? _fwdc.$body() : _fwdc.currentDocumentContainer());

                $container.find(".DocRichTextBox.HasCKEditor").each(function ()
                {
                    try
                    {
                        var editor = $(this).ckeditorGet();
                        editor.destroy(true);
                    }
                    catch (ex) { }
                });

                $container.find(".FastCameraInputVideoPlaying").each(function ()
                {
                    try
                    {
                        var stream = this.srcObject;
                        if (stream && stream.getTracks()[0])
                        {
                            stream.getTracks()[0].stop();
                            this.load();
                        }

                        $(this).removeClass("FastCameraInputVideoPlaying");
                    }
                    catch (ex)
                    {
                        _fwdc._warn("Error destroying stream: ", ex);
                    }
                });

                var $cmFields = $container.findElementsByClassName("FastCodeMirrorBox");
                $cmFields.each(function (index, cmField)
                {
                    var $field = $(cmField);
                    var cm = $field.data("fast-code-mirror-editor");
                    if (cm)
                    {
                        if (cm.state.completionActive
                            && cm.state.completionActive.widget)
                        {
                            cm.state.completionActive.widget.close();
                        }

                        cm.toTextArea();
                        $field.data("fast-code-mirror-editor", null);
                    }
                });

                if (_fwdc.FusionCharts)
                {
                    $container.find(".DocTableGraphContainerFC").each(function ()
                    {
                        try
                        {
                            var chart = $(this).data("fast-fc");
                            if (chart)
                            {
                                $(this).data("fast-fc", null);
                                chart.dispose();
                            }
                        }
                        catch (ex) { }
                    });
                }

                if (_googleMapsInitialized)
                {
                    $container.find(".DocMap.HasMap").each(function ()
                    {
                        if ($(this).data("fast-map-id"))
                        {
                            _destroyMap($(this).data("fast-map-id"));
                        }
                    });
                }

                // Cleaning this element up quicker would be nice, but it has a problem that it can be triggeredby other modal logic,
                // and create a scenario where it's removed before it's actually used.
                //_fwdc.supportElementsContainer().find(".TemporaryUploadForm").remove();
            };

            _fwdc.managerContainers = {};
            _fwdc.managerContainerIds = [];
            _fwdc.documentContainers = {};
            _fwdc.documentContainerIds = [];

            _fwdc.getManagerContainerId = function ($container)
            {
                return $container.data("manager-container");
            };

            _fwdc.getDocContainerId = function ($container)
            {
                var id = $container.data("document-container");

                return id[0] * 1000 + id[1];
            };

            _fwdc.setDocContainer = function ($container, id)
            {
                id = (id === undefined) ? _fwdc.getDocContainerId($container) : id;

                $container.children(".DocumentForm").on('scroll.doccontainer', _onStructureScroll);

                _fwdc.documentContainers[id] = $container;

                if (_fwdc.documentContainerIds.indexOf(id) < 0)
                {
                    _fwdc.documentContainerIds.push(id);
                }
            };

            _fwdc.clearDocContainer = function ($container, id)
            {
                id = (id === undefined) ? _fwdc.getDocContainerId($container) : id;
                if ($container.equals(_fwdc.documentContainers[id]))
                {
                    $container.off(".doccontainer");
                    delete _fwdc.documentContainers[id];

                    var idIndex = _fwdc.documentContainerIds.indexOf(id);
                    if (idIndex > -1)
                    {
                        _fwdc.documentContainerIds.splice(idIndex, 1);
                    }

                    return true;
                }
                else
                {
                    _fwdc._warn("clearDocContainer failed.  ID: ", id, " Current: ", _fwdc.managerContainers[id], " Clearing: ", $container);
                }

                return false;
            };

            _fwdc.currentDocumentContainer = function (id)
            {
                if (id === undefined)
                {
                    id = _fwdc.documentContainerIds[_fwdc.documentContainerIds.length - 1];
                }

                return (id !== undefined && _fwdc.documentContainers[id]) || $();
            };

            _fwdc.setManagerContainer = function ($container, id)
            {
                if ($container && $container.length > 1)
                {
                    $container = $container.filter(".ManagerContainer");
                }

                $container.findElementsByClassName("ControlContainer").on('scroll.managercontainer', _onStructureScroll);

                id = (id === undefined) ? _fwdc.getManagerContainerId($container) : id;

                _fwdc.managerContainers[id] = $container;

                if (_fwdc.managerContainerIds.indexOf(id) < 0)
                {
                    _fwdc.managerContainerIds.push(id);
                }

                var $docContainer = $container.find(".DocumentContainer").first();
                if ($docContainer.length)
                {
                    _fwdc.setDocContainer($docContainer);
                }
            };

            _fwdc.clearManagerContainer = function ($container, id)
            {
                id = (id === undefined) ? _fwdc.getManagerContainerId($container) : id;
                if ($container.equals(_fwdc.managerContainers[id]))
                {
                    $container.off(".managercontainer");
                    delete _fwdc.managerContainers[id];

                    var idIndex = _fwdc.managerContainerIds.indexOf(id);
                    if (idIndex > -1)
                    {
                        _fwdc.managerContainerIds.splice(idIndex, 1);
                    }

                    var $docContainer = $container.find(".DocumentContainer").first();
                    if ($docContainer.length)
                    {
                        _fwdc.clearDocContainer($docContainer);
                    }

                    return true;
                }
                else
                {
                    _fwdc._warn("clearManagerContainer failed.  ID: ", id, " Current: ", _fwdc.managerContainers[id], " Clearing: ", $container);
                }

                return false;
            };

            _fwdc.currentManagerContainer = function (id)
            {
                //return $("#MANAGER_CONTAINER__" + (id === undefined ? _fwdc.modalManagerCount : id));
                if (id === undefined)
                {
                    id = _fwdc.managerContainerIds[_fwdc.managerContainerIds.length - 1];
                }

                return (id !== undefined && _fwdc.managerContainers[id]) || $();
            };

            _fwdc.parentDocumentContainer = function ($field)
            {
                return $field && $field.closest(_fwdc.selectors.documentContainer);
            };

            _fwdc.containerZIndex = function ($element)
            {
                var $container = $element.closest(".ui-dialog");
                if ($container.length) { return $container.css("zIndex"); }

                return 0;
            };

            /*function autoHeightButton($element)
            {
                var $parent = $element.parent();
                return _fwdc.appVersion >= 10 && ($parent.hasClass("FGIC") || $parent.hasClass("ViewFieldWrapper"));
            }*/

            _fwdc.setupCheckboxButtons = function ($container)
            {
                var updated = false;
                ($container || _fwdc.currentDocumentContainer())
                    .findElementsByAnyClassName("FastCheckboxButton,FastRadioButtonButton")
                    .each(function ()
                    {
                        var $input = $(this);
                        //var radio = $input.is("input.FastRadioButtonButton");
                        // Visible check can cause slowness due to style recalculation.  Should not be necessary now that no measurement happens.
                        if (!$input.data("uiCheckboxradio") /*&& $input.is(":visible")*/)
                        {
                            updated = true;
                            //var id = $input.attr("id");
                            //_wrapUiButtonText($input.next("label"), "caption2_" + id);

                            var $button = $input.checkboxradio({ wrapLabel: true, appendToggle: true }).checkboxradio("widget");

                            $button
                                .attr("title", $input.attr("title"));
                            //.append('<div class="FastToggle"></div>');
                        }
                    });

                return updated;
            };

            _fwdc.setupButtonSets = function ($container, $field, forceSetup)
            {
                var created = false;
                var setup;

                ($field || ($container || _fwdc.currentDocumentContainer()).findElementsByClassName("FastComboButtonSet"))
                    .each(function ()
                    {
                        var $input = $(this);

                        if (forceSetup || !$input.hasClass("FastComboButtonSetSelector"))
                        {
                            setup = true;

                            $input
                                .addClass("FastComboButtonSetSelector")
                                .findElementsByClassName("FastComboButtonSetButtons")
                                .append('<span role="presentation" class="SelectorUnderline ComboSelectorUnderline Init" data-current-selector=".FastComboButtonRadio:checked + .FastComboButton" role="presentation"></span>');
                            created = true;
                        }
                    });

                if (setup)
                {
                    _fwdc.setTimeout("setupButtonSets.updatSelectorUnderlines", function ()
                    {
                        _fwdc.updateSelectorUnderlines($container);
                    });
                }

                return created;
            };

            _fwdc.setButtonSetButtons = function ($field, buttons)
            {
                $field.children(".FastComboButtonSetButtons").html(buttons);
                _fwdc.setupButtonSets(null, $field, true);
            };

            _fwdc.resizeButtonSets = function ($field)
            {
            };

            _fwdc.sortTable = function (event, column, docId, linkId)
            {
                if (_busy()) { return false; }
                _fwdc.commitEdits("SortTable");

                event = $.event.fix(event);

                var data =
                {
                    "Append": !!event.ctrlKey,
                    "Outline": !!event.shiftKey
                };

                if (linkId)
                {
                    data.LASTFOCUSFIELD__ = linkId;
                }

                FWDC.setProperties(docId || "", "Sort", column, data);
            };

            var _captchaApi;

            var _grecaptchaInit;
            var _grecaptchaEnterprise;
            var _grecaptchaReady = $.Callbacks("once unique memory");
            var _grecaptchaApi;

            _fwdc.setupRecaptcha = function ($container, $fields, callback)
            {
                if (!_grecaptchaInit)
                {
                    _grecaptchaInit = true;

                    window.onGRecaptchaReady = _grecaptchaReady.fire;

                    _grecaptchaEnterprise = !!$fields.attr("data-captchaenterprise");

                    if (_grecaptchaEnterprise)
                    {
                        _fwdc.loadScripts(["https://www.google.com/recaptcha/enterprise.js?onload=onGRecaptchaReady&render=explicit"]);
                    }
                    else
                    {
                        _fwdc.loadScripts(["https://www.google.com/recaptcha/api.js?onload=onGRecaptchaReady&render=explicit"]);
                    }

                    _grecaptchaReady.add(function ()
                    {
                        _captchaApi = _grecaptchaApi = _grecaptchaEnterprise ? window.grecaptcha.enterprise : window.grecaptcha;
                    });
                }

                _grecaptchaReady.add(function ()
                {
                    var captchas = $fields.map(function ()
                    {
                        var $this = $(this);
                        if ($this.hasClass("FastSetupCaptcha"))
                        {
                            if ($this.hasClass("FastCaptchaPlaceholderWrapper"))
                            {
                                if ($this.outerWidth() > 0 && $this.outerWidth() < 304)
                                {
                                    $this.addClass("FastCaptchaPlaceholderWrapperCompact");
                                }

                                return -1;
                            }
                            else
                            {
                                var options = { "sitekey": $this.attr("data-sitekey"), "action": $this.attr("data-captchaaction") };

                                /** 304 based on width of non-compact recaptcha widget **/
                                if ($this.outerWidth() > 0 && $this.outerWidth() < 304)
                                {
                                    options.size = "compact";
                                }

                                if ($this.attr("data-tabindex"))
                                {
                                    options.tabindex = $this.attr("data-tabindex");
                                }

                                if ($this.hasClass("FastCaptchaField"))
                                {
                                    //var verLast = _fwdc.fastVerLast;
                                    options.callback = function (recaptchaResponse)
                                    {
                                        _fwdc.busy.done(function ()
                                        {
                                            var id = $this.attr("id");
                                            var $current = _fwdc.formField($this.attr("id"), true);

                                            if (!id || !$current || !$current.hasClass("FastCaptchaField"))
                                            {
                                                _fwdc._warn("reCAPTCHA Callback found a mismatch.  Refreshing to ensure page is up to date.");
                                                _fwdc.refreshPage("RecaptchaCallbackMismatch");
                                                return;
                                            }

                                            _fwdc.busy.done(function ()
                                            {
                                                var recalcData = {};
                                                recalcData[id] = recaptchaResponse;
                                                recalcData = _fwdc.getDocPostParameters(recalcData, "input[type='hidden']");

                                                _recalc({ async: true, 'data': recalcData, 'source': $this, 'trigger': 'RecaptchaCallback' });
                                            });
                                        });
                                    };
                                }

                                var captchaId = _grecaptchaApi.render(this, options);

                                $this.data("fast-recaptcha-id", captchaId).removeClass("FastSetupCaptcha");

                                return captchaId;
                            }
                        }
                        else
                        {
                            return $this.data("fast-recaptcha-id");
                        }
                    }).get();

                    if (callback)
                    {
                        callback(captchas);
                    }
                });

                return true;
            };

            var _hCaptchaInit;
            var _hCaptchaReady = $.Callbacks("once unique memory");
            var _hcaptchaApi;

            _fwdc.setupHCaptcha = function ($container, $fields, callback)
            {
                if (!_hCaptchaInit)
                {
                    _hCaptchaInit = true;

                    window.onHCaptchaReady = _hCaptchaReady.fire;

                    _fwdc.loadScripts(["https://js.hcaptcha.com/1/api.js?onload=onHCaptchaReady&render=explicit"]);

                    _hCaptchaReady.add(function ()
                    {
                        _captchaApi = _hcaptchaApi = window.hcaptcha;
                    });
                }

                _hCaptchaReady.add(function setupHCaptchaInternal()
                {
                    var captchas = $fields.map(function ()
                    {
                        var $this = $(this);
                        if ($this.hasClass("FastSetupCaptcha"))
                        {
                            if ($this.hasClass("FastCaptchaPlaceholderWrapper"))
                            {
                                if ($this.outerWidth() > 0 && $this.outerWidth() < 304)
                                {
                                    $this.addClass("FastCaptchaPlaceholderWrapperCompact");
                                }

                                return -1;
                            }
                            else
                            {
                                var options = { "sitekey": $this.attr("data-sitekey"), "action": $this.attr("data-captchaaction") };

                                /** 304 based on width of non-compact recaptcha widget **/
                                if ($this.outerWidth() > 0 && $this.outerWidth() < 304)
                                {
                                    options.size = "compact";
                                }

                                if ($this.attr("data-tabindex"))
                                {
                                    options.tabindex = $this.attr("data-tabindex");
                                }

                                if ($this.hasClass("FastCaptchaField"))
                                {
                                    //var verLast = _fwdc.fastVerLast;
                                    options.callback = function HCaptchaCallback(recaptchaResponse)
                                    {
                                        _fwdc.busy.done(function ()
                                        {
                                            var id = $this.attr("id");
                                            var $current = _fwdc.formField($this.attr("id"), true);

                                            if (!id || !$current || !$current.hasClass("FastCaptchaField"))
                                            {
                                                _fwdc._warn("hCaptcha Callback found a mismatch.  Refreshing to ensure page is up to date.");
                                                _fwdc.refreshPage("HCaptchaCallbackMismatch");
                                                return;
                                            }

                                            _fwdc.busy.done(function ()
                                            {
                                                var recalcData = {};
                                                recalcData[id] = recaptchaResponse;
                                                recalcData = _fwdc.getDocPostParameters(recalcData, "input[type='hidden']");

                                                _recalc({ async: true, 'data': recalcData, 'source': $this, 'trigger': 'HCaptchaCallback' });
                                            });
                                        });
                                    };
                                }

                                var captchaId = _hcaptchaApi.render(this, options);

                                $this.data("fast-hcaptcha-id", captchaId).removeClass("FastSetupCaptcha");

                                return captchaId;
                            }
                        }
                        else
                        {
                            return $this.data("fast-hcaptcha-id");
                        }
                    }).get();

                    if (callback)
                    {
                        callback(captchas);
                    }
                });

                return true;
            };

            _fwdc.setupCaptchas = function ($container, $fields, callback)
            {
                $fields = ($fields || ($container || _fwdc.currentDocumentContainer()).find(".FastSetupCaptcha"));

                if (!$fields || !$fields.length)
                {
                    return false;
                }

                switch (_fwdc.captchaType)
                {
                    case "recaptcha":
                        return _fwdc.setupRecaptcha($container, $fields, callback);

                    case "hcaptcha":
                        return _fwdc.setupHCaptcha($container, $fields, callback);

                    case "":
                    case null:
                        return false;

                    default:
                        _fwdc._error("captchaType not supported: [" + _fwdc.captchaType + "]");
                        return false;
                }
            };

            var _pushInitialized;
            var _pushTokens;
            var _signalrLoaded;
            var _pushConnection;

            // cht is a legacy handler for old gaCht data format.
            _fwdc.pushHandlers = { Chat: _handleChatPush };

            _fwdc.NotificationStatus = {
                NotStarted: 1,
                Connecting: 2,
                Connected: 3,
                Error: 4
            };

            var _notificationStatus = _fwdc.NotificationStatus.NotStarted;

            _fwdc.updateNotificationStatus = function (status)
            {
                if (status !== undefined)
                {
                    _notificationStatus = status;
                }

                var $elements = $(".SidebarUnreadNotifications");

                $elements.removeClass("NotificationStatusNotStarted NotificationStatusConnecting NotificationStatusConnected NotificationStatusError");

                switch (_notificationStatus)
                {
                    case _fwdc.NotificationStatus.NotStarted:
                        break;
                    case _fwdc.NotificationStatus.Connecting:
                        $elements.addClass("NotificationStatusConnecting");
                        break;
                    case _fwdc.NotificationStatus.Connected:
                        $elements.addClass("NotificationStatusConnected");
                        break;
                    case _fwdc.NotificationStatus.Error:
                        $elements.addClass("NotificationStatusError");
                        break;
                }

                _fwdc.updateChatConnection(_notificationStatus);

            };

            _fwdc.updateChatConnection = function (connectionStatus)
            {
                var $chatStatus = $($.parseHTML('<div class="ChatStatus"></div>'));
                var $chatStatusDisplay = $($.parseHTML('<div class="FastStatusLabel FastStatusColor ChatStatusDisplay"></div>'));

                var $chatEntry = $.findElementsByClassName("ChatEntryWrapper");
                $chatEntry.childrenWithClass("ChatStatus").remove();

                var $chatEntryContainer = $.findElementsByClassName("ChatEntryContainer");
                $chatEntryContainer.find("input.ChatEntry").removeAttr("disabled");
                $chatEntryContainer.find("input.ChatEntry").removeClass("FieldDisabled FieldEnabled");
                $chatEntryContainer.find("button.ChatSend").removeAttr("disabled");

                if (!_fwdc.tap)
                {
                    var $chatTools = $.findElementsByClassName("ChatTools");
                    $chatTools.find("button.ChatSupportView").removeAttr("disabled");
                    $chatTools.find("button.ChatInvite").removeAttr("disabled");
                    $chatTools.find("button.ChatSendLibrary").removeAttr("disabled");
                    $chatTools.find("button.ChatAttach").removeAttr("disabled");
                    $chatTools.find("button.ChatRequestForm").removeAttr("disabled");
                    $chatTools.find("button.ChatReqAttach").removeAttr("disabled");
                    $chatTools.find("button.ChatReqShare").removeAttr("disabled");
                    //$chatTools.find("button.ChatAddNote").removeAttr("disabled");
                }

                switch (connectionStatus)
                {
                    case _fwdc.NotificationStatus.NotStarted:
                    case _fwdc.NotificationStatus.Connecting:
                        $chatStatusDisplay.text(_fwdc.getDecode("Chat"));
                        $chatStatusDisplay.addClass("ChatConnecting");
                        $chatStatus.addClass("Hidden");

                        $chatEntryContainer.find("input.ChatEntry").addClass("FieldEnabled");
                        break;

                    case _fwdc.NotificationStatus.Connected:
                        $chatStatusDisplay.text(_fwdc.getDecode("Chat"));
                        $chatStatusDisplay.addClass("ChatConnected");
                        $chatStatus.addClass("Hidden");

                        $chatEntryContainer.find("input.ChatEntry").addClass("FieldEnabled");
                        break;

                    case _fwdc.NotificationStatus.Error:
                        $chatStatusDisplay.text(_fwdc.getDecode("ChatDisonnectStatus"));
                        $chatStatusDisplay.addClass("FastStatusColorBad");
                        $chatStatus.append($($.parseHTML('<div class="ChatConnectSpinner FIC RotateIconEaseInOut FastStatusColorBad"></div>')));

                        $chatEntryContainer.find("input.ChatEntry").attr("disabled", "disabled");
                        $chatEntryContainer.find("input.ChatEntry").addClass("FieldDisabled");
                        $chatEntryContainer.find("button.ChatSend").attr("disabled", "disabled");

                        if (!_fwdc.tap)
                        {
                            $chatTools.find("button.ChatSupportView").attr("disabled", "disabled");
                            $chatTools.find("button.ChatInvite").attr("disabled", "disabled");
                            $chatTools.find("button.ChatSendLibrary").attr("disabled", "disabled");
                            $chatTools.find("button.ChatAttach").attr("disabled", "disabled");
                            $chatTools.find("button.ChatRequestForm").attr("disabled", "disabled");
                            $chatTools.find("button.ChatReqAttach").attr("disabled", "disabled");
                            $chatTools.find("button.ChatReqShare").attr("disabled", "disabled");
                            //$chatTools.find("button.ChatAddNote").attr("disabled", "disabled");                            
                        }

                        break;
                }

                $chatStatus.prepend($chatStatusDisplay);

                $chatEntry.prepend($chatStatus);
            }

            _fwdc.connectPush = function (options)
            {
                if (_fwdc.exporting) { return; }

                try
                {
                    _fwdc.pushOptions = options;

                    if (options.managerLastNotification)
                    {
                        _fwdc.managerLastNotification = options.managerLastNotification;
                        options.lastUpdated = null;
                    }

                    if (options.commandsSince)
                    {
                        _fwdc.commandsSince = options.commandsSince;
                    }

                    //var tokens = options.token.tokens.join(",");
                    var tokens = _fwdc.language;
                    for (var ii = 0; ii < options.token.length; ++ii)
                    {
                        tokens += "/";
                        tokens += options.token[ii].type;
                        tokens += "/";
                        tokens += options.token[ii].token;
                    }

                    if (_pushTokens && _pushTokens !== tokens)
                    {
                        _fwdc.disconnectPush();
                    }
                    _pushTokens = tokens;

                    if (!_pushInitialized)
                    {
                        _pushInitialized = true;
                    }

                    if (!_fwdc.pushActive && _pushTokens)
                    {
                        _fwdc.updateNotificationStatus(_fwdc.NotificationStatus.Connecting);
                        _fwdc.pushActive = true;
                        _fwdc.pushToken = _generateS4() + "-" + _generateS4() + "-" + _generateS4();

                        if (!_signalrLoaded)
                        {
                            _signalrLoaded = $.Callbacks("once unique memory");

                            _fwdc.loadScripts(['Script/SignalR/signalr.min.js'], function ()
                            {
                                _signalrLoaded.fire();
                            });
                        }

                        _signalrLoaded.add(function ()
                        {
                            function getRetryDelay(reconnections)
                            {
                                return reconnections === 0 ? 0 : (5000 * reconnections * reconnections);
                            }

                            _pushConnection = new signalR.HubConnectionBuilder()
                                .withUrl("../Push?FastPushToken=" + _fwdc.pushToken, {
                                    logger: 3
                                    //logger: 0,
                                    //logMessageContent: true
                                })
                                .withAutomaticReconnect({
                                    nextRetryDelayInMilliseconds: function (retryContext)
                                    {
                                        var previousRetryCount = retryContext.previousRetryCount;
                                        return getRetryDelay(previousRetryCount);
                                    }
                                })
                                .build();

                            // 60 Second Keepalive Interval + 2.5x timeout
                            _pushConnection.keepAliveIntervalInMilliseconds = 60 * 1000;
                            _pushConnection.serverTimeoutInMilliseconds = 60 * 10000 * 2.5;

                            var reconnectCounter = 0;

                            function startConnection()
                            {
                                if (reconnectCounter > 0)
                                {
                                    _fwdc._log("Reconnecting Push (Attempt " + reconnectCounter + ")...");
                                }

                                _pushConnection
                                    .start()
                                    .then(function ()
                                    {
                                        _fwdc.pushActive = true;
                                        //_fwdc._log("Push connection activated");
                                        return _fwdc.registerPush();
                                    })
                                    .then(function ()
                                    {
                                        reconnectCounter = 0;
                                        //_fwdc._log("startConnection success?");                                        

                                        if (options.conversations)
                                        {
                                            _fwdc.initializingChat = true;
                                            for (var ii = 0; ii < options.conversations.length; ii++)
                                            {
                                                _fwdc.getConversation(options.conversations[ii], false, true, options);
                                            }

                                            _fwdc.initializingChat = false;
                                            _fwdc.showChatDialog();

                                            options.conversations = null;
                                        }

                                        _fwdc.updateNotificationStatus(_fwdc.NotificationStatus.Connected);
                                    })
                                    .catch(function (ex)
                                    {
                                        _fwdc.updateNotificationStatus(_fwdc.NotificationStatus.Error);
                                        _fwdc._error("Error creating Push connection:", ex);
                                        if (_fwdc.pushActive && reconnectCounter < 10)
                                        {
                                            _fwdc.setTimeout(
                                                "Reconnect Push Connection",
                                                startConnection,
                                                getRetryDelay(reconnectCounter));
                                        }
                                        reconnectCounter++;
                                    });
                            }

                            $.each(_fwdc.pushHandlers, function (type, handler)
                            {
                                //_fwdc._log("Registered push handler [" + type + "]: ", handler);
                                _pushConnection.on(type, handler);
                            });

                            _pushConnection.onreconnecting(function (error)
                            {
                                _fwdc.updateNotificationStatus(_fwdc.NotificationStatus.Error);
                                _fwdc._error("Reconnecting Push. Error: [" + error + "]");
                            });

                            _pushConnection.onreconnected(function ()
                            {
                                _fwdc.updateNotificationStatus(_fwdc.NotificationStatus.Connected);
                                _fwdc._log("Reconnected Push.");
                                _fwdc
                                    .registerPush()
                                    .catch(function (ex)
                                    {
                                        _fwdc._error("Error re-registering Push connection:", ex);
                                        _fwdc.disconnectPush();

                                        reconnectCounter++;

                                        _fwdc.setTimeout(
                                            "Reconnect Push Connection",
                                            startConnection,
                                            getRetryDelay(reconnectCounter));
                                    });
                            });

                            //_pushConnection.onclosed(function (ex)
                            //{
                            //    if (ex)
                            //    {
                            //        _fwdc._warn("Push connection closed with error: ", ex);
                            //    }
                            //    else
                            //    {
                            //        _fwdc._log("Push connection closed.");
                            //    }
                            //});

                            startConnection();


                            //_pushRequest = _fwdc.ajax({
                            //    url: 'Push',
                            //    busy: false,
                            //    commitEdits: false,
                            //    fastRequest: false,
                            //    data: $.param({ WindowId: _fwdc.getFastWindowName(), Token: JSON.stringify(options.token) }),
                            //    headers: { 'Fast-Request-Timeout': '250000' },
                            //    timeout: 240000,
                            //    ignoreAutoRefresh: true,
                            //    error: function (request, status, error)
                            //    {
                            //        //_fwdc._log("Error in push response: " + status, request);
                            //        if (request.status !== 403)
                            //        {
                            //            setTimeout(function () { FWDC.getPushData(options); }, status === "timeout" ? 1 : 5000);
                            //        }
                            //        return false;
                            //    },
                            //    success: function (data, status, request)
                            //    {
                            //        _fwdc.handlePushData(data, options);
                            //    },
                            //    complete: function ()
                            //    {
                            //        _fwdc.pushActive = false;
                            //        _pushRequest = null;
                            //    }
                            //});
                        });

                    }
                }
                catch (ex)
                {
                    _fwdc._error(ex);
                }
            };

            _fwdc.registerPush = function ()
            {
                //_fwdc._log("Starting push registration");
                return _pushConnection
                    .invoke("register", _fwdc.language, _fwdc.pushOptions.token)
                    //.then(function ()
                    //{
                    //    _fwdc._log("Registered tokens: ", _fwdc.pushOptions.token.tokens);
                    //})
                    ;
            };

            _fwdc.disconnectPush = function ()
            {
                if (_fwdc.pushActive)
                {
                    if (_pushConnection)
                    {
                        //_fwdc._log("Closing existing push connection.");
                        _pushConnection
                            .stop()
                            //.then(function ()
                            //{
                            //    //_fwdc._log("Push connection stopped.");
                            //})
                            .catch(function (error)
                            {
                                _fwdc._error("Error stopping push connection:", error);
                            });
                        _pushConnection = null;
                    }

                    _fwdc.pushActive = false;
                }
            };


            //_fwdc.pushHandlers = { cht: _handleChatPush };

            //_fwdc.pausePush = function ()
            //{
            //    if (_pushRequest)
            //    {
            //        _pushRequest.abort();
            //        _pushRequest = null;
            //        _fwdc.pollingNotifications = false;
            //    }
            //};

            //_fwdc.resumePush = function ()
            //{
            //    if (_fwdc.pushOptions)
            //    {
            //        FWDC.getPushData(_fwdc.pushOptions);
            //    }
            //};


            //var _fwdc.chatConversations = _fwdc.chatConversations;

            _fwdc.sendChat = function (event, conversationToken, text)
            {
                return _fwdc.setPropertiesInternalJson("MANAGER__", "SendChat", conversationToken, false, { text: text }, function (response)
                {
                    if (!response.success)
                    {
                        _fwdc._warn("Sending chat failed!");
                    }
                });
            };

            _fwdc.showChatDialog = function ()
            {
                if (_fwdc.$chatDialog)
                {
                    var chatSettings = _fwdc.$chatDialog.chatSettings;
                    var select = -1;
                    var conversationIndex = -1;
                    _fwdc.$chatDialog.removeClass("ChatInitializing").closest(".ui-dialog").css("display", "");
                    $.each(_fwdc.chatConversations, function (conversationId, conversation)
                    {
                        if (conversation && conversation.$widget)
                        {
                            conversationIndex++;
                            if (chatSettings && chatSettings.currentConversationId && (conversationId === chatSettings.currentConversationId))
                            {
                                select = conversationIndex;
                            }
                            conversation.$chatArea.scrollTop(1000000000);
                        }
                    });

                    _fwdc.$chatDialog.refreshTabs(select);

                }
            };

            _fwdc.minimizeChatDialog = function ()
            {
                if (_fwdc.$chatDialog && _fwdc.screenWidth == _fwdc.ScreenWidths.Small)
                {
                    _fwdc.hideChats();
                }

            };

            var _chatUpdateLastActivityHandle;
            function _chatUpdateLastActivity()
            {
                //Do this in a get so it doesn't count as session activity - only meant to notify the server to make an update
                //Otherwise, this is causing constant activity so a session with a chat window would never go idle
                _fwdc.getData({
                    control: "MANAGER__",
                    type: "ChatUpdateLastActive",
                    target: null,
                    dataType: "json",
                    busy: false,
                    // We don't need session ver last info - whatever's current will work
                    ignoreSessionData: true,
                    // Don't send up manager/doc modal IDs, as these do not need to be validated
                    managerModalId: -1,
                    docModalId: -1
                });

            }

            /**
             * Adds a queued chat message to the chat window.
             * @param {string} conversationId Id of the conversation to add the message to
             * @param {string} type Type of message to add
             * @param {jQuery} $chatWrapper Chat wrapper object to add
             * @param {boolean} loaded If true, the message has already been loaded into the chat window and is simply being readded due to a screen refresh. If false, the message is new to the chat window.
             */
            _fwdc.displayChatMessage = function (conversationId, type, $chatWrapper, loaded)
            {
                var conversation = _fwdc.getConversation(conversationId);
                var $chatArea = conversation.$chatArea;
                var $chatMessages = $chatArea.children();
                var nextFrom = "";

                $chatArea.children(".ChatReport").remove();
                if ($chatMessages.length <= 1)
                {
                    if ($chatWrapper.attr("date"))
                    {
                        var $chatDate = $($.parseHTML('<div class="ChatDate"></div>'));
                        $chatDate.text($chatWrapper.attr("date"));
                        $chatArea.append($chatDate);
                    }

                    $chatArea.append($chatWrapper);
                }
                else
                {
                    var insertIndex = 0;
                    var messageInserted = false;
                    for (var i = $chatMessages.length - 1; i > 0; i--)
                    {
                        if ($($chatMessages[i]).attr("when") && parseInt($($chatMessages[i]).attr("when")) <= parseInt($chatWrapper.attr("when")))
                        {
                            $chatWrapper.insertAfter($chatMessages[i]);
                            insertIndex = i + 1;
                            messageInserted = true;

                            if ($chatWrapper.attr("date") && $($chatMessages[i]).attr("date")
                                && Date.parse($chatWrapper.attr("date")) != Date.parse($($chatMessages[i]).attr("date")))
                            {
                                var $chatDate = $($.parseHTML('<div class="ChatDate"></div>'));
                                $chatDate.text($chatWrapper.attr("date"));
                                $chatDate.insertAfter($chatMessages[i]);
                            }
                            break;
                        }

                        var $chatSender = $($chatMessages[i]).findElementsByClassName("ChatSender");
                        if ($chatSender.length > 0) nextFrom = $chatSender.text();
                    }

                    if (!messageInserted)
                    {
                        $chatWrapper.insertBefore($chatMessages[0]);
                    }

                    if (insertIndex < $chatMessages.length - 1)
                    {
                        var $newChatSender = $($chatWrapper[0]).findElementsByClassName("ChatSender");
                        if ($newChatSender.length > 0)
                        {
                            //If the message that follows is a different sender, remove ChatRepeatSender class from next message
                            if ($newChatSender.text() != nextFrom)
                            {
                                $chatMessages[insertIndex + 1].classList.remove("ChatRepeatSender");
                            }

                            //If the message prior is from the same sender, add ChatRepeatSender class to new message
                            if (insertIndex > 0)
                            {
                                var $priorChatSender = $($chatMessages[insertIndex - 1]).findElementsByClassName("ChatSender");
                                if ($priorChatSender.length > 0 && $priorChatSender.text() === $newChatSender.text())
                                {
                                    $chatWrapper[0].classList.add("ChatRepeatSender");
                                }
                            }
                        }
                    }
                }

                if (!loaded)
                {
                    $chatWrapper.addClass("NewMessage");
                }

                if (_fwdc.chatMin)
                {
                    _fwdc.$body().addClass("FastChatUnreadMessages");
                }


                $chatArea.scrollTop(1000000000);

                if (!_fwdc.initializingChat && !conversation.$tab.hasClass("ui-state-active"))
                {
                    conversation.hasNewMessages = true;
                }
            };

            var _addChatHandle;
            _fwdc.queueChatMessage = function (conversationId, type, chatWrapper, loaded)
            {
                var message = [conversationId, type, chatWrapper, loaded];

                if (_fwdc.messages)
                {
                    _fwdc.messages.push(message);
                }
                else
                {
                    _fwdc.messages = new Array(message);
                }

                if (!_addChatHandle)
                {
                    _addChatHandle = window.setInterval(_addChatMessage, 1000);
                }
            };

            function _addChatMessage()
            {
                var message = _fwdc.messages.shift();

                var conversation = _fwdc.getConversation(message[0]);
                var $chatArea = conversation.$chatArea;
                var $chatTyping = $chatArea.children(".ChatTyping").remove();

                _fwdc.displayChatMessage(message[0], message[1], message[2], message[3]);


                if (_fwdc.messages && _fwdc.messages.length > 0)
                {

                    if ($chatTyping.length === 0)
                    {
                        $chatTyping = $($.parseHTML('<div class="ChatWrapper ChatTyping ChatLine ChatReceived ChatAssistant"></div>'));

                        $chatTyping.append($($.parseHTML('<div class="ChatDot ChatDotFirst"></div>')));
                        $chatTyping.append($($.parseHTML('<div class="ChatDot ChatDotSecond"></div>')));
                        $chatTyping.append($($.parseHTML('<div class="ChatDot ChatDotThird"></div>')));
                    }

                    $chatArea.append($chatTyping);


                }
                else
                {
                    if (_fwdc.tap)
                    {
                        _fwdc.setupChatReport(message[1], message[0], conversation, $chatArea);
                    }

                    window.clearInterval(_addChatHandle);
                    _addChatHandle = null;
                }

                $chatArea.scrollTop(1000000000);
            };

            var _chatConfig;
            function _getChatConfig(type)
            {
                if (!_chatConfig)
                {
                    _fwdc.ajax({
                        url: "../Config/ChatConfiguration.json" + _versionUrlSuffix + "&Language=" + encodeURIComponent(_fwdc.language),
                        method: "GET",
                        cache: false,
                        busy: false,
                        dataType: "json",
                        ignoreReady: true,
                        ignoreAutoRefresh: true,
                        fastLog: false,
                        async: false,
                        success: function (data)
                        {
                            _chatConfig = data;
                        }
                    });
                }

                return _chatConfig[type] || _chatConfig[""];
            }

            var _recentChats = {};
            function _showChatMessage(conversationId, id, timestamp, data)
            {
                var conversation = _fwdc.getConversation(conversationId, data.type === "JOIN" || data.type === "INIT");
                if (!conversation) { return false; }

                switch (data.type)
                {
                    case "INIT":
                        {
                            return true;
                        }
                    case "SYNC":
                        {
                            _fwdc.syncConversation(conversation);
                            return true;
                        }
                    case "REFRESH":
                        {
                            var conversationInfo = _fwdc.getData({
                                control: "MANAGER__",
                                type: "ConversationInfo",
                                target: conversationId,
                                dataType: "json",
                                busy: false,
                                // We don't need session ver last info - whatever's current will work
                                ignoreSessionData: true,
                                // Don't send up manager/doc modal IDs, as these do not need to be validated
                                managerModalId: -1,
                                docModalId: -1
                            });

                            if (!conversationInfo)
                            {
                                throw "Could not get conversation info: " + conversationId;
                            }

                            conversation.support = conversationInfo.support;
                            conversation.observer = conversationInfo.observer;
                            conversation.actions = conversationInfo.actions;

                            _fwdc.setupConversationWidget(conversationId, conversation);

                            return true;
                        }
                    case "EXIT":
                    case "LEAVE":
                        {
                            if (data.sent && conversation.member == data.fromId)
                            {
                                var $dialog = _fwdc.getChatDialog();
                                _fwdc.closeConversation(conversationId, conversation);
                                if ($dialog.$tabs.children().length < 1)
                                {
                                    $dialog.hideChat = false;
                                    $dialog.dialog("close");
                                    _fwdc.$chatDialog = null;

                                }

                                return true;
                            }

                            break;
                        }
                }


                var $chatLine = $($.parseHTML('<div class="ChatLine"></div>'));
                var newMessage = true;


                if (id && _recentChats[id])
                {
                    if (_recentChats[id] == data.receive) { return true; }

                    var $chatWrapper = $.findElementById(id).empty();
                    newMessage = false;
                    $chatLine.addClass("ChatEditUpdate");

                    _fwdc.setTimeout("ChatLine.ChatEditUpdate", function () { $chatLine.removeClass("ChatEditUpdate"); }, 1000);

                    _recentChats[id] = data.receive;
                }
                else
                {
                    var $chatWrapper = $($.parseHTML('<div class="ChatWrapper"></div>'));
                    _recentChats[id] = data.receive;
                }


                $chatWrapper.attr("id", id);

                var text = data.text;
                var link;

                $chatWrapper.addClass("Chat_" + data.type);

                if (conversation.observer)
                {
                    data.displayFrom = data.from;
                }
                else
                {
                    data.displayFrom = data.from ? (data.sent ? _fwdc.standardDecode("ChatYou") : data.from) : "";
                }

                var messageConfig = _getChatConfig(data.type);

                if (!messageConfig)
                {
                    _fwdc._warn("Chat type config not found: " + data.type);
                    return true;
                }

                if (messageConfig.hidden)
                {
                    return true;
                }

                if (messageConfig.class)
                {
                    $chatWrapper.addClass(messageConfig.class);
                    $chatLine.addClass(messageConfig.class);
                }

                var text = data.text;

                if (messageConfig.participantmessage)
                {
                    if (data.displayFrom)
                    {
                        var $chatSender = $($.parseHTML('<span class="ChatFrom"></span>'));

                        var $chatIconWrapper = $($.parseHTML('<div class="ChatIcon"></div>'));

                        if (data.iconFont && data.iconFontClass)
                        {
                            var $chatIcon = $($.parseHTML('<div class="FICF FICF_' + data.iconFontClass + ' FICFTAuto ChatIconBubble" role="presentation" aria-hidden="true"></div>'));
                            $chatIcon.attr("data-icon", data.iconFont);
                            //if (data.iconStatus)
                            //{
                            //    $chatIcon.addClass(_fwdc.StatusColorParse[data.iconStatus]);
                            //}

                        }
                        else if (data.iconSrc && data.iconSrcSet)
                        {
                            var $chatIcon = $($.parseHTML('<img class="FICImg FICI ChatIconBubble" role="presentation" aria-hidden="true"></img>'));
                            $chatIcon.attr("src", data.iconSrc);
                            $chatIcon.attr("srcset", data.iconSrcSet);

                        }

                        if ($chatIcon && data.iconSize)
                        {
                            $chatIcon.addClass(data.iconSize);
                            $chatIconWrapper.addClass(data.iconSize);

                            $chatIconWrapper.append($chatIcon);
                            $chatSender.append($chatIconWrapper);
                        }

                        $chatSender.append($($.parseHTML('<div class="ChatSender"></div>')).text(data.displayFrom));

                        if (!_fwdc.tap && data.time)
                        {
                            $chatSender.append($($.parseHTML('<div class="ChatSentTime"></div>')).text(data.time));
                        }

                        $chatWrapper.append($chatSender);
                    }


                    //if (data.sent)
                    //{
                    //    $chatWrapper.addClass("ChatSent");
                    //    $chatLine.addClass("ChatSent");
                    //    $chatSender.addClass("Hidden");
                    //}
                    //else if (conversation.observer && data.source)
                    //{
                    //    $chatWrapper.addClass("ChatSent");
                    //    $chatLine.addClass("ChatSent");
                    //}
                    //else
                    //{
                    //    $chatWrapper.addClass("ChatReceived");
                    //    $chatLine.addClass("ChatReceived");
                    //}

                    if (_fwdc.tap)
                    {
                        if (data.sent)
                        {
                            $chatWrapper.addClass("ChatSent");
                            $chatLine.addClass("ChatSent");
                            $chatSender.addClass("Hidden");
                        }
                        else
                        {
                            $chatWrapper.addClass("ChatReceived");
                            $chatLine.addClass("ChatReceived");
                        }
                    }
                    else
                    {
                        if (data.source)
                        {
                            $chatWrapper.addClass("ChatReceived");
                            $chatLine.addClass("ChatReceived");
                        }
                        else
                        {
                            $chatWrapper.addClass("ChatSent");
                            $chatLine.addClass("ChatSent");
                        }
                    }

                }


                if (messageConfig.participantmessage)
                {
                    if (conversation.priorFrom === data.fromId && data.fromId != 0)
                    {
                        $chatWrapper.addClass("ChatRepeatSender");
                    }
                    else
                    {
                        conversation.priorFrom = data.fromId;
                    }
                }
                else
                {
                    conversation.priorFrom = "";
                }

                if (text)
                {
                    //var validLink = false;
                    //if (data.type === "SNP")
                    //{
                    //    validLink = !_fwdc.tap;
                    //}
                    //else
                    //{
                    //    validLink = messageConfig.textlink;
                    //}

                    //var $textElement;
                    //if (validLink)
                    //{
                    //    $textElement = $($.parseHTML('<a class="ChatText ChatLink" href="#"></a>'))
                    //        .data("chatlink", { conversationId: conversationId, token: id, type: data.type });
                    //}
                    //else
                    //{
                    //    $textElement = $($.parseHTML('<span class="ChatText"></span>')).text(text);
                    //}

                    var $textElement = $($.parseHTML('<span class="ChatText"></span>')).text(text);

                    var html = text;
                    if (messageConfig.htmlformat)
                    {
                        $textElement.addClass("FHTML").html(html);
                    }
                    else
                    {
                        $textElement.addClass("ChatPlainText");
                        $textElement.text(text);
                        html = $textElement.html();
                    }

                    // Inline Links
                    if (data.links && data.links.Links && data.links.Links.length)
                    {
                        for (var ii = 0; ii < data.links.Links.length; ++ii)
                        {
                            var link = data.links.Links[ii];

                            var chatData = { conversationId: conversationId, token: id, type: data.type, data: JSON.stringify(link.Data) };

                            if (link.DestMember === "0" || link.DestMember === conversation.member)
                            {
                                var $link = $textElement.find("[data-linkid='" + link.Replacement + "']")
                                    .addClass("ChatInlineLink")
                                    .addClass("FastEvt")
                                    .removeAttr("data-linkid")
                                    .attr("href", "#")
                                    .text(link.Text);

                                if (data.type === "ATT")
                                {
                                    $link.click(_fwdc.Events.Chat.chatlinkclick).data("chatlink", { conversationId: conversationId, token: id, type: data.type });
                                }
                                else
                                {
                                    $link.attr("data-event", "ChatTextLinkClick").data("chatdata", chatData);
                                }
                            }
                            else
                            {
                                var $link = $textElement.find("[data-linkid='" + link.Replacement + "']")
                                    .addClass("ChatInlineLink")
                                    .removeAttr("data-linkid")
                                    .data("chatdata", chatData)
                                    .text(link.Text);
                            }

                        }

                    }

                    $chatLine.append($textElement);
                    //Menu buttons
                    if (data.links && data.links.Menus && data.links.Menus.length)
                    {
                        var $menu = $($.parseHTML("<div></div>"))
                            .addClass("ChatMenu");

                        for (var ii = 0; ii < data.links.Menus.length; ++ii)
                        {
                            var link = data.links.Menus[ii];

                            var chatData = { conversationId: conversationId, token: id, type: data.type, data: JSON.stringify(link.Data) };
                            var $button = $($.parseHTML('<button></button>'))
                                .addClass("ChatMenuButton")
                                .addClass("FastEvt")
                                .text(link.Text)
                                .appendTo($menu);

                            if (data.type === "ATT")
                            {
                                $button.click(_fwdc.Events.Chat.chatlinkclick).data("chatlink", { conversationId: conversationId, token: id, type: data.type });
                            }
                            else
                            {
                                $button.attr("data-event", "ChatTextLinkClick").data("chatdata", chatData);
                            }

                            if (link.DestMember != "0" && link.DestMember !== conversation.member)
                            {
                                $button.attr("disabled", "disabled");
                            }
                        }

                        $menu.appendTo($chatLine);
                    }

                    //Attachments
                    if (data.links && data.links.Attachments && data.links.Attachments.length > 0)
                    {
                        for (var ii = 0; ii < data.links.Attachments.length; ++ii)
                        {
                            if (data.links.Attachments[ii].AttachType === "IMAGE")
                            {
                                var values = { messageId: id, index: ii };

                                var args = {
                                    'CONTROL__': 'MANAGER__',
                                    'CONTROL_ID__': '',
                                    'TARGET__': conversationId,
                                    'MANAGER_MODAL_ID__': '',
                                    'DOC_MODAL_ID__': '',
                                    'TYPE__': 'ChatAttachmentThumbnail',
                                    'VALUES': values
                                }

                                var imageSrc = "./GetData?" + $.param(args);

                                var $attachment = $($.parseHTML("<img class=\"ChatAttachThumbnail\">"))
                                $attachment.on("load", function ()
                                {
                                    $chatArea.scrollTop(1000000000);
                                });
                                $attachment.attr("src", imageSrc);
                                if (data.links.Attachments[0].FileName) $attachment.attr("alt", data.links.Attachments[0].FileName);

                                $attachment.appendTo($chatLine);
                            }
                        }
                    }
                }

                //$chatLine.attr("title", when);

                if (data.sent && !_fwdc.tap && conversation.actions && conversation.actions.allowActions)
                {
                    var chatActions = conversation.actions;
                    if (chatActions && chatActions.allowEdits)
                    {
                        _fwdc.setupChatEdit(data.type, id, conversation, $chatLine, text);
                    }
                }

                var $chatArea = conversation.$chatArea;


                if (!_fwdc.tap && conversation.loadMore)
                {
                    _fwdc.setupChatHistory(conversationId, conversation, $chatArea);
                }

                if (data.formatClass)
                {
                    $chatLine.addClass(data.formatClass);
                }

                if (!_fwdc.tap && data.date)
                {
                    $chatWrapper.attr("date", data.date);
                }

                $chatWrapper.append($chatLine);
                $chatWrapper.attr("when", data.when);


                var assistDelay = ((data.type === "ASSIST" || data.type === "ASSISTSIMPLE") && !data.loaded && _fwdc.tap);

                if (assistDelay)
                {
                    _fwdc.setTimeout("QueueChat", function ()
                    {
                        _fwdc.queueChatMessage(conversationId, data.type, $chatWrapper, data.loaded);

                        var $chatTyping = $chatArea.children(".ChatTyping").remove();

                        if ($chatTyping.length === 0)
                        {
                            $chatTyping = $($.parseHTML('<div class="ChatWrapper ChatTyping ChatLine ChatReceived ChatAssistant"></div>'));

                            $chatTyping.append($($.parseHTML('<div class="ChatDot ChatDotFirst"></div>')));
                            $chatTyping.append($($.parseHTML('<div class="ChatDot ChatDotSecond"></div>')));
                            $chatTyping.append($($.parseHTML('<div class="ChatDot ChatDotThird"></div>')));
                        }

                        $chatArea.append($chatTyping);
                        $chatArea.scrollTop(1000000000);

                    }, 200);
                }
                else
                {
                    _fwdc.displayChatMessage(conversationId, data.type, $chatWrapper, data.loaded);
                }

                return true;
            }

            _fwdc.showChatMessage = _showChatMessage;

            _fwdc.getChatDialog = function ()
            {
                if (!_fwdc.$chatDialog)
                {
                    var dialogHtml = '<aside class="ChatDialog"><div class="ChatTabSet"><ul class="ChatTabs"></ul></div></aside>';
                    var $dialog = $($.parseHTML(dialogHtml));
                    $dialog.$tabset = $dialog.children(".ChatTabSet");
                    $dialog.$tabs = $dialog.$tabset.children(".ChatTabs");

                    var chatSettings = $dialog.chatSettings = _fwdc.getJsonCookie("chatSettings");

                    var allowClose = false;
                    $dialog.hideChat = true;
                    _fwdc.chatMin = false;

                    function initTabs($dialog)
                    {
                        // Delay tabset creation until we're attached to the DOM to prevent jQuery from attaching focusin handlers to a fake document, then removing it from the real one.
                        $dialog.$tabset.tabs({
                            activate: function (event, ui)
                            {
                                if (ui.newTab)
                                {
                                    var selectedTabId = $(ui.newTab).removeClass("ChatNewMessages").children("a.ui-tabs-anchor").attr("href").substring(10);
                                    if (chatSettings.currentConversationId !== selectedTabId)
                                    {
                                        chatSettings.currentConversationId = selectedTabId;
                                        _fwdc.setJsonCookie("chatSettings", chatSettings);
                                    }
                                    var conversation = _fwdc.chatConversations[selectedTabId];
                                    if (conversation && conversation.hasNewMessages)
                                    {
                                        conversation.$chatArea.scrollTop(1000000000);
                                        conversation.hasNewMessages = false;
                                    }
                                    if (conversation.support)
                                    {
                                        $dialog.addClass("ChatSupport");
                                    }
                                    else
                                    {
                                        $dialog.removeClass("ChatSupport");
                                    }
                                }
                                else
                                {
                                    dialogSettings.currentConversation = "";
                                    $dialog.removeClass("ChatSupport");
                                }

                                if (ui.oldTab)
                                {
                                    //Since unselected tabs can't be tabbed to, do not allow chat close to be tabbed to for unselected tabs
                                    $(ui.oldTab).children("a.ChatClose").attr("tabindex", -1);
                                }
                            }
                        }).removeClass("ui-corner-all ui-widget-content");
                    }

                    _fwdc.hideChats = function ()
                    {
                        if (_fwdc.embedded) return;

                        _fwdc.chatMin = true;

                        if (_fwdc.chatConversations && !_fwdc.tap)
                        {
                            if ($dialog.hideChat)
                            {
                                if (!_fwdc.onTransition("ChatHideDialog", $dialog.closest(".ui-dialog"), "ChatHide", function ()
                                {
                                    $dialog.closest(".ui-dialog").addClass("Hidden");
                                }, true))
                                {
                                    $dialog.closest(".ui-dialog").addClass("Hidden");
                                }

                                _fwdc.$chatBubble = $('<div></div>').addClass("ChatBubble").attr("title", _fwdc.standardDecode("ChatShow")).appendTo(_fwdc.$body());
                                var $button = $('<button></button>').attr("type", "button").addClass("ChatMin").text(_fwdc.standardDecode("ChatShow")).appendTo(_fwdc.$chatBubble).click(_fwdc.showChats);
                                $('<div></div>').addClass("ChatUnread").appendTo($button);
                            }
                            else
                            {
                                allowClose = true;
                            }
                        }
                        else
                        {

                            var chatSettings = _fwdc.getJsonCookie("chatSettings");
                            chatSettings.minimizeChat = _fwdc.getFastWindowName();
                            _fwdc.setJsonCookie("chatSettings", chatSettings);

                            _fwdc.$body().removeClass("FastChatConversationOpen");
                            //_fwdc.Assistant.removeClass("Hidden");

                            if (!_fwdc.onTransition("ChatHideDialog", _fwdc.$chatDialog, "ChatHide", function ()
                            {
                                _fwdc.$chatDialog.addClass("Hidden");
                            }, true))
                            {
                                _fwdc.$chatDialog.addClass("Hidden");
                            }
                        }
                    }

                    _fwdc.showChats = function ()
                    {
                        if (_fwdc.chatConversations && !_fwdc.tap)
                        {
                            $.each(_fwdc.chatConversations, function (conversationId, conversation)
                            {
                                $dialog.closest(".ui-dialog").removeClass("Hidden");
                                _fwdc.setTimeout("ChatDialogShow", function ()
                                {
                                    $dialog.closest(".ui-dialog").removeClass("ChatHide");
                                });
                                return false;
                            });

                            _fwdc.$chatBubble.remove();
                            _fwdc.$chatBubble = null;
                        }
                        else
                        {
                            var chatSettings = _fwdc.getJsonCookie("chatSettings");
                            chatSettings.minimizeChat = "";
                            _fwdc.setJsonCookie("chatSettings", chatSettings);

                            _fwdc.$chatDialog.removeClass("Hidden");
                            _fwdc.setTimeout("ChatDialogShow", function ()
                            {
                                _fwdc.$chatDialog.removeClass("ChatHide");
                            });
                            _fwdc.$body().addClass("FastChatConversationOpen");
                            //_fwdc.Assistant.addClass("Hidden");
                        }

                        var blnUnread = _fwdc.$body().hasClass("FastChatUnreadMessages");

                        _fwdc.chatMin = false;
                        _fwdc.$body().removeClass("FastChatUnreadMessages");

                        if (blnUnread)
                        {
                            $.each(_fwdc.chatConversations, function (conversationId, conversation)
                            {
                                if (conversation.$chatArea)
                                {
                                    conversation.$chatArea.scrollTop(1000000000);
                                }
                            });
                        }

                        var $chatInput = _fwdc.$chatDialog.findElementById("ChatEntryField");
                        if ($chatInput)
                        {
                            _fwdc.focus($chatInput);
                        }
                    }

                    function closeDialog()
                    {
                        if (!allowClose)
                        {
                            FWDC.messageBox({
                                message: _fwdc.standardDecode("ChatConfirmClose"),
                                icon: FWDC.MessageBoxIcon.Question,
                                buttons: FWDC.MessageBoxButton.YesNo,
                                callback: function ($modal, tag, result)
                                {
                                    if (result === FWDC.MessageBoxResult.Yes)
                                    {
                                        allowClose = true;
                                        if (_fwdc.chatConversations)
                                        {
                                            $.each(_fwdc.chatConversations, function (conversationId, conversation)
                                            {
                                                if (conversation && !_fwdc.closeConversation(conversationId, conversation))
                                                {
                                                    allowClose = false;
                                                }
                                            });
                                        }

                                        if (allowClose)
                                        {
                                            if (_fwdc.tap)
                                            {
                                                $dialog.remove();
                                                _fwdc.$body().removeClass("FastChatConversationOpen");
                                                _fwdc.$chatDialog = null;
                                            }
                                            else
                                            {
                                                $dialog.dialog("close");
                                            }
                                        }
                                    }
                                }
                            });
                        }
                    }

                    if (_fwdc.tap)
                    {
                        $dialog.addClass("ChatAssistantWindow");

                        $($.parseHTML("<div></div>"))
                            .addClass("ChatAssistantTitlebar")
                            .append($($.parseHTML("<h2></h2>")).addClass("ChatAssistantTitlebarCaption").text(_fwdc.standardDecode("Chat")))
                            //.append($($.parseHTML("<button></button>")).attr("type", "button").addClass("ChatSupportButton").attr("title", _fwdc.standardDecode("ChatSupport")).text(_fwdc.standardDecode("ChatSupport")).click(_fwdc.Events.Chat.livechatclick))
                            .append($($.parseHTML("<button></button>")).attr("type", "button").addClass("ChatAssistantCloseButton").attr("title", _fwdc.standardDecode("ChatHide")).text(_fwdc.standardDecode("ChatHide")).click(_fwdc.hideChats))
                            .prependTo($dialog);

                        $dialog.appendTo(_fwdc.$body());

                        initTabs($dialog);

                    }
                    else
                    {
                        $dialog.appendTo(_fwdc.$body());

                        var dialogSettings = chatSettings.dialogSettings;
                        var position = { my: "center", at: "center", of: window };
                        if (!dialogSettings)
                        {
                            dialogSettings = (chatSettings.dialogSettings = {});
                        }
                        else
                        {
                            if (dialogSettings.position && dialogSettings.position.length === 2)
                            {
                                position = { my: "left+" + (dialogSettings.position[0] || 0) + " top+" + (dialogSettings.position[1] || 0), at: "left top", of: window };
                            }
                        }

                        $dialog.dialog({
                            height: dialogSettings.height || 400,
                            width: dialogSettings.width || 600,
                            position: position,
                            title: _fwdc.standardDecode("Chat"),
                            closeOnEscape: false,
                            dialogClass: "ChatWindow",
                            classes: { "ui-dialog-title": "ChatTitlebar", "ui-dialog-titlebar-close": "ChatMinimize" },
                            closeText: _fwdc.standardDecode("ChatHide"),
                            open: function ()
                            {
                                initTabs($dialog);
                            },
                            beforeClose: function ()
                            {
                                _fwdc.hideChats();

                                return allowClose;
                            },
                            close: function ()
                            {
                                $dialog.$tabs = null;
                                $dialog.tryDestroyDialog();
                                $dialog.remove();
                                chatSettings.currentConversationId = "";
                                _fwdc.setJsonCookie("chatSettings", chatSettings);
                                _fwdc.refreshWindowContent();
                                _fwdc.$chatDialog = null;
                            },
                            resizeStop: function (event, ui)
                            {
                                var size = ui.size;
                                dialogSettings.height = size.height;
                                dialogSettings.width = size.width;
                                var position = ui.position;
                                dialogSettings.position = [Math.floor(position.left), Math.floor(position.top)];
                                _fwdc.setJsonCookie("chatSettings", chatSettings);
                            },
                            dragStop: function (event, ui)
                            {
                                var position = ui.position;
                                dialogSettings.position = [Math.floor(position.left), Math.floor(position.top)];
                                _fwdc.setJsonCookie("chatSettings", chatSettings);
                            }
                        });
                    }

                    $dialog.refreshTabs = function (select)
                    {
                        $dialog.$tabset.tabs("refresh");
                        $dialog.$tabs.removeClass("ui-widget-header ui-corner-all ui-helper-clearfix");

                        //if ($dialog.$tabs.children().length < 2)
                        //{
                        //    $dialog.$tabset.addClass("ChatSingleConversation");
                        //}
                        //else
                        //{
                        //    $dialog.$tabset.removeClass("ChatSingleConversation");
                        //}

                        if (_fwdc.tap) { $dialog.$tabset.addClass("ChatSingleConversation"); }

                        if (select !== null && select !== undefined)
                        {
                            $dialog.$tabset.tabs("option", "active", select);
                        }
                    };

                    if (_fwdc.initializingChat)
                    {
                        $dialog.closest(".ui-dialog").css("display", "none");
                    }

                    _fwdc.$chatDialog = $dialog;

                    _fwdc.updateChatWindowOffset();

                    if (!_fwdc.tap)
                    {
                        var $chatTitle = $.findElementsByClassName("ChatTitlebar");
                        var $chatStatus = $($.parseHTML('<div class="ChatStatus ChatConnected"></div>'));
                        $chatTitle.prepend($chatStatus);
                    }


                    _fwdc.$body().addClass("FastChatConversationOpen");
                    //_fwdc.Assistant = _fwdc.$body().find(".ManagerHeaderLinkContainerAssistant");
                    //_fwdc.Assistant.addClass("Hidden");
                    _fwdc.$chatDialog.addClass("Hidden");

                    var chatSettings = _fwdc.getJsonCookie("chatSettings");
                    if (chatSettings && chatSettings.minimizeChat && chatSettings.minimizeChat === _fwdc.getFastWindowName())
                    {
                        _fwdc.hideChats();
                        _fwdc.chatMin = false;


                    }
                    _fwdc.$chatDialog.removeClass("Hidden");
                }
                return _fwdc.$chatDialog;
            };

            _fwdc.closeConversation = function (conversationId, conversation)
            {
                conversation = conversation || _fwdc.chatConversations[conversationId];

                var closed = false;

                if (conversation)
                {
                    _fwdc.setPropertiesInternalJson("MANAGER__", "CloseConversation", conversationId, true, null, function (response)
                    {
                        if (response && response.success)
                        {
                            _fwdc.chatConversations[conversation.id] = null;
                            conversation.$tab.remove();
                            conversation.$widget.remove();
                            conversation.$tab = null;
                            conversation.$widget = null;
                            closed = true;
                            _fwdc.getChatDialog().refreshTabs();
                        }
                        else
                        {
                            closed = false;
                        }
                    });
                }

                if (closed)
                {
                    var blnConversationsOpen = false;
                    $.each(_fwdc.chatConversations, function (conversationId, conversation)
                    {
                        if (conversation)
                        {
                            blnConversationsOpen = true;
                            return false;
                        }
                    });

                    if (!blnConversationsOpen)
                    {
                        _fwdc.$body().removeClass("FastChatConversationOpen");
                        //_fwdc.Assistant.removeClass("Hidden");

                        window.clearInterval(_chatUpdateLastActivityHandle);
                        _chatUpdateLastActivityHandle = null;
                    }

                    return true;
                }

                return false;
            };

            //Default is no tools - internal class has support actions
            _fwdc.setupConversationTools = function (conversationId, conversation, $tools)
            {
                //var send = _fwdc.standardDecode("ChatSend");
                //$('<button type="button" class="ChatToolButton ChatSend"></button>').text(send).attr("title", send).appendTo($tools).click(conversation, _fwdc.Events.Chat.sendclick);

            };

            _fwdc.setupConversationWidget = function (conversationId, conversation)
            {
                if (!conversation.$chatEntryContainer)
                {
                    var html = '<div class="ChatWidget"><div class="ChatArea"></div><div class="ChatEntryWrapper"><div class="ChatEntryContainer"><textarea type="text" rows="1" class="FieldEnabled ChatEntry" id="ChatEntryField"></textarea></div></div></div>';

                    var $widget = conversation.$widget = $($.parseHTML(html));

                    if (conversation.support)
                    {
                        $widget.addClass("ChatSupport");
                    }

                    $widget.attr("id", "chat-cnv-" + conversationId);
                    conversation.$chatArea = $widget.children(".ChatArea");
                    conversation.$chatArea.attr("aria-live", "polite");

                    var $input = conversation.$input = $widget.find("textarea.ChatEntry").watermark(_fwdc.standardDecode("ChatBox"));
                    if ($input)
                    {
                        $input.attr("autocomplete", "off");
                        $input.attr("maxlength", "2000");
                    }

                    conversation.send = function (event)
                    {
                        var text = $input.val();
                        if (text && (text = text.trim()))
                        {
                            $input.val("");
                            _fwdc.sendChat(event, conversationId, text);
                        }
                    };
                    function resizeChatInput()
                    {
                        var $canvas = $($.parseHTML("<canvas></canvas>")).appendTo(_fwdc.supportElementsContainer());
                        var canvas = $canvas[0];
                        var context = canvas.getContext("2d");
                        context.font = $input.css("font-size") + " " + $input.css("font-family");

                        $canvas.remove();

                        var padding = parseInt($input.css("padding-left")) + parseInt($input.css("padding-right"));

                        var textWidth = context.measureText($input.val()).width;

                        var width = $input.width() - padding;
                        if (width == 0)
                        {
                            $input.attr("rows", 1);
                            return;
                        }

                        var rows = Math.floor((textWidth) / width);

                        switch (rows)
                        {
                            case 0:
                                $input.attr("rows", 1);
                                $input.css("overflow", "hidden");
                                break;
                            case 1:
                                $input.attr("rows", 2);
                                $input.css("overflow", "hidden");
                                break;
                            case 2:
                                $input.attr("rows", 3);
                                $input.css("overflow", "hidden");
                                break;
                            default:
                                $input.attr("rows", 4);
                                $input.css("overflow", "auto");
                                break;
                        }
                    };
                    $input.keydown(function chatInputKeydown(event)
                    {
                        if (event.which === _fwdc.keyCodes.ENTER)
                        {
                            _fwdc.stopEvent(event);
                            conversation.send(event);
                        }
                        else if (event.which === _fwdc.keyCodes.ESCAPE)
                        {
                            _fwdc.stopEvent(event);
                            $input.val("");
                        }
                        //resizeChatInput();
                    });

                    var $chatEntryContainer = conversation.$chatEntryContainer = $widget.find(".ChatEntryContainer");

                    var send = _fwdc.standardDecode("ChatSend");
                    $('<button type="button" class="ChatSend"></button>').text(send).attr("title", send).appendTo($chatEntryContainer).click(conversation, _fwdc.Events.Chat.sendclick);
                }

                if (conversation.observer)
                {
                    conversation.$chatEntryContainer.addClass("Hidden");
                }
                else
                {
                    conversation.$chatEntryContainer.removeClass("Hidden");
                }

                if (!conversation.$tools)
                {
                    conversation.$tools = $($.parseHTML('<div class="ChatTools"></div>'));
                }
                else
                {
                    conversation.$tools.children(".ChatToolButton").remove();
                }

                var $tools = conversation.$tools;
                _fwdc.setupConversationTools(conversationId, conversation, $tools);

                if ($tools && $tools.children().length > 0) { $widget.append($tools); }
            };

            _fwdc.updateChatWindowOffset = function ()
            {
                if (!_fwdc.$chatDialog || !_fwdc.tap)
                    return;

                var offsetTop = 0;

                if (_fwdc.screenWidth != _fwdc.ScreenWidths.Small)
                {
                    var $target = _fwdc.$body().findElementsByClassName("AnnouncementHeaderContainer");
                    if (!$target.length)
                    {
                        $target = $(".ManagerBase .ManagerControlsContainer");
                    }

                    if ($target.length)
                    {
                        offsetTop = Math.floor($target.offset().top);
                    }
                }

                _fwdc.$chatDialog.css("top", offsetTop + "px");
            }

            _fwdc.setupChatHistory = function (conversationId, conversation, $chatArea)
            {
                if ($chatArea.children(".ChatHistory").length === 0)
                {
                    var history = _fwdc.standardDecode("ChatHistory");
                    $('<a class="ChatWrapper ChatHistory" href="#"></a>').text(history).attr("title", history).appendTo($chatArea).click(conversation, _fwdc.Events.Chat.historyclick)
                        .data("chatconversation", { conversationId: conversationId });
                }
            };

            _fwdc.setupChatReport = function (messageType, conversationId, conversation, $chatArea)
            {
                $chatArea.children(".ChatReport").remove();

                if (messageType === "ASSIST")
                {
                    var report = _fwdc.standardDecode("ChatReport");
                    $('<a class="ChatReport" href="#"></a>').text(report).attr("title", report).appendTo($chatArea).click(conversation, _fwdc.Events.Chat.reportclick)
                        .data("chatmessage", { conversationId: conversationId });
                }
            };

            _fwdc.setupChatEdit = function (messageType, messageId, conversation, $chatLine, text)
            {
                if (messageType === "CHAT")
                {
                    var edit = _fwdc.standardDecode("ChatEdit");
                    $('<a class="ChatEdit" href="#"></a>').attr("title", edit).appendTo($chatLine).click({ conversation: conversation, messageId: messageId, text: text }, _fwdc.Events.Chat.editclick);
                }
            };

            _fwdc.syncConversation = function (conversation)
            {
                _fwdc.setPropertiesInternal(null, "MANAGER__", "ConversationSync", conversation.id, true, null);
            }

            _fwdc.getConversation = function (conversationId, allowReinit, loadRecent, loadPushOptions)
            {
                var conversation = _fwdc.chatConversations[conversationId];
                if (!conversation)
                {
                    if (conversation === null && !allowReinit) { return null; }

                    _fwdc.chatConversations[conversationId] = conversation = { id: conversationId };

                    var conversationInfo = _fwdc.getData({
                        control: "MANAGER__",
                        type: "ConversationInfo",
                        target: conversationId,
                        dataType: "json",
                        busy: false,
                        // We don't need session ver last info - whatever's current will work
                        ignoreSessionData: true,
                        // Don't send up manager/doc modal IDs, as these do not need to be validated
                        managerModalId: -1,
                        docModalId: -1,
                        data: {
                            messages: !!loadRecent
                        }
                    });

                    if (!conversationInfo)
                    {
                        throw "Could not get conversation info: " + conversationId;
                    }

                    conversation.support = conversationInfo.support;
                    conversation.external = conversationInfo.external;
                    conversation.exchange = conversationInfo.exchange;
                    conversation.observer = conversationInfo.observer;
                    conversation.member = conversationInfo.member;
                    conversation.requester = conversationInfo.requester;
                    conversation.loadMore = conversationInfo.loadMore;
                    conversation.actions = conversationInfo.actions;
                    conversation.standalone = false;

                    var $dialog = _fwdc.getChatDialog();

                    if (_fwdc.chatStandalone())
                    {
                        conversation.standalone = true;
                        //Remove minimize button
                        var $title = $dialog.childrenWithClass("ChatAssistantTitlebar").remove();
                        $title.childrenWithClass("ChatAssistantCloseButton").remove();
                        $dialog.prepend($title);
                    }

                    //******** */
                    //var html = '<div class="ChatWidget"><div class="ChatArea"></div><div class="ChatEntryWrapper"><div class="ChatEntryContainer"><input type="text" size="0" class="FieldEnabled ChatEntry" id="ChatEntryField"></div></div></div>';

                    //var $widget = conversation.$widget = $($.parseHTML(html));

                    //if (conversation.support)
                    //{
                    //    $widget.addClass("ChatSupport");
                    //}

                    //$widget.attr("id", "chat-cnv-" + conversationId);
                    //conversation.$chatArea = $widget.children(".ChatArea");
                    //conversation.$chatArea.attr("aria-live", "polite");

                    //var $input = conversation.$input = $widget.find("input.ChatEntry").watermark(_fwdc.standardDecode("ChatBox"));

                    //conversation.send = function (event)
                    //{
                    //    var text = $input.val();
                    //    if (text && (text = text.trim()))
                    //    {
                    //        $input.val("");
                    //        _fwdc.sendChat(event, conversationId, text);
                    //    }
                    //};

                    //$input.keydown(function (event)
                    //{
                    //    if (event.which === _fwdc.keyCodes.ENTER)
                    //    {
                    //        _fwdc.stopEvent(event);
                    //        conversation.send(event);
                    //    }
                    //    else if (event.which === _fwdc.keyCodes.ESCAPE)
                    //    {
                    //        _fwdc.stopEvent(event);
                    //        $input.val("");
                    //    }
                    //});

                    //var $chatEntryContainer = conversation.$chatEntryContainer = $widget.find(".ChatEntryContainer");

                    //var send = _fwdc.standardDecode("ChatSend");
                    //$('<button type="button" class="ChatSend"></button>').text(send).attr("title", send).appendTo($chatEntryContainer).click(conversation, _fwdc.Events.Chat.sendclick);

                    //if (conversation.observer)
                    //{
                    //    $chatEntryContainer.addClass("Hidden");
                    //}

                    //var $tools = conversation.$tools = $($.parseHTML('<div class="ChatTools"></div>'));

                    //_fwdc.setupConversationTools(conversationId, conversation, $tools);

                    //if ($tools && $tools.children().length > 0) { $widget.append($tools); }
                    //********** */


                    _fwdc.setupConversationWidget(conversationId, conversation);

                    var strTabName = conversation.requester === "" ? _fwdc.standardDecode("NewConversation") : conversation.requester;

                    conversation.$tab = $($.parseHTML('<li></li>')).appendTo($dialog.$tabs);
                    conversation.$link = $($.parseHTML('<a href="#chat-cnv-' + conversationId + '"></a>')).appendTo(conversation.$tab);
                    conversation.$title = $($.parseHTML('<span class="ChatTitle"></span>')).text(strTabName).appendTo(conversation.$link);
                    var $close = $($.parseHTML('<a href="#" class="ChatClose" role="presentation"></a>')).text(_fwdc.standardDecode("DialogClose")).appendTo(conversation.$tab);
                    conversation.$tab.append('<div class="clearer"></div>');
                    conversation.$widget.appendTo($dialog.$tabset);
                    conversation.participants = [];

                    conversation.close = function (event)
                    {
                        _fwdc.stopEvent(event);

                        FWDC.messageBox({
                            message: _fwdc.standardDecode("ChatConfirmClose"),
                            icon: FWDC.MessageBoxIcon.Question,
                            buttons: FWDC.MessageBoxButton.YesNo,
                            callback: function ($modal, tag, result)
                            {
                                if (result === FWDC.MessageBoxResult.Yes)
                                {
                                    _fwdc.closeConversation(conversation.id, conversation);
                                    if ($dialog.$tabs.children().length < 1)
                                    {
                                        $dialog.hideChat = false;
                                        $dialog.dialog("close");
                                        _fwdc.$chatDialog = null;

                                    }
                                }
                            }
                        });
                    };

                    $close.click(conversation.close);


                    if (loadRecent)
                    {
                        var chats = conversationInfo.push;

                        if (chats && chats.length)
                        {
                            _fwdc.handlePushData(chats, loadPushOptions, false);
                        }
                    }

                    if (!_fwdc.initializingChat)
                    {
                        $dialog.refreshTabs(-1);
                    }

                    if ($dialog.chatSettings.minimizeChat === "")
                    {
                        window.setTimeout(function ()
                        {
                            var $chatEntryContainer = $.findElementsByClassName("ChatEntryContainer");
                            $chatEntryContainer.find("input.ChatEntry").focus();

                        }, 1);
                    }

                    if (!_chatUpdateLastActivityHandle && conversationInfo.updateActivity)
                    {
                        window.setTimeout(_chatUpdateLastActivity, 1000);
                        _chatUpdateLastActivityHandle = window.setInterval(_chatUpdateLastActivity, 120000);
                    }
                }

                return conversation;
            };

            function _handleChatPush(id, timestamp, data)
            {
                if (typeof data === "string")
                {
                    data = JSON.parse(data);
                }

                if (data && data.cnv)
                {
                    _showChatMessage(data.cnv, id, timestamp, data);
                }
            }

            _fwdc.handlePushData = function (pushResponse, pushOptions, continuePush)
            {
                var handler;
                if (pushResponse && !pushResponse.nodata && pushResponse.length)
                {
                    for (var ii = 0; ii < pushResponse.length; ++ii)
                    {
                        var pushData = pushResponse[ii];
                        try
                        {
                            // Legacy handler for cht conversation loads
                            if (pushData.type === "cht")
                            {
                                _handleChatPush(pushData.id, pushData.timestamp, pushData.data);
                            }
                            else if (pushData.type && (handler = _fwdc.pushHandlers[pushData.type]))
                            {
                                handler(pushData.type, pushData.token, pushData.id, pushData.timestamp, pushData.when, pushData.data);
                            }
                            else
                            {
                                _fwdc._warn("Unhandled push data:", pushData);
                            }
                        }
                        catch (e)
                        {
                            _fwdc._warn("Error in handlePushData", pushData, e);
                        }

                        if (pushData.token && pushData.timestamp)
                        {
                            for (var jj = 0; jj < pushOptions.token.length; jj++)
                            {
                                if (pushOptions.token[jj].token === pushData.token)
                                {
                                    pushOptions.token[jj].timestamp = pushData.timestamp;
                                    break;
                                }
                            }
                        }
                    }
                }

                //if (pushOptions && continuePush !== false)
                //{
                //    setTimeout(function () { FWDC.getPushData(pushOptions); }, 1);
                //}
            };

            //function _loadScript(scripts, index, scriptCallbacks, finishedCallback)
            //{
            //    if (index < scripts.length)
            //    {
            //        var script = scripts[index];

            //        if (script && !script.startsWith("http"))
            //        {
            //            script = "../Resource/" + scripts[index] + _versionUrlSuffix;
            //        }

            //        _fwdc.ajax({
            //            url: script,
            //            method: "GET",
            //            cache: true,
            //            busy: false,
            //            dataType: "script",
            //            ignoreReady: true,
            //            ignoreAutoRefresh: true,
            //            fastLog: false,
            //            success: function ()
            //            {
            //                if (scriptCallbacks && scriptCallbacks[index])
            //                {
            //                    scriptCallbacks[index]();
            //                }
            //                _loadScript(scripts, index + 1, scriptCallbacks, finishedCallback);
            //            },
            //            error: function ()
            //            {
            //                return false;
            //            }
            //        });
            //    }
            //    else if (finishedCallback)
            //    {
            //        finishedCallback();
            //    }
            //}

            function _loadScript(scripts, index, scriptCallbacks, finishedCallback)
            {
                if (index < scripts.length)
                {
                    var src = scripts[index];
                    var blnCrossOrigin = src && src.startsWith("http");

                    if (!blnCrossOrigin)
                    {
                        src = "../Resource/" + src + _versionUrlSuffix;
                    }

                    var script = document.createElement("script");
                    script.setAttribute("src", src);
                    //if (blnCrossOrigin)
                    //{
                    //    script.setAttribute("crossorigin", "");
                    //}

                    script.onload = function ()
                    {
                        if (scriptCallbacks && scriptCallbacks[index])
                        {
                            scriptCallbacks[index]();
                        }
                        _loadScript(scripts, index + 1, scriptCallbacks, finishedCallback);
                    };

                    script.onerror = function (event)
                    {
                        _fwdc._error(event);
                    };

                    document.body.appendChild(script);

                    //_fwdc.ajax({
                    //    url: script,
                    //    method: "GET",
                    //    cache: true,
                    //    busy: false,
                    //    dataType: "script",
                    //    ignoreReady: true,
                    //    ignoreAutoRefresh: true,
                    //    fastLog: false,
                    //    success: function ()
                    //    {
                    //        if (scriptCallbacks && scriptCallbacks[index])
                    //        {
                    //            scriptCallbacks[index]();
                    //        }
                    //        _loadScript(scripts, index + 1, scriptCallbacks, finishedCallback);
                    //    },
                    //    error: function ()
                    //    {
                    //        return false;
                    //    }
                    //});
                }
                else if (finishedCallback)
                {
                    finishedCallback();
                }
            }

            _fwdc.loadScripts = function (scripts, scriptCallbacks, finishedCallback)
            {
                if (scriptCallbacks && !finishedCallback && !scriptCallbacks.length)
                {
                    finishedCallback = scriptCallbacks;
                    scriptCallbacks = null;
                }

                _loadScript(scripts, 0, scriptCallbacks, finishedCallback);
            };

            _fwdc.showFieldPopup = function (field, options)
            {
                var $field;
                if (typeof field === "string")
                {
                    $field = _fwdc.formField(field);
                }
                else
                {
                    $field = $(field);
                    field = $field.attr("data-field-id") || $field.attr("id");
                }

                if (!($field && $field.length)) { return; }

                if (!options)
                {
                    options = {};
                }

                var customFieldPopup = $field.hasClass("CustomFieldPopup");

                if (customFieldPopup)
                {
                    _fwdc.setPropertiesInternal(null, "", "CustomFieldPopup", field, true, { "value": $field.val() });
                }
                else
                {
                    var $accessKeyElements = _fwdc.disableAccessKeys();

                    var $menu = $($.parseHTML(_getFieldProperty(field, "fieldpopup", "html", $field.val(), options.menuOptions)));
                    var $modal = $("<div></div>").attr("id", "popup_" + field).addClass("FastFieldPopup");
                    $modal.attr("title", $menu.attr("title"));
                    $menu.attr("title", "");
                    $modal.append($menu);
                    _fwdc.$body().append($modal);

                    var width = 800;
                    var height = 800;

                    if (options.large)
                    {
                        width = Math.round(_fwdc.windowWidth * 0.9);
                        height = Math.round(_fwdc.windowHeight * 0.9);
                    }

                    $modal.dialog({
                        modal: true,
                        draggable: true,
                        resizable: true,
                        width: width,
                        height: height,
                        minWidth: 400,
                        minHeight: 200,
                        dialogClass: "FastFieldPopupDialog FastPanelDialog " + _fwdc.getFastModalClass(),
                        closeOnEscape: false,
                        position: { my: "center", at: "center", collision: "none" },
                        closeText: _fwdc.getCloseText(),
                        open: function (event, ui)
                        {
                            FWDC.hideViewMenus();
                            _fwdc.hideToolTips();
                            _fwdc.closeComboboxes();
                            _fwdc.updateScreenReader();

                            var $popupField;
                            if (($popupField = $menu.find("textarea.DocCalcBox")) && $popupField.length)
                            {
                                _fwdc.createCalcEditor($popupField.attr("id"), $popupField, _sizeFieldPopupCodeMirror, true);
                                $modal.on("dialogresize", function (event, ui)
                                {
                                    _sizeFieldPopupCodeMirror($popupField);
                                });
                            }
                            else if (($popupField = $menu.find("textarea.DocSqlBox")) && $popupField.length)
                            {
                                _fwdc.createSqlEditor($popupField.attr("id"), $popupField, _sizeFieldPopupCodeMirror, true, true);
                                $modal.on("dialogresize", function (event, ui)
                                {
                                    _sizeFieldPopupCodeMirror($popupField);
                                });
                            }
                            else if (($popupField = $menu.find("textarea.DocVbBox")) && $popupField.length)
                            {
                                _fwdc.createVbEditor($popupField.attr("id"), $popupField, _sizeFieldPopupCodeMirror, true);
                                $modal.on("dialogresize", function (event, ui)
                                {
                                    _sizeFieldPopupCodeMirror($popupField);
                                });
                            }
                            else if (($popupField = $menu.find("textarea.DocCSharpBox")) && $popupField.length)
                            {
                                _fwdc.createCSharpEditor($popupField.attr("id"), $popupField, _sizeFieldPopupCodeMirror, true);
                                $modal.on("dialogresize", function (event, ui)
                                {
                                    _sizeFieldPopupCodeMirror($popupField);
                                });
                            }
                            else if (($popupField = $menu.find("textarea.DocRichTextBox")) && $popupField.length)
                            {
                                var cssClass = $popupField.parent().attr("class") + " " + $popupField.attr("class");
                                cssClass = cssClass.replace("FieldPopupContainer", "");
                                _fwdc.createRichTextBox(field, $popupField, cssClass, true);
                            }
                            else if (($popupField = $menu.find("textarea[data-syntax-highlight-mode]")) && $popupField.length)
                            {
                                _fwdc.setupSyntaxHighlight($popupField.attr("id"), $popupField.attr("data-syntax-highlight-mode"), $popupField, _sizeFieldPopupCodeMirror, true);
                                $modal.on("dialogresize", function (event, ui)
                                {
                                    _sizeFieldPopupCodeMirror($popupField);
                                });
                            }
                            else if (($popupField = $menu.find("textarea")) && $popupField.length)
                            {
                                $popupField.focus();
                            }
                            _fwdc.showCurrentFieldTip();
                        },
                        close: function ()
                        {
                            var accepted = $modal.data("fast-dialog-accepted");
                            var editor = $field.data("fast-code-mirror-editor");

                            FWDC.hideViewMenus();
                            _fwdc.hideToolTips();
                            _fwdc.closeComboboxes();
                            $modal.tryDestroyDialog();
                            $modal.remove();

                            _fwdc.restoreAccessKeys($accessKeyElements);

                            if (!accepted && options.cancelCallback && options.cancelCallback($field) === false)
                            {
                                return;
                            }

                            if (editor)
                            {
                                editor.focus();
                            }
                            else
                            {
                                $field.focus();
                            }
                            _fwdc.showCurrentFieldTip();
                        },
                        resizeStart: function (ui)
                        {
                            $modal.closest(".ui-dialog").addClass("ModalResized");
                        },
                        //resize: _fwdc.evaluateDialogScreenResize
                    });
                }
            };

            _fwdc.chatStandalone = function ()
            {
                var docPage = document.documentElement;
                return (docPage && docPage.classList && docPage.classList.contains("FastChatStandalone") && _fwdc.embedded);
            }

            _fwdc.runUrlFragment = function (fragment)
            {
                if (!fragment) { return false; }

                var fragmentLower = fragment.toLowerCase();

                if (fragment === "error")
                {
                    _fwdc.currentHash = "error";
                    return true;
                }
                else if (fragment.endsWith("reload"))
                {
                    _fwdc.refreshPage("#reload");
                    return true;
                }
                else if (_fwdc.currentHash === "error")
                {
                    _fwdc.refreshPage("#error");
                    return true;
                }
                else if (fragmentLower.indexOf("log") > -1 || fragmentLower.indexOf("context") > -1)
                {
                    if (fragmentLower.indexOf(" ") > -1 || fragmentLower.indexOf("%") > -1)
                    {
                        _fwdc.setHistoryStep(_fwdc.currentHash);
                        return;
                    }

                    try
                    {
                        var $target = $("#" + fragment + ",[name='" + fragment + "']");
                        if ($target && $target.length)
                        {
                            _fwdc.setHistoryStep(_fwdc.currentHash);
                            return;
                        }
                    }
                    catch (ex)
                    {
                    }

                    _busy.hideUnloading();
                    _fwdc.toggleLog();
                    _fwdc.setHistoryStep(_fwdc.currentHash);
                    return true;
                }
                else if (fragmentLower === "navigatehome")
                {
                    _fwdc.setHistoryStep(_fwdc.currentHash);
                    _fwdc.navigate(null, "URL Fragment Home", -2);
                    return true;
                }
            };

            _fwdc.onHashChange = function (prior, current)
            {
                if (current < prior)
                {
                    if (!_fwdc.hideManagerMenu() && !_fwdc.navigateCloseModal())
                    {
                        // Force a scroll to top to prevent the browser from scrolling down because of the hash change.
                        // Not entirely certain why it scrolls down for certain hash changes.
                        _fwdc.scrollToTop();
                        _fwdc.navigate(null, "BrowserBack", 0, null, "BACK", false, true);
                    }
                }
            };

            _fwdc.baseScrollContainer = function ($form, $default)
            {
                var $formDialog = ($form || _fwdc.currentForm());
                var $dialog;
                if ($formDialog)
                {
                    $dialog = $formDialog.closest(".ui-dialog");
                }

                return ($dialog && $dialog.length) ? $dialog : ($default || _fwdc.$window);
            };

            _fwdc.scrollToTop = function (containerId)
            {
                _fwdc.invalidateTransitionScroll = true;

                if (containerId)
                {
                    // If the scroll call belongs to a modal that hasn't opened yet, we can simply skip this.
                    if (!$.findElementById(containerId).length)
                        return;
                }

                _fwdc.baseScrollContainer().scrollTop(0);
                if (!_fwdc.autoFocusMode)
                {
                    // Reinitialize the skip to main link to fix focus order.
                    _fwdc.setupSkipToMain();
                }
            };

            _fwdc.modalMaxWidth = function ()
            {
                var $baseManager = $("#MANAGER_CONTAINER__0");
                if ($baseManager && $baseManager.length)
                {
                    return $baseManager.outerWidth() * 0.9;
                }

                return 850;
            };

            _fwdc.fixCKEditorValue = function (value)
            {
                return value
                    // Remove non-breaking spaces that aren't next to tags.
                    .replace(/([^<>\s;])&nbsp;([^<>\s&])/g, "$1 $2")
                    // Replace self-closing line breaks with standard HTML linebreaks.
                    .replace(/<([bh]r)\s*\/>/, "<$1>");
            };

            _fwdc.getFieldValue = function (field, $field)
            {
                try
                {
                    $field = $field || $(field);
                    if ($field.hasClass("FCBRB"))
                    {
                        if ($field.is(":checked"))
                        {
                            return $field.attr("value");
                        }
                        else
                        {
                            return undefined;
                        }
                    }
                    if ($field.is("select"))
                    {
                        return $field.val();
                    }
                    else if (_fwdc.isCombobox($field))
                    {
                        return $field.data("fast-combo-value");
                    }
                    else if ($field.is("input[type='checkbox']") || $field.is("input[type='radio']"))
                    {
                        return $field.is(":checked");
                    }
                    else if ($field.hasClass("DocRichTextBox"))
                    {
                        if ($field.attr("data-loading-html") || !$field.hasClass("HasCKEditor"))
                        {
                            return $field.val();
                        }

                        var cke = $field.ckeditorGet();
                        cke.updateElement();
                        return _fwdc.fixCKEditorValue(cke.getData());
                    }
                    else if ($field.hasClass("FastCodeMirrorBox"))
                    {
                        var cm = $field.data("fast-code-mirror-editor");
                        var selection = null;
                        var selections = null;

                        if (cm)
                        {
                            cm.save();
                            selection = cm.getSelection();
                            // Pre-stringify selections so the server doesn't have to worry about the JSON data.
                            selections = JSON.stringify(cm.listSelections());
                        }
                        else
                        {
                            _fwdc._warn("code mirror box has no editor:", $field);
                        }

                        if ($field.hasClass("DocSqlBox"))
                        {
                            return JSON.stringify({
                                "value": $field.val(),
                                "selections": selections,
                                "selection": selection
                            });
                        }
                        else
                        {
                            return $field.val();
                        }
                    }
                    else if ($field.hasClass("DocSqlBox"))
                    {
                        // Fallback for a SQL field that hasn't completed initialization.
                        return JSON.stringify({
                            "value": $field.val()
                        });
                    }
                    else if ($field.hasClass("DocControlDatepicker") || $field.hasClass("DocControlDatepickerCombo"))
                    {
                        var date = $field.datepicker("getDate");
                        //return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
                        return _fwdc.getCanonDateString(date);
                    }
                    else
                    {
                        return $field.val();
                    }
                }
                catch (e)
                {
                    _fwdc._warn(e);
                }
            };

            _fwdc.setRichTextValue = function ($field, value)
            {
                //var fixedValue = _fwdc.fixCKEditorValue($field.val());
                var fixedValue = $field.val();
                if (fixedValue !== value)
                {
                    $field.val(value);
                    $field.attr("data-loading-html", "1");
                    var editor = $field.ckeditorGet();
                    var scrollTop = editor.document.$.scrollingElement.scrollTop;
                    editor.setData(value, function ()
                    {
                        $field.removeAttr("data-loading-html");
                        editor.fwdc_setupEditorBasics();
                        editor.resetDirty();
                        editor.document.$.scrollingElement.scrollTop = scrollTop;
                    });
                }
                else
                {
                    $field.ckeditorGet().resetDirty();
                }
            };

            //_fwdc.checkValueChanged = function (sender, async, test, callback, trigger)
            _fwdc.checkValueChanged = function (sender, trigger, options)
            {
                if (_inRecalc) { return false; }

                if (!sender)
                {
                    sender = _currentField;
                }

                var async = options && options.async;
                var test = options && options.test;
                var callback = options && options.callback;
                var extraRecalcData = options && options.extraRecalcData;

                /*if (typeof sender === "string")
                {
                    trigger = sender;
                    sender = _currentField;
                }
                else if (sender === undefined)
                {
                    sender = _currentField;
                }
     
                if (typeof async === "function")
                {
                    callback = async;
                    async = false;
     
                    if (typeof test === "string")
                    {
                        trigger = test;
                        test = null;
                    }
                }
                else if (typeof async === "string")
                {
                    trigger = async;
                    async = false;
                }
     
                if (trigger === undefined && typeof callback === "string")
                {
                    trigger = callback;
                    callback = null;
                }*/

                if (!sender || sender !== _currentField)
                {
                    return false;
                }

                var value = _fwdc.getFieldValue(sender);

                if (value === undefined)
                {
                    return false;
                }

                var $sender = $(sender);

                if ((!$sender.inDom()) || $sender.hasClass("FastNoRecalc") || (_fwdc.currentModalId() !== _fwdc.fieldModalId($sender) && !$sender.closest("#CONTEXT_LOG_CONTAINER__").length))
                {
                    return false;
                }

                var richTextBox = $sender.hasClass("HasCKEditor") ? $sender.ckeditorGet() : null;

                var force = (options && options.force) || (richTextBox && richTextBox.checkDirty());

                if (force || value !== _lastFieldValue)
                {
                    if (!test)
                    {
                        _setLastValue(sender, value);
                        _recalc({
                            async: async,
                            callback: callback,
                            source: sender,
                            trigger: trigger || 'checkValueChanged',
                            extraData: extraRecalcData
                        });

                        var newValue;
                        if ($sender.inDom())
                        {
                            newValue = _fwdc.getFieldValue(sender);
                            if (newValue === undefined) { return true; }
                            _setLastValue(sender, newValue);
                        }
                        else if ($sender.attr("id") && (sender = _fwdc.formField($sender.attr("id"), true)))
                        {
                            $sender = $(sender);
                            newValue = _fwdc.getFieldValue(sender);
                            if (newValue === undefined) { return true; }
                            _setLastValue(sender, newValue);
                        }
                    }
                    return true;
                }
                else
                {
                    return false;
                }
            };

            _fwdc.commitEdits = function (trigger, ignoreTable)
            {
                if (_editingCell())
                {
                    if (ignoreTable)
                    {
                        return;
                    }
                    _endEditCell(true);
                }
                else if (_commitCombobox(_currentField))
                {
                    return;
                }

                if (!ignoreTable || !_currentFieldCell)
                {
                    _fwdc.checkValueChanged(null, trigger || "commitEdits");
                }
            };

            _fwdc.getColorClass = function ($element)
            {
                var cssClass = $element.attr("class");
                return (cssClass && cssClass.match(/\bMC_\w+\b/)) || "";
            };

            _fwdc.setColorClass = function ($element, colorClass)
            {
                if ($element && $element.length)
                {
                    var cssClass = $element.attr("class");
                    if (cssClass && cssClass.match(/\bMC_\w+\b/))
                    {
                        var newClass = cssClass.replace(/\bMC_\w+\b/, colorClass || "");
                        $element.attr("class", newClass);
                    }
                    else if (colorClass)
                    {
                        $element.addClass(colorClass);
                    }
                }
            };

            _fwdc.getBaseManagerColor = function ()
            {
                return _fwdc.getColorClass($(".ManagerBase"));
            };

            _fwdc.getCurrentManagerColor = function ()
            {
                return _fwdc.getColorClass(_fwdc.currentManagerContainer());
            };

            _fwdc.isSinglePanelContent = function ($content, setSinglePanelClass)
            {
                // Row group view stacks can cause too many problems with the Auto sizing on doc tables.
                if ($content.find(".VSTableContainer").length)
                {
                    return false;
                }

                var $visiblePanels = $content.find(_fwdc.selectors.panel).filter(function ()
                {
                    return !$(this).closest(".Hidden").length;
                });

                var $rootPanels = $visiblePanels.filter(function ()
                {
                    return !$(this).parent().closest(_fwdc.selectors.panel).length;
                });

                if ($rootPanels.length === 1)
                {
                    var $nonStacks = $visiblePanels.filter(function ()
                    {
                        return !$(this).hasClass("ViewStackLayout");
                    });

                    if ($rootPanels.hasClass("ViewStackLayout") && $nonStacks.length === 1)
                    {
                        $nonStacks.addClass("SingleFastPanel");
                    }
                    else
                    {
                        $rootPanels.addClass("SingleFastPanel");
                    }

                    return true;
                }

                //var rootPanels = $.uniqueSort($panels.root(_fwdc.selectors.panel).get());

                //return rootPanels && rootPanels.length === 1;

                return false;
            };

            _fwdc.contextMenuPosition = function ($content)
            {
                var fastMousePos, offset, leftOffset, topOffset, $graphSource;

                var $source = (_linkSourceInfo && _linkSourceInfo.element && _fwdc.formField(_linkSourceInfo.element))
                    || ($content && $content.attr("data-source-id") && _fwdc.formField($content.attr("data-source-id")));

                if (_fwdc.FusionCharts
                    && _linkSourceInfo
                    && _linkSourceInfo.sourceChart
                    && ($graphSource = _fwdc.formField("graph_" + _linkSourceInfo.sourceChart))
                    && $graphSource.length
                    && (fastMousePos = $graphSource.data("fast-mousedown-pos")))
                {
                    offset = $graphSource.offset();
                    leftOffset = fastMousePos.pageX - _fwdc.$window.scrollLeft();
                    topOffset = fastMousePos.pageY - _fwdc.$window.scrollTop();

                    return { my: "left+" + leftOffset + " top+" + topOffset, at: "left top", of: _fwdc.window, collision: "flipfit", within: window };
                }
                else if ($source && $source.length)
                {
                    //offset = $field.offset();
                    //_fwdc.ensureElementVisible($source);
                    _fwdc.scrollIntoView($source);
                    //leftOffset = offset.left - _fwdc.$window.scrollLeft();
                    //topOffset = offset.top + $field.outerHeight() - _fwdc.$window.scrollTop();
                    //return { my: "left+" + leftOffset + " top+" + topOffset, at: "left top", of: _fwdc.window, collision: "fit", within: window };
                    return { my: "left top+2", at: "left bottom", of: $source, collision: "flipfit", within: window };
                }
                else
                {
                    return _modalPosition();
                }
            };

            _fwdc.onScreenWidthChanged = function ()
            {
                _fwdc.hideManagerMenu();
                _fwdc.updateScreenSizeSpecificElements();
            };

            _fwdc.evaluateDialogScreenSize = function ($modal)
            {
                // Context menus should be excluded from this logic.
                var $dialog = $modal.parent();
                if ($dialog.hasClass("ContextMenuModal") || $modal.childrenWithClass("FastModalCustomSize").length || _fwdc.embedded)
                {
                    return;
                }

                var pixelWidth = $modal.width();
                var priorWidth = $modal.data("fast-modal-screen-width");
                var newWidth = priorWidth;
                var newWidthClass;

                if (pixelWidth < _fwdc.ModalScreenWidthSizes.Medium)
                {
                    newWidth = _fwdc.ScreenWidths.Small;
                    newWidthClass = "Small";
                }
                else if (pixelWidth < _fwdc.ModalScreenWidthSizes.Large)
                {
                    newWidth = _fwdc.ScreenWidths.Medium;
                    newWidthClass = "Medium";
                }
                else if (pixelWidth < _fwdc.ModalScreenWidthSizes.Wide)
                {
                    newWidth = _fwdc.ScreenWidths.Large;
                    newWidthClass = "Large";
                }
                else
                {
                    newWidth = _fwdc.ScreenWidths.Wide;
                    newWidthClass = "Wide";
                }

                if (priorWidth !== newWidth)
                {
                    $modal
                        .removeClass("FastModalSizeSmall FastModalSizeMedium FastModalSizeLarge FastModalSizeWide")
                        .addClass("FastModalSize" + newWidthClass)
                        .data("fast-modal-screen-width", newWidth);

                    _fwdc.updateScreenSizeSpecificElements($modal);
                }
            };

            _fwdc.evaluateDialogScreenResize = function (event, ui)
            {
                _fwdc.evaluateDialogScreenSize($(this));
            };

            function _createModalManager(content)
            {
                var $accessKeyElements = _fwdc.disableAccessKeys();

                _fwdc.modalManagerCount += 1;
                var $modal = $('<div id="MODAL_MANAGER_' + _fwdc.modalManagerCount + '" class="FastDialogElement FastModalDialog ManagerModalContainer" style="display:none"></div>');
                var $content = $($.parseHTML(content, true));
                if ($content.attr("title"))
                {
                    $modal.attr("title", $content.attr("title"));
                    $content.removeAttr("title");
                }
                var colorClass = _fwdc.getColorClass($content);
                $modal.append($content);

                var id = parseInt($content.attr("data-manager-container"), 10);

                var contextMenu = $content.hasClass("ManagerContextMenu");
                var resizable = !contextMenu && !_fwdc.embedded;
                var draggable = !contextMenu && !_fwdc.embedded;

                var position;
                var width = "auto";
                var height = "auto";

                var show;
                var hide;

                var dialogClass = " " + colorClass;


                if (contextMenu)
                {
                    dialogClass = "ContextMenuModal";
                    if (_fwdc.isSinglePanelContent($content, false))
                    {
                        dialogClass += " FastPanel SingleFastPanel";
                    }

                    position = _fwdc.contextMenuPosition($content);
                }
                else if (_fwdc.embedded)
                {
                    dialogClass += " FastModalFullDisplay";
                }
                else
                {
                    position = _modalPosition($content.attr("data-open-position"));
                }

                _fwdc.minimizeChatDialog();

                $modal.dialog({
                    modal: true,
                    draggable: draggable,
                    resizable: resizable,
                    width: width,
                    height: height,
                    title: $content.attr('data-modal-title') || "",
                    minWidth: 100,
                    minHeight: 50,
                    position: position,
                    dialogClass: "ManagerModalDialog ContainerModal " + dialogClass + " " + _fwdc.getFastModalClass(),
                    closeOnEscape: contextMenu,
                    closeText: _fwdc.getCloseText(),
                    show: show,
                    hide: hide,
                    opening: function (event, ui)
                    {
                        _fwdc.setupControls($content);
                        _fwdc.resizeElements($content, true);
                    },
                    open: function (event, ui)
                    {
                        _fwdc.setManagerContainer($content, id);

                        FWDC.hideViewMenus();

                        var $this = $(this);

                        _fwdc.setupModalOverlay($this, contextMenu);

                        if (resizable) { $modal.addClass("ModalResizable"); }

                        _fwdc.checkModalsOpen();

                        _fwdc.setupControls();
                        _fwdc.resizeElements($content, true);

                        _fwdc.sizeContentModals($modal);
                        _fwdc.updateScreenReader();

                        _fixModalOrder();

                        FWDC.resumeAutoRefresh();

                        _fwdc.setTimeout("_createModalManager.Dialog", function ()
                        {
                            _fwdc.showCurrentFieldTip();
                        });

                        _fwdc.evaluateDialogScreenSize($this);
                    },
                    beforeClose: _onManagerModalClosing,
                    drag: function () { FWDC.checkFieldTipPositions(); },
                    hiding: function ()
                    {
                        _fwdc.modalManagerCount -= 1;
                        _fwdc.clearManagerContainer($modal.find(".ManagerContainer").first(), id);
                    },
                    close: function ()
                    {
                        FWDC.hideViewMenus();
                        _fwdc.restoreAccessKeys($accessKeyElements);
                        _fwdc.hideToolTips();
                        _fwdc.closeComboboxes();
                        _fwdc.destroyRichElements(false, $modal);
                        $modal.remove();
                        _fwdc.showCurrentFieldTip();
                        //_fwdc.modalManagerCount -= 1;
                        _fwdc.checkModalsOpen();
                    },
                    resizeStart: function (ui)
                    {
                        $modal.closest(".ui-dialog").addClass("ModalResized");
                    },
                    resize: _fwdc.evaluateDialogScreenResize
                });
            }

            var _contentReady = null;
            _fwdc.onContentReady = function (callback)
            {
                if (!_contentReady)
                {
                    _fwdc.busy.done(callback);
                }
                else
                {
                    if (_contentReady === true)
                    {
                        _contentReady = $.Callbacks('once unique memory');
                    }

                    _contentReady.add(callback);
                }
            };

            _fwdc.fireContentReady = function ()
            {
                _fwdc.busy.done(function ()
                {
                    if (_contentReady && _contentReady !== true)
                    {
                        _contentReady.fire();
                    }
                    _contentReady = null;
                });
            };

            //_fwdc.loadManager = function (trigger, noRefresh, copy, prepareCallback, busy, switchingBack, lightRefresh)

            _fwdc.loadManager = function (trigger, options)
            {
                options = $.extend({}, options);

                var initial = options.initial;
                var noRefresh = options.noRefresh;
                var copy = options.copy;
                var prepareCallback = options.prepareCallback;
                var busy = options.busy;
                var switchingBack = options.switchingBack;
                var lightRefresh = options.lightRefresh;

                var args = {
                    'Load': '1',
                    'FAST_SCRIPT_VER__': _fwdc.scriptVersion,
                    'FAST_VERLAST__': _fwdc.fastVerLast,
                    'FAST_VERLAST_SOURCE__': _fwdc.fastVerLastSource,
                    'FAST_CLIENT_WHEN__': _fwdc.now(),
                    'FAST_CLIENT_WINDOW__': _fwdc.getFastWindowName(),
                    "FAST_CLIENT_AJAX_ID__": ++_ajaxId,
                    "FAST_CLIENT_TRIGGER__": trigger
                };

                _fwdc.autoRevealBody(2000);

                if (noRefresh)
                {
                    args.NoRefresh = true;
                }

                if (lightRefresh)
                {
                    args.LightRefresh = "1";
                }

                if (copy)
                {
                    args.Copy = copy;
                }

                if (busy === undefined)
                {
                    busy = true;
                }

                return _fwdc.ajax({
                    url: './?' + $.param(args),
                    displayOperation: "Page.Load",
                    type: 'GET',
                    busy: false,
                    forceVerLast: true,
                    beforeSend: function ()
                    {
                        if (busy) { busy = _busy.show("Page.Load"); }
                    },
                    success: function (data, status, request)
                    {
                        _contentReady = true;
                        try
                        {
                            if (prepareCallback) { prepareCallback(); }

                            var contents = data.contents;

                            if (contents && contents.length)
                            {
                                var contentLengths = contents.length;
                                for (var ii = 0; ii < contentLengths; ii++)
                                {
                                    var content = contents[ii];

                                    if (content.pagetitle)
                                    {
                                        _fwdc.setPageTitle(content.pagetitle);
                                    }

                                    var $updateContainer = null;

                                    if (content.manager)
                                    {
                                        _fwdc.runResponseFunctions(content, false);
                                        _fwdc.setCurrentManagerHtml(content.manager, true, switchingBack);
                                        _fwdc.runResponseFunctions(content, true);
                                        $updateContainer = _fwdc.currentManagerContainer();
                                    }
                                    else if (content.managerModal)
                                    {
                                        _fwdc.runResponseFunctions(content, false);
                                        _createModalManager(content.managerModal);
                                        _fwdc.runResponseFunctions(content, true);
                                        $updateContainer = _fwdc.currentManagerContainer();
                                    }
                                    else if (content.docModal)
                                    {
                                        _fwdc.runResponseFunctions(content, false);
                                        _openModalViewDialog(content.docModal, true);
                                        _fwdc.runResponseFunctions(content, true);
                                        $updateContainer = _fwdc.currentDocumentContainer();
                                    }

                                    if ($updateContainer)
                                    {
                                        _fwdc.setupControls($updateContainer);
                                        _fwdc.resizeElements($updateContainer, true);
                                        _fwdc.sizeContentModals();
                                    }
                                }
                            }
                            else if (data.content)
                            {
                                var $manager = $($.parseHTML(data.content, null, true));
                                var id = $manager.attr("id");
                                var $target = $.findElementById(id);
                                if ($target && $target.length)
                                {
                                    $target.replaceWith($manager);
                                }
                                else
                                {
                                    $("#FAST_ROOT_MANAGER__").append($manager);
                                }
                                _fwdc.onManagerHtmlUpdated($manager);
                            }

                            if (data.redirect)
                            {
                                FWDC.openUrl(data.redirect);
                            }

                            if (data.message)
                            {
                                setTimeout(function () { FWDC.messageBox(data.message); }, 1);
                            }

                            if (busy)
                            {
                                _busy.hide(busy);
                            }

                            _fwdc.focusCurrentField(true);

                            _fwdc.updateLastScrollFocusIn();

                            _fwdc.showCurrentFieldTip();

                            _fwdc.updateScreenReader();

                            if (initial)
                            {
                                _fwdc.runInitialScreenSetup();
                            }
                        }
                        finally
                        {
                            _fwdc.fireContentReady();
                        }
                    },
                    error: function ()
                    {
                        if (busy) { _busy.hide(busy); }
                    },
                    complete: function ()
                    {
                        _fwdc.revealBody();
                    }
                });
            };

            _fwdc.openModalManager = function (modalId)
            {
                return _fwdc.ajax({
                    url: './?' + $.param({
                        'Load': '1',
                        'ModalId': modalId,
                        'FAST_SCRIPT_VER__': _fwdc.scriptVersion,
                        'FAST_VERLAST__': _fwdc.fastVerLast,
                        'FAST_VERLAST_SOURCE__': _fwdc.fastVerLastSource,
                        'FAST_CLIENT_WHEN__': _fwdc.now(),
                        'FAST_CLIENT_WINDOW__': _fwdc.getFastWindowName(),
                        'FAST_CLIENT_AJAX_ID__': ++_ajaxId
                    }),
                    async: false,
                    busy: false,
                    type: 'GET',
                    dataType: "json",
                    success: function (data, status, request)
                    {
                        _createModalManager(data.manager);
                    }
                });
            };

            _fwdc.checkModalsOpen = function ()
            {
                var $modals = $(_fwdc.selectors.fullModals);
                if ($modals.length)
                {
                    $(".ManagerBase").addClass("FullModalOpen");
                    $modals.removeClass("TopFullModal").last().addClass("TopFullModal");
                }
                else
                {
                    $(".ManagerBase").removeClass("FullModalOpen");
                }
            };

            // Based on: http://stackoverflow.com/questions/11076975/insert-text-into-textarea-at-cursor-position-javascript
            _fwdc.insertAtCursor = function (element, text)
            {
                // Internet Explorer
                if (document.selection)
                {
                    element.focus();
                    var sel = document.selection.createRange();
                    sel.text = text;
                }
                else if (element.selectionStart || element.selectionStart === 0)
                {
                    var startPos = element.selectionStart;
                    var endPos = element.selectionEnd;
                    element.value = element.value.substring(0, startPos) + text + element.value.substring(endPos, element.value.length);
                    element.selectionStart = startPos + text.length;
                    element.selectionEnd = startPos + text.length;
                }
                else
                {
                    element.value += text;
                }
            };

            _fwdc.topModal = function ()
            {
                var $modals = $(_fwdc.selectors.modalContainers);
                if ($modals.length)
                {
                    return $modals.last();
                }

                return null;
            };

            _fwdc.topDialog = function ()
            {
                var $dialogs = $(_fwdc.selectors.nonTopDialogs);
                if ($dialogs.length)
                {
                    return $dialogs.last();
                }

                return null;
            };

            _fwdc.navigateCloseModal = function ()
            {
                var $modal = _fwdc.topDialog();
                if ($modal)
                {
                    $modal.dialog("close");
                    return true;
                }

                return false;
            };

            _fwdc.setupFastTabs = function (elementOrId, options)
            {
                if (elementOrId)
                {
                    var $element;
                    if (typeof elementOrId === "string")
                    {
                        $element = $("#" + elementOrId);
                    }
                    else
                    {
                        $element = $(elementOrId);
                    }

                    if ($element && $element.is(".FastTabContainer"))
                    {
                        var $tabContainer = $element.children(".FastTabs");

                        var $tabs = $tabContainer.children(".FastTab");
                        $tabs.first().addClass("FastTabCurrent");

                        var $contents = $element.children(".FastTabContent");
                        $contents.first().addClass("FastTabCurrentContent");

                        options = options || {};

                        if (options.vertical)
                        {
                            $element.addClass("Vertical");
                        }

                        return $element;
                    }
                }
            };

            _fwdc.showStandardDialog = function (event, options)
            {
                var checkBusy = _default(options.checkBusy, true);
                if (checkBusy && _busy())
                {
                    return false;
                }

                if (!options || !options.dialog) { return false; }

                FWDC.hideViewMenus();

                _fwdc.stopEvent(event);

                var dialog = options.dialog;
                var setupCallback = options.setupCallback;
                var height = options.height || "auto";
                var width = options.width || "auto";
                var dialogClass = options.dialogClass || "";
                var contextMenu = options.contextMenu;
                var noFocus = options.noFocus;
                var titlebar = _default(options.titlebar, !contextMenu);
                var autoCreate = _default(options.autoCreate, true);

                if (!titlebar)
                {
                    dialogClass = "FastDialogNoTitlebar " + dialogClass;
                }

                if (contextMenu)
                {
                    dialogClass = "FastStandardContextMenu " + dialogClass;
                }

                return _fwdc.ajax({
                    url: 'Dialog/' + dialog,
                    type: 'GET',
                    data: options.data,
                    dataType: "html",
                    checkBusy: checkBusy,
                    async: options.async,
                    success: function (data, status, request)
                    {
                        var $accessKeyElements = _fwdc.disableAccessKeys();
                        var $body = _fwdc.$body();
                        var $modal = $('<div id="STANDARD_DIALOG_' + dialog + '" class="FastDialogElement FastStandardDialog" style="display:none"></div>');

                        var $content = $($.parseHTML(request.responseText));
                        if ($content.attr("title"))
                        {
                            $modal.attr("title", $content.attr("title"));
                            $content.removeAttr("title", "");
                        }
                        $modal.append($content);

                        var createDialog = function ()
                        {
                            $body.append($modal);
                            $modal.dialog({
                                modal: true,
                                draggable: true,
                                resizable: true,
                                width: width,
                                height: height,
                                position: { my: "center", at: "center", collision: "none" },
                                dialogClass: _fwdc.getFastModalClass() + " FastPanelDialog " + dialogClass,
                                closeOnEscape: contextMenu,
                                closeText: _fwdc.getCloseText(),
                                open: function ()
                                {
                                    if (options && options.dialogData)
                                    {
                                        $content.data("fast-dialog-data", options.dialogData);
                                    }

                                    FWDC.hideViewMenus();
                                    _fwdc.updateScreenReader();
                                    _fwdc.showCurrentFieldTip();

                                    var $this = $(this);
                                    _fwdc.setupModalOverlay($this, contextMenu);

                                    _fwdc.updateScreenReader();

                                    _fixModalOrder();

                                    // This logic caused early focus and a jump when the tooltip had to be adjusted.  Native dialog focus can handle it.
                                    //if (!noFocus)
                                    //{
                                    //    _fwdc.setTimeout("showStandardDialog.Dialog", function ()
                                    //    {
                                    //        _fwdc.focusCurrentField();
                                    //        _fwdc.showCurrentFieldTip();
                                    //    });
                                    //}

                                    if (options.open)
                                    {
                                        options.open.call(this, $modal, $content, options);
                                    }
                                },
                                drag: function ()
                                {
                                    FWDC.hideViewMenus();
                                    FWDC.checkFieldTipPositions();
                                },
                                close: function ()
                                {
                                    FWDC.hideViewMenus();
                                    _fwdc.hideToolTips();
                                    _fwdc.closeComboboxes();
                                    $modal.remove();
                                    _fwdc.restoreAccessKeys($accessKeyElements);
                                    _fwdc.showCurrentFieldTip();
                                    FWDC.resumeAutoRefresh();
                                }
                            });
                        };

                        if (setupCallback)
                        {
                            setupCallback($modal, $content, options, createDialog);
                        }

                        if (autoCreate)
                        {
                            createDialog();
                        }
                    }
                });
            };

            _fwdc.getStandardDialog = function (event)
            {
                var $dialog;
                if (event && event.currentTarget)
                {
                    $dialog = $(event.currentTarget).closest(".FastStandardDialog");
                }
                if (!$dialog || !$dialog.length)
                {
                    $dialog = $.findElementsByClassName("FastStandardDialog").last();
                }

                return $dialog && $dialog.length && $dialog;
            };

            _fwdc.closeStandardDialog = function (event, $dialog)
            {
                _fwdc.stopEvent(event);

                if (!$dialog)
                {
                    $dialog = _fwdc.getStandardDialog(event);
                }

                if ($dialog)
                {
                    try
                    {
                        $dialog.dialog("close");
                    }
                    catch (ignore)
                    {
                        $dialog.tryDestroyDialog().remove();
                    }
                    FWDC.resumeAutoRefresh();
                }

                $(event.currentTarget).data("dialog-closed", true);
            };

            _fwdc.selectFieldText = function (fieldId, selectionStart, selectionLength)
            {
                var $field = _fwdc.formField(fieldId, true);
                if ($field && $field.length && !isNaN(selectionStart) && !isNaN(selectionLength))
                {
                    var cmSetup = $field.data("fast-code-mirror-editor-setup");
                    if (cmSetup)
                    {
                        cmSetup.add(function ()
                        {
                            var cm = $field.data("fast-code-mirror-editor");
                            if (cm)
                            {
                                var selectionEnd = cm.posFromIndex(selectionStart + selectionLength);
                                selectionStart = cm.posFromIndex(selectionStart);

                                cm.setSelection(selectionEnd, selectionStart);
                            }
                            else
                            {
                                _fwdc._warn("code mirror box has no editor after setup:", $field);
                            }
                        });
                    }
                    else
                    {
                        var field = $field[0];

                        if (field)
                        {
                            if (field.createTextRange)
                            {
                                var range = field.createTextRange();
                                range.collapse(true);
                                range.moveStart('character', selectionStart);
                                range.moveEnd('character', selectionStart + selectionLength);
                                range.select();
                                field.focus();
                            }
                            else if (field.setSelectionRange)
                            {
                                field.focus();
                                field.setSelectionRange(selectionStart, selectionStart + selectionLength);
                            }
                            else if (typeof field.selectionStart !== 'undefined')
                            {
                                field.selectionStart = selectionStart;
                                field.selectionEnd = selectionStart + selectionLength;
                                field.focus();
                            }
                        }
                    }
                }
            };

            _fwdc.attachmentDialog = function (event, options, force, hidden)
            {
                _fwdc.stopEvent(event);

                if (!options)
                {
                    options = { control: "" };
                }
                else if (typeof options === "string")
                {
                    options = { control: options };
                }

                var width = "35rem";
                if (_fwdc.screenWidth < _fwdc.ScreenWidths.Medium)
                {
                    width = "90%";
                }

                var data = { CONTROL__: options.control || "", FIELD__: options.field || "", TARGET__: options.target || "", TYPE__: options.type || "" };

                var $currentForm = $("#ATTACHMENT_DIALOG");
                if (!$currentForm.closest(".ui-dialog").length)
                {
                    $currentForm.remove();
                }

                _fwdc.showStandardDialog(event,
                    {
                        dialog: "Attachment",
                        autoCreate: false,
                        data: data,
                        width: width,
                        async: false, // iOS Safari panics when we try to do input.click later if we break the call stack from the event.
                        setupCallback: function ($modal, $form, dialogOptions, createDialogCallback)
                        {
                            var $progress = $form.find(".DialogProgressBar").addClass("InactiveProgressBar").progressbar({ value: 0 });
                            if ($("<input type='file'/>").get(0).files === undefined)
                            {
                                $progress.hide();
                                hidden = false;
                            }

                            $form.ajaxForm({
                                global: false,
                                dataType: "script",
                                beforeSerialize: function ($form, options)
                                {
                                    $form.find("#FAST_SCRIPT_VER__").val(_fwdc.scriptVersion);
                                    $form.find("#FAST_VERLAST__").val(_fwdc.fastVerLast);
                                    $form.find("#FAST_VERLAST_SOURCE__").val(_fwdc.fastVerLastSource);
                                    $form.find("#FAST_CLIENT_WINDOW__").val(_fwdc.getFastWindowName());
                                },
                                beforeSubmit: function (data, $form, options)
                                {
                                    $progress.progressbar("value", 0);

                                    var $attachmentType = $form.find('#AttachmentType');
                                    if ($attachmentType.length)
                                    {
                                        if (!$attachmentType.val() && $attachmentType.hasClass("FieldRequired"))
                                        {
                                            _fwdc.getData({
                                                control: "MANAGER__",
                                                dataType: "text",
                                                type: "ManagerDecode",
                                                target: "AttachTypeRequired",
                                                callback: function (decode)
                                                {
                                                    FWDC.messageBox({ message: decode, icon: FWDC.MessageBoxIcon.Error, buttons: FWDC.MessageBoxButton.Ok });
                                                }
                                            });
                                            return false;
                                        }
                                    }

                                    var $attachmentDesc = $form.find('#AttachmentDescription');
                                    if ($attachmentDesc.length)
                                    {
                                        $attachmentDesc.val(($attachmentDesc.val() || "").trim());

                                        if (!$attachmentDesc.val() && $attachmentDesc.hasClass("FieldRequired"))
                                        {
                                            _fwdc.getData({
                                                control: "MANAGER__",
                                                dataType: "text",
                                                type: "ManagerDecode",
                                                target: "AttachDescRequired",
                                                callback: function (decode)
                                                {
                                                    FWDC.messageBox({ message: decode, icon: FWDC.MessageBoxIcon.Error, buttons: FWDC.MessageBoxButton.Ok });
                                                }
                                            });
                                            return false;
                                        }
                                    }

                                    var $attachmentFile = $form.find('#AttachmentFile');
                                    if ($attachmentFile.length)
                                    {
                                        if (!$attachmentFile.val() && $attachmentFile.hasClass("FieldRequired"))
                                        {
                                            _fwdc.getData({
                                                control: "MANAGER__",
                                                dataType: "text",
                                                type: "ManagerDecode",
                                                target: "AttachFileRequired",
                                                callback: function (decode)
                                                {
                                                    FWDC.messageBox({ message: decode, icon: FWDC.MessageBoxIcon.Error, buttons: FWDC.MessageBoxButton.Ok });
                                                }
                                            });
                                            return false;
                                        }
                                    }

                                    _busy.show("BeforeSubmitAttachmentForm", { delay: 0, showProgress: true });

                                    return true;
                                },
                                uploadProgress: function (event, position, total, percent)
                                {
                                    if (hidden)
                                    {
                                        _busy.setProgress(position, total);
                                    }
                                    else
                                    {
                                        $progress.removeClass("InactiveProgressBar").progressbar("value", percent);
                                    }
                                },
                                success: function (data, status, request, $form)
                                {
                                    if (!_fwdc.handleResponse(request, this, data))
                                    {
                                        $form.find(".DialogProgressBar").progressbar("value", 0);
                                        this.error();
                                        return false;
                                    }

                                    if (hidden)
                                    {
                                        $modal.remove();
                                        $form.remove();
                                    }
                                },
                                error: function ()
                                {
                                    if (!hidden)
                                    {
                                        $progress.progressbar("value", 0);
                                    }
                                    FWDC.attachmentFailed(_fwdc.getDecode("AttachmentError"), null, null, true);

                                    if (hidden)
                                    {
                                        $modal.remove();
                                        $form.remove();
                                    }
                                }
                            });

                            var showDialog = true;
                            if (hidden)
                            {
                                var $input = $form.find("input[type='file']");
                                if ($input && $input.length)
                                {
                                    try
                                    {
                                        var submitted;
                                        $input.on("change", function (event)
                                        {
                                            if (!submitted)
                                            {
                                                submitted = true;
                                                $form.submit();
                                            }
                                        });

                                        showDialog = false;

                                        if (!showDialog && !submitted)
                                        {
                                            // iOS Wants the input to be in the DOM to allow access.
                                            _fwdc.supportElementsContainer().find(".TemporaryUploadForm").remove();
                                            _fwdc.supportElementsContainer().append($form.addClass("Hidden TemporaryUploadForm"));
                                        }

                                        $input.click();

                                        // Older MSIE browsers suspend the script thread after the .click(), so we need to check if we should submit right away.
                                        if (!submitted && $input.val().length)
                                        {
                                            submitted = true;
                                            $form.submit();
                                        }
                                    }
                                    catch (ignore)
                                    {
                                        _busy.hide();
                                        showDialog = true;
                                        hidden = false;
                                        $form.remove();
                                    }
                                }
                            }

                            if (showDialog)
                            {
                                createDialogCallback();
                            }
                        }
                    });
            };

            _fwdc.importDialog = function (event)
            {
                return _fwdc.showStandardDialog(event, {
                    dialog: "Import",
                    setupCallback: function ($modal, $form, dialogOptions, createDialog)
                    {
                        var $progress = $form.find(".DialogProgressBar").addClass("InactiveProgressBar").progressbar({ value: 0 });
                        if ($("<input type='file'/>").get(0).files === undefined)
                        {
                            $progress.hide();
                        }

                        $form.ajaxForm({
                            global: false,
                            dataType: "script",
                            beforeSerialize: function ($form, options)
                            {
                                $form.find("#FAST_SCRIPT_VER__").val(_fwdc.scriptVersion);
                                $form.find("#FAST_VERLAST__").val(_fwdc.fastVerLast);
                                $form.find("#FAST_VERLAST_SOURCE__").val(_fwdc.fastVerLastSource);
                                $form.find("#FAST_CLIENT_WINDOW__").val(_fwdc.getFastWindowName());
                            },
                            beforeSubmit: function (data, $form, options)
                            {
                                $progress.progressbar("value", 0);
                                if ($form.find("#File").val() === "")
                                {
                                    return false;
                                }
                                _busy.show("BeforeSubmitImportForm", { delay: 0 });
                            },
                            uploadProgress: function (event, position, total, percent)
                            {
                                $progress.removeClass("InactiveProgressBar").progressbar("value", percent);
                            },
                            success: function (data, status, request, $form)
                            {
                                if (!_fwdc.handleResponse(request, this, data))
                                {
                                    this.error();
                                    return false;
                                }
                            },
                            error: function ()
                            {
                                _busy.hide();
                                $progress.progressbar("value", 0);
                                FWDC.importFailed(_fwdc.getDecode("ImportError"), null, null, true);
                            }
                        });
                    }
                });
            };

            _fwdc.currentForm = function ()
            {
                var $dialog = _fwdc.currentDialogContainer(true);

                var $form = ($dialog && $dialog.length) ? $dialog.find(".FastForm") : $(_fwdc.selectors.documentContainer).children(".FastForm");

                return ($form && $form.length) ? $form.last() : null;
            };

            _fwdc.specialDialogOpen = function ()
            {
                return !!$(_fwdc.selectors.specialDialogs).length;
            };

            _fwdc.executeAction = function (event, actionId, type, confirmed)
            {
                _fwdc.stopEvent(event);
                return _fwdc.ajax({
                    url: 'ExecuteAction',
                    data: function ()
                    {
                        return _fwdc.getDocPostParameters({
                            ACTION_ID__: actionId,
                            TYPE__: type,
                            CLOSECONFIRMED__: !!confirmed,
                            EVENT_TYPE__: _fwdc.EventType.fromEvent(event)
                        });
                    },
                    beforeRequest: function (args)
                    {
                        _fwdc.setConfirmCallback(function ()
                        {
                            _fwdc.executeAction(event, actionId, type, true);
                        });
                    },
                    success: function (data, status, request)
                    {
                        _fwdc.handleActionResult(data, { actionId: actionId, type: type });
                    }
                });
            };

            _fwdc.viewLinkClicked = function (options)
            {
                var fieldId = options.fieldId;
                var sourceId = options.sourceid || fieldId;
                var trigger = options.trigger;
                var force = options.fource;
                var server = options.server;

                return _fwdc.ajax({
                    url: 'ViewLinkClicked',
                    async: !force,
                    busy: !force,
                    checkBusy: !force,
                    trigger: trigger,
                    //sender: event && (event.currentTarget || event.target),
                    sourceId: sourceId,
                    data: function ()
                    {
                        return _fwdc.getDocPostParameters({ EVENT__: fieldId });
                    },
                    beforeRequest: function (args)
                    {
                        if (!server) { _linkSourceInfo = { field: fieldId }; }
                    },
                    success: function (data, status, request)
                    {
                        _fwdc.handleActionResult(data);
                    }
                });
            };

            //_fwdc.getElementCaption = function (element)
            //{
            //    var $element = element instanceof jQuery ? element : $(element);
            //    if ($element.is("input,select,textarea"))
            //    {
            //        var ariaLabel = $element.attr("aria-label");
            //        if (ariaLabel)
            //        {
            //            return ariaLabel;
            //        }

            //        var $cgContainer = $element.closest(".ControlGridField");
            //        if ($cgContainer && $cgContainer.length)
            //        {

            //            var $label = $cgContainer.find(".ControlGridDecode2 > label");
            //            if ($label && $label.length)
            //            {
            //                var decode2caption = $label.text();
            //                if (decode2caption) { return decode2caption; }
            //            }

            //            return $element.attr("id");
            //        }

            //        var $cell = $element.closest(".TDC");
            //        if ($cell && $cell.length)
            //        {
            //            var $table = $cell.closest("table");
            //            var tableCaption = $table.attr("aria-label") || "Unlabelled Table";

            //            var cellIdSplit = $cell.attr("id").split("-");
            //            _currentColumnId = cellIdSplit.slice(0, -1).join("-");

            //            var caption = $cell.attr("id");
            //            var $columnHeader = $table.find("th#" + _currentColumnId + "-CH");
            //            if ($columnHeader && $columnHeader.length)
            //            {
            //                caption = $columnHeader.text() || caption;
            //            }

            //            var $row = $cell.parent("tr");
            //            if ($row && $row.length && $row.attr("data-fastrow") !== undefined)
            //            {
            //                caption = caption + ":" + $row.attr("data-fastrow");
            //            }

            //            return tableCaption + "\\" + caption;
            //        }
            //    }
            //    else if ($element.is("a,button"))
            //    {
            //        return $element.text() || $element.attr("id") || "";
            //    }
            //};

            _fwdc.disableChildLinks = function ($containers)
            {
                return $containers.find("a").removeAttr("onclick").addClass("DisableLink").attr("href", "#");
            };

            _fwdc.onManagerMenuLinkClicked = function (event)
            {
                var $link = $(event.currentTarget);
                if ($link && $link.hasClass("KeepManagerMenu")) { return; }
                _fwdc.setTimeout("onManagerMenuLinkClicked", function ()
                {
                    _fwdc.hideManagerMenu();
                });
            };

            var _$managerMenu;
            var _$managerMenuOverlay;
            _fwdc.showManagerMenu = function (event, force, callback)
            {
                if (!force && _fwdc.uiBusy())
                {
                    return false;
                }

                _fwdc.stopEvent(event);

                if (_$managerMenu)
                {
                    if (callback)
                    {
                        callback();
                    }
                    else
                    {
                        _fwdc.hideManagerMenu(event);
                    }
                    return null;
                }

                var $sidebar = $("#Sidebar,#SidebarMenu").filterVisible().last();
                if ($sidebar.length)
                {
                    //_fwdc.ensureElementVisible($sidebar);
                    _fwdc.scrollIntoView($sidebar);
                    _tryFocusContainer($sidebar);
                    if (callback) callback();
                    return null;
                }

                var request = _fwdc.getData({
                    control: "MANAGER__",
                    type: "ManagerMenu",
                    dataType: "html",
                    busy: true,
                    callback: function (menuhtml)
                    {
                        _fwdc.hideManagerMenu(null, true);

                        _$managerMenuOverlay = $($.parseHTML("<div></div>"))
                            .addClass("ManagerMenuOverlay")
                            .appendTo(_fwdc.supportElementsContainer())
                            .click(_fwdc.hideManagerMenu);

                        _$managerMenu = $($.parseHTML(menuhtml))
                            .appendTo(_fwdc.supportElementsContainer())
                            .on("click", "a", _fwdc.onManagerMenuLinkClicked)
                            .on("click", "button", _fwdc.onManagerMenuLinkClicked);

                        _fwdc.initElements(_$managerMenu, true);

                        _fwdc.updateNotificationStatus();

                        _fwdc.onTransition("showManagerMenu.overlay", _$managerMenuOverlay, "ManagerMenuOpen", null, true);
                        _fwdc.onTransition("showManagerMenu.menu", _$managerMenu, "ManagerMenuOpen", function ()
                        {
                            var $linkset = _$managerMenu.findElementsByClassName("FastLinkSet");
                            if ($linkset && $linkset.length)
                            {
                                $linkset.linkset("focus");
                            }
                            else
                            {
                                _tryFocusContainer(_$managerMenu);
                            }

                            if (callback) callback();
                        }, true);
                    }
                });

                return request;
            };

            _fwdc.hideManagerMenu = function (event, immediate)
            {
                _fwdc.stopEvent(event);

                if (_$managerMenu)
                {
                    var $menu = _$managerMenu;
                    _$managerMenu = null;
                    if (immediate)
                    {
                        $menu.remove();
                    }
                    else
                    {
                        _fwdc.onTransition("hideManagerMenu.menu", $menu, "ManagerMenuHiding", function ()
                        {
                            $menu.remove();
                        }, true);
                    }

                    if (_$managerMenuOverlay)
                    {
                        var $overlay = _$managerMenuOverlay;
                        _$managerMenuOverlay = null;
                        if (immediate)
                        {
                            $overlay.remove();
                        }
                        else
                        {
                            _fwdc.onTransition("hideManagerMenu.Overlay", $overlay, "ManagerMenuHiding", function ()
                            {
                                $overlay.remove();
                            }, true);
                        }
                    }

                    _fwdc.busy.done(function ()
                    {
                        _fwdc.focusCurrentField();
                    });

                    return true;
                }

                return false;
            };

            _fwdc.navigate = function (event, trigger, step, managerRow, action, confirmed, browserNavigating, ignoreState)
            {
                _closeBasicDialogs();

                return _fwdc.ajax({
                    url: 'Navigate',
                    async: (action !== "NEWWINDOW"),
                    data: $.param({
                        MANAGERROW__: managerRow || "",
                        STEP__: step,
                        ACTION__: action || "",
                        CLOSECONFIRMED__: !!confirmed,
                        IGNORESTATE__: !!ignoreState,
                        EVENT_TYPE__: _fwdc.EventType.fromEvent(event)
                    }),
                    beforeRequest: function ()
                    {
                        _destroyMessageBoxes();
                        _fwdc.setConfirmCallback(function ()
                        {
                            _fwdc.navigate(event, trigger, step, managerRow, action, true, browserNavigating, ignoreState);
                        });
                    },
                    trigger: trigger,
                    success: function (data, status, request)
                    {
                        _fwdc.handleActionResult(data, { incrementHistory: !browserNavigating });
                    }
                });
            };

            _fwdc.setupViewSelectors = function ($container)
            {
                var found;
                $container = ($container || _fwdc.currentDocumentContainer());
                var $containers = $container.find(".TabContainer").each(function ()
                {
                    found = true;
                    var $tabs = $(this);
                    if (!$tabs.data("fast-ui-viewselector"))
                    {
                        $tabs.data("fast-ui-viewselector", true);

                        //var $inner = _fwdc.tap ? $tabs.find(".ViewTabSet") : $tabs.find(".InnerTabSet");
                        var $inner = $tabs.find(".TabSet");
                        if ($inner.length)
                        {
                            $inner.append('<li class="SelectorUnderline Init" data-current-selector=".ViewSelected .DocTabText" role="presentation"></li>');
                            /*$inner.find(".DocViewCaption").each(function ()
                            {
                                var $caption = $(this);
                                var $link = $caption.parent();
     
                                $caption
                                    .clone()
                                    .addClass("TabGhostSelectedCaption")
                                    .attr({
                                        "id": null,
                                        "role": "presentation",
                                        "aria-hidden": "true"
                                    })
                                    .prependTo($link);
                            });*/
                        }
                    }

                    /*_fwdc.setTimeout("setupViewSelectors.animateSelectorUnderline", function ()
                    {
                        _fwdc.animateSelectorUnderline($tabs, true);
                    });*/
                });

                if (found)
                {
                    _fwdc.updateSelectorUnderlines($containers);
                }
            };

            _fwdc.animateSelectorUnderline = function ($selectorContainers, immediate)
            {
                $selectorContainers.each(function ()
                {
                    var $container = $(this);

                    var $underline = $container.findElementsByClassName("SelectorUnderline");
                    if ($underline.length)
                    {
                        $container = $underline.parent();
                        var vertical = $container.css("flex-direction") === "column";
                        var currentSelector = $underline.attr("data-current-selector");
                        var $selected = $container.querySelectorAll(currentSelector).first();
                        var oldPos = $underline.data("selector-pos");

                        var position;

                        var selectorPosition;
                        var selectorSize;
                        var containerSize;

                        if ($selected.length)
                        {
                            // Use custom .nativeOffset to prevent issues with CSS transform affecting jQuery's .offset/.position.
                            if (vertical)
                            {
                                selectorPosition = Math.ceil($selected.nativeOffsetClosest($container).top);
                                selectorSize = Math.ceil($selected.outerHeight());
                                containerSize = $container.outerHeight();
                            }
                            else
                            {
                                selectorPosition = Math.ceil($selected.nativeOffsetClosest($container).left);
                                selectorSize = Math.ceil($selected.outerWidth());
                                containerSize = $container.outerWidth();
                            }

                            var oversize = containerSize - selectorPosition - selectorSize;
                            if (oversize < 0)
                            {
                                selectorSize += oversize;
                            }

                            position = {
                                "vertical": vertical,
                                "position": selectorPosition,
                                "size": selectorSize
                            };
                        }
                        else
                        {
                            position = {
                                "vertical": vertical,
                                "position": 0,
                                "size": 0
                            };
                        }

                        if (!oldPos || oldPos.vertical !== position.vertical || oldPos.position !== position.position || oldPos.size !== position.size)
                        {
                            if (immediate)
                            {
                                $underline.addClass("Init");
                            }

                            if (position.vertical)
                            {
                                $underline.css({ "top": position.position + "px", "height": position.size + "px", "left": "", "width": "" });
                            }
                            else
                            {
                                $underline.css({ "left": position.position + "px", "width": position.size + "px", "top": "", "height": "" });
                            }

                            $underline.data("selector-pos", position);

                            if (immediate)
                            {
                                _fwdc.setTimeout("animateSelectorUnderlineFinished", function ()
                                {
                                    $underline.removeClass("Init");
                                });
                            }
                        }
                    }
                });
            };

            _fwdc.updateSelectorUnderlines = function ($container)
            {
                var $underlines = $.findElementsByClassName("SelectorUnderline", $container);
                if ($underlines.length)
                {
                    _fwdc.animateSelectorUnderline($underlines.parent(), true);
                }
            };

            _fwdc.queueUpdateSelectorUnderlines = _fwdc.debounce(function ($container)
            {
                _fwdc.updateSelectorUnderlines($container);
            }, 100);

            _fwdc.updateScreenSizeSpecificElements = function ($container)
            {
                $.findElementsByClassName("ScreenSizeSpecific", $container).each(function ()
                {
                    var $element = $(this);

                    if ($element.is(".DocTable"))
                    {
                        var $fullSpanCells = $element.findElementsByClassName("FullSpanCell");

                        if ($fullSpanCells.length)
                        {
                            var $row = $element.querySelectorAll(".TableColumnHeaderRow,.TDR").first();

                            if ($row.length)
                            {
                                var $cells = $row.children();
                                var span = $cells.filter(":visible").length;

                                $fullSpanCells.attr("colspan", span || $cells.length);
                            }
                        }
                    }
                    else if ($element.is("colgroup.AdjustedPercentColumns"))
                    {
                        var $cols = $element.children("col");
                        _fwdc.resetColumnPercentWidths($cols);
                    }
                });

                _fwdc.initElements($container, true);
            };

            _fwdc.setupControls = function ($container, preferImmediate)
            {
                _scrollContainers().off("scroll", _onStructureScroll).on("scroll", _onStructureScroll);
                _setupTextareaPopups($container);
                //_setupDatePickers($container);
                _setupNoPaste($container);
                _fwdc.setupCheckboxButtons($container);
                _fwdc.setupButtonSets($container);
                _fwdc.setupCaptchas($container);
                _fwdc.setupViewSelectors($container);
                _fwdc.setupViewStacks($container);
                _fwdc.setupPanels($container);
                _fwdc.initElements($container, preferImmediate);
                //_fwdc.setupTableStickyElements($container);
                _fwdc.checkHeaderLinks($container);
                _fwdc.updateScreenSizeSpecificElements($container);
                _setupStepLists($container);
                _clearHelpElementClickHandlers($container);
                _fadeInMessages($container);
                //_fwdc.setupMobileViewHeader();
                //_setupViewTabsets();
            };

            _fwdc.raiseSelected = function (force, elements)
            {
                elements = elements || _fwdc.selectedIds();

                if (_$pendingNudgeElements)
                {
                    _nudgePendingElements(function ()
                    {
                        _fwdc.raiseSelected(force, elements);
                    }, true);
                }
                else
                {
                    if (elements.length > 0)
                    {
                        _fwdc.setLastFocusField(elements[elements.length - 1]);
                    }

                    _fwdc.ajax({
                        url: 'FieldsSelected',
                        checkBusy: !force,
                        async: false,
                        commitEdits: false,
                        data: function ()
                        {
                            return _fwdc.getDocPostParameters({ 'SELECTED_FIELDS__': elements.join(",") }, "input[type='hidden']");
                        },
                        error: function (request, status, error)
                        {
                            _fwdc.onAjaxError("FieldsSelected", request.responseText);
                        },
                        success: function (data, status, request)
                        {
                            _handleRecalcUpdates(data);
                            if (_recalcDocUpdated)
                            {
                                _fwdc.setSelectable(data.selectedFields);
                            }
                            else
                            {
                                _setSelectedFields(elements);
                            }
                        }
                    });
                }
            };

            _fwdc.clearSelected = function ()
            {
                var $container = _fwdc.currentDocumentContainer();
                $container.find(".ui-selected").removeClass("ui-selected");
                $container.find(".FastSelectionMenu").remove();
            };

            _fwdc.disableClick = function ()
            {
                /*jshint validthis: true */
                if (this.onclick)
                {
                    $(this).data("onclick_temp", this.onclick);
                    this.onclick = function () { return false; };
                }
            };

            _fwdc.enableClick = function ()
            {
                /*jshint validthis: true */
                var onclick = $(this).data("onclick_temp");
                if (onclick)
                {
                    $(this).data("onclick_temp", null);
                    this.onclick = onclick;
                }
            };

            _fwdc.selectedIds = function ($elements)
            {
                var $selectedElements = ($elements || _fwdc.currentDocumentContainer().find(".ui-selected"));
                var elements = [];
                $selectedElements.each(function ()
                {
                    var name = _findElementName(this);
                    if (name) { elements.push(name); }
                });

                return elements;
            };

            _fwdc.logOff = function (event, force)
            {
                if (!force && _busy()) { return false; }

                _fwdc.stopEvent(event);

                if (!force)
                {
                    var prompt = _fwdc.getDecode("LogOffPrompt", "");
                    if (prompt)
                    {
                        FWDC.messageBox({
                            message: prompt,
                            icon: FWDC.MessageBoxIcon.Question,
                            buttons: FWDC.MessageBoxButton.YesNo,
                            callback: function ($modal, tag, result)
                            {
                                if (result === FWDC.MessageBoxResult.Yes)
                                {
                                    _fwdc.logOff(null, true);
                                }
                            }
                        });
                        return;
                    }
                }

                _fwdc.clearJsonCookie("chatSettings");

                FWDC.openUrl("./LogOff/");
            };

            _fwdc.elementOnCurrentModal = function (element)
            {
                var $element = $(element);
                var $dialog = $element.closest(".FastModal");
                var $topDialog = $(".FastModal").filterNotHasClassName("fast-ui-dialog-closing").last();
                return $dialog.equals($topDialog);
            };

            _fwdc.elementOnCurrentDialog = function (element)
            {
                var $element = $(element);
                var $dialog = $element.closest(".ui-dialog");
                var $topDialog = $(".ui-dialog").filterNotHasClassName("fast-ui-dialog-closing").last();
                return $dialog.equals($topDialog);
            };

            _fwdc.messageBoxOpen = function ()
            {
                return !!$.querySelectorAll(".ui-dialog.FastMessageBox").filterNotHasClassName("fast-ui-dialog-closing").length;
            };

            _fwdc.lockSession = function (event)
            {
                return _fwdc.setPropertiesInternal(event, "MANAGER__", "LockSession", "True");
            };

            _fwdc.isCombobox = function ($field)
            {
                return $field.hasClass("DocControlCombobox") || $field.hasClass("DocControlUser");
            };

            _fwdc.acceptModal = function (event, force)
            {
                if (!force && _busy()) { return false; }
                _fwdc.commitEdits("AcceptModal");
                if (_fwdc.modalDocCount > 0)
                {
                    _fwdc.setModalState("OK");
                    _onDocViewModalClosing(null, _currentDocModal(), false, force);
                }
            };

            _fwdc.cancelModal = function (event, force)
            {
                if (!force && _busy()) { return false; }
                _fwdc.commitEdits("CancelModal");
                if (_fwdc.modalDocCount > 0)
                {
                    _fwdc.setModalState("Cancel");
                    _onDocViewModalClosing(null, _currentDocModal(), false, force);
                }
            };

            _fwdc.saveScrollPositions = function (local, alwaysElementsOnly)
            {
                //var savedScrollPositions = { "$window": { top: _fwdc.$window.scrollTop(), left: _fwdc.$window.scrollLeft() }, "ver": _scrollPositionVer };
                var savedScrollPositions = { "__ver": _scrollPositionVer };
                //$(".SnapScrollTop,.FastModal .DocumentForm,.FastModal .ControlContainer,.ManagerContentContainer,#Sidebar,.ViewScrollContainer,.DocScrollContainer .DataDocWrapper,.PanelScrollContainer,.FastScrollContainer,.ui-dialog-content,.ScrollTogether").each(function ()

                var selector = alwaysElementsOnly ? _fwdc.selectors.scrollElementsAlwaysPreserve : _fwdc.selectors.scrollElements;

                $(selector).each(function ()
                {
                    var $this = $(this);
                    var id = $this.attr("id");

                    if ($this.tagIs("html"))
                    {
                        id = "$window";
                        // Edge does not handle scrollposition on <html> properly.
                        $this = _fwdc.$window;
                    }

                    var scrollPos = { top: $this.scrollTop(), left: $this.scrollLeft() };

                    if (id)
                    {
                        savedScrollPositions[id] = scrollPos;
                    }
                });

                if (!local)
                {
                    _savedScrollPositions = savedScrollPositions;
                }

                return savedScrollPositions;
            };

            function _restoreScrollPosition($element, scrollPos)
            {
                if ($element && $element.length && scrollPos)
                {
                    if (scrollPos.top !== undefined && scrollPos.top !== null)
                    {
                        $element.scrollTop(scrollPos.top);
                    }

                    if (scrollPos.left !== undefined && scrollPos.left !== null)
                    {
                        $element.scrollLeft(scrollPos.left);
                    }
                }
            }

            _fwdc.restoreScrollPositions = function (scrollPositions, keepSaved)
            {
                var global;
                if (!scrollPositions)
                {
                    global = true;
                    scrollPositions = _savedScrollPositions;
                }

                if (scrollPositions)
                {
                    if (scrollPositions.__ver === _scrollPositionVer)
                    {
                        //_restoreScrollPosition(_fwdc.$window, scrollPositions.$window);

                        $.each(scrollPositions, function (element, scrollPos)
                        {
                            if (element !== "__ver")
                            {
                                var $element = null;
                                if (element === "$window")
                                {
                                    $element = _fwdc.$window;
                                }
                                else if (typeof element === "string")
                                {
                                    $element = $("#" + element);
                                }
                                else
                                {
                                    $element = $(element);
                                    if (!$element.inDom())
                                    {
                                        $element = null;
                                    }
                                }

                                if ($element && $element.length)
                                {
                                    _restoreScrollPosition($element, scrollPos);
                                }
                            }
                        });

                        if (global && !keepSaved)
                        {
                            _savedScrollPositions = null;
                        }
                    }
                    else if (global)
                    {
                        _savedScrollPositions = null;
                    }
                }
            };

            _fwdc.invalidateSavedScrollPositions = function ()
            {
                _scrollPositionVer++;
            };

            var _inFocus = false;

            function _updateMobileScrollInfo($layout, $container)
            {
                $container = $container || $layout.children(".DocTableMobileScrollContainer");
                $layout = $layout || $container.parent();

                if (!$layout.hasClass("Scrollable"))
                {
                    $layout.removeClass("LeftAvailable").removeClass("RightAvailable");
                    return;
                }

                var scrollWidth = $container.prop("scrollWidth");
                var scrollLeft = $container.scrollLeft();
                var innerWidth = $container.innerWidth();

                if (scrollLeft)
                {
                    $layout.addClass("LeftAvailable");
                }
                else
                {
                    $layout.removeClass("LeftAvailable");
                }

                if ((scrollLeft + innerWidth) < scrollWidth)
                {
                    $layout.addClass("RightAvailable");
                }
                else
                {
                    $layout.removeClass("RightAvailable");
                }

                //$container.find("td.TableTitlebar").css("left", scrollLeft + "px");
            }

            var _codeMirrorReady = (!window.CodeMirror) ? null : $.Callbacks("once unique memory").fire();
            var _codeMirrorModeReady = {};

            _fwdc.loadStylesheet = function (url)
            {
                if (document.createStyleSheet)
                {
                    document.createStyleSheet(url);
                }
                else
                {
                    $("head").append($.parseHTML("<link rel='stylesheet' href='" + url + "' type='text/css' />"));
                }
            };

            _fwdc.loadCodeMirror = function (mode, callback)
            {
                if (!_codeMirrorReady)
                {
                    _codeMirrorReady = $.Callbacks("once unique memory");
                    /*_codeMirrorReady.add(function ()
                    {
                        _fwdc.loadStylesheet("../Resource/codemirror-5.40.2.min.css" + _versionUrlSuffix);
                    });*/

                    _fwdc.loadScripts(['codemirror-5.40.2.js'], function ()
                    {
                        _codeMirrorReady.fire();
                    });
                }

                _codeMirrorReady.add(function ()
                {
                    if (!_codeMirrorModeReady[mode])
                    {
                        _codeMirrorModeReady[mode] = $.Callbacks("once unique memory");
                        _fwdc.loadScripts(['fast.codemirror.' + mode + '.js'], function ()
                        {
                            _codeMirrorModeReady[mode].fire();
                        });
                    }

                    _codeMirrorModeReady[mode].add(function ()
                    {
                        //callback();
                        _fwdc.setTimeout("codeMirrorReady." + mode, callback);
                    });
                });
            };

            _fwdc.createCodeMirrorBox = function (textArea, mode, options)
            {
                var $textArea = $(textArea);

                var readOnly = !!$textArea.attr("readonly");

                if (options && options.onBlur)
                {
                    options.afterBlur = options.onBlur;
                    delete options.onBlur;
                }

                if (options && options.onFocus)
                {
                    options.afterFocus = options.onFocus;
                    delete options.onFocus;
                }

                var selectionsData = $textArea.attr("data-cm-selections");
                var selections;
                if (selectionsData)
                {
                    selections = JSON.parse(selectionsData);
                }

                options = $.extend({
                    mode: mode,
                    indentUnit: 4,
                    matchBrackets: true,
                    theme: "fast",
                    readOnly: readOnly,
                    lineWrapping: $textArea.hasClass("Wrap"),
                    tabindex: $textArea.attr("tabIndex")
                }, options);

                if ($textArea.outerHeight() < 40)
                {
                    options.scrollbarStyle = "null";
                }

                var $container = $textArea.parent();

                $container.focusin(function (event) { $container.addClass("FastCmFocus"); });
                $container.focusout(function (event) { $container.removeClass("FastCmFocus"); });
                $container.mouseenter(function (event) { $container.addClass("FastCmHover"); });
                $container.mouseleave(function (event) { $container.removeClass("FastCmHover"); });
                //var $heightTarget = $container;

                var cm = CodeMirror.fromTextArea(textArea, options);

                var ignoreChange = false;
                cm.fastSetValue = function (value)
                {
                    ignoreChange = true;
                    cm.setValue(value);
                    ignoreChange = false;
                };

                cm.on("focus", function ()
                {
                    setTimeout(function ()
                    {
                        cm.save();

                        // Ensure we're still focused on the correct element before re-raising to the Fast focus logic.
                        var $focused = $(document.activeElement);
                        if ($focused.length && $focused.closest($container).length)
                        {
                            if (_fwdc.currentModalId() === _fwdc.fieldModalId($textArea))
                            {
                                _fwdc.Events.Field.focus(textArea);
                            }
                            if (options.afterFocus) { options.afterFocus(); }
                        }
                    }, 1);
                });

                cm.on("blur", function ()
                {
                    cm.fastLastCursor = cm.getCursor();
                    cm.save();
                    if (_fwdc.currentModalId() === _fwdc.fieldModalId($textArea))
                    {
                        _fwdc.Events.Field.blur(textArea);
                    }
                    if (options.afterBlur) { options.afterBlur(); }
                });

                var editorChangeTimeoutHandle = null;

                function onCodeMirrorUserActivity(eventName)
                {
                    if (editorChangeTimeoutHandle) { clearTimeout(editorChangeTimeoutHandle); }
                    editorChangeTimeoutHandle = setTimeout(function ()
                    {
                        cm.save();
                        _fwdc.onUserActivity({ event: eventName, fieldId: $textArea.attr("id"), getValue: function () { return $textArea.val(); }, async: true });
                        editorChangeTimeoutHandle = null;
                    }, 1000);
                }

                cm.on("change", function ()
                {
                    if (!ignoreChange) { onCodeMirrorUserActivity("CodeMirrorChange"); }
                });

                var $cmWrapper = $(cm.getWrapperElement());
                //$cmWrapper.height($textArea.innerHeight());


                cm.fast_refresh = function (checkHeight)
                {
                    if (checkHeight && (!options || !options.autoSize))
                    {
                        if ($textArea.attr("rows"))
                        {
                            $cmWrapper.outerHeight($textArea.outerHeight());
                        }
                        else
                        {
                            $cmWrapper.outerHeight($container.outerHeight());
                        }
                    }

                    cm.refresh();
                };

                cm.fast_refresh(true);

                if (selections)
                {
                    cm.setSelections(selections);
                }

                //_fwdc.resizeElements();
                //_fwdc.sizeContentModals();

                _fwdc.showCurrentFieldTip();

                $textArea.data("fast-code-mirror-editor", cm);
                $textArea.addClass("FastCodeMirrorBox").removeClass("FastCodeMirrorInit");
                $textArea.trigger("fastcmready");

                var codeMirrorSetup = $textArea.data("fast-code-mirror-editor-setup");
                if (codeMirrorSetup)
                {
                    codeMirrorSetup.fire();
                }

                return cm;
            };

            _fwdc.hideToggleLog = function ()
            {
                var $container = $('#CONTEXT_LOG_CONTAINER__');
                $container.remove();
                $("body").removeClass("ContextLogDocked");
            };

            _fwdc.toggleLog = function (value, force)
            {
                var $container = $('#CONTEXT_LOG_CONTAINER__');
                value = value || ($container.length ? "false" : "true");
                /*_fwdc.setPropertiesInternal(null, "MANAGER__", "ToggleLog", value, true, null, function ()
                {
                    if (value === "false" && $container.length)
                    {
                        _fwdc.hideToggleLog();
                    }
                });*/

                _fwdc.setProperties(null, {
                    control: "MANAGER__",
                    type: "ToggleLog",
                    target: value,
                    busy: true,
                    confirmedCallback: function ()
                    {
                        if (value === "false" && $container.length)
                        {
                            _fwdc.hideToggleLog();
                        }
                    }
                });
            };

            function _getContextScrollContainer()
            {
                return $("#CONTEXT_LOG_CONTAINER__ > .ContextDocumentContainer > .ContextLogDocumentForm > .DocumentContentWrapper > .ViewContainer");
            }

            _fwdc.setContextLog = function (html)
            {
                var $logContainer = $('#CONTEXT_LOG_CONTAINER__');
                var transition;
                if (!html)
                {
                    _fwdc.hideToggleLog();
                    return;
                }
                else if (!$logContainer.length)
                {
                    var settings = _fwdc.getJsonCookie("CtxLog");

                    $logContainer = $('<div id="CONTEXT_LOG_CONTAINER__" class="ContextLogContainer FastModalDialog"></div>').appendTo("body");

                    // TODO: Handle tiny browser context log?
                    if (settings.floating)
                    {
                        $logContainer.addClass("Floating").addClass("TopMostModal");

                        var width = 1000;
                        var height = 400;
                        var left = 50;
                        var top = 50;

                        if (settings.position)
                        {
                            left = settings.position.left;
                            top = settings.position.top;
                        }

                        if (settings.size)
                        {
                            width = settings.size.width;
                            height = settings.size.height;
                        }

                        var position = { my: "left+" + left + " top+" + top, at: "left top", of: _fwdc.window };

                        $("body").removeClass("ContextLogDocked");
                        $logContainer.dialog({
                            modal: false,
                            draggable: true,
                            resizable: true,
                            width: width,
                            height: height,
                            minHeight: 200,
                            minWidth: 750,
                            position: position,
                            // FastModal on this causes problems with other code that checks for the top modal.
                            // This dialog really isn't modal, so it should not use that class.
                            //dialogClass: "FastModal ContextLog",
                            dialogClass: "ContextLog",
                            closeOnEscape: false,
                            closeText: _fwdc.getCloseText(),
                            dragStop: function (event, ui)
                            {
                                _fwdc.editJsonCookie("CtxLog", function (settings)
                                {
                                    settings.position = { left: Math.floor(ui.position.left), top: Math.floor(ui.position.top) };
                                });
                            },
                            resizeStop: function (event, ui)
                            {
                                _fwdc.editJsonCookie("CtxLog", function (settings)
                                {
                                    settings.size = { width: Math.floor(ui.size.width), height: Math.floor(ui.size.height) };
                                    settings.position = { left: Math.floor(ui.position.left), top: Math.floor(ui.position.top) };
                                });
                            },
                            open: function ()
                            {
                                _fwdc.evaluateDialogScreenSize($(this));
                            },
                            close: function ()
                            {
                                $logContainer.remove();
                                _fwdc.toggleLog("false");
                            },
                            resize: _fwdc.evaluateDialogScreenResize
                        });
                    }
                    else
                    {
                        $logContainer.addClass("Docked");
                        $("body").addClass("ContextLogDocked");
                    }

                    $logContainer.html(html);
                }
                else
                {
                    transition = true;
                }

                var $scrollContainer = _getContextScrollContainer();
                var scrollTop = $scrollContainer.scrollTop();
                var scrollLeft = $scrollContainer.scrollLeft();

                var setup = function ($content)
                {
                    var $tabContainer = $content.find(".TabSet").first();
                    if ($tabContainer.length)
                    {
                        $('<li class="ViewSelectorButtonContainer"><button type="button"></li>')
                            .appendTo($tabContainer)
                            .children()
                            .addClass("ViewSelectorButton ContextLogToggleWindow")
                            .click(function ()
                            {
                                _fwdc.editJsonCookie("CtxLog", function (settings)
                                {
                                    settings.floating = !settings.floating;
                                });

                                $logContainer.remove();
                                _fwdc.toggleLog("true");
                            });

                        $('<li class="ViewSelectorButtonContainer"><button type="button"></li>')
                            .appendTo($tabContainer)
                            .children()
                            .addClass("ViewSelectorButton ContextLogClose")
                            .click(function ()
                            {
                                _fwdc.toggleLog("false");
                            });
                    }

                    //_fwdc.setupControls($logContainer);
                    _fwdc.setupControls($content);

                    //_fwdc.setupCheckboxButtons($logContainer);
                    //_fwdc.setupButtonSets($logContainer);

                    //_fwdc.setManagerContainer($new, id);
                    //_fwdc.setupControls($new);
                    ////_fwdc.isSinglePanelContent($new, true);
                    //_fwdc.resizeElements($new);
                    //_fwdc.sizeContentModals();
                    //_fwdc.applyVerLast($new);
                    //_fwdc.updateScreenReader();
                    //_fwdc.onManagerHtmlUpdated($new);
                    //_fwdc.handleManagerBusy($newManager);
                };

                if (transition)
                {
                    var $newManager = $($.parseHTML(html, document, true));
                    _fwdc.crossTransition($logContainer.children(), $newManager, null, "contextlog", {
                        //newClass: switchingClass,
                        //ignoreScroll: switching,
                        setup: function (transition, $new)
                        {
                            setup($new);
                        },
                        teardown: function ()
                        {

                        }
                    });
                }
                else
                {
                    setup($logContainer);
                }

                _getContextScrollContainer().scrollTop(scrollTop).scrollLeft(scrollLeft);
            };

            _fwdc.selectTablePage = function (table, id)
            {
                return _fwdc.ajax({
                    url: 'SelectTablePage',
                    data: function ()
                    {
                        return _fwdc.getDocPostParameters({ TABLE_VIEW__: table, TABLE_PAGE__: id }, "input[type='hidden']");
                    },
                    success: _fwdc.handleActionResult
                });
            };

            _fwdc.hideMenu = function (event, control, getMenuType, id)
            {
                event = $.event.fix(event);

                var $tipTarget = $(event.currentTarget);
                if ($tipTarget.data("hasqtip") !== undefined && $tipTarget.qtip().elements.tooltip.is(":visible"))
                {
                    $tipTarget.qtip("api").hide(event);
                    return true;
                }

                return false;
            };

            function _showMenuInternal(event, control, getMenuType, id, options, $menu)
            {
                if ($menu && $menu.length)
                {
                    if (options && options.setupContentCallback)
                    {
                        options.setupContentCallback($menu);
                    }

                    var $source = $(event.currentTarget);

                    var $tipTarget = $(event.currentTarget);
                    var position =
                        (options && options.position) ||
                        ((options && options.atCursor) ?
                            {
                                my: (_fwdc.ltr ? 'top left' : 'top right'),
                                target: 'mouse',
                                adjust: { mouse: false, method: 'shift' }
                            } :
                            _fwdc.standardMenuPosition(event));

                    if (!position.container)
                    {
                        position.container = _fwdc.supportElementsContainer();
                        position.viewport = _fwdc.$window;
                    }

                    var autoHideLinkSelector = 'a';
                    if (options)
                    {
                        if (options.container)
                        {
                            position.container = options.container;
                        }

                        if (options.autoHideLinkSelector === false)
                        {
                            autoHideLinkSelector = false;
                        }
                        else if (options.autoHideLinkSelector)
                        {
                            autoHideLinkSelector = options.autoHideLinkSelector;
                        }

                        if (options.adjust)
                        {
                            position.adjust = $.extend(position.adjust, options.adjust);
                        }
                    }

                    var linkset = false;
                    var strFocusGuardClass = "FastShowTipFocusGuard";

                    $tipTarget.qtip($.extend({}, {
                        content: { text: $menu, title: { text: false, button: false } },
                        viewport: _fwdc.$window,
                        position: position,
                        style:
                        {
                            classes: 'FastPanel FastMenuTip ' + getMenuType + 'Tip',
                            tip:
                            {
                                corner: false
                            }
                        },
                        events:
                        {
                            render: function (event, api)
                            {
                                api.elements.tooltip.attr('role', (options && options.role) || (options && options.linkset ? "menu" : "navigation"));
                            },
                            show: function (event, api)
                            {
                                if (autoHideLinkSelector)
                                {
                                    $(autoHideLinkSelector, api.elements.content).bind('click.fastHideMenu', function ()
                                    {
                                        api.hide();
                                        _fwdc.setTimeout("showMenuHideManagerMenu", function ()
                                        {
                                            _fwdc.hideManagerMenu();
                                        });
                                    });
                                }

                                _fwdc.setTimeout("showMenuInternal.show.focus", function ($menu, linkset)
                                {
                                    if (linkset)
                                    {
                                        $menu.linkset("focus");
                                    }
                                    else
                                    {
                                        var $link = $menu.find('a:visible').first();
                                        if ($link.length)
                                        {
                                            $link.focus();
                                        }
                                    }
                                }, 0, $menu, linkset);

                                // Attach focus guards to the tooltip's root element so they can manage keeping focus inside the "tooltip".
                                $("<div/>",
                                    {
                                        "class": strFocusGuardClass,
                                        "tabindex": "0"
                                    })
                                    .on("focus", function ()
                                    {
                                        $(this)
                                            .closest(".qtip")
                                            .find(":focusable")
                                            .filterNotHasClassName(strFocusGuardClass)
                                            .last()
                                            .focus();
                                    })
                                    .prependTo(api.elements.tooltip);

                                $("<div/>",
                                    {
                                        "class": strFocusGuardClass,
                                        "tabindex": "0"
                                    })
                                    .on("focus", function ()
                                    {
                                        $(this)
                                            .closest(".qtip")
                                            .find(":focusable")
                                            .filterNotHasClassName(strFocusGuardClass)
                                            .first()
                                            .focus();
                                    })
                                    .appendTo(api.elements.tooltip);
                            },
                            hidden: function (event, api)
                            {
                                if (autoHideLinkSelector)
                                {
                                    $(autoHideLinkSelector, api.elements.content).unbind('click.fastHideMenu');
                                }
                                api.destroy();
                                $menu.remove();

                                if ($source && $source.length) { $source.focus(); }
                            }
                        }
                    }, (options && options.tipOptions) || {}));

                    if (options && options.beforeShow)
                    {
                        options.beforeShow($menu, event);
                    }

                    $tipTarget.qtip('show', event);

                    if (!options || options.linkset !== false)
                    {
                        linkset = true;
                        if (options && options.linkset)
                        {
                            $menu.linkset({ optionSelector: options.linkset });
                        }
                        else
                        {
                            $menu.linkset();
                        }
                    }

                    $menu.attr("aria-expanded", "true");

                    return $menu;
                }
            }

            _fwdc.standardMenuPosition = function (event)
            {
                var $target = event && $(event.currentTarget);

                var position;
                if (!$target || !$target.closest(".Sidebar").length)
                {
                    position = { "my": "top right", "at": "bottom right", adjust: { method: "shift" } };
                }
                else
                {
                    position = { "my": "top left", "at": "bottom left", adjust: { method: "shift" } };
                }

                if ($target && $target.closest(".ManagerHeader").length)
                {
                    if (position.adjust)
                    {
                        position.adjust.y = 20;
                    }
                    else
                    {
                        position.adjust = { y: 20 };
                    }
                }

                return position;
            };

            _fwdc.showMenu = function (event, control, getMenuType, id, options)
            {
                var checkBusy = !options || options.checkBusy === undefined || !!options.checkBusy;
                if (checkBusy && _busy()) { return false; }

                FWDC.hideViewMenus();

                event = $.event.fix(event);
                event.preventDefault();
                event.stopImmediatePropagation();

                if (getMenuType)
                {
                    if (!id) { id = control; }
                    _fwdc.getData(control || '', getMenuType, id, 'html', true, (options && options.data) || undefined, function (data)
                    {
                        var $menu = $($.parseHTML($.trim(data)));
                        _showMenuInternal(event, control, getMenuType, id, options, $menu);
                    });
                }
                else
                {
                    var $menu = $('<div></div>').attr('id', id + '__Menu').addClass('DocMenuContainer');
                    _showMenuInternal(event, control, getMenuType, id, options, $menu);
                }
            };

            function _getVisibleHeaderLinks($container)
            {
                return $container.find("a.EnabledLink").filter(function ()
                {
                    var $link = $(this);
                    return !$link.hasClass("TitleMenuLink") && !$link.parent().hasClass("Hidden");
                });
            }

            _fwdc.checkHeaderLinks = function ($container)
            {
                if ($container === true)
                {
                    $container = _fwdc.currentDocumentContainer();
                }
                else if (!$container)
                {
                    $container = _fwdc.$body();
                }

                $container.find(".HeaderLinkContainer").each(function ()
                {
                    var $container = $(this).removeClass("HasHeaderLinks HasSingleHeaderLink");

                    var $enabledLinks = _getVisibleHeaderLinks($container);

                    switch ($enabledLinks.length)
                    {
                        case 0:
                            break;
                        case 1:
                            $container.addClass("HasSingleHeaderLink");
                            break;
                        default:
                            $container.addClass("HasHeaderLinks");
                            break;
                    }
                });
            };

            _fwdc.setupTitleMenuLinks = function ($title, $linksColumn)
            {
                if ($linksColumn && $linksColumn.length)
                {
                    var $headerLinks = _getVisibleHeaderLinks($title.find(".HeaderLinkContainer"));
                    var linkExists;

                    $headerLinks.each(function ()
                    {
                        var $link = $(this);

                        var text = $link.text();

                        if (text)
                        {
                            linkExists = true;
                            $linksColumn.append($('<a class="MenuItem MenuLink"></a>')
                                .text(text)
                                .attr("href", $link.attr("href"))
                                .click(function (event)
                                {
                                    $link.click();
                                    return _fwdc.stopEvent(event);
                                }));
                        }
                    });

                    if (!linkExists)
                    {
                        $linksColumn.remove();
                    }
                }
            };

            _fwdc.showTableFilter = function (table, show)
            {
                return _fwdc.ajax({
                    url: 'FilterTable',
                    successOptions: {
                        show: !!show
                    },
                    data: function ()
                    {
                        return _fwdc.getDocPostParameters({ TABLE__: table, SHOW__: !!show }, "input[type='hidden']");
                    },
                    success: _handleFilterResponse
                });
            };

            _fwdc.toggleTableErrorFilter = function (table)
            {
                return _fwdc.ajax({
                    url: 'FilterTableErrors',
                    data: function ()
                    {
                        return _fwdc.getDocPostParameters({ TABLE__: table }, "input[type='hidden']");
                    },
                    success: _handleFilterResponse
                });
            };

            function _handleFilterResponse(data, status, request)
            {
                /*jshint validthis: true */
                var show = this && this.successOptions && this.successOptions.show;

                var restoreFocus = !show && _fwdc.captureFocus();

                _handleDocResponse.call(this, data, status, request);

                if (restoreFocus)
                {
                    _fwdc.restoreFocus();
                }
                else
                {
                    _fwdc.focusCurrentField();
                }
            }

            _fwdc.filterTable = function (table, filter, async)
            {
                return _fwdc.ajax({
                    url: 'FilterTable',
                    async: !!async,
                    data: function ()
                    {
                        return _fwdc.getDocPostParameters({ TABLE__: table, FILTER__: filter }, "input[type='hidden']");
                    },
                    success: _handleFilterResponse
                });
            };

            _fwdc.autoRefresh = function (displayElementId, timeout, callback, timeoutMs, useEndDate)
            {
                if (_fwdc.exporting) { return; }

                _fwdc.stopAutoRefresh(displayElementId);

                if (_fwdc.preventAutoRefresh)
                {
                    _fwdc.preventAutoRefresh = false;
                    _fwdc.cancelAutoRefresh(displayElementId, true);
                    return;
                }

                if (timeout)
                {
                    callback = callback || function ()
                    {
                        _fwdc.refreshPage("autoRefresh.NoCallback");
                    };

                    var delay = (timeoutMs && timeout < 1000) ? timeout : 1000;

                    var autoRefreshElapsed = 0;
                    var autoRefreshTimeout = timeout;
                    if (!_fwdc.fastAutoRefreshElements)
                    {
                        _fwdc.fastAutoRefreshElements = {};
                    }

                    var autoRefreshInfo = _fwdc.fastAutoRefreshElements[displayElementId] = {
                        displayElementId: displayElementId,
                        timeout: timeout,
                        callback: callback,
                        lastTimeout: timeout,
                        useEndDate: useEndDate
                    };

                    var showCancelRefresh = timeoutMs;

                    var $displayElement = _fwdc.formField(displayElementId, true);
                    if (!$displayElement) { return; }

                    if ($displayElement.hasClass("FGNVV"))
                    {
                        $displayElement = $displayElement.children(".FGNVT");
                    }

                    var displayInput = $displayElement.is("input");
                    var displayTimeout = timeoutMs ? autoRefreshTimeout : _fwdc.formatSeconds(autoRefreshTimeout, true);
                    if (displayInput)
                    {
                        $displayElement.val(displayTimeout).addClass("FastNoRecalc");
                    }
                    else
                    {
                        $displayElement.text(displayTimeout);
                    }

                    if (showCancelRefresh && displayInput)
                    {
                        var $container = $displayElement.closest(".ControlGridField");
                        if ($container && $container.length)
                        {
                            $container.children().hide();
                            $('<a class="StopRefreshButton" href="javascript:;"></a>')
                                .click(function ()
                                {
                                    if (!_fwdc.stopAutoRefresh() || !_fwdc.cancelAutoRefresh(displayElementId))
                                    {
                                        _fwdc.preventAutoRefresh = true;
                                    }
                                })
                                .text(_fwdc.getDecode("StopAutoRefresh"))
                                .appendTo($container);
                        }
                    }

                    autoRefreshInfo.handle = setInterval(function ()
                    {
                        autoRefreshElapsed += (timeoutMs ? 1000 : 1);
                        var displayTime = Math.max(autoRefreshTimeout - autoRefreshElapsed, 0);
                        var displayTimeout = timeoutMs ? displayTime : _fwdc.formatSeconds(displayTime, true);
                        autoRefreshInfo.lastTimeout = displayTime;
                        if (displayInput)
                        {
                            $displayElement.val(displayTimeout);
                        }
                        else
                        {
                            $displayElement.text(displayTimeout);
                        }

                        if (autoRefreshElapsed >= autoRefreshTimeout && (autoRefreshInfo.useEndDate || !_fwdc.specialDialogOpen()))
                        {
                            _fwdc.stopAutoRefresh();
                            callback();
                        }
                    }, delay);
                }
            };

            _fwdc.stopAutoRefresh = function (element, $container)
            {
                if ($container === true)
                {
                    if (_fwdc.fastAutoRefreshHandle)
                    {
                        clearInterval(_fwdc.fastAutoRefreshHandle);
                        _fwdc.fastAutoRefreshHandle = null;
                    }

                    if (_fwdc.fastAutoRefreshElements)
                    {
                        $.each(_fwdc.fastAutoRefreshElements, function (elementId, autoRefreshInfo)
                        {
                            if (autoRefreshInfo.handle)
                            {
                                clearInterval(autoRefreshInfo.handle);
                                autoRefreshInfo.handle = null;
                            }
                        });
                        _fwdc.fastAutoRefreshElements = null;
                    }

                    return true;
                }

                if (_fwdc.fastAutoRefreshElements)
                {
                    if (element)
                    {
                        var elementAutoRefreshInfo = _fwdc.fastAutoRefreshElements[element];
                        var handle = elementAutoRefreshInfo && elementAutoRefreshInfo.handle;
                        if (handle)
                        {
                            clearInterval(handle);
                            elementAutoRefreshInfo.handle = null;
                        }
                    }
                    else
                    {
                        $.each(_fwdc.fastAutoRefreshElements, function (elementId, autoRefreshInfo)
                        {
                            if (!$container || $container.find("#" + elementId).length)
                            {
                                if (autoRefreshInfo.handle)
                                {
                                    clearInterval(autoRefreshInfo.handle);
                                    autoRefreshInfo.handle = null;
                                }
                            }
                        });
                    }
                    return true;
                }

                return false;
            };

            _fwdc.closestScrollContainer = function ($element, defaultContainer)
            {
                // Should this switch to use selectors.scrollContainers?
                var $container = $element.closest(".ViewScrollContainer,.DocScrollContainer .DataDocWrapper,.FastDialogElement,.ScrollStyleContent.csspositionsticky .ManagerBase .ManagerControlsContainer,.ScrollStyleContent.no-csspositionsticky .ManagerBase .ManagerControlsContainer");
                return $container.length ? $container : (defaultContainer === undefined ? _fwdc.$window : defaultContainer);
            };

            _fwdc.setupSyntaxHighlight = function (fieldId, mode, $field, callback, focus)
            {
                mode = "" + mode;
                _fwdc.loadCodeMirror(mode, function ()
                {
                    $field = ($field || _fwdc.formField(fieldId, false));
                    if ($field)
                    {
                        if ($field.is("textarea"))
                        {
                            var textArea = $field[0];
                            var editor = _fwdc.createCodeMirrorBox(textArea, mode, { lineNumbers: false }, focus);

                            if (callback) { callback($field, editor); }
                            if (focus) { editor.focus(); }
                        }
                        else
                        {
                            var $label = $field.find(".CaptionLabel,.FGVO");
                            if ($label && $label.length)
                            {
                                var text = $label.text();

                                $label.empty();

                                CodeMirror.runMode(text, mode, $label[0]);

                                $label.addClass("FastSyntaxHighlighted").data("fast-higlighted-mode", mode);
                            }
                        }
                    }
                    else
                    {
                        _fwdc._warn("setupSyntaxHighlight: Field not found: " + fieldId);
                    }
                });
            };

            _fwdc.setupMediaPlayer = function ($media)
            {
                //var fieldId = $media.attr("id");
                var $controls = $media.next(".DocMediaControls"); //_fwdc.formField("controls_" + fieldId);

                //var $log = $media.closest(".ViewFieldContainer").find(".ViewFieldCaption > span");

                if (!$media || !$media.length || !$controls || !$controls.length) { return; }

                var $container = $media.closest(".DocMediaContainer");

                var media = $media.get(0);
                var isVideo = $media.is("video");

                // If the media element has no ID, apply an automatic unique ID
                var id = $media.uniqueId().attr("id");

                if (!media.play)
                {
                    $media.remove();
                    $controls.children(".DocMediaControlsUnsupported").css("display", "block").css("visibility", "visible");
                    return;
                }

                if ($controls.data("fast-media-controls"))
                {
                    return;
                }

                var tabIndex = $controls.attr("tabindex");
                $controls.data("fast-media-controls", 1).empty().removeAttr("tabindex");

                var $action = $($.parseHTML('<button type="button" class="DocMediaAction">'))
                    .attr("tabindex", tabIndex)
                    .click(function (event)
                    {
                        if (media.readyState < 3)
                        {
                            media.load();
                        }
                        else if (media.paused)
                        {
                            if (media.currentTime >= media.duration)
                            {
                                media.currentTime = 0;
                            }
                            media.play();
                        }
                        else
                        {
                            media.pause();
                        }
                        _fwdc.stopEvent(event);
                    })
                    .appendTo($controls);

                var mediaSettings = _fwdc.getJsonCookie("mediaSettings", function () { return { volume: 1 }; });

                var defaultVolume = (mediaSettings && (mediaSettings.volume || mediaSettings.volume === 0)) ? mediaSettings.volume : 1;
                if (defaultVolume < 0)
                {
                    media.volume = 0;
                }
                else if (defaultVolume > 1)
                {
                    media.volume = 1;
                }
                else
                {
                    media.volume = defaultVolume;
                }

                var $time = $($.parseHTML('<div class="DocMediaTimeInfo"></div>')).appendTo($controls);

                var $timeSliderText = $($.parseHTML('<label class="DocMediaSliderText"></label>')).attr("for", "tim_" + id).appendTo($time);
                var userSliding = false;
                var userSlidingUnpause = false;

                var onStartInput = function ()
                {
                    userSliding = true;
                    userSlidingUnpause = $action.hasClass("DocMediaPause");
                    if (userSlidingUnpause)
                    {
                        media.pause();
                    }
                };

                var onEndInput = function ()
                {
                    var currentTime = parseFloat(this.value);
                    if (media.currentTime !== currentTime)
                    {
                        media.currentTime = parseFloat(this.value);
                        if (userSlidingUnpause)
                        {
                            media.play();
                        }
                        updateControls();
                    }
                    userSliding = false;
                };

                var $timeSlider =
                    $($.parseHTML('<input class="DocMediaSlider" type="range">'))
                        .attr({
                            id: "tim_" + id,
                            value: 0,
                            min: 0,
                            max: 1,
                            step: 0.1,
                        })
                        .on({
                            "mousedown": onStartInput,
                            "touchstart": onStartInput,
                            "keydown": onStartInput,
                            "mouseup": onEndInput,
                            "touchend": onEndInput,
                            "keyup": onEndInput
                        })
                        .appendTo($time);

                var $volume = $($.parseHTML('<div class="DocMediaVolumeInfo"></div>')).appendTo($controls);
                var $volumeSliderText = $($.parseHTML('<label class="DocMediaSliderText"></label>'))
                    .attr("for", "vol_" + id)
                    .text(_fwdc.getDecode("MediaVolume", "Volume"))
                    .appendTo($volume);

                var $volumeSlider =
                    $($.parseHTML('<input class="DocMediaSlider" type="range">'))
                        .attr({
                            id: "vol_" + id,
                            value: 100,
                            min: 0,
                            max: 100,
                            step: 1
                        })
                        .on("input", function ()
                        {
                            media.volume = parseInt(this.value, 10) / 100;
                            //console.log("input: " + media.volume);
                        })
                        .on("change", function ()
                        {
                            media.volume = parseInt(this.value, 10) / 100;
                            mediaSettings.volume = media.volume;
                            _fwdc.setJsonCookie("mediaSettings", mediaSettings);
                            updateControls();
                            //console.log("change: " + media.volume);
                        })
                        .appendTo($volume);


                if (isVideo)
                {
                    $media.click(function ()
                    {
                        if (media.readyState < 3)
                        {
                            media.load();
                        }
                        else if (media.paused)
                        {
                            if (media.currentTime >= media.duration)
                            {
                                media.currentTime = 0;
                            }
                            media.play();
                        }
                        else
                        {
                            media.pause();
                        }
                    });

                    if ($container.hasClass("DocMediaAllowFullscreen"))
                    {
                        var $fullscreenButton = $($.parseHTML('<button type="button" class="DocMediaAction DocMediaFullscreen">'))
                            .attr("tabindex", tabIndex)
                            .text(_fwdc.getDecode("MediaToggleFullscreen"))
                            .attr("title", _fwdc.getDecode("MediaToggleFullscreen"))
                            .click(function (event)
                            {
                                $container.toggleClass("DocMediaFakeFullscreen");
                                $fullscreenButton.toggleClass("DocMediaExitFullscreen");
                                _fwdc.stopEvent(event);
                            })
                            .appendTo($controls);
                    }
                }

                function updateControls(event)
                {
                    var mediaReady;

                    $action.removeClass("DocMediaLoading DocMediaError DocMediaPlay DocMediaPause");
                    if (media.networkState === 3 /* NETWORK_NO_SOURCE */)
                    {
                        $action.addClass("DocMediaError").text(_fwdc.getDecode("MediaError")).attr("title", _fwdc.getDecode("MediaError"));
                        $timeSlider.attr("disabled", "disabled");
                    }
                    else if (media.readyState < 3 /* 0: HAVE_NOTHING, 1: HAVE_METADATA, 2: HAVE_CURRENT_DATA, 3: HAVE_FUTURE_DATA */)
                    {
                        $action.addClass("DocMediaLoading").text(_fwdc.getDecode("MediaLoading")).attr("title", _fwdc.getDecode("MediaLoading"));
                    }
                    else if (media.paused)
                    {
                        mediaReady = true;
                        $action.addClass("DocMediaPlay").text(_fwdc.getDecode("MediaPlay")).attr("title", _fwdc.getDecode("MediaPlay"));
                    }
                    else
                    {
                        mediaReady = true;
                        $action.addClass("DocMediaPause").text(_fwdc.getDecode("MediaPause")).attr("title", _fwdc.getDecode("MediaPause"));
                    }

                    var seekStart = 0;
                    var seekEnd = 0;
                    var currentTime = 0;
                    var duration = 0;

                    if (mediaReady && media.seekable.length)
                    {
                        seekStart = media.seekable.start(media.seekable.length - 1);
                        seekEnd = media.seekable.end(media.seekable.length - 1);

                        currentTime = media.currentTime;
                        duration = media.duration;
                    }

                    //$timeSlider.slider({ "value": currentTime, "max": duration, "disabled": seekStart === seekEnd });

                    if (mediaReady)
                    {
                        // We don't want the input to flicker and lose its position or focus, so don't change its attributes unless media is ready.
                        $timeSlider.attr("max", duration).val(currentTime).removeAttr("disabled");
                    }
                    //$timeSlider.attr("max", duration).attr("disabled", !mediaReady).val(currentTime);

                    $timeSliderText.html(_fwdc.formatSeconds(currentTime) + '<span class="DocMediaDurationTotal">/' + _fwdc.formatSeconds(duration) + '</span>');

                    //$volumeSlider.slider({ "value": (media.volume * 100) });
                    $volumeSlider.val(media.volume * 100);
                }

                $media.off(".wdcMedia").children("source").off(".wdcMedia");
                $media.on("loadstart.wdcMedia loadedmetadata.wdcMedia loadeddata.wdcMedia stalled.wdcMedia suspend.wdcMedia abort.wdcMedia error.wdcMedia play.wdcMedia pause.wdcMedia timeupdate.wdcMedia ended.wdcMedia durationchange.wdcMedia slider.wdcMedia progress.wdcMedia canplay.wdcMedia playing.wdcMedia volumechange.wdcMedia",
                    function (event)
                    {
                        if (!userSliding)
                        {
                            updateControls(event);
                        }
                    });

                $media.children("source").on("error.wdcMedia", function (event)
                {
                    updateControls(event);
                });

                updateControls();
            };

            var _signaturePadReady = null;
            _fwdc.loadSignaturePad = function (callback)
            {
                if (!_signaturePadReady)
                {
                    _signaturePadReady = $.Callbacks("once unique memory");

                    if ($ && $.fn && $.fn.signaturePad)
                    {
                        _signaturePadReady.fire();
                    }
                    else
                    {
                        // Load both SignaturePad libraries
                        _fwdc.loadScripts(['SignaturePad/jquery.signaturepad.js', 'Script/SignaturePad/signature_pad.4.2.0.es5.min.js'], function ()
                        {
                            _signaturePadReady.fire();
                        });
                    }
                }

                _signaturePadReady.add(callback);
            };

            var _signaturePadDefaultVersion = 1;

            function _setupSignaturePad2($signatureForm, signatureData)
            {
                var canvas = $signatureForm.findElementsByClassName("pad")[0];
                // Internal signature rendering defaults velocityFilterWeight to 0.9
                var options = { velocityFilterWeight: 0.9 };

                if (signatureData && signatureData.penColor)
                {
                    options.penColor = signatureData.penColor;
                }

                if (signatureData && signatureData.minWidth)
                {
                    options.minWidth = signatureData.minWidth;
                }

                if (signatureData && signatureData.maxWidth)
                {
                    options.maxWidth = signatureData.maxWidth;
                }

                signatureData.signaturePad = new SignaturePad(canvas, options);

                var clearLink = $signatureForm.findElementsByClassName("clearLink");
                clearLink.click(function ()
                {
                    signatureData.signaturePad.clear()
                });
            }

            //_fwdc.acceptSignatureDialog = function (event /*, control, fieldId*/)
            //{
            //    _fwdc.stopEvent(event);

            //    if (_busy()) { return false; }

            //    var $button = $(event.currentTarget);
            //    var targetData = $button.data("target");
            //    var control = targetData.docId;
            //    var fieldId = targetData.fieldId;

            //    var $form = $("#SignatureDialogForm");
            //    var signaturePad = $form.signaturePad();

            //    _fwdc.setPropertiesInternal(null, control, "Signature", fieldId, true, { jsonData: signaturePad.getSignatureString() });
            //    $("#SignatureDialog").dialog("close");

            //    return false;
            //};

            //_fwdc.cancelSignatureDialog = function (event)
            //{
            //    _fwdc.stopEvent(event);
            //    if (_busy()) { return false; }
            //    $("#SignatureDialog").dialog("close");
            //    return false;
            //};

            var _updateScrollPanelsHandle;
            _fwdc.updateScrollPanels = function ($container, checkSize)
            {
                if (_updateScrollPanelsHandle)
                {
                    _fwdc.clearTimeout("_fwdc.updateScrollPanels", _updateScrollPanelsHandle);
                    _updateScrollPanelsHandle = null;
                }

                _updateScrollPanelsHandle = _fwdc.setTimeout("_fwdc.updateScrollPanels", function ()
                {
                    _updateScrollPanelsHandle = null;
                    $.findElementsByClassName("PanelScrollContainer", $container).each(function ()
                    {
                        _fwdc.updateScrollPanel($(this), _default(checkSize, true));
                    });
                }, 10);
            };

            _fwdc.updateScrollPanel = function ($container, checkSize, immediate)
            {
                var init = !$container.data("fast-scroll-panel");
                if (init)
                {
                    $container
                        .data("fast-scroll-panel", true)
                        .on("scroll", _fwdc.Events.Panel.scrollpanelscroll);
                    checkSize = true;
                }

                var innerWidth = $container.innerWidth();
                var $scrollWrapper = $container.children(".PanelScrollContentContainer");
                var $parentPanel = $scrollWrapper.parent(".TablePanelScrollWrapper");
                var $content = $scrollWrapper.children().first();

                var isScrollPanel = !$container.hasClass("TabSetWrapper");

                var scrollable;

                if (checkSize)
                {
                    if ($content.outerWidth() > innerWidth)
                    {
                        if (isScrollPanel && !$container.hasClass("CanScroll"))
                        {
                            $container.parentsUntil(".ManagerContainer,.DocumentContainer").addClass("HasScrollableChild");
                        }
                        $container.addClass("CanScroll");
                        $parentPanel.addClass("CanScroll");
                        scrollable = true;
                    }
                    else
                    {
                        $container.removeClass("CanScroll CanScrollLeft CanScrollRight");
                        $parentPanel.removeClass("CanScroll");
                        scrollable = false;
                    }
                }
                else
                {
                    scrollable = $container.hasClass("CanScroll");
                }

                if (scrollable)
                {
                    if (checkSize)
                    {
                        immediate = true;

                        var $ensureVisible = $content.children(".EnsureVisible");
                        if ($ensureVisible.length)
                        {
                            _fwdc.scrollIntoView($ensureVisible, { $parentsUntil: $container, minHSpace: _fwdc.remSize(3) });
                            //if (_fwdc.ensureElementVisible($ensureVisible, false, $container, _fwdc.remSize(3)))
                            //{
                            var $tabs = $container.closest(".TabSetScrollWrapper");
                            if ($tabs.length)
                            {
                                _fwdc.animateSelectorUnderline($tabs, true);
                            }
                            //}
                        }
                    }

                    var timeoutHandle = $container.data("scrollpaneltimeout");
                    if (timeoutHandle)
                    {
                        _fwdc.clearTimeout("UpdateScrollPanel", timeoutHandle);
                        $container.data("scrollpaneltimeout", null);
                    }

                    if (immediate)
                    {
                        _updateScrollPanel($container, innerWidth);
                    }
                    else
                    {
                        timeoutHandle = _fwdc.setTimeout("UpdateScrollPanel", function ()
                        {
                            _updateScrollPanel($container, innerWidth);
                        }, 1);

                        $container.data("scrollpaneltimeout", timeoutHandle);
                    }
                }
            };

            function _updateScrollPanel($container, innerWidth)
            {
                var scrollWidth = $container.prop("scrollWidth");
                var scrollLeft = $container.scrollLeft();

                if (scrollLeft)
                {
                    $container.addClass("CanScrollLeft");
                }
                else
                {
                    $container.removeClass("CanScrollLeft");
                }

                if (Math.ceil(scrollLeft + innerWidth) < scrollWidth)
                {
                    $container.addClass("CanScrollRight");
                }
                else
                {
                    $container.removeClass("CanScrollRight");
                }

                if ($container.parent().hasClass("TablePanelScrollWrapper"))
                {
                    var offset = $container.offset();
                    var height = $container.outerHeight();
                    var top = offset.top;
                    var windowScrollTop = _fwdc.$window.scrollTop();
                    var windowHeight = _fwdc.windowHeight;

                    var buttonTop;

                    var displayTop = top - windowScrollTop;
                    var displayBottom = displayTop + height;

                    if (displayTop < windowHeight && displayBottom > 0)
                    {
                        var visibleTop = displayTop < 0 ? (-displayTop) : 0;
                        var visibleBottom = displayBottom > windowHeight ? (displayBottom - windowHeight) : 0;
                        visibleBottom = height - visibleBottom;

                        buttonTop = visibleTop + (visibleBottom - visibleTop) / 2;
                    }

                    var $buttons = $container.children(".PanelScrollButton");
                    if (buttonTop)
                    {
                        $buttons.css("top", buttonTop + "px");
                    }
                    else
                    {
                        $buttons.css("top", "");
                    }
                }
            }

            _fwdc.scrollPanel = function ($container, direction)
            {
                var distance = $container.width() * 0.8;
                var newLeft = $container.scrollLeft() + (direction * distance);

                $container.animate({ scrollLeft: newLeft }, 200);
            };

            function _buildAuditTrail(data)
            {
                if (!data || data.blank) { return null; }

                var $trail = $($.parseHTML('<div class="AuditTrail"></div>'));
                var $text = $($.parseHTML(data.link ? '<a class="AuditTrailText FastEvt" data-event="ViewAuditTrail" href="#"></a>' : '<span class="AuditTrailText"></span>'))
                    .attr("title", data.tooltip)
                    .appendTo($trail);
                if (data.who)
                {
                    $($.parseHTML('<span class="AuditWho"></span>')).text(data.who).appendTo($text);
                }
                if (data.when)
                {
                    $($.parseHTML('<span class="AuditWhen"></span>')).text(data.when).appendTo($text);
                }

                return $trail;
            }

            function _buildModalTitleButton(button)
            {
                return $('<button type="button" class="FastButton ModalTitleButton FastEvt"></button>')
                    .text(button.text)
                    .attr("title", button.title || button.text)
                    .attr("aria-label", button.label || button.title || button.text)
                    .addClass(button.class)
                    .attr("data-event", button.event)
                    .attr("data-itemdata", button.itemdata);
            }

            _fwdc.setupModalTitle = function ($element, options)
            {
                var $dialog = $element.closest(".ui-dialog");
                if ($dialog && $dialog.length)
                {
                    var $titlebar = $dialog.children(".ui-dialog-titlebar");
                    if ($titlebar && $titlebar.length)
                    {
                        var $title = $titlebar.children(".ui-dialog-title");
                        if (!$title.length)
                        {
                            $title = null;
                        }

                        var $close = $titlebar.children(".ui-dialog-titlebar-close");
                        if (!$close.length)
                        {
                            $close = null;
                        }
                        else
                        {
                            $close.removeAttr("title");
                        }

                        var $auditTrail = $titlebar.children(".AuditTrail").remove();

                        if (options.audittrail && !options.audittrail.blank)
                        {
                            $auditTrail = _buildAuditTrail(options.audittrail);
                            if ($auditTrail)
                            {
                                if ($title)
                                {
                                    $auditTrail.insertAfter($title);
                                }
                                else
                                {
                                    $auditTrail.prependTo($titlebar);
                                }
                            }
                        }

                        if (options.buttons)
                        {
                            $titlebar.children(".ModalTitleButton").remove();

                            for (var ii = 0; ii < options.buttons.length; ++ii)
                            {
                                var $button = _buildModalTitleButton(options.buttons[ii]);
                                if ($button)
                                {
                                    if ($close)
                                    {
                                        $button.insertBefore($close);
                                    }
                                    else
                                    {
                                        $button.appendTo($titlebar);
                                    }
                                }
                            }
                        }
                    }
                }
            };

            _fwdc.onDocSelectChange = function (sender, event, noRecalc, recalcTrigger)
            {
                var $sender = $(sender);

                var $option = $sender.children("option:selected");

                if ($option.length && $option.hasClass("watermark") && $option.text())
                {
                    $sender.addClass("watermark");
                }
                else if ($option.length && $option.hasClass("ComboMoreItems"))
                {
                    var fieldId = $sender.attr("data-name") || $sender.attr("name");
                    var text = $option.text();
                    _fwdc.raiseComboMoreItem(event, fieldId, text);
                    return;
                }
                else
                {
                    $sender.removeClass("watermark");
                }

                if (noRecalc || !$sender.hasClass("FastNoRecalc"))
                {
                    _fwdc.showCurrentFieldTip();
                    _fwdc.checkValueChanged(sender, recalcTrigger || "OnDocSelectChange");
                }
            };

            _fwdc.raiseComboMoreItem = function (event, fieldId, text)
            {
                _fwdc.setPropertiesInternal(event, "", "ComboMoreItems", fieldId, true, { "moreCombotext": text });
            };

            _fwdc.scrollTogether = function ($elements, contentId, data)
            {
                if ($elements && $elements.length > 1)
                {
                    var scrollData = {
                        $elements: $elements,
                        lastElement: null,
                        lastTimestamp: 0,
                        finalHandle: null
                    };

                    $elements.off(".scrollTogether");

                    var scrollLeft = 0;
                    var ii;

                    if (!contentId)
                    {
                        contentId = $elements.data("fast-scrolltogether-contentid");
                    }

                    if (contentId)
                    {
                        for (ii = 0; ii < $elements.length; ++ii)
                        {
                            var $element = $($elements[ii]);
                            if ($element.attr("id") === contentId)
                            {
                                scrollLeft = $element.scrollLeft();
                                break;
                            }
                        }
                    }

                    if (scrollLeft)
                    {
                        //for (ii = 0; ii < $elements.length; ++ii)
                        //{
                        //}
                        $elements.scrollLeft(scrollLeft);
                    }

                    if (contentId)
                    {
                        $elements.data("fast-scrolltogether-contentid", contentId);
                    }

                    if (data !== undefined)
                    {
                        $elements.data("fast-scrolltogether-data", data);
                    }

                    var onScrollTogether = function (event, final)
                    {
                        var scrollData = event.data;

                        var now = _fwdc.now();

                        // Ignore scroll events between the grouped elements by skipping events that happen close together for different elements.
                        if (!final && (now - scrollData.lastTimestamp < 100 && event.target !== scrollData.lastElement))
                        {
                            return;
                        }

                        scrollData.lastTimestamp = now;
                        scrollData.lastElement = event.target;

                        var $scrollElements = scrollData.$elements;
                        var $scrollingElement = $(event.target);
                        var scrollLeft = $scrollingElement.scrollLeft();

                        for (var ii = 0; ii < $scrollElements.length; ++ii)
                        {
                            var element = $scrollElements[ii];
                            if (element !== event.target)
                            {
                                $(element).scrollLeft(scrollLeft);
                            }
                        }

                        _fwdc.clearTimeout("onScrollTogether.final", scrollData.finalHandle);
                        scrollData.finalHandle = null;

                        if (!final)
                        {
                            scrollData.finalHandle = _fwdc.setTimeout("onScrollTogether.final", onScrollTogether, 100, event, true);
                        }
                    };

                    $elements
                        .addClass("ScrollTogether")
                        .on("scroll.scrollTogether", null, scrollData, onScrollTogether);
                }
            };

            function _gotFocusRemoveCancelHandlers(event)
            {
                /*jshint validthis: true */
                $(this).off(".fieldgotfocus");
            }

            function _gotFocusCancelMouseUp(event)
            {
                /*jshint validthis: true */
                _gotFocusRemoveCancelHandlers.call(this, event);
                $(this).select();
                return _fwdc.stopEvent(event);
            }

            _fwdc.findPercentColumns = function ($cols)
            {
                var percentTotal = 0;
                var percentCols = [];

                var $table = $cols.closest("table");
                if ($table.hasClass("ResponsiveCols"))
                {
                    var widths = $cols.colsCssWidths();
                    return {
                        percentCols: $cols.map(function (ii)
                        {
                            var $col = $(this);
                            var widthCss = widths[ii] || ""; //($col.cssWidth() || "").trim();
                            if (widthCss && widthCss.endsWith("%"))
                            {
                                var width = parseFloat(widthCss, 10);
                                if (width && !isNaN(width))
                                {
                                    //$percentCols.push($col);
                                    percentTotal += width;
                                }

                                percentCols.push(this);

                                return { $col: $col, width: width };
                            }
                            else
                            {
                                return null;
                            }
                        }),
                        $percentCols: $(percentCols),
                        percentTotal: percentTotal
                    };
                }

                return null;
            };

            _fwdc.resetColumnPercentWidths = function ($cols)
            {
                // Reset any temporarily adjusted percentages so the original sizes are used for re-calculating.
                var $colgroup = $cols.parent().first();
                var colgroupSetupWidth = $colgroup.data("initscreenwidth");
                if (colgroupSetupWidth !== _fwdc.screenWidthClass)
                {
                    $cols.each(function ()
                    {
                        var $col = $(this);
                        if ($col.data("percentadjusted"))
                        {
                            var defaultWidth = _default($col.attr("data-width"), "");
                            $col.css("width", defaultWidth);
                        }
                    });
                }

                var colInfo = _fwdc.findPercentColumns($cols);
                if (!colInfo)
                {
                    return null;
                }

                $colgroup
                    .data("initscreenwidth", _fwdc.screenWidthClass)
                    .addClass("AdjustedPercentColumns ScreenSizeSpecific ScreenSize" + _fwdc.screenWidth);

                var percentTotal = colInfo.percentTotal;
                var percentCols = colInfo.percentCols;

                if (percentTotal && (percentTotal !== 100))
                {
                    var percentRemaining = 100;

                    var factor = 100 / percentTotal;

                    var $lastCol;
                    var lastWidth;

                    $.each(percentCols, function (index, colAndWidth)
                    {
                        var $col = colAndWidth.$col;
                        var width = colAndWidth.width;
                        var newWidth = parseFloat((width * factor).toFixed(2));
                        $col.css("width", newWidth + "%");
                        $col.data("percentadjusted", true);
                        percentRemaining -= newWidth;

                        $lastCol = $col;
                        lastWidth = newWidth;
                    });

                    if ($lastCol && percentRemaining !== 0)
                    {
                        $($lastCol).css("width", (lastWidth + percentRemaining) + "%");
                    }
                }

                return colInfo.$percentCols;
            };

            _fwdc.resizeVirtualHeaderRows = function ($container)
            {
                var $headers = $.findElementsByClassName("DocTableVirtualHeadersContainer", $container);
                $headers.each(function ()
                {
                    _fwdc.resizeVirtualHeaderRow($(this));
                });
            };

            _fwdc.resizeVirtualHeaderRow = function ($virtualHeaderContainer, height)
            {
                if (height === undefined)
                {
                    height = $virtualHeaderContainer.height();
                }

                if (height && $virtualHeaderContainer.isVisible())
                {
                    $virtualHeaderContainer
                        //.css("margin-bottom", (-1 * height) + "px")
                        .data("fast-tvh", true);

                    // Apply the negative margin to the top of the data element instead of the bottom of the virtual element.
                    // This prevents an issue where the sticky section could extend beyond the bottom of the table (SQR 63845).
                    $virtualHeaderContainer
                        .parent()
                        .next()
                        .css("margin-top", (-1 * height) + "px");

                    return true;
                }
                else if ($virtualHeaderContainer.data("fast-tvh"))
                {
                    $virtualHeaderContainer.parent().next().css("margin-top", "");
                }

                return false;
            };

            var _currentFieldTipUpdateHandle;
            var _currentFieldTipUpdateContent;
            function _showCurrentFieldTip(updateContent)
            {
                if ($(".FastSoloTip.qtip-focus").length)
                {
                    _setTipField("error", null, null, false);
                    _setTipField("focus", null, null, false);
                    return;
                }

                var $container = _fwdc.topDialog() || _fwdc.currentDialogContainer(true);

                if (!$container || !$container.length)
                {
                    $container = _fwdc.currentDocumentContainer();
                }

                var $errorField;
                var $errorTarget;
                var $button;
                if (!_toolTipSettings.noFirstError)
                {
                    $errorField = _filterErrorFields($container, _toolTipSettings.noFirstRequired).first();
                    var $errorInput = $errorField && ($errorField.is("input,textarea,.ui-buttonset,.FastComboButtonSetSelector,.FCBRadioSet") ? null : $errorField.find("input,textarea"));

                    if ($errorInput && $errorInput.length)
                    {
                        $errorField = $errorInput;
                    }

                    $errorTarget = $errorField;

                    if ($errorField.hasClass("FCBRadioSet"))
                    {
                        $errorInput = $errorField.find("input:checked");
                        if ($errorInput && $errorInput.length)
                        {
                            $errorTarget = $errorInput;
                        }
                    }

                    if ($errorField.is(".FastCheckboxButton,.FastRadioButtonButton"))
                    {
                        $button = $errorField.next(".ui-checkboxradio-label");
                        if ($button && $button.length)
                        {
                            $errorTarget = $button;
                        }
                    }

                    var errorTargetId = $errorField && $errorField.data("fast-tip-target");
                    if (errorTargetId)
                    {
                        var $customErrorTarget = _fwdc.formField(errorTargetId, true);
                        if ($customErrorTarget && $customErrorTarget.length)
                        {
                            $errorTarget = $customErrorTarget;
                        }
                    }

                    if ($errorTarget.is("div.CodeMirror textarea"))
                    {
                        $errorTarget = $errorTarget.closest(".CodeMirror").siblings("textarea.FastCodeMirrorBox");
                    }
                    if (!$errorTarget.is(":visible"))
                    {
                        $errorTarget = $errorTarget.closest(":visible");
                    }
                }

                var $activeElement = $(document.activeElement);

                var $activeField;

                try
                {
                    $activeField = $activeElement.filter("input,select,textarea").not(".NoQTip");
                }
                catch (ex)
                { }

                // If there is no active input, but focus is inside an active field tip, then pretend the focus is already on the tip target field.
                if (!$activeField.length)
                {
                    var $activeTip = $activeElement.closest(".FastFieldQTip");
                    if ($activeTip.length)
                    {
                        var qtip = $activeTip.data("qtip");
                        if (qtip && qtip.target)
                        {
                            $activeField = qtip.target;
                        }
                    }
                }

                var $activeTarget = $activeField;

                var $activeInput = $activeField && ($activeField.is("input,textarea,.ui-buttonset") ? null : $activeField.find("input,textarea"));
                if ($activeInput && $activeInput.length)
                {
                    $activeField = $activeInput;
                }

                if ($activeField.is(".FastCheckboxButton,.FastRadioButtonButton"))
                {
                    $button = $activeField.next(".ui-checkboxradio-label");
                    if ($button && $button.length)
                    {
                        $activeTarget = $button;
                    }
                }
                else if ($activeField.is(".FCBRadio"))
                {
                    $activeInput = $activeField;
                    $activeField = $activeInput.closest(".FCBRadioSet");
                    $activeTarget = $activeField;
                    $activeInput = $activeField.find("input:checked");
                    if ($activeInput && $activeInput.length)
                    {
                        $activeTarget = $activeInput;
                    }
                }

                var activeTargetId = $activeField && $activeField.data("fast-tip-target");
                if (activeTargetId)
                {
                    var $customActiveTarget = _fwdc.formField(activeTargetId, true);
                    if ($customActiveTarget && $customActiveTarget.length)
                    {
                        $activeTarget = $customActiveTarget;
                    }
                }

                if ($activeField && !$activeField.length) { $activeField = null; }
                if ($activeTarget && !$activeTarget.length) { $activeTarget = null; }
                if ($errorField && !$errorField.length) { $errorField = null; }
                if ($errorTarget && !$errorTarget.length) { $errorTarget = null; }

                // Checkboxes/Radio buttons have a separate display element to use for the tip target.
                if ($activeTarget && $activeTarget.hasClass("FastToggleInput"))
                {
                    $activeTarget = $activeTarget.next(".FastToggleDisplay");
                }
                else if ($activeTarget && $activeTarget.is("div.CodeMirror textarea"))
                {
                    $activeTarget = $activeTarget.closest(".CodeMirror").siblings("textarea.FastCodeMirrorBox");
                }

                if ($activeTarget && !$activeTarget.is(":visible"))
                {
                    $activeTarget = $activeTarget.closest(":visible");
                }

                /*if (_setTipField("focus", $activeField, $activeTarget, updateContent))
                {
                    _setTipField("error", null, null, false);
                }
                else
                {
                    _setTipField("error", $errorField, $errorTarget, updateContent);
                }*/

                if (!$activeField || !_setTipField("field", $activeField, $activeTarget, updateContent, true))
                {
                    _setTipField("field", $errorField, $errorTarget, updateContent);
                }

                _currentFieldTipUpdateContent = false;
            }

            _fwdc.showCurrentFieldTip = function (updateContent, immediate)
            {
                if (_currentFieldTipUpdateHandle)
                {
                    clearTimeout(_currentFieldTipUpdateHandle);
                }

                _currentFieldTipUpdateContent = _currentFieldTipUpdateContent || updateContent;

                _fwdc.afterCrossTransition(function ()
                {
                    if (immediate)
                    {
                        _showCurrentFieldTip(_currentFieldTipUpdateContent);
                    }

                    _currentFieldTipUpdateHandle = setTimeout(function ()
                    {
                        _showCurrentFieldTip(_currentFieldTipUpdateContent);
                    }, 1);
                });
            };

            _fwdc.submitMonitoringBrowserEvent = function (browserEvent, browserData)
            {
                _fwdc.setMonitoringData("Browser", null, null, null, browserEvent, browserData, null);
            };

            _fwdc.submitMonitoringImageEvent = function (method, dataUrl, cameraInfo, callback)
            {
                _fwdc.setMonitoringData(method, dataUrl, cameraInfo, null, null, null, callback);
            };

            _fwdc.submitMonitoringPhotoEndedEvent = function ()
            {
                _fwdc.setMonitoringData("Photo", null, null, true, null, null, null);
            };

            _fwdc.submitMonitoringScreenEndedEvent = function ()
            {
                _fwdc.setMonitoringData("Screen", null, null, true, null, null, null);
            };

            _fwdc.submitMonitoringError = function (method, error)
            {
                //_fwdc.setMonitoringData(method, null, null, null, null, null, error, null);
                _fwdc.setPropertiesNoAction("", "MonitoringError", method, true, { "error": JSON.stringify(error) }, null);
            };

            _fwdc.setMonitoringData = function (method, dataUrl, cameraInfo, streamEnded, browserEvent, browserData, callback)
            {
                var monitoringData = {};
                monitoringData.imageData = dataUrl;
                if (cameraInfo)
                {
                    monitoringData.cameraName = cameraInfo.name;
                    monitoringData.cameraInfo = JSON.stringify(cameraInfo);
                }
                monitoringData.streamEnded = streamEnded;
                monitoringData.browserEvent = browserEvent;
                monitoringData.browserData = JSON.stringify(browserData);

                _fwdc.setPropertiesInternalJson("", "MonitoringOccurred", method, false, monitoringData, function (response)
                {
                    if (!response.success)
                    {
                        _fwdc._warn("Monitoring failed for " + method);
                    }

                    if (callback)
                    {
                        callback();
                    }
                });
            };

            _fwdc.setInputImage = function (fieldId, dataUrl, cameraInfo, showProgress)
            {
                var busyId;
                var onfinished = null;
                var uploadprogress = null;
                if (showProgress)
                {
                    busyId = _busy.show("_fwdc.setInputImage", { delay: 0, showProgress: true });
                    onfinished = function ()
                    {
                        _busy.hide(busyId);
                    };

                    uploadprogress = function (event)
                    {
                        _busy.setProgress(event.loaded, event.total);
                    };
                }

                _fwdc.setPropertiesInternal(null, "", "InputImage", fieldId, !showProgress, { "imageData": dataUrl, "cameraInfo": JSON.stringify(cameraInfo) }, null, onfinished, uploadprogress);
            };

            _fwdc.setCameraImageData = function (fieldId, cameraInfo, data, width, height, rotation, imageType, imageQuality, busyId)
            {
                var imageValues = _fwdc.getCameraImageData(fieldId, cameraInfo, data, width, height, rotation, imageType, imageQuality, busyId);
                var dataUrl = imageValues.dataUrl;
                var $canvas = imageValues.canvas;

                _fwdc.setCameraImageFieldData(fieldId, cameraInfo, busyId, dataUrl, $canvas);
            };

            function _setMonitoringImageData(imageInfo)
            {
                var imageValues = _fwdc.getMonitoringCameraImageData(imageInfo.fieldId, imageInfo.cameraInfo, imageInfo.video, imageInfo.imageWidth, imageInfo.imageHeight, imageInfo.idealWidth, imageInfo.idealHeight, imageInfo.rotation, imageInfo.imageType, imageInfo.imageQuality, imageInfo.busyId);
                var dataUrl = imageValues.dataUrl;

                var minInterval = _fwdc.monitoringIntervals.Photo.Min;
                var rangeInterval = _fwdc.monitoringIntervals.Photo.Range;
                var captureMethod = _captureMonitoringPhoto;
                var typeHandle = _monitoringPhotoHandle;
                if (imageInfo.type === "Screen")
                {
                    minInterval = _fwdc.monitoringIntervals.Screen.Min;
                    rangeInterval = _fwdc.monitoringIntervals.Screen.Range;
                    captureMethod = _captureMonitoringScreen;
                    typeHandle = _monitoringScreenHandle;
                }

                if (imageInfo.manual && imageInfo.manual === true)
                {
                    minInterval = 0;
                }

                _fwdc.submitMonitoringImageEvent(imageInfo.type, dataUrl, imageInfo.cameraInfo, function resetMonitoringInterval()
                {
                    _setMonitoringImageInterval(captureMethod, false, minInterval, rangeInterval, typeHandle);
                });
            };

            _fwdc.getCameraImageData = function (fieldId, cameraInfo, data, width, height, rotation, imageType, imageQuality, busyId, dataUrl, $canvas)
            {
                try
                {
                    var $field = $.findElementById(fieldId);
                    var $canvas = $($.parseHTML("<canvas></canvas>")).appendTo(_fwdc.supportElementsContainer());
                    var canvas = $canvas[0];

                    rotation = rotation || 0;
                    switch (rotation)
                    {
                        case 0:
                        case 180:
                            canvas.height = height;
                            canvas.width = width;
                            break;

                        case 90:
                        case 270:
                            canvas.height = width;
                            canvas.width = height;
                            break;

                        default:
                            throw "Unhandled rotation: " + rotation;
                    }

                    var context = canvas.getContext("2d");

                    if (rotation === 0)
                    {
                        context.drawImage(data, 0, 0, width, height);
                    }
                    else
                    {
                        var centerX = Math.round(canvas.width / 2);
                        var centerY = Math.round(canvas.height / 2);
                        var rotateRadians = rotation / 180 * Math.PI;
                        context.translate(centerX, centerY);
                        context.rotate(rotateRadians);
                        context.drawImage(data, width / -2, height / -2, width, height);
                        context.rotate(-rotateRadians);
                        context.translate(-centerX, -centerY);
                    }

                    var dataUrl = canvas.toDataURL(imageType, imageQuality);

                    $canvas.remove();

                    if (busyId)
                    {
                        _fwdc.busy.hide(busyId);
                        busyId = null;
                    }

                    return { "dataUrl": dataUrl, "canvas": $canvas };
                }
                catch (ex)
                {
                    if (busyId)
                    {
                        _fwdc.busy.hide(busyId);
                    }
                    throw ex;
                }
            };

            _fwdc.getMonitoringCameraImageData = function (fieldId, cameraInfo, data, imageWidth, imageHeight, idealWidth, idealHeight, rotation, imageType, imageQuality, busyId, dataUrl, $canvas)
            {
                try
                {
                    var $field = $.findElementById(fieldId);
                    var $canvas = $($.parseHTML("<canvas></canvas>")).appendTo(_fwdc.supportElementsContainer());
                    var canvas = $canvas[0];

                    var width = imageWidth;
                    var height = imageHeight;

                    if (idealWidth > 0 && imageWidth > idealWidth && idealHeight > 0 && imageHeight > idealHeight)
                    {
                        //Scale the image down to the ideal image size
                        var ratio = imageWidth / imageHeight;
                        width = idealWidth;
                        height = Math.round(idealWidth / ratio);
                        if (height > idealHeight)
                        {
                            height = idealHeight;
                            width = Math.round(idealHeight * ratio);
                        }
                    }

                    rotation = rotation || 0;
                    switch (rotation)
                    {
                        case 0:
                        case 180:
                            canvas.height = height;
                            canvas.width = width;
                            break;

                        case 90:
                        case 270:
                            canvas.height = width;
                            canvas.width = height;
                            break;

                        default:
                            throw "Unhandled rotation: " + rotation;
                    }

                    var context = canvas.getContext("2d");


                    if (rotation === 0)
                    {
                        context.drawImage(data, 0, 0, width, height);
                    }
                    else
                    {
                        var centerX = Math.round(canvas.width / 2);
                        var centerY = Math.round(canvas.height / 2);
                        var rotateRadians = rotation / 180 * Math.PI;
                        context.translate(centerX, centerY);
                        context.rotate(rotateRadians);
                        context.drawImage(data, width / -2, height / -2, width, height);
                        context.rotate(-rotateRadians);
                        context.translate(-centerX, -centerY);
                    }

                    var dataUrl = canvas.toDataURL(imageType, imageQuality);

                    $canvas.remove();

                    if (busyId)
                    {
                        _fwdc.busy.hide(busyId);
                        busyId = null;
                    }

                    return { "dataUrl": dataUrl, "canvas": $canvas };
                }
                catch (ex)
                {
                    if (busyId)
                    {
                        _fwdc.busy.hide(busyId);
                    }
                    throw ex;
                }
            };

            _fwdc.setCameraImageFieldData = function (fieldId, cameraInfo, busyId, dataUrl, $canvas)
            {
                try
                {
                    var $field = $.findElementById(fieldId);
                    var modal = $field.parent().hasClass("FastCameraCaptureModal");
                    if (modal)
                    {
                        _fwdc.showCameraCaptureModal(fieldId, $canvas, dataUrl, cameraInfo);
                    }
                    else
                    {
                        _fwdc.setInputImage(fieldId, dataUrl, cameraInfo, true);
                    }
                }
                catch (ex)
                {
                    if (busyId)
                    {
                        _fwdc.busy.hide(busyId);
                    }
                    throw ex;
                }
            }

            _fwdc.showCameraCaptureModal = function (fieldId, $canvas, dataUrl, cameraInfo)
            {
                var $accessKeyElements = _fwdc.disableAccessKeys();

                var $field = $.findElementById(fieldId);

                $canvas.remove();

                var $modal = $($.parseHTML("<div></div>")).addClass("FastCameraCaptureDialogContent");
                $modal.append($("<label></label>").addClass("FastCameraCaptureModalPrompt").text(_fwdc.standardDecode("CapturePhotoPrompt")));
                var $wrapper = $($.parseHTML("<div></div>")).addClass("FastCameraCapturePreviewContainer");
                $canvas
                    .css({
                        "max-width": Math.max(300, _fwdc.windowWidth * 0.75) + "px",
                        "max-height": Math.max(300, _fwdc.windowHeight * 0.75) + "px"
                    })
                    .addClass("FastCameraCapturePreview")
                    .appendTo($wrapper);

                $wrapper.appendTo($modal);

                var standardDecodes = _fwdc.standardDecodes();

                var buttons = [];
                buttons.push({
                    "text": standardDecodes.MsgBoxNo,
                    "class": "FastMessageBoxButtonNo",
                    "click": function (event)
                    {
                        $modal.dialog("close");
                        $modal.tryDestroyDialog();
                        $modal.remove();

                        var $video = $.findElementById("vid_" + fieldId);
                        if ($video.length)
                        {
                            var video = $video[0];
                            video.play();
                        }
                        else
                        {
                            _fwdc.refreshWindowContent();
                        }

                        _fwdc.stopEvent(event);
                    }
                });
                buttons.push({
                    "text": standardDecodes.MsgBoxYes,
                    "class": "FastMessageBoxButtonYes",
                    "click": function (event)
                    {
                        $modal.dialog("close");
                        $modal.tryDestroyDialog();
                        $modal.remove();
                        _fwdc.setInputImage(fieldId, dataUrl, cameraInfo, true);

                        _fwdc.stopEvent(event);
                    }
                });

                var position = { my: "center", at: "center", collision: "none", of: window };
                var minWidth = 300;
                var minHeight = 100;
                //var maxWidth = "90%";
                //var maxHeight //= "90%"; 90% max height 

                var maxWidth = _fwdc.windowWidth - 20;
                var maxHeight = _fwdc.windowHeight - 20;

                var titleCaption = $.findElementById("lb_" + fieldId).text() || $field.attr("alt");
                var colorClass = _fwdc.getCurrentManagerColor();
                var titleClass = titleCaption ? "" : " BlankTitle";

                $modal.appendTo(_fwdc.$body());

                $modal.dialog({
                    modal: true,
                    title: titleCaption,
                    draggable: true,
                    resizable: false,
                    width: "auto",
                    minWidth: minWidth,
                    minHeight: minHeight,
                    maxWidth: maxWidth,
                    maxHeight: maxHeight,
                    dialogClass: "FastCameraCaptureDialog FastPanelDialog " + _fwdc.getFastModalClass() + colorClass + titleClass,
                    closeOnEscape: false,
                    closeText: _fwdc.getCloseText(),
                    position: position,
                    open: function (event, ui)
                    {
                        FWDC.hideViewMenus();
                        _fwdc.hideToolTips();
                        _fwdc.closeComboboxes();
                        _fixModalOrder();
                        _fwdc.updateScreenReader();
                        _fwdc.showCurrentFieldTip();
                    },
                    initFocus: function ()
                    {
                        var uiDialog = $(this).data("uiDialog");
                        if (uiDialog)
                        {
                            uiDialog.uiDialogButtonPane.find("button").last().focus();
                        }
                    },
                    drag: function () { FWDC.checkFieldTipPositions(); },
                    close: function ()
                    {
                        _fwdc.restoreAccessKeys($accessKeyElements);
                        FWDC.hideViewMenus();
                        _fwdc.hideToolTips();
                        _fwdc.closeComboboxes();
                        $modal.remove();
                        _fwdc.showCurrentFieldTip();
                    },
                    buttons: buttons
                });
            };

            _fwdc.sizeCameraInputVideo = function ($video)
            {
                // parent1 = wrapper
                // parent2 = videocontainer
                // parent2 = field
                // parent3 = fieldcontainer
                var $wrapper = $video.parent();
                var $container = $wrapper.parent();
                var $field = $container.parent();

                var constraintWidth = $field.width();

                var maxHeight = $video.attr("data-maxheight");

                var aspectRatio = $video.data("fast-camera-aspectRatio");
                //$wrapper.css({ "max-height": "none", "box-sizing": "content-box", "padding": "" });
                if ($wrapper.hasClass("FastCameraRotate90") || $wrapper.hasClass("FastCameraRotate270"))
                {
                    // Swap height/width on the video
                    var newHeight = constraintWidth * aspectRatio;
                    if (maxHeight && maxHeight < newHeight)
                    {
                        newHeight = maxHeight;
                        constraintWidth = maxHeight / aspectRatio;
                    }

                    $wrapper.width(constraintWidth);
                    $wrapper.height(newHeight);
                    $video.width(newHeight);
                    $video.height(constraintWidth);
                }
                else
                {
                    var newHeight = constraintWidth / aspectRatio;
                    if (maxHeight && maxHeight < newHeight)
                    {
                        newHeight = maxHeight;
                        constraintWidth = maxHeight * aspectRatio;
                    }
                    $wrapper.width(constraintWidth);
                    $wrapper.height(newHeight);
                    $video.width(constraintWidth);
                    $video.height(newHeight);
                }
            };

            _fwdc.getCameraInputRotation = function ($video)
            {
                var $wrapper = $video.parent();
                if ($wrapper.hasClass("FastCameraRotate90"))
                {
                    return 90;
                }
                else if ($wrapper.hasClass("FastCameraRotate180"))
                {
                    return 180;
                }
                else if ($wrapper.hasClass("FastCameraRotate270"))
                {
                    return 270;
                }
                else
                {
                    return 0;
                }
            };

            _fwdc.setCameraInputClass = function ($element, statusClass)
            {
                $element.removeClass("FastCameraInputImageReady").removeClass("FastCameraInputImageLoading").removeClass("FastCameraInputImageError").addClass("FastCameraInputImage" + statusClass);

                if (statusClass === "Loading")
                {
                    $element.findElementsByClassName("FastCameraToolSelect").attr("disabled", "disabled");
                }
                else
                {
                    $element.findElementsByClassName("FastCameraToolSelect").removeAttr("disabled");
                }
            };

            _fwdc.cameraMediaError = function (ex, message, $element)
            {
                _fwdc._error("Error setting up camera input:", ex);

                $element.data("fast-current-stream-id", null);

                _fwdc.lastMediaError = ex;

                if (typeof ex === "OverconstrainedError")
                {
                    _fwdc.lastMediaError = "Overconstrained: " + ex.constraint + ":\r\n" + ex.message;
                }

                if (!_fwdc.lastMediaError)
                {
                    _fwdc.lastMediaError = "Unknown error occurred";
                }

                _fwdc.setCameraInputClass($element, "Error");

                //if (_fwdc.development)
                //{
                //    var err = ex + "";
                //    if (err.length > 1000)
                //    {
                //        err = err.substring(0, err.length - 1000);
                //    }

                //    $element.find(".DevErrorMessage").remove();
                //    $element.append($($.parseHTML('<div class="DevErrorMessage" style="font-family:monospace;white-space:pre-wrap;"></div>')).text("Dev Error Info:\r\n" + err));
                //} 
            };

            _fwdc.deviceMediaError = function (ex, message, $element)
            {
                var error = { "code": "monitoring_streamerror", "details": JSON.stringify(ex) + " - " + JSON.stringify(message) };

                _fwdc.submitMonitoringError($element.data("method"), error);
                return;
            };

            _fwdc.setupMediaStream = function ($element, callback, options, errorCallback)
            {
                _fwdc.lastMediaError = null;

                function onMediaError(ex, message)
                {
                    if (ex === false)
                    {
                        if (message)
                            _fwdc._warn(message);
                        // Media was not available, an error should already be logged
                        if (_fwdc.lastMediaError)
                        {
                            return;
                        }
                    }

                    if (errorCallback)
                    {
                        _fwdc.busy.done(function ()
                        {
                            errorCallback(ex, message, $element);
                        });
                    }
                }

                var mediaAvailable = "mediaDevices" in navigator;

                if (!mediaAvailable)
                {
                    // TODO: Show media not available error
                    onMediaError(false, "Media API not available");
                    return;
                }

                var supports = navigator.mediaDevices.getSupportedConstraints();

                if (!supports.width || !supports.height || !supports.facingMode)
                {
                    // TODO: Show media not available error
                    onMediaError(false, "Supports width/height/facingMode failed");
                    return;
                }

                if (options && options.displayMedia && !navigator.mediaDevices.getDisplayMedia)
                {
                    onMediaError(null, "Media API not available for monitoring.");
                    return;
                }

                var $container = $element.parent();
                var $toolbar = $element.children(".FastCameraToolbar");

                var idealWidth = parseInt($element.attr("data-camera-width"), 10) || 1920;
                var idealHeight = parseInt($element.attr("data-camera-height"), 10) || 1080;

                var settings = _fwdc.getJsonCookie("camerainput") || {};

                if (settings.defaultRotation)
                {
                    var $video = $element.findElementById("vid_" + $element.attr("data-field-id"), $element);
                    $video.parent().addClass("FastCameraRotate" + settings.defaultRotation);
                }

                var mediaConstraints = {
                    audio: false,
                    video:
                    {
                        width: { ideal: idealWidth },
                        height: { ideal: idealHeight },
                        facingMode: "user",
                        resizeMode: "none"
                    }
                };

                if (options && options.mediaConstraints)
                {
                    mediaConstraints = options.mediaConstraints;
                }

                if (settings && settings.defaultDeviceId)
                {
                    mediaConstraints.video.deviceId = { ideal: settings.defaultDeviceId };
                }

                function loadStream(mediaStream)
                {
                    var track = mediaStream.getTracks()[0];
                    var capabilities = track.getCapabilities && track.getCapabilities();
                    var settings = track.getSettings();
                    var streamHeight = settings.height;
                    var streamWidth = settings.width;
                    var aspectRatio = (streamWidth / streamHeight);

                    $element.data("fast-camera-info", { "name": track.label, "capabilities": capabilities });

                    $element.data("fast-current-stream-id", settings.deviceId);

                    if ($element.data("fast-onended"))
                    {
                        track.onended = $element.data("fast-onended");
                    }

                    var showSettings = false;
                    var showAdvanced = false;

                    // This is explicitly necessary for iOS in some cases to prevent black screens
                    track.enabled = true;

                    function setupSetting($element, capabilities, attr, track)
                    {
                        var capability = capabilities && capabilities[attr];
                        var $setting = $element.findElementsByClassName("FastCameraToolSetting_" + attr);
                        if ($setting.length && capability && capability.max && capability.max !== capability.min)
                        {
                            $element.addClass("FastCameraAllow_" + attr);
                            var $input = $element.findElementsByClassName("FastCameraTool_" + attr);
                            var input = $input[0];

                            var mySettings = _fwdc.getJsonCookie("camerainput") || {};
                            var myValue = (mySettings.constraints || {})[attr];

                            input.min = capability.min;
                            input.max = capability.max;
                            input.step = capability.step;

                            var applyConstraint = function (track, attr, value)
                            {
                                try
                                {
                                    //if (typeof value === "string")
                                    //{
                                    //    value = parseInt(value);
                                    //}

                                    var constraint = {};
                                    constraint[attr] = value;
                                    var constraints = {
                                        advanced: [
                                            constraint
                                        ]
                                    };

                                    track.applyConstraints(constraints).then(function ()
                                    {
                                        _fwdc.editJsonCookie("camerainput", function (settings)
                                        {
                                            if (!settings.constraints)
                                            {
                                                settings.constraints = {};
                                            }
                                            settings.constraints[attr] = value;
                                        });
                                    }).catch(function (ex)
                                    {
                                        _fwdc._error("Error applying constraints: ", ex);
                                    });
                                }
                                catch (ex)
                                {
                                    _fwdc._error("Error applying constraints: ", ex);
                                }
                            };

                            if (myValue !== undefined && input.min <= myValue && input.max >= myValue)
                            {
                                input.value = myValue;
                                if (myValue !== settings[attr])
                                {
                                    applyConstraint(track, attr, input.value);
                                }
                            }
                            else
                            {
                                input.value = settings[attr];
                            }

                            input.oninput = function (event)
                            {
                                applyConstraint(track, attr, input.value);
                            };

                            // Clear any display:hidden
                            $setting.css("display", "");
                            return true;
                        }

                        $setting.hide();
                        $element.removeClass("FastCameraAllow_" + attr);
                        return false;
                    }

                    var $settings = $element.findElementsByClassName("FastCameraToolSettingInput");

                    $settings.each(function ()
                    {
                        var $setting = $(this);
                        var attr = $setting.attr("data-attr");
                        var shown = setupSetting($element, capabilities, attr, track);
                        if (shown)
                        {
                            if ($setting.closest(".FastCameraAdvanced").length)
                            {
                                showAdvanced = true;
                            }
                            else
                            {
                                showSettings = true;
                            }
                        }
                    });

                    if (showSettings)
                    {
                        $element.addClass("FastCameraShowSettings");
                    }
                    else
                    {
                        $element.removeClass("FastCameraShowSettings");
                    }

                    if (showAdvanced)
                    {
                        $element.addClass("FastCameraShowAdvanced");
                    }
                    else
                    {
                        $element.removeClass("FastCameraShowAdvanced");
                    }

                    //$("#mediasettings").remove();
                    //$element.append($("<div id='mediasettings' style='white-space:pre-wrap'></div>").text("Settings:\r\n" + JSON.stringify(settings, null, 4) + "\r\n\r\nCapabilities:\r\n" + JSON.stringify(capabilities, null, 4)));

                    var $video = $element.findElementById("vid_" + $element.attr("data-field-id"), $element);
                    $video.data("fast-camera-aspectRatio", aspectRatio);

                    _fwdc.sizeCameraInputVideo($video);

                    var video = $video[0];
                    video.srcObject = mediaStream;
                    video.play();
                    $video.addClass("FastCameraInputVideoPlaying");
                    _fwdc.setCameraInputClass($element, "Ready");
                    _previewMonitoringVideo($element.attr("id"));
                }

                function displayStream(id)
                {
                    var currentStreamId = $element.data("fast-current-stream-id");
                    if (currentStreamId === id)
                    {
                        return;
                    }
                    if (options && options.displayMedia)
                    {
                        return;
                    }

                    // Stop any in-progress streams
                    _fwdc.destroyRichElements(false, $element);

                    var constraints = $.extend({}, mediaConstraints);
                    constraints.video.deviceId = { exact: id };

                    _fwdc.setCameraInputClass($element, "Loading");

                    navigator
                        .mediaDevices
                        .getUserMedia(constraints)
                        .then(loadStream)
                        .catch(onMediaError);
                }

                function deviceSelect(videoSources, deviceId, deviceLabel)
                {
                    var $select = $element.findElementById("sel_" + $element.attr("data-field-id")).attr("disabled", "disabled");
                    $select.empty();

                    var $first;
                    var $default;

                    for (var ii = 0; ii < videoSources.length; ++ii)
                    {
                        var $option = $($.parseHTML("<option></option>")).attr("value", videoSources[ii].deviceId).text(videoSources[ii].label).appendTo($select);

                        if (ii === 0)
                        {
                            $first = $option;
                        }
                        else
                        {
                            $select.removeAttr("disabled");
                        }

                        if (deviceLabel && deviceLabel === videoSources[ii].label)
                        {
                            $default = $option;
                        }
                        else if (deviceId && deviceId === videoSources[ii].deviceId && !$default)
                        {
                            $default = $option;
                        }
                    }

                    if (!$default)
                    {
                        $default = $first;
                        deviceId = $default.attr("value");
                    }

                    $default.attr("selected", "selected");

                    $select.change(function (event)
                    {
                        var deviceId = $(event.target).val();
                        _fwdc.editJsonCookie("camerainput", function (settings)
                        {
                            settings.defaultDeviceId = deviceId;
                        });
                        displayStream(deviceId);

                    });

                    return deviceId;
                }

                function deviceMenu(videoSources, deviceId)
                {
                    var $menu = $element.findElementById($element.attr("id") + "__Menu");
                    var menuId = $menu.attr("id");
                    var defaultId = videoSources[0].deviceId;

                    for (var ii = 0; ii < videoSources.length; ++ii)
                    {
                        //Still loop through video sources to verify deviceId passed back is valid
                        if (deviceId && deviceId === videoSources[ii].deviceId)
                        {
                            defaultId = videoSources[ii].deviceId;
                        }
                    }

                    _fwdc.monitoringInputs = videoSources;

                    return defaultId;

                }

                function loadDevices()
                {
                    if ($(document.activeElement).closest($element).equals($element))
                    {
                        _fwdc.focus("Camera Input Loaded", $element);
                    }

                    navigator
                        .mediaDevices
                        .enumerateDevices()
                        .then(function loadDevicesEnumerate(devices)
                        {
                            if (options && options.ignoreUserDevices)
                            {
                                if (callback)
                                {
                                    callback();
                                }
                                return;
                            }

                            var videoSources = [];
                            for (var ii = 0; ii < devices.length; ++ii)
                            {
                                var device = devices[ii];
                                if (device.kind === "videoinput" && device.deviceId)
                                {
                                    videoSources.push(device);
                                }
                            }

                            if (videoSources.length === 0)
                            {
                                onMediaError(false, "No video sources available, or no video sources permitted.");
                                return;
                            }

                            var settings = _fwdc.getJsonCookie("camerainput") || {};

                            if (settings.defaultRotation)
                            {
                                var $video = $element.findElementById("vid_" + $element.attr("data-field-id"), $element);
                                $video.parent().addClass("FastCameraRotate" + settings.defaultRotation);
                            }

                            var deviceId = settings.defaultDeviceId;
                            if (videoSources.length > 0)
                            {
                                if (options && options.inputMenu && options.inputMenu === true)
                                {
                                    deviceId = deviceMenu(videoSources, deviceId);
                                }
                                else
                                {
                                    var cameraName = options && options.cameraName ? options.cameraName : null;
                                    deviceId = deviceSelect(videoSources, deviceId, cameraName);
                                }
                                //var $select = $element.findElementById("sel_" + $element.attr("data-field-id")).attr("disabled", "disabled");
                                //$select.empty();

                                //var $first;
                                //var $default;

                                //for (var ii = 0; ii < videoSources.length; ++ii)
                                //{
                                //    var $option = $($.parseHTML("<option></option>")).attr("value", videoSources[ii].deviceId).text(videoSources[ii].label).appendTo($select);

                                //    if (ii === 0)
                                //    {
                                //        $first = $option;
                                //    }
                                //    else
                                //    {
                                //        $select.removeAttr("disabled");
                                //    }

                                //    if (deviceId && deviceId === videoSources[ii].deviceId)
                                //    {
                                //        $default = $option;
                                //    }
                                //}

                                //if (!$default)
                                //{
                                //    $default = $first;
                                //    deviceId = $default.attr("value");
                                //}

                                //$default.attr("selected", "selected");

                                //$select.change(function (event)
                                //{
                                //    var deviceId = $(event.target).val();
                                //    _fwdc.editJsonCookie("camerainput", function (settings)
                                //    {
                                //        settings.defaultDeviceId = deviceId;
                                //    });
                                //    displayStream(deviceId);

                                //});
                            }
                            else
                            {
                                // One source, just lock it to the only available camera.
                                deviceId = videoSources[0].deviceId;
                            }

                            displayStream(deviceId);

                            if (callback)
                            {
                                callback();
                            }
                        })
                        .catch(function loadDevicesEnumerateFailed(ex)
                        {
                            // We don't want to re-trigger error logic if we're already in an error state.
                            if (!_fwdc.lastMediaError)
                            {
                                onMediaError(ex);
                            }
                        });
                }

                if (options && options.displayMedia)
                {
                    navigator
                        .mediaDevices
                        .getDisplayMedia(mediaConstraints)
                        .then(loadStream)
                        .catch(onMediaError)
                        .finally(loadDevices);

                    return;
                }

                // Need to use getUserMedia FIRST so that permission is granted.
                navigator
                    .mediaDevices
                    .getUserMedia(mediaConstraints)
                    .then(loadStream)
                    .catch(onMediaError)
                    .finally(loadDevices);

            };

            _fwdc.lastMediaError = null;

            _fwdc.setPageTitle = function (title)
            {
                if (title && document.title !== title)
                {
                    document.title = title;
                    _fwdc.liveRegionSay(title);
                }
            };

            var _$liveRegion;
            _fwdc.liveRegionSay = function (text, level)
            {
                if (_$liveRegion)
                {
                    _$liveRegion.remove();
                    _$liveRegion = null;
                }

                level = level || "polite";

                _$liveRegion = $($.parseHTML('<div class="AccessibleLiveRegion AccessibleHelper"></div>'))
                    .attr("aria-live", level)
                    .attr("role", level !== "assertive" ? "status" : "alert")
                    .appendTo(_fwdc.supportElementsContainer());

                _fwdc.requestIdleCallback("liveRegionSay", function ()
                {
                    _$liveRegion.text(text);
                });
            };

            _fwdc.Init = {
                filterbox: function ($element, data)
                {
                    $element.each(function ()
                    {
                        var $input = $(this);
                        if (!$input.data("fastQuickFilterBox") && $input.is(":visible"))
                        {
                            var options = data.options;

                            var $filterContainer = $input.closest(".ViewStackLayout,.QuickFilterContainer");

                            if (!$filterContainer || !$filterContainer.length)
                            {
                                $filterContainer = _fwdc.parentDocumentContainer($input);
                            }

                            var $links = $filterContainer.find("a").map(function ()
                            {
                                var $link = $(this);
                                if ($link.closest(".NoQuickFilter").length) { return null; }
                                /*if ($.trim($link.text())) { return this; }
                                return null;*/
                                return this;
                            });

                            var $tables = $links.closest(".DocTable");
                            var $tableContainers = $tables.parent(".DocTableWrapper,.QuickFilterContainer");

                            var $wrapItems = $filterContainer.find(".ItemListRow");

                            var viewMenuFilter = $input.hasClass("ViewSelectorMenuFilter");
                            var filterRows = !viewMenuFilter && (!!$input.closest(".QuickRowFilter").length || $filterContainer.is(".QuickFilterRows"));
                            var filterOutlineGroups = !viewMenuFilter && !!$input.closest(".WebMenuFilter").length;

                            var filteredClass = "QuickFiltered";

                            var $viewGroups;

                            if (viewMenuFilter)
                            {
                                $viewGroups = $links.closest(".ViewSelectorMenuGroupItem");
                            }

                            var clearFiltered = function ()
                            {
                                $links
                                    .removeClass(filteredClass + " QuickFilterMatch QuickFilterTarget")
                                    .closest("tr.TDR,.ViewSelectorMenuViewItem,.ItemListRow,.ItemListRow")
                                    .removeClass(filteredClass + " QuickFilterMatch");

                                if (viewMenuFilter)
                                {
                                    $links
                                        .closest(".ViewSelectorMenuGroupItem")
                                        .removeClass(filteredClass + " QuickFilterMatch");
                                }
                                else
                                {
                                    $links
                                        .closest("table")
                                        .children("tbody")
                                        .removeClass(filteredClass + " QuickFilterMatch");

                                    $links
                                        .closest(".ItemListContainer").removeClass(filteredClass + " QuickFilterMatch")
                                        .closest(".ItemListOutlineGroup").removeClass(filteredClass + " QuickFilterMatch");

                                    $wrapItems
                                        .removeClass(filteredClass + " QuickFilterMatch");

                                    if (!filterRows)
                                    {
                                        $links.parent(".TableHeaderLink").removeClass(filteredClass);

                                        $links.each(function ()
                                        {
                                            var $this = $(this);
                                            var index = $this.attr("filtered-tabindex");
                                            if (index !== undefined)
                                            {
                                                $this
                                                    .attr("tabindex", index)
                                                    .removeAttr("filtered-tabindex");
                                            }
                                        });
                                    }
                                }

                                $filterContainer.removeClass("QuickFiltering");
                            };

                            $input.data("clearFiltered", clearFiltered);

                            $input
                                .removeClass("FieldDisabled")
                                .addClass("FieldEnabled")
                                .data("fast-norecalc", true)
                                .addClass("FastNoRecalc")
                                .removeAttr("readonly")
                                .removeAttr("onkeydown")
                                .removeAttr("onfocus")
                                .removeAttr("onblur")
                                .keyup(function (event)
                                {
                                    if (event.which === _fwdc.keyCodes.ESCAPE)
                                    {
                                        $input.val("");

                                        if (options && options.escape && options.escape() === false)
                                        {
                                            clearFiltered();
                                            _evaluateBaseManagerAboveFold();
                                            return;
                                        }
                                    }

                                    var filter = $.trim($input.val() || "");

                                    $input.removeClass("QuickFilterMatched");

                                    $tableContainers.removeClass(filteredClass);

                                    clearFiltered();

                                    if (filter)
                                    {
                                        $filterContainer.addClass("QuickFiltering");

                                        var $visibleLinks = $links.filterVisible(); //$links.filter(":visible");

                                        var filters = filter.split(" ");
                                        var $matchingLinks;
                                        var $matchingRows;
                                        var $filteredRows;
                                        var $filteredLinks;
                                        var $regularLinks;
                                        var $regularMatchingLinks;
                                        if (filterOutlineGroups)
                                        {
                                            var $bodies = $visibleLinks.closest(".DocTableBody,.ItemListOutlineGroup");
                                            $matchingRows = $bodies.filtercontainsi(filters);
                                            $filteredRows = $bodies.not(".QuickFilterMatch");
                                            $regularLinks = $visibleLinks.not(".RowLinkWrapper");
                                            $regularMatchingLinks = $regularLinks.filtercontainsi(filters);
                                            if ($regularMatchingLinks.length)
                                            {
                                                $matchingLinks = $regularMatchingLinks.addClass("QuickFilterMatch");

                                                $filteredLinks = $regularLinks.not(".QuickFilterMatch").addClass(filteredClass);
                                            }
                                            else
                                            {
                                                $matchingLinks = $matchingRows.find("a").first().addClass("QuickFilterMatch");
                                                $matchingRows.find("a").removeClass(filteredClass);
                                            }
                                        }
                                        else if (filterRows)
                                        {
                                            var $rows = $visibleLinks.closest("tr.TDR,.ViewSelectorMenuViewItem,.ItemListRow");
                                            $matchingRows = $rows.filtercontainsi(filters);
                                            $filteredRows = $rows.not(".QuickFilterMatch");
                                            $regularLinks = $visibleLinks.not(".RowLinkWrapper");
                                            $regularMatchingLinks = $regularLinks.filtercontainsi(filters);
                                            if ($regularMatchingLinks.length)
                                            {
                                                $matchingLinks = $regularMatchingLinks.addClass("QuickFilterMatch");

                                                $filteredLinks = $regularLinks.not(".QuickFilterMatch").addClass(filteredClass);
                                            }
                                            else
                                            {
                                                $matchingLinks = $matchingRows.find("a").first().addClass("QuickFilterMatch");
                                                $matchingRows.find("a").removeClass(filteredClass);
                                            }
                                        }
                                        else
                                        {
                                            $matchingLinks = $visibleLinks.filtercontainsi(filters).addClass("QuickFilterMatch");

                                            $filteredLinks = $visibleLinks.not(".QuickFilterMatch").addClass(filteredClass);

                                            $filteredLinks.each(function ()
                                            {
                                                var $this = $(this);
                                                var index = $this.attr("tabindex");
                                                if (index !== undefined)
                                                {
                                                    $this
                                                        .attr("filtered-tabindex", index)
                                                        .attr("tabindex", -1);
                                                }
                                            });

                                            $filteredLinks.closest(".TableHeaderLink").addClass(filteredClass);
                                            $matchingRows = $matchingLinks.closest("tr.TDR,.ViewSelectorMenuViewItem,.ItemListRow");
                                            $filteredRows = $filteredLinks.closest("tr.TDR,.ViewSelectorMenuViewItem,.ItemListRow");
                                        }
                                        $filteredRows.addClass(filteredClass);
                                        $matchingRows.addClass("QuickFilterMatch").removeClass(filteredClass);

                                        if (filterOutlineGroups)
                                        {
                                            // Post-process to hide rows that only have filtered links.
                                            $visibleLinks.closest(".TDR,.ViewSelectorMenuViewItem,.ItemListRow").each(function ()
                                            {
                                                var $this = $(this);

                                                var $links = $this.find("a");

                                                // We scan for non-filtered links instead of being based on filter matches,
                                                // as the outlined tables are matched including their header text, so the links may not
                                                // always match the filter text.
                                                if (!$links.filterNotHasClassName(filteredClass).length)
                                                {
                                                    $this.addClass(filteredClass);
                                                }
                                                else
                                                {
                                                    $this.addClass("QuickFilterMatch");
                                                }
                                            });
                                        }
                                        else if (filterRows)
                                        {
                                            $tables.each(function ()
                                            {
                                                var $table = $(this);
                                                var isTable = $table.tagIs("table");
                                                //var $outlineElements = isTable
                                                //    ? $table.children("tbody")
                                                //    : $table.children(".DocTableWrapOutlineList").children(".ItemListOutlineGroup");

                                                var $outlineElements;
                                                var hasVisibleRows;

                                                if (isTable)
                                                {
                                                    // Table
                                                    $outlineElements = $table.children("tbody");
                                                    hasVisibleRows = $outlineElements.children("tr.QuickFilterMatch").length > 0
                                                }
                                                else if ($table.children(".DocTableWrapOutlineList").length)
                                                {
                                                    // Outlined Item List
                                                    $outlineElements = $table.children(".DocTableWrapOutlineList").children(".ItemListOutlineGroup");
                                                    hasVisibleRows = $outlineElements.children(".ItemListContainer").children(".ItemListRow.QuickFilterMatch").length > 0;
                                                }
                                                else
                                                {
                                                    // Normal Item List
                                                    $outlineElements = $table.children(".ItemListContainer");
                                                    hasVisibleRows = $outlineElements.children(".ItemListRow.QuickFilterMatch").length > 0;
                                                }

                                                //var hasVisibleRows = isTable
                                                //    ? $outlineElements.children("tr.QuickFilterMatch").length > 0
                                                //    : $outlineElements.children(".ItemListContainer").children(".ItemListRow.QuickFilterMatch").length > 0;

                                                if (!hasVisibleRows)
                                                {
                                                    $table.parent().addClass(filteredClass);
                                                }
                                                else
                                                {
                                                    $outlineElements.each(function ()
                                                    {
                                                        var $tbody = $(this);

                                                        if (isTable)
                                                        {
                                                            // Table
                                                            if (!$tbody.children("tr.QuickFilterMatch").length)
                                                            {
                                                                $tbody.addClass(filteredClass);
                                                            }
                                                        }
                                                        else if ($table.children(".DocTableWrapOutlineList").length)
                                                        {
                                                            // Outlined Item List
                                                            if (!$tbody.children(".ItemListContainer").children(".ItemListRow.QuickFilterMatch").length)
                                                            {
                                                                $tbody.addClass(filteredClass);
                                                            }
                                                        }
                                                        else
                                                        {
                                                            // Normal Item List
                                                            if (!$tbody.children(".ItemListRow.QuickFilterMatch").length)
                                                            {
                                                                $tbody.addClass(filteredClass);
                                                            }
                                                        }
                                                    });
                                                }
                                            });
                                        }
                                        else if (viewMenuFilter)
                                        {
                                            $matchingLinks.closest(".ViewSelectorMenuGroupItem").addClass("QuickFilterMatch");
                                            $viewGroups.not(".QuickFilterMatch").addClass(filteredClass);
                                        }
                                        else
                                        {
                                            $wrapItems.each(function ()
                                            {
                                                var $this = $(this);
                                                if (!$this.find("a.QuickFilterMatch").length)
                                                {
                                                    $this.addClass(filteredClass);
                                                }
                                                else
                                                {
                                                    $this.addClass("QuickFilterMatch");
                                                }
                                            });

                                            var $tbodies = $tables.children("tbody");
                                            $tbodies.each(function ()
                                            {
                                                var $tbody = $(this);
                                                if (!$tbody.children("tr.QuickFilterMatch").length)
                                                {
                                                    $tbody.addClass(filteredClass);
                                                }
                                            });
                                        }

                                        if ($matchingLinks.length && !_fwdc.tap)
                                        {
                                            var $exactMatch;
                                            var $firstMatch;
                                            $matchingLinks.each(function ()
                                            {
                                                var $link = $(this);
                                                var linkText = $link.text() || "";

                                                if (!$firstMatch) { $firstMatch = $link; }

                                                if (!$exactMatch && (linkText.toLowerCase() === filter.toLowerCase()))
                                                {
                                                    $exactMatch = $link;
                                                }
                                            });

                                            var click = (event.which === _fwdc.keyCodes.ENTER);

                                            var $target = $exactMatch || $firstMatch;

                                            if ($target)
                                            {
                                                $input.addClass("QuickFilterMatched");
                                                $target.addClass("QuickFilterTarget");
                                                if (click)
                                                {
                                                    $target.click();
                                                }
                                            }
                                        }
                                    }

                                    _fwdc.requestIdleCallback("QuickFilterPostEval", function ()
                                    {
                                        _evaluateBaseManagerAboveFold();
                                    });
                                });
                        }
                    });
                },
                tablebarscale: function ($element, data)
                {
                    var $header = $element;
                    var $table = $header.closest("table");
                    if ($table.hasClass("DocTableInverted")) { return; }

                    if ($header && $header.length)
                    {
                        $header.find("div.BarScaleLabel").each(function ()
                        {
                            var $label = $(this);
                            if ($label.hasClass("Last"))
                            {
                                $label.css({ "left": "auto", "right": "0" });
                            }
                            else
                            {
                                var labelWidth = $label.width();
                                $label.css("width", labelWidth + "px");

                                if (!$label.hasClass("First"))
                                {
                                    $label.css("margin-left", (labelWidth / -2) + "px");

                                    var headerOffset = $header.offset();
                                    var headerRight = (headerOffset ? headerOffset.left : 0) + $header.width();
                                    var labelOffset = $label.offset();
                                    var labelRight = (labelOffset ? labelOffset.left : 0) + $label.width();

                                    if (labelRight > headerRight)
                                    {
                                        $label.addClass("Last").css({ "left": "auto", "right": "0px", "margin": "" });
                                    }
                                }
                            }
                        });
                    }
                },
                tablescrollrow: function ($element, data)
                {
                    if ($element && $element.length)
                    {
                        _fwdc.setTimeout("Init.tablescrollrow", function ()
                        {
                            /*var $scrollContainer = $element.closest(".FastScrollContainer");
                            var padding = 50;
                            if ($scrollContainer && $scrollContainer.length)
                            {
                                padding = $scrollContainer.height() / 3;
                            }
                            else
                            {
                                padding = 200;
                                $scrollContainer = _fwdc.$body();
                            }
                            _fwdc.ensureElementVisible($element, false, $scrollContainer, padding);*/
                            _fwdc.scrollIntoView($element);
                        });
                    }
                },
                tableviewselector: function ($element, data)
                {
                    /*var $container = $element;
                    if ($container && !$container.data("uiControlgroup"))
                    {
                        $container.buttonset();
                    }*/
                },
                watermark: function ($element, data)
                {
                    FWDC.watermark($element, data.watermark === undefined ? data : data.watermark);
                },
                mask: function ($element, data)
                {
                    $element.setMask((data && data.mask) || "");
                },
                datepicker: function ($element, data)
                {
                    var inline = $element.hasClass("DocControlDatepicker") || $element.hasClass("DocControlDatepickerCombo");

                    var options = {
                        beforeShow: function (input, picker)
                        {
                            var $this = $(this);
                            if ($this.is("[readonly]"))
                            {
                                return false;
                            }

                            $this.addClass("DatePickerOpen");
                            if (!inline)
                            {
                                var $button = $element.siblings(".ui-datepicker-trigger");
                                $button.attr("aria-expanded", "true");
                            }
                        },
                        onSelect: function (input, picker)
                        {
                            var $this = $(this);
                            // Put focus back on date input field after selecting date.
                            _fwdc.focus("DatePickerSelect", $this);
                            var id = $this.attr("id");
                            if (id)
                            {
                                // Inline datepicker not a normal field, so set last focus field to capture it
                                _fwdc.setLastFocusField(id);
                            }
                            _recalc({ 'source': input, 'trigger': 'DatePickerSelect' });
                            _fwdc.focusCurrentField();
                        },
                        onClose: function (picker)
                        {
                            $(this).removeClass("DatePickerOpen");
                            var $this = $(this);
                            // Put focus back on date input field after closing date picker.
                            _fwdc.focus("DatePickerSelect", $this);
                            if (!inline)
                            {
                                var $button = $element.siblings(".ui-datepicker-trigger");
                                $button.attr("aria-expanded", "false");
                            }
                        },
                        minDate: $element.attr("data-dp-mindate") || null,
                        maxDate: $element.attr("data-dp-maxdate") || null
                    };

                    if (inline)
                    {
                        options.dateFormat = data.jqueryDateFormat;
                        options.defaultDate = $element.attr("data-value") || null;
                        options.changeMonth = false;
                        options.changeYear = false;
                        options.disabled = $element.hasClass("FieldDisabled");
                        options.showOn = "";
                        options.showButtonPanel = false;

                        if (data.dates)
                        {
                            var allowedDates = {};
                            for (var ii = 0; ii < data.dates.length; ++ii)
                            {
                                var date = data.dates[ii];
                                allowedDates[date.value] = {
                                    "value": date.value,
                                    "label": date.label,
                                    "class": date.class || null
                                };
                            }
                            $element.data("fast-datepicker-dates", allowedDates);
                        }
                        else
                        {
                            $element.data("fast-datepicker-dates", null);
                        }

                        options.beforeShowDay = function (date)
                        {
                            var allowedDates = $element.data("fast-datepicker-dates");
                            if (allowedDates)
                            {
                                var canonDate = _fwdc.getCanonDateString(date);
                                var date = allowedDates[canonDate];
                                if (date)
                                {
                                    return [
                                        !$element.datepicker("option", "disabled"),
                                        date.class || "",
                                        date.label || ""
                                    ];
                                }

                                return [false, "", ""];
                            }

                            return [!$element.datepicker("option", "disabled"), ""];
                        };
                    }

                    $element.datepicker($.extend({},
                        _datepickerRegionalData(),
                        _datepickerSettings,
                        options));

                    var $button = $element.siblings(".ui-datepicker-trigger");

                    if (inline)
                    {
                        $element.datepicker("setDate", $element.attr("data-value"));
                    }
                    else
                    {
                        $button.attr("aria-expanded", "false");
                        $button.attr("aria-controls", "ui-datepicker-div");
                        $button.attr("aria-haspopup", "menu");
                    }


                    var describedBy = $element.attr("id");
                    if (describedBy)
                    {
                        var $lb = $.findElementById("lb_" + describedBy);
                        if ($lb && $lb.length)
                        {
                            describedBy = "lb_" + describedBy;
                        }
                        $button.attr("aria-describedby", describedBy);
                    }

                    if (_fwdc.datePickerNoFocus)
                    {
                        $button.attr("tabIndex", -1);
                    }
                },
                autorefresh: function ($element, data)
                {
                    _fwdc.autoRefresh(data.id, data.refreshTime, function ()
                    {
                        _closeBasicDialogs();
                        return FWDC.eventOccurred(null, { field: data.id, eventType: _fwdc.EventType.AutoRefresh });
                    }, data.refreshMs, data.refreshDate);
                },
                syntaxhighlight: function ($element, data)
                {
                    _fwdc.setupSyntaxHighlight($element.attr("id"), data.syntaxhighlighttype);
                },
                media: function ($element, data)
                {
                    _fwdc.setupMediaPlayer($element);
                },
                modaltitlebar: function ($element, data)
                {
                    _fwdc.setupModalTitle($element, data.modaltitlebar || data);
                },

                // Init the explicit pixel width of fixed width pixel tables.  Necessary to handle standard class-based column widths.
                fixedtable: function ($table)
                {
                    if ($table.hasClass("DocTableResponsive") || $table.css("table-layout") !== "fixed")
                    {
                        return;
                    }

                    var $cols = $table.children("colgroup").children("col");

                    if (!$cols.length)
                    {
                        return;
                    }

                    var $percentCols = _fwdc.findPercentColumns($cols);
                    if ($percentCols && $percentCols.length)
                    {
                        $table.css("width", "100%");
                        return;
                    }

                    var width = 0;

                    var colWidths = $cols.colsCssWidths();

                    $cols.each(function (ii)
                    {
                        //var $col = $(this);
                        var widthPx = colWidths[ii]; //$col.cssWidth();
                        var colWidth = parseFloat(widthPx);
                        if (!isNaN(colWidth))
                        {
                            width += colWidth;
                        }
                    });

                    $table.css("width", width + "px");
                    $table
                        .closest(".TableContainer")
                        .children(".DocTableStickyHeader")
                        .children(".DocTableVirtualHeadersContainer")
                        .children(".DocTableVirtualHeaders")
                        .css("width", width + "px");
                },
                responsivecols: function ($colgroup)
                {
                    //_fwdc.resetColumnPercentWidths($colgroup.children("col"));
                },
                panelscrollcontainer: function ($scrollContainer)
                {
                    // Can we delay this to prevent layout calc?
                    _fwdc.setTimeout("panelscrollcontainer.init", function ()
                    {
                        // Panels that use Init to force this must do it earlier than the standard updateScrollPanel allows.
                        _fwdc.updateScrollPanel($scrollContainer, true);
                    });
                },
                tablescrolltogether: function ($table)
                {
                    _fwdc.setTimeout("Init.tablescrolltogether", function ($table)
                    {
                        var $container = $table.closest(".TableContainer");
                        if ($container.length)
                        {
                            var $content = $table.closest(".PanelScrollContainer");
                            var $elements = $($content);
                            if ($elements.length)
                            {
                                $elements = $elements
                                    .add($container.children(".DocTableVirtualHeadersContainer,.DocTableVirtualScrollbar"))
                                    .add($container.children(".DocTableStickyHeader").children(".DocTableVirtualHeadersContainer"));

                                if ($elements.length > 1)
                                {
                                    _fwdc.scrollTogether($elements, $content.attr("id"), $table.attr("id"));
                                }
                            }
                        }
                    }, 0, $table);
                },
                tablevirtualheaders: function ($container, data, preferImmediate)
                {
                    if (!$container.data("fast-tvh"))
                    {
                        //var caption = $container.closest(".DocTableHeader").find(".FastTitlebarCaption");
                        //caption = caption.text();

                        var rtn;

                        _fwdc.setTimeout("tablevirtualheaders", function ($container, preferImmediate)
                        {
                            $container.addClass("Ready");
                            //var height = $container.height();
                            if (_fwdc.resizeVirtualHeaderRow($container))
                            {
                                //$container
                                //    .css("margin-bottom", (-1 * height) + "px")
                                //    .data("fast-tvh", true);
                                //_fwdc.resizeVirtualHeaderRow($container, height);

                                var scrollTogetherTableId = $container.data("fast-scrolltogether-data");
                                if (scrollTogetherTableId)
                                {
                                    _fwdc.Init.tablescrolltogether(_fwdc.parentDocumentContainer($container).find("#" + scrollTogetherTableId));
                                }
                            }
                            else
                            {
                                if (preferImmediate)
                                {
                                    rtn = false;
                                }
                                else
                                {
                                    _fwdc.setInitType($container, "tablevirtualheaders");
                                }
                            }
                        }, preferImmediate ? -1 : 0, $container, preferImmediate);

                        return rtn;
                    }
                },
                tablevirtualscrollbar: function ($scrollbar, data, preferImmediate)
                {
                    _fwdc.setTimeout("tablevirtualscrollbar", function ($scrollbar)
                    {
                        var $content = $scrollbar.children(".DocTableVirtualScrollbarContent");
                        var $table = $scrollbar.parent().find(".DocTable").first();
                        $content.outerWidth($table.outerWidth());

                        // Have to use outerHeight to account for the scrollbar.
                        $scrollbar
                            .css("display", "block")
                            .css("margin-top", (-1 * $scrollbar.outerHeight()) + "px")
                            .css("display", "");

                        var scrollTogetherTableId = $scrollbar.data("fast-scrolltogether-data");
                        if (scrollTogetherTableId)
                        {
                            _fwdc.Init.tablescrolltogether(_fwdc.parentDocumentContainer($scrollbar).find("#" + scrollTogetherTableId));
                        }
                    }, preferImmediate ? -1 : 0, $scrollbar);
                },
                linkset: function ($element, data)
                {
                    var options = { optionSelector: data.optionSelector };

                    if (data.role !== undefined)
                    {
                        options.role = data.role;
                    }

                    if (data.itemrole !== undefined)
                    {
                        options.itemrole = data.itemrole;
                    }

                    $element.linkset(options);
                },

                showpassword: function ($element)
                {
                    var $button = $($.parseHTML('<button type="button" class="FastInputButton ShowPasswordButton FastEvt" data-event="ToggleShowPassword"></button>'));
                    $button.data("$passwordField", $element);
                    $button.text(_fwdc.getDecode("ToggleShowPassword"));
                    $button.attr("aria-pressed", "false");
                    var id = $element.attr("id");
                    if (id)
                    {
                        var describedBy = "lb_" + id;
                        var $label = $.findElementById(describedBy);
                        if ($label.length)
                        {
                            $button.attr("aria-describedby", describedBy);
                        }
                    }

                    if (_fwdc.autoFocusMode)
                    {
                        $button.attr("tabIndex", -1);
                    }

                    $element.parent().append($button);

                    $element.addClass("HasShowPassword");
                },

                camerainputimage: function ($element)
                {
                    _fwdc.setupMediaStream($element, null, null, _fwdc.cameraMediaError);
                },
                rotatelabel: function ($field, data)
                {
                    var $container = $field.closest('.CGDC');
                    var $text = $field.children('span');

                    if ($container.hasClass('FastRotated')) { return; }

                    switch (data.rotation)
                    {
                        case -90:
                        case 270:                            
                            $container.css({
                                'width': $container.height() + 'px',
                                'height': $container.width() + 'px'
                            }).addClass('FastRotated Rotated270');

                            break;
                        case 90:
                            $container.css({
                                'width': $container.height() + 'px',
                                'height': $container.width() + 'px'
                            }).addClass('FastRotated Rotated90');
                            break;
                        case 180:
                            $container.addClass('FastRotated Rotated180');
                            break;
                    }
                }

            };

            _fwdc.InitClasses = {
                AssistantTranscript: function ()
                {
                    _fwdc.resizeAssistant();
                    $(this).querySelectorAll(".AssistantTranscript > .DocTableWrapper").scrollTop(1000000);
                },
                AssistantThinkingIndicator: function ()
                {
                    $(this).html("<div></div><div></div><div></div>");
                }
            };

            _fwdc.setInitType = function ($element, type, data)
            {
                $element.addClass("FastInitElement");

                data = (data === undefined) ? $element.data("fi") : data;

                if (!data)
                {
                    data = {};
                }

                if (!data.fi)
                {
                    data.fi = [];
                }

                var fi = data.fi;

                if (fi.indexOf(type) < 0)
                {
                    fi.push(type);
                }

                $element.data("fi", data);
            };

            _fwdc.initElement = function (element, preferImmediate)
            {
                var $element = $(element);
                var data = $element.data("fi");
                $element.removeAttr("data-fi");

                if (data)
                {
                    if (typeof data === "string")
                    {
                        data = { fi: [data] };
                    }
                    else if (!data.fi)
                    {
                        data = { fi: data };
                    }

                    var delayInit;
                    for (var ii = 0; ii < data.fi.length; ++ii)
                    {
                        var type = data.fi[ii];

                        if (type)
                        {
                            var func = type && _fwdc.Init[type];
                            var initOk = true;

                            if (func)
                            {
                                if (func($element, data, preferImmediate) === false)
                                {
                                    //_fwdc._debug("Delaying init [" + type + "] for element: ", $element);
                                    delayInit = true;
                                    initOk = false;
                                }
                            }
                            else
                            {
                                _fwdc._warn("Unhandled init type: " + type);
                            }

                            if (initOk)
                            {
                                data.fi[ii] = null;
                            }
                        }
                    }

                    if (delayInit)
                    {
                        $element.data("fi", data);
                    }
                    else
                    {
                        $element.removeClass("FastInitElement").removeData("fi");
                    }
                }
                else
                {
                    _fwdc._warn("Could not find init data for element: ", element);
                    $element.removeClass("FastInitElement");
                }
            };

            _fwdc.initElements = function ($container, preferImmediate)
            {
                var $initElements = $.findElementsByClassName("FastInitElement", $container);
                if ($container)
                {
                    var $initContainers = $container.filterHasClassName("FastInitElement");
                    if ($initContainers && $initContainers.length)
                    {
                        if ($initElements)
                        {
                            $initElements = $initElements.add($initContainers);
                        }
                        else
                        {
                            $initElements = $initContainers;
                        }
                    }
                }

                if ($initElements && $initElements.length)
                {
                    $initElements.each(function ()
                    {
                        _fwdc.initElement(this, preferImmediate);
                    });
                }

                var $classInitElements;
                $.each(_fwdc.InitClasses, function (initClass, initFunction)
                {
                    var $elements = $.findElementsByClassName(initClass, $container).filterNotHasClassName("FCI").each(initFunction);

                    if ($classInitElements)
                    {
                        $classInitElements = $classInitElements.add($elements);
                    }
                    else
                    {
                        $classInitElements = $elements;
                    }
                });

                if ($classInitElements)
                {
                    $classInitElements.addClass("FCI");
                }
            };

            _fwdc.setUserSelectedRow = function ($row, options)
            {
                if (!options.force && $row.hasClass("TableHighlightRow")) { return; }

                var isTemplateRow = $row.hasClass("TTDR");
                if (isTemplateRow)
                {
                    var $templateCell = $row.children();
                    if ($templateCell.hasClass("TableHighlightCell"))
                    {
                        return;
                    }
                }

                var row = $row.data("row");
                if (!row) { return; }

                var $table = $row.closest("table");
                if (!$table.hasClass("UserSelectable")) { return; }

                var tableId = $table.attr("id");
                if (!tableId) { return; }

                _fwdc.setProperties(null, {
                    control: "",
                    type: "UserSelectedRow",
                    target: tableId,
                    busy: true,
                    async: !!options.async,
                    properties: { row: row },
                    action: false,
                    commitEdits: false,
                    callback: function (response)
                    {
                        if (response)
                        {
                            if (response.success)
                            {
                                _highlightUserSelectedRow($row);
                            }
                            else if (response.success === null || response.success === undefined)
                            {
                                _highlightUserSelectedRow($row);
                                _handleRecalcUpdates(response);
                                //_fwdc.handleActionResult(response);
                            }
                        }
                    }
                });
            };

            _fwdc.checkRequired = function (element)
            {
                $(element).each(function ()
                {
                    var $field = $(this);
                    if ($field.attr("data-fast-required") === "") { return; }

                    var $indicator = $("#indicator_" + $field.attr("id"));

                    var $container = $field.closest(".BasicField");

                    var val = ($field.val() || "").trim();

                    if (!val)
                    {
                        $field.addClass("FieldRequired");
                        $field.attr("title", $field.attr("data-requiredtitle"));

                        if ($field.tag() === "SELECT")
                        {
                            $field.addClass("watermark");
                        }

                        $indicator.addClass("FIFieldRequired");

                        $container.addClass("FieldRequired");

                        $field.val("");
                    }
                    else
                    {
                        if (!$field.attr("data-requiredtitle"))
                        {
                            $field.attr("data-requiredtitle", $field.attr("title"));
                        }

                        $field.removeClass("FieldRequired watermark");
                        //$field.removeAttr("title");
                        $field.attr("title", "");

                        $indicator.removeClass("FIFieldRequired");

                        $container.removeClass("FieldRequired");
                    }

                    _fwdc.showCurrentFieldTip(true);
                });
            };

            _fwdc.postAppMessage = function (interfaceName, data, refresh)
            {
                var handlerSource = window.webkit ? window.webkit.messageHandlers : window;

                if (handlerSource && handlerSource[interfaceName])
                {
                    handlerSource[interfaceName].postMessage(data);
                }
                else
                {
                    // TODO: Raise a messagebox on failing to access the handler?
                    _fwdc._warn("No handler source for interface: [" + interfaceName + "] to post data: " + data);
                }

                if (_default(refresh, true))
                {
                    _fwdc.refreshPage("postAppMessage:" + interfaceName);
                }
            };

            _fwdc.eventBusySource = function (event)
            {
                if (event && event.target)
                {
                    if ($(event.target).closest("#MANAGER_ASSISTANT__0").length)
                    {
                        return _fwdc.busySources.Assistant;
                    }
                }

                return null;
            };

            // Test if an element has been removed from the DOM or is in an old transition parent.
            _fwdc.ignoreFieldEvents = function ($field)
            {
                if (!$field.inDom())
                {
                    return true;
                }

                if ($field.closest(".FastTransitionOld").length)
                {
                    return true;
                }


                return false;
            };

            // Creates a temporary <a> with the provided URL so it can specify the referrerpolicy attribute, which window.location cannot.
            _fwdc.referUrl = function (url, newWindow)
            {
                var $link = $($.parseHTML("<a></a>"))
                    .attr("href", url)
                    .text("Refer Link: " + url)
                    .attr("referrerpolicy", "unsafe-url");

                if (newWindow)
                {
                    $link.attr("target", "_blank");
                }

                $link.appendTo(_fwdc.supportElementsContainer());

                _fwdc.setTimeout("Deferred referUrl click", function ($link)
                {
                    // Use the native .click API for the link element, as the jQuery version does not properly activate the link.
                    $link[0].click();

                    _fwdc.setTimeout("Deferred referUrl remove", function ($link)
                    {
                        $link.remove();
                    }, 100, $link);

                }, 0, $link);
            };

            var _standardEventTrigger = "";

            var _rippleStartEvent = null;
            //var _rippleHandle = null;

            _fwdc.showClickRipple = function (event, $clicked, clickPos)
            {
                if (_rippleStartEvent === event)
                {
                    return;
                }

                if (!$clicked)
                {
                    $clicked = $(event.currentTarget);
                }

                var $clickTarget = $clicked;
                var clickFor = $clicked.attr("for");
                if (clickFor)
                {
                    $clickTarget = $.findElementById(clickFor);
                    if (!$clickTarget || !$clickTarget.length)
                    {
                        $clickTarget = $clicked;
                    }
                }

                if (!$clickTarget.attr("disabled"))
                {
                    var clickedRect = $clicked.displayBoundingBox();
                    if (clickedRect)
                    {
                        _rippleStartEvent = event;
                        var size = Math.max(clickedRect.width, clickedRect.height) * 2.5;

                        if (!clickPos)
                        {
                            if (event && event.clientX !== undefined)
                            {
                                clickPos = {
                                    "left": (event.clientX - clickedRect.left),
                                    "top": (event.clientY - clickedRect.top)
                                };
                            }
                            else
                            {
                                clickPos = {
                                    "left": (clickedRect.width / 2),
                                    "top": (clickedRect.height / 2)
                                };
                            }
                        }

                        var clickedClickPos = {
                            "left": clickPos.left + "px",
                            "top": clickPos.top + "px",
                            "height": size + "px",
                            "width": size + "px"
                        };

                        var $ripple = $($.parseHTML('<div class="RippleEffect" role="presentation" aria-hidden="true"></div>')).css(clickedClickPos).appendTo($clicked);

                        _fwdc.setTimeout(event.type + " Ripple Start", function ($ripple)
                        {
                            var onTransition = function (event, $ripple)
                            {
                                if (this)
                                {
                                    $(this).off(".ripple");
                                }

                                _fwdc.onTransition(event.type + " Ripple End", ($ripple || event.data), "RippleEnd", function ($ripple)
                                {
                                    $ripple.remove();
                                }, false);
                            };

                            switch (event.type)
                            {
                                case "mousedown":
                                    $ripple.addClass("RippleStart");
                                    $clicked.one("mouseup.ripple mouseleave.ripple", $ripple, onTransition);
                                    break;
                                /*case "keydown":
                                    $clicked.one("keyup.ripple blur.ripple", $ripple, onTransition);
                                    break;*/
                                case "keypress":
                                    var that = this;
                                    _fwdc.onTransition("Ripple Start", $ripple, "RippleStart", function ($ripple)
                                    {
                                        onTransition.call(that, event, $ripple);
                                    }, false);

                                    break;
                            }

                            _rippleStartEvent = null;

                        }, 0, $ripple);
                    }
                }
            };

            _fwdc.createMiddleMouseHandler = function (standardEventName)
            {
                var handler;
                return function (event, $link)
                {
                    if (_fwdc.isMiddleClick(event))
                    {
                        if (!handler)
                        {
                            handler = _fwdc.Events.Standard[standardEventName];
                        }

                        return handler.call(this, event, $link);
                    }
                };
            };

            function _onGotUserLocation(position, requestId)
            {
                try
                {
                    _fwdc.setProperties(null, {
                        type: "UserLocation",
                        target: requestId,
                        properties: {
                            position: JSON.stringify({
                                latitude: _default(position.coords.latitude, null),
                                longitude: _default(position.coords.longitude, null),
                                altitude: _default(position.coords.altitude, null),
                                accuracy: _default(position.coords.accuracy, null),
                                altitudeAccuracy: _default(position.coords.altitudeAccuracy, null),
                                heading: _default(position.coords.heading, null),
                                speed: _default(position.coords.speed, null),
                                timestamp: position.timestamp
                            })
                        }
                    });
                }
                catch (ex)
                {
                    _onErrorUserLocation({ code: -1, message: ex + "" }, requestId);
                }
            }

            function _onErrorUserLocation(error, requestId)
            {
                _fwdc.setProperties(null, {
                    type: "UserLocation",
                    target: requestId,
                    properties: {
                        code: error.code,
                        message: error.message
                    }
                });
            }

            _fwdc.requestUserLocation = function (requestId)
            {
                if (!navigator.geolocation)
                {
                    _onErrorUserLocation({ code: -1, message: "navigator.geolocation not supported" }, requestId);
                    return;
                }

                navigator.geolocation.getCurrentPosition(
                    function (position)
                    {
                        return _onGotUserLocation(position, requestId);
                    },
                    function (error)
                    {
                        return _onErrorUserLocation(error, requestId);
                    });
            };

            function _getVirtualColumnHeaderLink($columnHeaderLink)
            {
                if ($columnHeaderLink.hasClass("TVCHL"))
                {
                    return null;
                }

                var id = $columnHeaderLink.attr("id");
                if (!id)
                {
                    return null;
                }

                var virtualId = id.slice(0, -2) + "VCH";

                return $.findElementById(virtualId);
            }

            _fwdc.setLinkSource = function (linkSourceInfo)
            {
                _linkSourceInfo = linkSourceInfo;
            };

            _fwdc.requestIdentityCredential = function (controlId, requestId, request)
            {
                function onIdentityCredentialError(error)
                {
                    _fwdc._error(error);

                    var result = { error: error + "" };

                    if (controlId)
                    {
                        _fwdc.setProperties(null, {
                            type: "IdentityCredential",
                            control: controlId,
                            target: requestId,
                            properties: result
                        });
                    }

                    return result;
                }

                try
                {
                    if (!navigator.identity)
                    {
                        throw "LOCAL_OR_HTTPS_REQUIRED";
                    }

                    return navigator.identity
                        .get(JSON.parse(request))
                        .then(function (identity)
                        {
                            if (controlId)
                            {
                                _fwdc.setProperties(null, {
                                    type: "IdentityCredential",
                                    control: controlId,
                                    target: requestId,
                                    properties: {
                                        identityJson: JSON.stringify({
                                            id: identity.id || "",
                                            token: identity.token || "",
                                            data: identity.data || null,
                                            protocol: identity.protocol || null,
                                            type: identity.type || "",
                                            origin: window.origin || ""
                                        })
                                    }
                                });
                            }

                            return identity;
                        })
                        .catch(onIdentityCredentialError);
                }
                catch (ex)
                {
                    return onIdentityCredentialError(ex);
                }
            };

            function _monitorVisibilityChange()
            {
                if (document.hidden)
                {
                    _fwdc.submitMonitoringBrowserEvent("Hidden");
                }
                else
                {
                    _fwdc.submitMonitoringBrowserEvent("Visible");
                }
            }

            function _monitorFocusChange()
            {
                if (document.hasFocus())
                {
                    _fwdc.submitMonitoringBrowserEvent("Focused");
                }
                else
                {
                    _fwdc.submitMonitoringBrowserEvent("Blurred");
                }
            }

            function _verifyMonitoring()
            {
                var photoImage = { "type": "Photo", "fieldId": "mp_vid" };
                var screenImage = { "type": "Screen", "fieldId": "ms_vid" };

                function _setMonitoringVerifiedData(photoImage, screenImage)
                {
                    var photoData = { "method": "photo" };
                    var screenData = { "method": "screen" };
                    var browserData = { "method": "browser" };
                    if (photoImage && photoImage.cameraInfo)
                    {
                        var imageValues = _fwdc.getMonitoringCameraImageData(photoImage.fieldId, photoImage.cameraInfo, photoImage.video, photoImage.imageWidth, photoImage.imageHeight, photoImage.idealWidth, photoImage.idealHeight, photoImage.rotation, photoImage.imageType, photoImage.imageQuality, photoImage.busyId);
                        photoData.imageData = imageValues.dataUrl;
                        photoData.cameraName = photoImage.cameraInfo.name;
                        photoData.cameraInfo = JSON.stringify(photoImage.cameraInfo);
                    }
                    if (screenImage && screenImage.cameraInfo)
                    {
                        var imageValues = _fwdc.getMonitoringCameraImageData(screenImage.fieldId, screenImage.cameraInfo, screenImage.video, screenImage.imageWidth, screenImage.imageHeight, screenImage.idealWidth, screenImage.idealHeight, screenImage.rotation, screenImage.imageType, screenImage.imageQuality, screenImage.busyId);
                        screenData.imageData = imageValues.dataUrl;
                        screenData.cameraName = screenImage.cameraInfo.name;
                        screenData.cameraInfo = JSON.stringify(screenImage.cameraInfo);
                    }
                    if (_fwdc.monitoringConfigJson && _fwdc.monitoringConfigJson.Browser && _fwdc.monitoringConfigJson.Browser.Enabled)
                    {
                        browserData.windowSize = JSON.stringify(_captureBrowserSizeData());
                    }


                    var verifiedData = { "photoData": photoData, "screenData": screenData, "browserData": browserData };

                    _fwdc.setPropertiesNoAction("", "MonitoringVerified", "", true, { "verifiedData": JSON.stringify(verifiedData) });
                }

                if (_fwdc.monitoringConfigJson && _fwdc.monitoringConfigJson.Photo && _fwdc.monitoringConfigJson.Photo.Enabled === true)
                {
                    var photoPromise = _takeMonitoringImage(photoImage)
                        .catch(function (error)
                        {
                            _fwdc.submitMonitoringError("Photo", error);
                        });
                }
                else
                {
                    var photoPromise = Promise.resolve(photoImage);
                }

                if (_fwdc.monitoringConfigJson && _fwdc.monitoringConfigJson.Screen && _fwdc.monitoringConfigJson.Screen.Enabled === true)
                {
                    var screenPromise = _takeMonitoringImage(screenImage)
                        .catch(function (error)
                        {
                            _fwdc.submitMonitoringError("Screen", error);
                        });
                }
                else
                {
                    var screenPromise = Promise.resolve(screenImage);
                }


                Promise.all([photoPromise, screenPromise])
                    .then(function (results)
                    {
                        _setMonitoringVerifiedData(results[0], results[1])
                    })
                    .catch(function (ex)
                    {
                        _fwddc._warn("Error setting verified monitoring data: ", ex);
                    });
            }

            function _manualCaptureMonitoring()
            {
                if (_fwdc.monitoringConfigJson)
                {
                    if (_fwdc.monitoringConfigJson.Photo && _fwdc.monitoringConfigJson.Photo.Enabled === true)
                    {
                        _captureMonitoringPhoto(true);
                    }

                    if (_fwdc.monitoringConfigJson.Screen && _fwdc.monitoringConfigJson.Screen.Enabled === true)
                    {
                        _captureMonitoringScreen(true);
                    }

                    if (_fwdc.monitoringConfigJson.Browser && _fwdc.monitoringConfigJson.Browser.Enabled)
                    {
                        _fwdc.submitMonitoringBrowserEvent("Resize", _captureBrowserSizeData());
                    }
                }
            }

            function _captureBrowserSizeData()
            {
                var $window = _fwdc.$window;
                var sizeData = {};
                if (_monitoringBrowserStartHeight && _monitoringBrowserStartWidth)
                {
                    sizeData.oldHeight = _monitoringBrowserStartHeight;
                    sizeData.oldWidth = _monitoringBrowserStartWidth;
                    sizeData.newHeight = $window.height();
                    sizeData.newWidth = $window.width();
                }
                else
                {
                    sizeData.newHeight = $window.height();
                    sizeData.newWidth = $window.width();
                }

                _monitoringBrowserStartHeight = $window.height();
                _monitoringBrowserStartWidth = $window.width();

                return sizeData;
            }

            function _captureMonitoringPhoto(manual)
            {
                var photoImage = { "type": "Photo", "fieldId": "mp_vid", "manual": manual };
                _takeMonitoringImage(photoImage)
                    .then(_setMonitoringImageData)
                    .catch(function (error)
                    {
                        _fwdc.submitMonitoringError("Photo", error);
                    });
            }

            function _captureMonitoringScreen(manual)
            {
                var screenInfo = { "type": "Screen", "fieldId": "ms_vid", "manual": manual };
                _takeMonitoringImage(screenInfo)
                    .then(_setMonitoringImageData)
                    .catch(function (error)
                    {
                        _fwdc.submitMonitoringError("Screen", error);
                    });
            }



            var _monitoringPhotoHandle;
            var _monitoringScreenHandle;

            function _takeMonitoringImage(imageInfo)
            {
                var error = {};
                if (!imageInfo)
                {
                    error.code = "monitoring_noimage";
                    return Promise.reject(error);
                }

                var $element = $(document.getElementById(imageInfo.fieldId));
                if (!$element || $element.length == 0)
                {
                    error.code = "monitoring_noelement";
                    return Promise.reject(error);
                }
                imageInfo.dataId = $element.attr("data-field-id");
                var $video = $element.findElementById("vid_" + imageInfo.dataId);
                imageInfo.video = $video[0];

                if (!imageInfo.video || !imageInfo.video.srcObject)
                {
                    error.code = "monitoring_nostream";
                    return Promise.reject(error);
                }
                if (imageInfo.video.srcObject.getVideoTracks().length === 0)
                {
                    error.code = "monitoring_nodevice";
                    return Promise.reject(error);
                }

                imageInfo.cameraInfo = $element.data("fast-camera-info");

                var track = imageInfo.video.srcObject.getVideoTracks()[0];
                imageInfo.imageHeight = track.getSettings().height;
                imageInfo.imageWidth = track.getSettings().width;

                if (track.readyState && track.readyState === "ended")
                {
                    error.code = "monitoring_streaminactive";
                    return Promise.reject(error);
                }

                if ($element.data("cameraIdealheight"))
                {
                    imageInfo.idealHeight = $element.data("cameraIdealheight");
                }
                else
                {
                    imageInfo.idealHeight = imageInfo.imageHeight;
                }
                if ($element.data("cameraIdealwidth"))
                {
                    imageInfo.idealWidth = $element.data("cameraIdealwidth");
                }
                else
                {
                    imageInfo.idealWidth = imageInfo.imageWidth;
                }

                imageInfo.imageType = $element.attr("data-camera-mimetype");
                imageInfo.imageQuality = parseInt($element.attr("data-camera-quality"), 10);
                imageInfo.rotation = 0;

                if (window.ImageCapture)
                {
                    var ic = new ImageCapture(track);
                    return ic
                        .takePhoto()
                        .then(function (blob)
                        {
                            return createImageBitmap(blob);
                        })
                        .then(function (imageBitmap)
                        {
                            // If photo capture succeeds, we'll use the height/width of the photo rather than the video track since it may be higher resolution
                            imageInfo.video = imageBitmap;
                            imageInfo.imageWidth = imageBitmap.width;
                            imageInfo.height = imageBitmap.height;

                            return imageInfo;
                        })
                        .catch(function (ex)
                        {
                            _fwdc._warn("Error using ImageCapture API: ", ex);
                            return imageInfo;
                        });
                }
                else
                {
                    return Promise.resolve(imageInfo);
                }
            }

            function _setMonitoringImageInterval(monitorMethod, immediate, minInterval, rangeInterval, typeHandle)
            {

                if (immediate && immediate === true)
                {
                    _fwdc.setTimeout("Immediate " + monitorMethod, monitorMethod, 1000);
                }
                else if (minInterval > 0)
                {
                    typeHandle = (minInterval + (Math.floor(Math.random() * rangeInterval))) * 1000;

                    switch (monitorMethod.name)
                    {
                        case "_captureMonitoringPhoto":
                            _monitoringPhotoHandle = _fwdc.setTimeout("Interval " + monitorMethod, monitorMethod, typeHandle);
                            break;
                        case "_captureMonitoringScreen":
                            _monitoringScreenHandle = _fwdc.setTimeout("Interval " + monitorMethod, monitorMethod, typeHandle);
                            break;
                        default:
                            _fwdc._warn("Invalid monitor method: " + monitorMethod);
                            break;
                    }
                }
            };

            function _startMonitoringImages(fieldId, method, monitoringConfig, methodCaptureFunction)
            {
                var minInterval = monitoringConfig.MinInterval;
                var maxInterval = monitoringConfig.MaxInterval;
                var options = monitoringConfig.ImageOptions;
                var cssClass = "MonitoringPreview MonitoringPreview" + method;

                var rangeInterval = maxInterval - minInterval;
                if (rangeInterval < 0) rangeInterval = 0;
                var typeHandle;
                var inputOptions;
                var mediaError;
                switch (method)
                {
                    case "Photo":
                        typeHandle = _monitoringPhotoHandle;
                        if (monitoringConfig.CameraName)
                        {
                            inputOptions = { inputMenu: false, cameraName: monitoringConfig.CameraName };
                        }
                        else
                        {
                            inputOptions = { inputMenu: true };
                        }
                        mediaError = _fwdc.cameraMediaError;
                        break;
                    case "Screen":
                        typeHandle = _monitoringScreenHandle;
                        var mediaConstraints = {
                            audio: false,
                            video:
                            {
                                displaySurface: "monitor"
                            }
                        };

                        inputOptions = { displayMedia: true, mediaConstraints: mediaConstraints, ignoreUserDevices: true };
                        mediaError = _fwdc.deviceMediaError;
                        break;
                }

                var $monitoring = _fwdc.supportElementsContainer().findElementById(fieldId);

                if ($monitoring.length > 0)
                {
                    //Update options
                    $monitoring.data("cameraMimetype", options.MimeType);
                    $monitoring.data("cameraQuality", options.Quality);
                    $monitoring.data("cameraIdealheight", options.IdealHeight);
                    $monitoring.data("cameraIdealwidth", options.IdealWidth);

                    if (monitoringConfig.CameraName)
                    {
                        var $buttons = $monitoring.find("button");
                        for (var ii = 0; ii < $buttons.length; ++ii)
                        {
                            if ($($buttons[ii]).attr("id") === "btn_" + fieldId)
                            {
                                $($buttons[ii]).remove();
                            }
                        }
                    }

                    if (minInterval > 0)
                    {
                        _setMonitoringImageInterval(methodCaptureFunction, true, minInterval, rangeInterval, typeHandle);
                    }

                    _previewMonitoringVideo(fieldId);
                    return;
                }

                $monitoring = $($.parseHTML("<div></div>"));
                var $videoTools = $($.parseHTML("<div></div>")).addClass("FastMonitorTools");
                _buildMonitoringElement("FastImageMonitoring FastInputImageLoading " + cssClass, options, fieldId, $monitoring, $videoTools, method, monitoringConfig.CameraName);

                var $videoContainer = $($.parseHTML("<div></div>")).addClass("FastImageMonitoringVideoContainer").appendTo($monitoring);
                $videoTools.appendTo($videoContainer);
                var $videoWrapper = $($.parseHTML("<div></div>")).addClass("FastImageMonitoringVideoWrapper").appendTo($videoContainer);

                var $video = $($.parseHTML("<video class=\"FastImageMonitoringVideo \" autoplay playsinline disablePictureInPicture></video>"))
                    .attr("id", "vid_" + fieldId)
                    .appendTo($videoWrapper);


                function startMonitoringInterval()
                {
                    if (minInterval > 0)
                    {
                        _setMonitoringImageInterval(methodCaptureFunction, true, minInterval, rangeInterval, typeHandle);
                    }
                }

                _fwdc.supportElementsContainer().append($monitoring);

                _fwdc.setupMediaStream($monitoring, startMonitoringInterval, inputOptions, mediaError);
            }

            function buildMonitoringInputMenu($menu)
            {
                $menu.addClass("FastCameraToolSelectMenu");
                var $videoInputTitle = $($.parseHTML("<div class=\"FastCameraToolSelectMenuTitle MenuHeader\"></div>"));
                $videoInputTitle.text(_fwdc.standardDecode("MonitoringInputs"));
                $videoInputTitle.appendTo($menu);

                for (var ii = 0; ii < _fwdc.monitoringInputs.length; ++ii)
                {
                    var $inputLink = $($.parseHTML("<a></a>"))
                        .addClass("MenuItem")
                        .addClass("menuLink")
                        .attr("role", "menuitem")
                        .attr("href", "#")
                        .attr("data-value", _fwdc.monitoringInputs[ii].deviceId)
                        .text(_fwdc.monitoringInputs[ii].label)
                        .appendTo($menu);

                    $inputLink.click(function (event)
                    {
                        var deviceId = $(event.target).data("value");
                        _fwdc.editJsonCookie("camerainput", function (settings)
                        {
                            settings.defaultDeviceId = deviceId;
                        });

                        var $monitoring = _fwdc.supportElementsContainer().findElementById("mp_vid");

                        _fwdc.setupMediaStream($monitoring, null, { inputMenu: true }, _fwdc.cameraMediaError);

                    });
                }
            }

            function showMonitoringInputs(event)
            {
                var button = event.target;
                var $button = $(button);
                var $monitorElement = _fwdc.supportElementsContainer().findElementById($button.attr("data-field-id"));

                _fwdc.showMenu(event, "MANAGER__", null, $button.attr("data-field-id") + "_Menu", {
                    setupContentCallback: buildMonitoringInputMenu,
                    position: {
                        my: "top left",
                        at: "top right"
                    }
                });
            }

            function _buildMonitoringElement(monitorClass, options, fieldId, $monitoring, $videoTools, method, cameraName)
            {
                $monitoring.addClass(monitorClass);
                $monitoring.attr("data-field-id", fieldId); //leave as attr for camera stream logic
                $monitoring.data("cameraMimetype", options.MimeType);
                $monitoring.data("cameraQuality", options.Quality);
                $monitoring.data("cameraIdealheight", options.IdealHeight);
                $monitoring.data("cameraIdealwidth", options.IdealWidth);
                $monitoring.data("method", method);
                $monitoring.attr("id", fieldId);
                $monitoring.attr("title", _fwdc.standardDecode("MonitoringPhotoTitle"));

                switch (method)
                {
                    case "Photo":
                        {
                            if (!cameraName)
                            {
                                var $button = $($.parseHTML("<button></button>"));
                                $button.attr("type", "button");
                                $button.addClass("FastMonitorToolButton");
                                $button.attr("id", "btn_" + fieldId);
                                $button.attr("data-field-id", fieldId);
                                $button.attr("title", _fwdc.standardDecode("MonitoringInputs"))
                                $button.click(showMonitoringInputs);
                                $button.appendTo($videoTools);
                            }

                            $monitoring.data("fast-onended", _fwdc.submitMonitoringPhotoEndedEvent);
                            break;
                        }
                    case "Screen":
                        {
                            $monitoring.data("fast-onended", _fwdc.submitMonitoringScreenEndedEvent);
                            break;
                        }
                    default:
                        {
                            _fwdc._warn("Invalid monitoring method: " + method);
                            break;
                        }
                }
            }

            function _previewMonitoringVideo(monitorId)
            {
                var $element = _fwdc.supportElementsContainer().findElementById(monitorId);

                if (!$element || $element.length == 0) return;
                var fieldId = $element.data("field-id");
                var $video = $element.findElementById("vid_" + fieldId);
                var method = $element.data("method");

                if (!$video) return;
                var video = $video[0];
                if (!video || !video.srcObject) return;
                var track = video.srcObject.getVideoTracks()[0];
                if (!track) return;

                var classes = "FastMonitoringPreviewInputImage" + method;
                var $previews = $.findElementsByClassName(classes);
                if (!$previews || $previews.length === 0) return;

                for (var ii = 0; ii < $previews.length; ++ii)
                {
                    var $previewElement = $($previews[ii]);
                    var elementId = $previewElement.data("fieldId");

                    var $previewVideo = $previewElement.find("video");
                    if ($previewVideo.length <= 0)
                    {
                        $previewVideo = $($.parseHTML("<video autoplay playsinline disablePictureInPicture></video>"))
                            .attr("id", "vid_" + elementId)
                            .appendTo($previewElement);

                        if (method === "Photo")
                        {
                            var $videoTools = $($.parseHTML("<div></div>")).addClass("FastMonitorTools");
                            var $button = $($.parseHTML("<button></button>"));
                            $button.attr("type", "button");
                            $button.addClass("FastMonitorToolButton");
                            $button.attr("id", "btn_" + fieldId);
                            $button.attr("data-field-id", fieldId);
                            $button.attr("title", _fwdc.standardDecode("MonitoringInputs"))
                            $button.click(showMonitoringInputs);
                            $button.appendTo($videoTools);
                            $videoTools.appendTo($previewElement);
                        }
                    }

                    if ($previewElement.hasClass("Hidden"))
                    {
                        $previewVideo[0].srcObject = null;
                        return;
                    }

                    var preview = $previewVideo[0];
                    preview.srcObject = video.srcObject;

                    $previewVideo.attr("style", $video.attr("style"));
                }
            }

            _fwdc.endImageMonitoring = function (monitorId)
            {
                var $element = _fwdc.supportElementsContainer().findElementById(monitorId);

                if (!$element || $element.length == 0) return;
                var fieldId = $element.attr("data-field-id");
                var method = $element.data("method");
                var $video = $element.findElementById("vid_" + fieldId);
                $element.remove();

                var classes = "FastMonitoringPreviewInputImage" + method;
                var $previews = $.findElementsByClassName(classes);
                if ($previews && $previews.length > 0)
                {
                    for (var ii = 0; ii < $previews.length; ++ii)
                    {
                        $($previews[ii]).remove();
                    }
                }

                if (!$video) return;
                var video = $video[0];
                if (!video || !video.srcObject) return;
                var track = video.srcObject.getVideoTracks()[0];
                if (!track) return;
                track.stop();
            };

            _fwdc.endMonitoringBrowser = function ()
            {
                document.removeEventListener("visibilitychange", _monitorVisibilityChange);
                window.removeEventListener("focus", _monitorFocusChange);
                window.removeEventListener("blur", _monitorFocusChange);
                if (_monitoringBrowserResizeHandle)
                {
                    _fwdc.clearTimeout("Monitor browser resizing", _monitoringBrowserResizeHandle);
                    _monitoringBrowserResizeHandle = null;
                }
            };

            var _$iframeOverlay;
            var _$iframe;
            _fwdc.showIFrame = function (src, options)
            {
                _$iframeOverlay = $($.parseHTML("<div/>")).addClass("FastLightboxOverlay");
                _$iframe = $($.parseHTML("<iframe/>")).attr("src", src).addClass("FastLightboxIFrame").appendTo(_$iframeOverlay);
                _$iframeOverlay.appendTo(_fwdc.supportElementsContainer());
            };

            var _documentDragging;
            var _documentDraggingHandle;
            var _documentDraggingClasses;
            function _clearPendingDrag()
            {
                $("html").removeClass(_documentDraggingClasses);
                if (_documentDraggingHandle)
                {
                    _fwdc.clearTimeout("_clearPendingDrag", _documentDraggingHandle);
                    _documentDraggingHandle = null;
                }
            }

            _fwdc.Events =
            {
                BrowserWindow:
                {
                    focus: function (event)
                    {
                        _fwdc.setTimeout("BrowserWindow.focus", function OnBrowserWindowFocus()
                        {
                            _fwdc.windowFocus = true;
                        });
                    },
                    blur: function (event)
                    {
                        _fwdc.windowFocus = false;
                    }
                },
                FastTransition:
                {
                    click: function (event)
                    {
                        //_fwdc._log("FastTransition.click: ", event);
                        //_fwdc._log(event.currentTarget);

                        _fwdc.cancelCrossTransition($(event.currentTarget));
                    }
                },
                Action:
                {
                    click: function (event)
                    {
                        var $button = $(event.currentTarget);

                        if ($button.attr("data-action-type").length > 0 && $button.attr("data-action-type") === "CLTACT")
                        {
                            _fwdc.Events.ClientButtonClicked.LinkClick.call(this, event);
                            _fwdc.stopEvent(event);
                        }
                        else
                        {
                            _fwdc.executeAction(event, $button.attr("data-action-id"), $button.attr("data-action-type"));
                        }
                    }
                },
                ClientButtonClicked:
                {
                    LinkClick: function (event)
                    {
                        if (_fwdc.busy())
                            return false;

                        if (!_onClientButtonClickedHandler)
                        {
                            _fwdc.clientActionMissing();
                        }
                        else
                        {
                            _onClientButtonClickedHandler.call(this, event);
                        }
                    }
                },
                Field:
                {
                    // Special focus interception for mobile devices to prevent select on focus from causing stuck copy/paste popups.
                    touchend: function (event)
                    {
                        var $this = $(this);
                        if (!$this.hasFocus() && !$this.hasAnyClass("FastInlineDatepicker", "FastToggleInput", "FastCameraInputImage"))
                        {
                            $this.focus();
                            return _fwdc.stopEvent(event);
                        }
                    },

                    /*indicatorclick: function(event)
                    {
                        $(event.currentTarget).find().children("input,select").first().click();
                    },*/

                    focus: function (senderOrEvent, noSelect)
                    {
                        if (!senderOrEvent)
                        {
                            return;
                        }

                        var sender;
                        var event;
                        if (senderOrEvent instanceof $.Event)
                        {
                            sender = senderOrEvent.target;
                            event = senderOrEvent;
                        }
                        else
                        {
                            sender = senderOrEvent;
                        }

                        if (sender === _currentField || _inFocus || _fwdc.exporting)
                        {
                            return;
                        }

                        try
                        {
                            _inFocus = true;

                            var $sender = $(sender);
                            var id = sender.id;

                            if (id)
                            {
                                _fwdc.setLastFocusField(id);
                            }

                            if (_currentField)
                            {
                                _fwdc.checkValueChanged(_currentField, "Events.Field.focus");
                            }

                            _setCurrentField(sender, $sender, _fwdc.getFieldValue(sender));

                            //_fwdc.ensureElementVisible($sender);

                            // This can cause unnecessary re-scrolling when focusing the window.
                            //_fwdc.scrollIntoView(sender);

                            if ($sender.hasClass("FieldRaiseFocus"))
                            {
                                _raiseGotFocus($sender.attr("data-field-id") || sender.id);
                            }

                            if ($sender.is("input[type='text'],input[type='email']"))
                            {
                                if (!noSelect && sender.select)
                                {
                                    sender.select();
                                }

                                $sender.one("mouseup.fieldgotfocus touchend.fieldgotfocus click.fieldgotfocus", _gotFocusCancelMouseUp);
                                $sender.one("keyup.fieldgotfocus keydown.fieldgotfocus blur.fieldgotfocus", _gotFocusRemoveCancelHandlers);
                            }
                            else if ($sender.is(".HandleBarcodeKeys textarea"))
                            {
                                if (sender.select)
                                {
                                    sender.select();

                                    $sender.one("mouseup.fieldgotfocus touchend.fieldgotfocus click.fieldgotfocus", _gotFocusCancelMouseUp);
                                    $sender.one("keyup.fieldgotfocus keydown.fieldgotfocus blur.fieldgotfocus", _gotFocusRemoveCancelHandlers);
                                }
                            }

                            // Disabling immediate display to try to resolve accessibility issues with NVDA when opening a modal.
                            _fwdc.showCurrentFieldTip(true, false);
                            //_fwdc.showCurrentFieldTip(true, true);
                        }
                        finally
                        {
                            _inFocus = false;
                        }
                    },
                    blur: function (senderOrEvent)
                    {
                        if (!senderOrEvent)
                        {
                            return;
                        }

                        var sender;
                        var event;
                        if (senderOrEvent instanceof $.Event)
                        {
                            sender = senderOrEvent.target;
                            event = senderOrEvent;
                        }
                        else
                        {
                            sender = senderOrEvent;
                        }

                        var $sender = $(sender);
                        if (!$sender.hasClass("FastNoRecalc"))
                        {
                            _fwdc.showCurrentFieldTip();
                            _fwdc.checkValueChanged(sender, "Events.Field.blur");
                        }

                        _clearCurrentField(sender);
                    },
                    drop: function (event)
                    {
                        var sender = event.target;
                        var $sender = $(sender);
                        if (!$sender.hasClass("FastNoRecalc"))
                        {
                            _fwdc.setTimeout("Events.Field.drop", function ()
                            {
                                _fwdc.checkValueChanged(sender, "Events.Field.drop");
                            });
                        }
                    },
                    keydown: function (event)
                    {
                        var sender = event.target;
                        var $sender = $(sender);

                        switch (event.which)
                        {
                            case _fwdc.keyCodes.TAB:
                                if (_busy())
                                {
                                    event.stopPropagation();
                                    event.preventDefault();
                                    event.stopImmediatePropagation();
                                    return false;
                                }

                                if (!$sender.attr("readonly") && !$sender.attr("disabled") && _fwdc.checkValueChanged(sender, "Events.Field.keydown:TAB", { test: true }))
                                {
                                    _handleTabRecalc(event, sender, $sender);
                                    return false;
                                }
                                break;

                            case _fwdc.keyCodes.ENTER:
                                if ($sender.is("textarea")) { return; }

                                if (_busy())
                                {
                                    event.stopPropagation();
                                    event.preventDefault();
                                    event.stopImmediatePropagation();
                                    return false;
                                }

                                if ($sender.is("input.DatePickerOpen"))
                                {
                                    var that = this;
                                    setTimeout(function ()
                                    {
                                        _fwdc.Events.Field.keydown.call(that, event);
                                    }, 1);
                                    return;
                                }

                                _fwdc.checkValueChanged(sender, "Events.Field.keydown:ENTER", { extraRecalcData: { ENTER_RECALC__: true } });

                                if ($sender.hasClass("FastFieldEnterTab"))
                                {
                                    $sender.focusNextInputField(false, true, false, true);
                                    _fwdc.stopEvent(event);
                                }
                                else if ($sender.hasClass("FastFieldEnterEvent") && !$sender.is("textarea"))
                                {
                                    //_fwdc.runFingerprinting(true);
                                    FWDC.eventOccurred(event, { field: $sender.attr("data-fast-enter-event"), eventType: _fwdc.EventType.Enter, trigger: "Events.Field.keydown:ENTER", sourceId: $sender.attr("data-fast-enter-event") });
                                }
                                break;

                            case _fwdc.keyCodes.F9:
                                if (_fwdc.handleF9)
                                {
                                    if (_busy())
                                    {
                                        event.stopPropagation();
                                        event.preventDefault();
                                        event.stopImmediatePropagation();
                                        return false;
                                    }
                                    _handleReview(sender, event);
                                }
                                break;

                            case _fwdc.keyCodes.NUM0:
                            case _fwdc.keyCodes.NUMPAD0:
                            case _fwdc.keyCodes.F:
                                if (!_fwdc.tap && _fwdc.noModifiers(event) && $sender.is("input.FieldEnabled:checkbox"))
                                {
                                    if ($sender.is(":checked"))
                                    {
                                        $sender.trigger('click');
                                    }
                                    $sender.focusNextInputField(false, true, false, true);

                                    _fwdc.stopEvent(event);
                                    return false;
                                }
                                break;

                            case _fwdc.keyCodes.NUM1:
                            case _fwdc.keyCodes.NUMPAD1:
                            case _fwdc.keyCodes.T:
                                if (!_fwdc.tap && _fwdc.noModifiers(event) && $sender.is("input.FieldEnabled:checkbox,input.FieldEnabled:radio"))
                                {
                                    if (!$sender.is(":checked"))
                                    {
                                        // Explicit trigger of Click fires native event on checkbox but not radio inputs.
                                        if ($sender.is(":radio"))
                                        {
                                            $sender.prop("checked", true);
                                        }
                                        $sender.trigger('click');
                                    }
                                    $sender.focusNextInputField(false, true, false, true);

                                    _fwdc.stopEvent(event);
                                    return false;
                                }
                                break;
                        }
                    },
                    linkmousedown: function (event)
                    {
                        if (_fwdc.isMiddleClick(event))
                        {
                            return _fwdc.Events.Field.linkclick.call(this, event);
                        }
                    },
                    linkclick: function (event)
                    {
                        // Legacy wrapper for older link click handlers.
                        _fwdc.stopEvent(event);
                        return _fwdc.Events.Standard.LinkClick.call(this, event, $(this));
                    },
                    inputclick: function (event)
                    {
                        // Workaround for IE issue where modifying the DOM during a click away from an element breaks focus.
                        if (this !== document.activeElement)
                        {
                            $(this).focus();
                        }
                    },
                    selectchange: function (event)
                    {
                        if (!_busy())
                        {
                            _fwdc.onDocSelectChange(event.target, event, false, "Events.Field.selectchange");
                        }
                    },
                    uploadclick: function (event)
                    {
                        // Legacy wrapper for older uploadlink click handlers.
                        _fwdc.stopEvent(event);
                        return _fwdc.Events.Standard.LinkClick.call(this, event, $(this));
                    },
                    fileclick: function (event)
                    {
                        var $input = $(event.currentTarget);
                        var $button = $input.parent().children("button");
                        if ($button.length)
                        {
                            _fwdc.stopEvent(event);
                            $button.click();
                        }
                    },
                    // Fix an IE issue where textareas do not receive focus if the DOM is modified during a focus-related click.
                    textareaClickFix: function (event)
                    {
                        if (document.activeElement !== this)
                        {
                            $(this).focus();
                        }
                    },
                    richtextlinkclick: function (event)
                    {
                        if (_busy()) { return false; }

                        if (event === null) { return; }

                        var $link = $(event.target);

                        if ($link.closest(_fwdc.selectors.specialClickElements).length > 0) { return false; }
                        $link = $link.closest("a,button");

                        _linkSourceInfo = { element: $link.attr("id") };

                        if ($link && $link.length > 0)
                        {
                            //FWDC.eventOccurred(event, { field: $link.attr("data-linkid"), elementId: $link.attr("id"), eventType: eventType, trigger: "DocFieldLinkClick", sourceId: $link.attr("data-linkid") });
                            _fwdc.setPropertiesInternal(event, $link.attr("data-docid"), "RichTextLink", $link.attr("id"));
                        }

                        return _fwdc.stopEvent(event);
                    },
                    richtextlinkmousedown: function (event)
                    {
                        if (_fwdc.isMiddleClick(event))
                        {
                            return _fwdc.Events.Field.richtextlinkclick.call(this, event);
                        }
                    },

                    helprichtextlinkclick: function (event)
                    {
                        var $link = $(event.target);
                        var href = $link.attr("href");
                        if (href && href.toLowerCase().startsWith("http"))
                        {
                            FWDC.openWindow(event, href);
                            return _fwdc.stopEvent(event);
                        }
                    },

                    rippleMouseDown: function (event)
                    {
                        if ($(this).hasClass("DisabledLink") || $(this).attr("aria-disabled") === "true")
                        {
                            // Disabled links should not show this cosmetic effect.
                            return;
                        }

                        _fwdc.showClickRipple(event);
                    },

                    rippleKeyPress: function (event)
                    {
                        switch (event.which)
                        {
                            case _fwdc.keyCodes.SPACE:
                                if ($(event.currentTarget).tag() === "BUTTON")
                                {
                                    _fwdc.showClickRipple(event);
                                }
                                return;

                            case _fwdc.keyCodes.ENTER:
                                //case _fwdc.keyCodes.A:
                                //case 97:
                                _fwdc.showClickRipple(event);
                                return;
                        }
                    }
                },
                AttachmentField:
                {
                    change: function (event)
                    {
                        var $input = $form.find("input[type='file']");
                        if ($input && $input.length)
                        {
                            try
                            {
                                var submitted;
                                $input.on("change", function (event)
                                {
                                    if (!submitted)
                                    {
                                        submitted = true;
                                        $form.submit();
                                    }
                                });

                                showDialog = false;

                                if (!showDialog && !submitted)
                                {
                                    // iOS Wants the input to be in the DOM to allow access.
                                    _fwdc.supportElementsContainer().find(".TemporaryUploadForm").remove();
                                    _fwdc.supportElementsContainer().append($form.addClass("Hidden TemporaryUploadForm"));
                                }

                                $input.click();

                                // Older MSIE browsers suspend the script thread after the .click(), so we need to check if we should submit right away.
                                if (!submitted && $input.val().length)
                                {
                                    submitted = true;
                                    $form.submit();
                                }
                            }
                            catch (ignore)
                            {
                                _busy.hide();
                                showDialog = true;
                                hidden = false;
                                $form.remove();
                            }
                        }
                    },
                    uploadDrop: function (event)
                    {
                        _fwdc.stopEvent(event);

                        var dropEvent = event.originalEvent;

                        var files = dropEvent.dataTransfer.items || dropEvent.dataTransfer.files;

                        if (files.length !== 1)
                        {
                            // TODO: Reject/notify user of bad data?
                            $(event.currentTarget).removeClass("DragOver");
                            return false;
                        }

                        var file = files[0];

                        if (file.kind === "file")
                        {
                            file = file.getAsFile();
                        }

                        var $button = $(event.currentTarget);
                        var $field = $button.parent();

                        _ajaxPostFieldAttachment($field.attr("id"), file);

                        return;
                    },
                    uploadDragOver: function (event)
                    {
                        // This prevents the doc handler from running
                        //return _fwdc.stopEvent(event);
                    },
                    uploadDragEnter: function (event)
                    {
                        _fwdc.stopEvent(event);
                        $(event.currentTarget).addClass("DragOver");
                        return false;
                    },
                    uploadDragLeave: function (event)
                    {
                        _fwdc.stopEvent(event);
                        $(event.currentTarget).removeClass("DragOver");
                        return false;
                    }
                },
                Table:
                {
                    //contextmenu: function (event)
                    //{
                    //    if (!event.ctrlKey)
                    //    {
                    //        var $table = $(this);
                    //        var $menuLink = $table.find("a.TableMenuLink");

                    //        if ($menuLink && $menuLink.length)
                    //        {
                    //            _fwdc.Events.Table.showTableMenu.call(this, event, true);
                    //            return _fwdc.stopEvent(event);
                    //        }
                    //    }
                    //},
                    click: function (event)
                    {
                        var $target = $(event.target);
                        if (!$target.closest(".DFL").length && _fwdc.isCtrlClick(event))
                        {
                            var $container = $target.closest(".TableContainer");
                            if ($container && $container.length)
                            {
                                var $menuLink = $container.find("a.TableMenuLink").first();

                                if ($menuLink && $menuLink.length)
                                {
                                    _fwdc.Events.Table.showTableMenu.call(this, event, true);
                                    return _fwdc.stopEvent(event);
                                }
                            }
                        }
                    },
                    showTableMenu: function (event, atCursor)
                    {
                        var $target = $(event.target);
                        var $container = $target.closest(".TableContainer");
                        if (!$container.length)
                        {
                            _fwdc._warn("Could not find table container for menu event: ", event);
                            return;
                        }

                        var $table = $container.find(".DocTable").first();

                        if (!$table || !$table.length)
                        {
                            _fwdc._warn("Could not find table for menu event: ", event);
                            return;
                        }

                        var id = $table.attr("id");
                        if (!id)
                        {
                            return;
                        }

                        atCursor = atCursor || $target.is("a.HiddenExportLink");

                        _fwdc.showMenu(event, "", "TableMenu", id, {
                            atCursor: atCursor,
                            beforeShow: function ($menu, event)
                            {
                                _fwdc.setupTitleMenuLinks($container.children(".DocTableHeader").children(".TableTitlebar").children(".FastTitlebar"), $menu.find(".DocMenuLinks"));
                            }
                        });

                        return _fwdc.stopEvent(event);
                    },

                    datarowclick: function (event)
                    {
                        if (!_fwdc.isNormalClick(event) && !_fwdc.isMiddleClick(event))
                        {
                            return;
                        }

                        var $target = $(event.target);
                        if ($target.tagIs("input"))
                        {
                            return;
                        }

                        var $row = $(event.currentTarget);
                        if (!$row.is("tr")) { $row = $row.closest("tr"); }
                        if ($row.hasClass("TableHighlightRow")) { return; }

                        var $target = $(event.target);
                        if ($target.closest("a").length)
                        {
                            _highlightUserSelectedRow($row);
                            return;
                        }

                        _fwdc.setUserSelectedRow($row, { async: true });
                    },

                    linkmousedown: function (event)
                    {
                        if (_fwdc.isMiddleClick(event))
                        {
                            return _fwdc.Events.Table.linkclick.call(this, event);
                        }
                    },

                    linkclick: function (event)
                    {
                        if (_fwdc.isCtrlClick(event))
                        {
                            return _fwdc.Events.Table.click.call(this, event);
                        }

                        _fwdc.Events.Table.datarowclick.call(this, event);
                        return _fwdc.Events.Field.linkclick.call(this, event);
                    },

                    columnheaderclick: function (event)
                    {
                        var $link = $(event.currentTarget);
                        var $th = $link.closest("th");

                        if ($th.length)
                        {
                            var $doc = $th.closest(".DocumentContainer,.ContextDocumentContainer");
                            var docId = $doc.length ? $doc.attr("data-docid") : "";
                            _fwdc.sortTable(event, $th.attr("data-id") || $th.attr("id"), docId, $link.attr("id"));
                        }

                        return _fwdc.stopEvent(event);
                    },

                    pageclick: function (event)
                    {
                        var data = $(event.currentTarget).data("page");

                        _fwdc.selectTablePage(data.table, data.id);

                        return _fwdc.stopEvent(event);
                    },

                    pagemenuclick: function (event)
                    {
                        var data = $(event.currentTarget).data("page");

                        _fwdc.showStandardDialog(event, {
                            dialog: "TablePage",
                            data: { TARGET__: data.table }
                        });

                        return _fwdc.stopEvent(event);
                    },

                    mobileScroll: function (event)
                    {
                        var $container = $(event.currentTarget);
                        _updateMobileScrollInfo(null, $container);
                    },

                    mobileScrollLinkClick: function (event)
                    {
                        _fwdc.stopEvent(event);

                        var $link = $(event.currentTarget);
                        var moveLeft = $link.is(".DocTableMobileScrollLeft");

                        var $layout = $link.parent(".DocTableMobileScroll");
                        var $container = $layout.children(".DocTableMobileScrollContainer");

                        var newLeft = $container.scrollLeft();
                        var distance = $container.width() * 0.9;

                        if (moveLeft)
                        {
                            newLeft -= distance;
                        }
                        else
                        {
                            newLeft += distance;
                        }

                        $container.animate({ scrollLeft: newLeft }, 200);
                    },

                    filterfocus: function (event)
                    {
                        var sender = event.target;
                        _currentFilter = sender;
                        _$currentFilter = $(sender);

                        if (_$currentFilter.attr("id"))
                        {
                            _fwdc.setLastFocusField(_$currentFilter.attr("id"));
                        }

                        _currentFilterValue = _$currentFilter.val();

                        if (sender === document.activeElement)
                        {
                            _$currentFilter.select();
                        }
                    },

                    filterblur: function (event)
                    {
                        var sender = event.target;

                        if (_currentFilter && _currentFilter === sender)
                        {
                            var filter = _$currentFilter.val();
                            if (filter !== _currentFilterValue && !_fwdc.ignoreFieldEvents(_$currentFilter))
                            {
                                if (_$currentFilter && _$currentFilter.attr("id"))
                                {
                                    _fwdc.clearLastFocusField(_$currentFilter.attr("id"));
                                }

                                var $filter = _$currentFilter;

                                _currentFilter = null;
                                _$currentFilter = null;
                                _currentFilterValue = null;

                                _fwdc.filterTable($filter.data("tableid"), filter, false);
                            }
                            else
                            {
                                _currentFilter = null;
                                _$currentFilter = null;
                                _currentFilterValue = null;
                            }
                        }
                        else
                        {
                            _currentFilter = null;
                            _$currentFilter = null;
                            _currentFilterValue = null;
                        }
                    },

                    filterkeydown: function (event, table)
                    {
                        var sender = event.target;

                        if (event.keyCode === _fwdc.keyCodes.ENTER)
                        {
                            _$currentFilter = $(sender);
                            _currentFilterValue = _$currentFilter.val();

                            if (!_fwdc.ignoreFieldEvents(_$currentFilter))
                            {
                                if (sender.id)
                                {
                                    _fwdc.setLastFocusField(sender.id);
                                }

                                _fwdc.filterTable(_$currentFilter.data("tableid"), _currentFilterValue, true);
                            }
                            return false;
                        }

                        return true;
                    },

                    columnlinkfocus: function (event)
                    {
                        var $virtualHeader = _getVirtualColumnHeaderLink($(this));
                        if ($virtualHeader)
                        {
                            $virtualHeader.addClass("DisplayFocus");
                        }
                    },

                    columnlinkblur: function (event)
                    {
                        var $virtualHeader = _getVirtualColumnHeaderLink($(this));
                        if ($virtualHeader)
                        {
                            $virtualHeader.removeClass("DisplayFocus");
                        }
                    }
                },
                ViewSelector:
                {
                    tabClicked: function (event)
                    {
                        if (_busy()) { return false; }

                        _fwdc.stopEvent(event);

                        var $link = $(event.currentTarget);

                        if ($link.closest(_fwdc.selectors.specialClickElements).length > 0) { return; }

                        var id = $link.attr("data-linkid") || $link.parent().attr("id");

                        //if ($link.parent().parent().hasClass("InnerTabSet"))
                        //{
                        var $tab = $link.closest(".GroupSelectorTab,.ViewSelectorTab");
                        if ($tab.length)
                        {
                            var $current = $tab.parent().children(".TabSetActive");

                            if (!$current.equals($tab))
                            {
                                $current.removeClass("TabSetActive GroupSelected ViewSelected EnsureVisible");
                                if ($tab.hasClass("GroupSelector"))
                                {
                                    $tab.addClass("TabSetActive GroupSelected EnsureVisible");
                                }
                                else
                                {
                                    $tab.addClass("TabSetActive ViewSelected EnsureVisible");
                                }

                                _fwdc.animateSelectorUnderline($tab.parent());
                            }
                        }
                        //}

                        _fwdc.viewLinkClicked({ fieldId: id, trigger: "Events.ViewSelector.tabClicked" });
                    },

                    tabkeydown: function (event)
                    {
                        var autoSelect = false;

                        var $eventTarget = $(event.currentTarget);
                        var $tabset = $eventTarget.closest(".TabSet");
                        var tabsetId = $tabset.attr("id");
                        var $tabLinks = $tabset.find(".TabSetLink").filterVisible();
                        var index = $tabLinks.index(event.currentTarget);
                        var targetIndex = index;

                        function activateTab($targetTab)
                        {
                            //_pendingFocusChange = true;
                            _fwdc.preventAutoFocus = true;

                            var tabId = $targetTab.attr("id");
                            $targetTab.click();

                            _fwdc.busy.done(function ()
                            {
                                var $tab = $.findElementById(tabId).focus();
                                if (!$tab.length && tabsetId)
                                {
                                    $.findElementById(tabsetId).find(".TabSetActive > .TabSetLink").focus();
                                }
                                //_pendingFocusChange = false;
                            });
                        }

                        switch (event.which)
                        {
                            case _fwdc.keyCodes.LEFT:
                                targetIndex--;
                                break;
                            case _fwdc.keyCodes.RIGHT:
                                targetIndex++;
                                break;
                            case _fwdc.keyCodes.ENTER:
                                // Custom ENTER handling allows us to keep focus here even if the system would normally move it.
                                // This is friendlier while keying around the tabs.
                                activateTab($(event.currentTarget));
                                return _fwdc.stopEvent(event);

                            default:
                                return;
                        }

                        _fwdc.stopEvent(event)

                        if (_fwdc.uiBusy()) { return false; }

                        var targetTab = $tabLinks[targetIndex];
                        if (!targetTab)
                        {
                            return;
                        }

                        var $targetTab = $(targetTab).focus();

                        if (autoSelect)
                        {
                            activateTab($targetTab);
                        }
                        else
                        {
                            $targetTab.focus();
                        }

                        return false;
                    },

                    mobileScroll: function (event)
                    {
                        var $tabset = $(event.currentTarget);
                        _updateMobileScrollInfo($tabset, $tabset);
                    }
                },
                Chat:
                {
                    chatlinkclick: function (event)
                    {
                        var chatData = $(event.target).data("chatlink");
                        switch (chatData.type)
                        {
                            case "ATT":
                                FWDC.viewAttachment({ Control: "MANAGER__", Type: "CHAT", Target: chatData.conversationId, Key: chatData.token });
                                return;
                        }
                        _fwdc.resetChatFocus();
                        _fwdc.setPropertiesInternal(event, "MANAGER__", "ChatLinkClicked", chatData.conversationId, true, { token: chatData.token, type: chatData.type });
                    },
                    sendclick: function (event)
                    {
                        event.data.send(event);
                    },
                    reportclick: function (event)
                    {
                        var chatData = event.data;
                        _fwdc.resetChatFocus();
                        FWDC.messageBox({
                            message: _fwdc.standardDecode("ChatConfirmReport"),
                            buttons: FWDC.MessageBoxButton.YesNo,
                            icon: FWDC.MessageBoxIcon.Question,
                            callback: function ($modal, tag, result)
                            {
                                if (result === FWDC.MessageBoxResult.Yes)
                                {
                                    _fwdc.setPropertiesInternal(event, "MANAGER__", "ChatReport", chatData.id, true, { source: "CHAT" });
                                }
                            }
                        });
                    },
                    //livechatclick: function (event)
                    //{
                    //    _fwdc.setPropertiesInternal(event, "MANAGER__", "RequestLiveChat", "", true);
                    //},
                    editclick: function (event)
                    {
                        var conversation = event.data.conversation;
                        _fwdc.stopEvent(event);
                        _fwdc.resetChatFocus();
                        _fwdc.setPropertiesInternal(event, "MANAGER__", "ChatEditMessage", conversation.id, true, { text: event.data.text, messageId: event.data.messageId });
                    },
                    historyclick: function (event)
                    {
                        var chatData = event.data;
                        _fwdc.resetChatFocus();
                        FWDC.messageBox({
                            message: _fwdc.standardDecode("ChatConfirmPush"),
                            buttons: FWDC.MessageBoxButton.YesNo,
                            icon: FWDC.MessageBoxIcon.Question,
                            callback: function ($modal, tag, result)
                            {
                                if (result === FWDC.MessageBoxResult.Yes)
                                {
                                    _fwdc.setPropertiesInternalJson("MANAGER__", "ChatHistory", chatData.id, true, { source: "CHAT" }, function (response)
                                    {
                                        if (response.success)
                                        {
                                            chatData.loadMore = response.loadMore;
                                            chatData.$chatArea.children(".ChatHistory").remove();
                                        }

                                    });
                                }
                            }
                        });
                    }
                },
                MessageBox:
                {
                    executeConfirmCallback: function ($modal, tag, result)
                    {
                        if (_fwdc.confirmCallback && (result === FWDC.MessageBoxResult.Yes))
                        {
                            _fwdc.confirmCallback.func.apply(_fwdc.confirmCallback.target);
                        }
                    },
                    confirmSupportId: function ($modal, tag, result)
                    {
                        if (result === FWDC.MessageBoxResult.Yes)
                        {
                            return FWDC.viewSupportId(null, true);
                        }

                        return false;
                    },
                    redirectHome: function ()
                    {
                        _fwdc.redirectHome();
                    }
                },
                FastTabs:
                {
                    click: function (event)
                    {
                        var $link = $(event.target);

                        var $tabControl = $link.closest(".FastTabContainer");
                        $tabControl.find("li.FastTab").removeClass("FastTabCurrent");
                        $tabControl.children(".FastTabContent").removeClass("FastTabCurrentContent");

                        $link.parent().addClass("FastTabCurrent");
                        $tabControl.find($link.attr("href")).addClass("FastTabCurrentContent");

                        $link.focus();

                        return _fwdc.stopEvent(event);
                    }
                },
                Manager:
                {
                    menuclick: function (event)
                    {
                        _fwdc.showManagerMenu(event);

                        return _fwdc.stopEvent(event);
                    },
                    logoffclick: function (event)
                    {
                        _fwdc.logOff(event);

                        return _fwdc.stopEvent(event);
                    }
                },
                Document: {
                    scrollmousedown: function (event)
                    {
                        _lastScrollMouseDown = this;
                        _fwdc.setTimeout("scrollmousedown", function ()
                        {
                            _lastScrollMouseDown = null;
                        }, 1);
                    },
                    scrollfocusin: function (event)
                    {
                        if (!event.target || !event.target.tagName || event.target === _lastScrollFocusIn || event.target === _lastScrollMouseDown)
                        {
                            return;
                        }

                        _lastScrollFocusIn = event.target;

                        if (_ignoreFocusScroll || !_fwdc.windowFocus)
                        {
                            return;
                        }

                        switch (event.target.tagName.toUpperCase())
                        {
                            case "A":
                            case "BUTTON":
                            case "INPUT":
                            case "TEXTAREA":
                                _fwdc.scrollIntoView(event.target);
                                return;
                        }

                        var $target = $(event.target);
                        if ($target.hasClass(".FastFocusable"))
                        {
                            _fwdc.scrollIntoView($target);
                        }
                    },
                    dragover: function (event)
                    {
                        if (_documentDraggingHandle)
                        {
                            _fwdc.clearTimeout("DocumentPendingDrag.Update", _documentDraggingHandle);
                        }
                        else
                        {
                            var strTypeClass = "FastDraggingContent";

                            var dt = event
                                && event.originalEvent
                                && event.originalEvent.dataTransfer;

                            var items = dt && dt.items;

                            var files = dt && dt.files;

                            if (items && items.length)
                            {
                                switch (items[0].kind)
                                {
                                    case "file":
                                        if (items.length > 1)
                                        {
                                            strTypeClass += " FastDraggingFiles";
                                        }
                                        else
                                        {
                                            strTypeClass += " FastDraggingFile";
                                        }
                                        break;
                                    default:
                                        //Not working with an attachment file, nothing to do
                                        return;
                                }
                            }
                            else if (files && files.length)
                            {
                                if (files.length > 1)
                                {
                                    strTypeClass += " FastDraggingFiles";
                                }
                                else
                                {
                                    strTypeClass += " FastDraggingFile";
                                }
                            }
                            else
                            {
                                //Not working with an attachment file, nothing to do
                                return;
                            }

                            //_fwdc._log(strTypeClass);

                            _documentDraggingClasses = strTypeClass;

                            $("html").addClass(strTypeClass);
                        }

                        _documentDraggingHandle = _fwdc.setTimeout("DocumentPendingDrag", _clearPendingDrag, 250);

                        return _fwdc.stopEvent(event);
                    }
                },
                Navigation:
                {
                    linkMouseEnter: function (event)
                    {
                        var $link = $(event.currentTarget);
                        var size = _fwdc.getElementContentSize($link, null, true);

                        if (size.contentWidth > size.cellWidth)
                        {
                            $link.attr("title", $link.text());
                        }
                        else
                        {
                            $link.removeAttr("title");
                        }
                    }
                },
                MessagePanel:
                {
                    linkclick: function (event)
                    {
                        var $link = $(event.currentTarget);
                        _fwdc.stopEvent(event);

                        _fwdc.setPropertiesInternal(event, $link.attr("data-docid"), "MessageLink", $link.attr("data-linkid"));
                    },
                    closeclick: function (event)
                    {
                        var $link = $(event.currentTarget);
                        var $panel = $link.closest(".MessagePanel");
                        var docId = $link.attr("data-docid");
                        _fwdc.stopEvent(event);

                        if (docId)
                        {
                            if ($panel && $panel.length)
                            {
                                if (_busy.tryShow("MessagePanel.close", { sync: false, check: true, delay: 1000 }))
                                {
                                    $panel.fadeOut(300, function ()
                                    {
                                        _busy.hide();
                                        _fwdc.setPropertiesInternal(event, docId, 'MessagePanel', 'Close');
                                    });
                                }
                            }
                            else
                            {
                                _fwdc.setPropertiesInternal(event, docId, 'MessagePanel', 'Close');
                            }
                        }
                    }
                },
                Interface:
                {
                    switchToDesktopClick: function (event)
                    {
                        _fwdc.setPropertiesNoAction("MANAGER__", "SetBrowserType", "DESKTOP", true, null, function () { });
                        return _fwdc.stopEvent(event);
                    },
                    acceptDialog: function (event)
                    {
                        var $target = $(event.currentTarget);

                        $target.closest("form").submit();
                        //$target.closest(".ui-dialog-content").dialog("close");

                        return _fwdc.stopEvent(event);
                    },
                    cancelDialog: function (event)
                    {
                        var $target = $(event.currentTarget);
                        $target.closest(".ui-dialog-content").dialog("close");

                        return _fwdc.stopEvent(event);
                    },
                    enterSubmitForm: function (event)
                    {
                        if (event.which === _fwdc.keyCodes.ENTER)
                        {
                            var $form = $(event.currentTarget).closest("form");
                            if ($form.length)
                            {
                                $form.submit();

                                return _fwdc.stopEvent(event);
                            }
                        }
                    },
                    setAppFontSize: function (event)
                    {
                        var fontSize = $(event.target).data("app-font-size");
                        _fwdc.setPropertiesInternalJson("MANAGER__", "FontSize", fontSize, true, null, function (data)
                        {
                            if (data.success)
                            {
                                _fwdc.persistOption({ 'Option': 'FontSize', 'Value': fontSize }, true, function ()
                                {
                                    _fwdc.refreshPage("Changed FontSize");
                                });
                            }
                        });
                    }
                },
                Panel:
                {
                    scrollpanelscroll: function (event)
                    {
                        // Immediate mode here prevents Chrome from triggering async scrolling problems when toggling the left/right scroll buttons.
                        _fwdc.updateScrollPanel($(event.target), false, true);
                    }
                },
                BasicForm:
                {
                    requiredfocus: function (event)
                    {
                        _fwdc.showCurrentFieldTip();
                    },
                    requiredblur: function (event)
                    {
                        _fwdc.checkRequired(this);
                    },
                    requiredkeydown: function (event)
                    {
                        if (event.keyCode === _fwdc.keyCodes.ENTER)
                        {
                            _fwdc.checkRequired(this);
                        }
                    },
                    requiredchange: function (event)
                    {
                        _fwdc.checkRequired(this);
                    },
                    submitted: function (event)
                    {
                        $(this).addClass("Submitted");
                    },
                    inputkeydown: function (event)
                    {
                        if (event.which === _fwdc.keyCodes.ENTER)
                        {
                            _fwdc.Events.Standard.SubmitStandardDialog(event);

                            return _fwdc.stopEvent(event);
                        }
                    }
                },
                standardclick: function (event)
                {
                    var $link = $(this);
                    var standardEvent = $link.attr("data-event");

                    if (_fwdc.isCtrlClick(event) && $link.attr("data-ctrl-event"))
                    {
                        standardEvent = $link.attr("data-ctrl-event");
                    }
                    else if (_fwdc.isShiftClick(event) && $link.attr("data-shift-event"))
                    {
                        standardEvent = $link.attr("data-shift-event");
                    }

                    var handler;
                    if (standardEvent && (handler = _fwdc.Events.Standard[standardEvent]))
                    {
                        try
                        {
                            _standardEventTrigger = "Events.Standard." + standardEvent;
                            handler.call(this, event, $link, $link.data("eventdata"));
                        }
                        finally
                        {
                            _standardEventTrigger = "";
                        }
                    }
                    else
                    {
                        _fwdc._warn("Unhandled standardclick: " + standardEvent);
                    }
                    return _fwdc.stopEvent(event);
                },
                standardmousedown: function (event)
                {
                    var $link = $(this);
                    var standardEvent = $link.attr("data-mousedown-event");

                    var optional = !standardEvent;

                    if (optional)
                    {
                        standardEvent = ($link.attr("data-event") + "MouseDown");
                    }

                    if (standardEvent)
                    {
                        //if (_fwdc.isCtrlClick(event) && $link.attr("data-ctrl-event"))
                        //{
                        //    standardEvent = $link.attr("data-ctrl-event");
                        //}
                        //else if (_fwdc.isShiftClick(event) && $link.attr("data-shift-event"))
                        //{
                        //    standardEvent = $link.attr("data-shift-event");
                        //}

                        var handler;
                        if (standardEvent && (handler = _fwdc.Events.Standard[standardEvent]))
                        {
                            try
                            {
                                _standardEventTrigger = "Events.StandardMouseDown." + standardEvent;
                                handler.call(this, event, $link);
                            }
                            finally
                            {
                                _standardEventTrigger = "";
                            }
                        }
                        else if (optional)
                        {
                            return;
                        }
                        else
                        {
                            _fwdc._warn("Unhandled StandardMouseDown: " + standardEvent);
                        }
                        return _fwdc.stopEvent(event);
                    }
                },
                Standard:
                {
                    LinkClick: function (event, $link)
                    {
                        if (_busy()) { return false; }

                        if (event === null) { return; }

                        var eventType = _fwdc.EventType.fromEvent(event, true);

                        if ($link.closest(_fwdc.selectors.specialClickElements).length > 0) { return false; }
                        $link = $link.closest("a,button,.FastClickable");
                        if ($link && $link.length > 0)
                        {
                            if ($link.hasClass("DisabledLink"))
                            {
                                return false;
                            }

                            //_fwdc.runFingerprinting(true);
                            FWDC.eventOccurred(event, { field: $link.attr("data-linkid"), elementId: $link.attr("id"), eventType: eventType, trigger: "DocFieldLinkClick", sourceId: $link.attr("data-linkid") });
                        }

                        return _fwdc.stopEvent(event);
                    },
                    RowLinkClick: function (event, $link)
                    {
                        var $target = $(event.target);
                        var $ignoreTarget = $target.closest("a,button,input,textarea,select");
                        if ($ignoreTarget.length && !$ignoreTarget.equals($link))
                        {
                            return;
                        }

                        return _fwdc.Events.Standard.LinkClick(event, $link);
                    },
                    ViewLinkClick: function (event, $link)
                    {
                        if (_busy()) { return false; }

                        _fwdc.viewLinkClicked({
                            fieldId: $link.attr("data-linkid"),
                            sourceId: $link.attr("id") || $link.attr("data-linkid"),
                            trigger: _standardEventTrigger
                        });
                    },
                    OpenUrl: function (event, $link)
                    {
                        if (_busy()) { return false; }

                        var url = $link.attr("href") || $link.attr("data-url");

                        FWDC.openUrl(event, url);
                    },
                    OpenWindow: function (event, $link)
                    {
                        if (_busy()) { return false; }

                        var url = $link.attr("href") || $link.attr("data-url");

                        FWDC.openWindow(event, url);
                    },
                    UploadLinkClick: function (event, $link)
                    {
                        _fwdc.attachmentDialog(event, { field: $link.attr("data-linkid") }, true, true);
                    },
                    Navigate: function (event, $link)
                    {
                        var navigationData = $link.data("navigation");

                        var trigger = _default(navigationData.trigger, "NavigateClick");
                        var step = _default(navigationData.step, 0);
                        var id = _default(navigationData.id, -1);
                        var action = _default(navigationData.action, "");

                        _fwdc.navigate(event, trigger, step, id, action);
                    },
                    NavigateMouseDown: _fwdc.createMiddleMouseHandler("Navigate"),
                    ShowTip: function (event, $link)
                    {
                        var element = this;
                        var showtipData = $link.data("showtip");
                        if (showtipData)
                        {
                            var key = showtipData.typ + "\\" + showtipData.idx + "\\" + showtipData.hsh + "\\" + showtipData.lng + "\\" + showtipData.fmt + "\\" + showtipData.key;
                            var panel = showtipData.panel; // Legacy parameter, wasn't available anymore.

                            var content = _tipCache[key];
                            if (content)
                            {
                                _showTip(element, content, panel);
                                return;
                            }

                            _fwdc.ajax({
                                url: '../ShowTip/' + encodeURIComponent(showtipData.typ) + "/" + encodeURIComponent(showtipData.idx) + "/" + encodeURIComponent(showtipData.hsh || "_") + "/" + encodeURIComponent(showtipData.lng) + "/" + encodeURIComponent(showtipData.fmt) + "/" + encodeURIComponent(showtipData.key),
                                type: 'GET',
                                contentType: '',
                                success: function (response, status, request)
                                {
                                    if (response)
                                    {
                                        _tipCache[key] = response;
                                        _showTip(element, response, panel);
                                    }
                                }
                            });
                        }
                    },

                    LogOff: function (event)
                    {
                        _fwdc.logOff(event);
                    },
                    WebProfileMenu: function (event)
                    {
                        _fwdc.showMenu(event, "MANAGER__", "WebProfileMenu", "");
                    },
                    LogonSettings: function (event)
                    {
                        _fwdc.setConfirmCallback(function ()
                        {
                            FWDC.setProperties('MANAGER__', 'EServicesSettings', '', null, true, { CLOSECONFIRMED__: true });
                        });
                        FWDC.setProperties('MANAGER__', 'EServicesSettings', '');
                    },
                    WebProfile: function (event)
                    {
                        _fwdc.setConfirmCallback(function ()
                        {
                            FWDC.setProperties('MANAGER__', 'EServicesSettings', '', null, true, { CLOSECONFIRMED__: true });
                        });
                        FWDC.setProperties('MANAGER__', 'EServicesSettings', '');
                    },
                    HelpMenu: function (event)
                    {
                        _fwdc.showMenu(event, "MANAGER__", "HelpMenu", "");
                    },
                    OpenAssistant: function (event)
                    {
                        _fwdc.preventAutoFocus = true;
                        _fwdc.setPropertiesInternal(event, "MANAGER__", "OpenAssistant", "", true, null, function ()
                        {
                            //_fwdc.afterCrossTransition(function openAssistantFocus()
                            //{
                            if (_tryFocusContainer($(".ManagerAssistantContainer .DocumentContainer")))
                            {
                                _fwdc.preventAutoFocus = false;
                                var $active = $(document.activeElement);
                                var id = $active.attr("id") || $active.attr("data-id");
                                _fwdc.setLastFocusField(id);
                            }
                            else
                            {
                                _fwdc.preventAutoFocus = false;
                                _fwdc.focusCurrentField();
                            }
                            //});
                        });
                    },
                    MinimizeAssistant: function (event)
                    {
                        FWDC.setProperties('MANAGER__', 'MinimizeAssistant', '');
                    },
                    CloseAssistant: function (event)
                    {
                        FWDC.setProperties('MANAGER__', 'CloseAssistant', '');
                    },
                    HelpUrl: function (event)
                    {
                        FWDC.openWindow($(event.target).attr("data-itemdata"));
                    },
                    SendSupportMessage: function (event)
                    {
                        _fwdc.setConfirmCallback(function ()
                        {
                            FWDC.setProperties('MANAGER__', 'SendSupportMessage', '', null, true, { CLOSECONFIRMED__: true });
                        });
                        _fwdc.setPropertiesInternal(event, "MANAGER__", "SendSupportMessage", "", true);
                    },
                    RequestSupportChat: function (event)
                    {
                        if (_fwdc.$chatDialog)
                        {
                            _fwdc.showChats();
                        }
                        else
                        {
                            _fwdc.setPropertiesInternal(event, "MANAGER__", "RequestChatAssistance", "", true);
                        }
                    },
                    ShowManagerMenu: function (event)
                    {
                        _fwdc.showManagerMenu(event);
                    },
                    ShowTitleMenu: function (event)
                    {
                        _fwdc.showMenu(event, null, null, "", {
                            beforeShow: function ($menu, event)
                            {
                                var $link = $(event.currentTarget);
                                var $title = $link.closest(".FastTitlebar");

                                var $links = $("<div></div>").addClass("MenuColumn DocMenuLinks").appendTo($menu);

                                _fwdc.setupTitleMenuLinks($title, $links);
                            }
                        });
                    },
                    ViewCart: function (event)
                    {
                        _fwdc.setConfirmCallback(function ()
                        {
                            FWDC.setProperties('MANAGER__', 'ViewCart', '', null, true, { CLOSECONFIRMED__: true });
                        });
                        FWDC.setProperties('MANAGER__', 'ViewCart', '');
                    },
                    ViewHelp: function (event)
                    {
                        //FWDC.setProperties('MANAGER__', 'Help', 'ApplicationHelp');
                        _fwdc.setPropertiesInternal(event, "MANAGER__", "Help", "ApplicationHelp", true);
                    },
                    ViewSupportId: function (event)
                    {
                        FWDC.viewSupportId(event);
                    },
                    NavigateHome: function (event)
                    {
                        _fwdc.navigate(event, "NavigateHome", -2, -1, "Home");
                    },

                    FieldPopup: function (event, $link)
                    {
                        if (_busy()) { return false; }
                        _endEditCell(false, false);

                        var $field = _fwdc.formField($link.data("field").field);
                        if ($field)
                        {
                            _fwdc.showFieldPopup($field, { large: true });
                        }
                    },

                    FilterTable: function (event, $link)
                    {
                        var data = $link.data("table-filter");
                        _fwdc.showTableFilter(data.table, data.show);
                    },

                    AcceptDocModal: function (event)
                    {
                        _fwdc.acceptModal(event);
                    },
                    CancelDocModal: function (event)
                    {
                        _fwdc.cancelModal(event);
                    },
                    DocModalAction: function (event, $link)
                    {
                        var data = $link.data("action");
                        _fwdc.setPropertiesInternal(event, data.doc, "DocModalButton", data.action, true);
                    },

                    SelectTableRow: function (event, $link)
                    {
                        var data = $link.data("row");
                        //FWDC.deleteTableRow(event, data.view, null, data.row, data.message, data.caption);

                        if (data.field)
                        {
                            return _fwdc.ajax({
                                url: 'SelectTableRow',
                                data: function ()
                                {
                                    return _fwdc.getDocPostParameters({ FIELD__: data.field }, "input[type='hidden']");
                                },
                                success: _handleDocResponse
                            });
                        }
                        else
                        {
                            return _fwdc.ajax({
                                url: 'SelectTableRow',
                                data: function ()
                                {
                                    return _fwdc.getDocPostParameters({ TABLE_VIEW__: data.view, TABLE_ROW__: data.row }, "input[type='hidden']");
                                },
                                success: _handleDocResponse
                            });
                        }
                    },

                    AddTableRow: function (event, $link)
                    {
                        if (!_fwdc.elementOnCurrentDialog($link) || _fwdc.uiBusy(false, event))
                        {
                            return;
                        }

                        _fwdc.commitEdits("CopyTableRow");

                        var data = $link.data("table");

                        _fwdc.ajax({
                            url: 'AddTableRow',
                            data: function ()
                            {
                                return _fwdc.getDocPostParameters({ TABLE_VIEW__: data.view }, "input[type='hidden']");
                            },
                            success: _handleDocResponse
                        });
                    },

                    CopyTableRow: function (event, $link)
                    {
                        if (!_fwdc.elementOnCurrentDialog($link) || _fwdc.uiBusy(false, event))
                        {
                            return;
                        }

                        _fwdc.commitEdits("CopyTableRow");

                        _setCurrentRow($link.closest("tr.TDR"));

                        var data = $link.data("row");
                        _fwdc.ajax({
                            url: 'AddTableRow',
                            data: function ()
                            {
                                return _fwdc.getDocPostParameters({ TABLE_VIEW__: data.view, COPY_ROW__: data.row }, "input[type='hidden']");
                            },
                            success: _handleDocResponse
                        });
                    },

                    DeleteTableRow: function (event, $link)
                    {
                        if (!_fwdc.elementOnCurrentDialog($link) || _fwdc.uiBusy(false, event))
                        {
                            return;
                        }

                        _fwdc.commitEdits("DeleteTableRow");

                        _setCurrentRow($link.closest("tr.TDR"));

                        var data = $link.data("row");

                        var view = data.view;
                        var row = data.row;
                        var message = data.message;
                        var caption = data.caption;

                        if (message)
                        {
                            if (typeof message !== "string")
                            {
                                var $parent = message === true ? $(event.target).closest("table") : $(message).closest("table");
                                if ($parent.length > 0)
                                {
                                    message = $parent.attr("data-delmsg");
                                    caption = $parent.attr("data-delcap");
                                }
                                else
                                {
                                    message = null;
                                    caption = null;
                                }
                            }
                        }

                        if (!message)
                        {
                            caption = "Delete Row";
                            message = "Are you sure you want to delete this row?";
                        }

                        FWDC.messageBox({
                            message: message,
                            caption: caption,
                            buttons: FWDC.MessageBoxButton.YesNo,
                            icon: FWDC.MessageBoxIcon.Question,
                            callback: function ($modal, tag, result)
                            {
                                if (result === FWDC.MessageBoxResult.Yes)
                                {
                                    _fwdc.ajax({
                                        url: 'DeleteTableRow',
                                        data: function ()
                                        {
                                            return _fwdc.getDocPostParameters({ TABLE_VIEW__: view, TABLE_ROW__: row }, "input[type='hidden']");
                                        },
                                        success: _handleDocResponse
                                    });
                                }
                            }
                        });
                    },
                    FilterTableErrors: function (event, $link)
                    {
                        _fwdc.toggleTableErrorFilter($link.attr("data-table-id"));
                    },

                    ShowHistory: function (event, $link, data)
                    {
                        _fwdc.ajax({
                            url: 'ShowHistory',
                            data: function ()
                            {
                                return _fwdc.getDocPostParameters({ TABLE__: data.table, SHOW__: data.show }, "input[type='hidden']");
                            },
                            success: _handleDocResponse
                        });
                    },
                    SelectAll: function (event, $link)
                    {
                        _fwdc.stopEvent(event);

                        if (_busy()) { return false; }

                        var fieldId = $link.data("col");
                        var value = $link[0].checked;
                        var tableId = $link.data("tbl");

                        _fwdc.setPropertiesInternal(event, "", "SelectAll", fieldId, true, { "selectValue": value, "tableId": tableId });
                    },
                    PanelScrollLeft: function (event, $link)
                    {
                        _fwdc.scrollPanel($link.parent(), -1);
                    },
                    PanelScrollRight: function (event, $link)
                    {
                        _fwdc.scrollPanel($link.parent(), 1);
                    },

                    AutoRefreshDialog: function (event, $link)
                    {
                        //FWDC.showBasicDialog(event, "AutoRefresh", $link.attr("data-linkid"));
                        _fwdc.showStandardDialog(event, {
                            dialog: "AutoRefresh",
                            data: { "TARGET__": $link.attr("data-linkid") }
                        });
                    },

                    SubmitStandardDialog: function (event, $link)
                    {
                        var $dialog = _fwdc.getStandardDialog(event);
                        if (!$dialog)
                        {
                            _fwdc._error("No standard dialog found for event: ", event);
                            return;
                        }

                        var $form = $dialog.findElementsByClassName("FastBasicDialogForm");
                        if (!$form.length)
                        {
                            _fwdc._error("No basic form found on standard dialog: ", $dialog);
                            return;
                        }

                        $form.submit();
                    },

                    CancelStandardDialog: function (event, $link)
                    {
                        _fwdc.closeStandardDialog(event);
                    },

                    StepClick: function (event, $link)
                    {
                        if ($link.closest(_fwdc.selectors.specialClickElements).length > 0) { return; }

                        var id = $link.attr("data-linkid") || $link.attr("id");

                        _fwdc.viewLinkClicked({
                            fieldId: id,
                            trigger: "Events.StepSelector.stepClicked"
                        });
                    },
                    StepActionClick: function (event, $link)
                    {
                        if ($link.closest(_fwdc.selectors.specialClickElements).length > 0) { return; }

                        var id = $link.attr("id");

                        FWDC.eventOccurred(event, {
                            field: id,
                            eventType: _fwdc.EventType.Standard,
                            trigger: "Events.StepSelector.stepActionClicked",
                            sourceId: id
                        });
                    },

                    ScrollForMore: function (event, $link)
                    {
                        var $container = $link.closest(_fwdc.selectors.scrollContainers);
                        //$container.scrollTop($container.scrollHeight() / 2);
                        var target = $container.scrollTop() + ($container.height() / 2);
                        $container.animate({ scrollTop: target }, 200);
                    },

                    ToggleShowPassword: function (event, $button)
                    {
                        var $passwordField = $button.data("$passwordField");
                        if ($passwordField)
                        {
                            if ($passwordField.hasClass("PasswordVisible"))
                            {
                                $passwordField.removeClass("PasswordVisible");
                                $passwordField.attr("type", "password");
                                $button.attr("aria-pressed", "false");
                            }
                            else
                            {
                                $passwordField.addClass("PasswordVisible");
                                $passwordField.attr("type", "text");
                                $button.attr("aria-pressed", "true");
                            }
                        }
                    },

                    // Comboboxes
                    ComboItemLink: function (event, $link)
                    {
                        var recalcData = { 'DOC_MODAL_ID__': _fwdc.currentModalId() };
                        var linkData = $link.data("ci");
                        var fieldId = linkData.fieldId;
                        var value = linkData.value;
                        recalcData[fieldId] = value;
                        _recalc({ 'data': recalcData, 'source': fieldId, 'trigger': 'SelectComboItem' });

                        $(".FastComboMenu").tryDestroyDialog();
                    },
                    ComboMoreItemLink: function (event, $link)
                    {
                        var $dialog = $link.closest(".FastComboMenu");
                        if ($dialog.length)
                        {
                            $dialog.tryDestroyDialog();
                        }

                        _fwdc.raiseComboMoreItem(event, $link.data("ci").fieldId, "");
                    },

                    // Development Panel Options
                    ToggleDevPanel: function (event)
                    {
                        _fwdc.setPropertiesInternal(event, "MANAGER__", "ToggleDevPanel", null, true);
                    },
                    ToggleDevTools: function (event)
                    {
                        _fwdc.setPropertiesInternal(event, "MANAGER__", "ToggleDevTools", null, true);
                    },
                    ToggleLog: function (event)
                    {
                        _fwdc.toggleLog();
                    },
                    ChangeSlice: function (event)
                    {
                        window.location = "./SliceForm";
                    },
                    ChangeRunDate: function (event)
                    {
                        window.location = "./SliceForm?Display=Date";
                    },
                    ToggleDecodeInfo: function (event)
                    {
                        _fwdc.setPropertiesInternal(event, "MANAGER__", "DecodeInfo", "DecodeInfo", true, { Toggle: true });
                    },
                    ToggleStructureInfo: function (event)
                    {
                        _fwdc.setPropertiesInternal(event, "MANAGER__", "StructureInfo", "StructureInfo", true, { Toggle: true });
                    },
                    ShowDevelopmentMenu: function (event)
                    {
                        _fwdc.showMenu(event, "MANAGER__", "DevelopmentMenu", "", {
                            position: {
                                my: "top center",
                                at: "bottom center",
                                adjust: { y: 10 }
                            }
                        });
                    },

                    ClearInputImage: function (event)
                    {
                        var $field = $(event.currentTarget);
                        _fwdc.setPropertiesInternal(event, "", "InputImage", $field.attr("data-field-id"), true, { "imageData": "" });
                        _fwdc.stopEvent(event);
                    },

                    CaptureCameraInputImage: function (event, $button)
                    {
                        var $element = $button.closest(".FastCameraInputImage");
                        var fieldId = $element.attr("data-field-id");
                        var $video = $element.findElementById("vid_" + fieldId);
                        var video = $video[0];

                        var cameraInfo = $element.data("fast-camera-info");

                        video.pause();

                        var rotation = _fwdc.getCameraInputRotation($video);

                        var track = video.srcObject.getVideoTracks()[0];
                        var height = track.getSettings().height;
                        var width = track.getSettings().width;
                        var busyId = _fwdc.busy.show();

                        var imageType = $element.attr("data-camera-mimetype");
                        var imageQuality = parseInt($element.attr("data-camera-quality"), 10);

                        if (window.ImageCapture)
                        {
                            var ic = new ImageCapture(track);

                            //ic
                            //    .getPhotoCapabilities()
                            //    .then(function (capabilities)
                            //    {
                            //        console.log(capabilities);
                            //    });

                            ic
                                // We may need to add more configuration options to manage the photo height/width.
                                //.takePhoto({ fillLightMode: "flash", imageHeight: 1080, imageWidth: 1920 })
                                .takePhoto({ fillLightMode: "flash" })
                                .then(function (blob)
                                {
                                    return createImageBitmap(blob);
                                })
                                .then(function (imageBitmap)
                                {
                                    // If photo capture succeeds, we'll use the height/width of the photo rather than the video track since it may be higher resolution
                                    _fwdc.setCameraImageData(fieldId, cameraInfo, imageBitmap, imageBitmap.width, imageBitmap.height, rotation, imageType, imageQuality, busyId);
                                })
                                .catch(function (ex)
                                {
                                    _fwdc._error("Error capturing image: ", ex);
                                    _fwdc.setCameraImageData(fieldId, cameraInfo, video, width, height, rotation, imageType, imageQuality, busyId);
                                });
                        }
                        else
                        {
                            //_fwdc.setCameraImageData(fieldId, video, width, height, rotation, busyId);
                            _fwdc.setCameraImageData(fieldId, cameraInfo, video, width, height, rotation, imageType, imageQuality, busyId);
                        }
                    },
                    RotateCameraInputImageCW: function (event, $button)
                    {
                        var $element = $button.parent().parent();
                        var fieldId = $element.attr("data-field-id");
                        var $video = $element.findElementById("vid_" + fieldId);
                        var $wrapper = $video.parent();

                        var newRotation = 0;
                        switch (_fwdc.getCameraInputRotation($video))
                        {
                            case 0:
                                newRotation = 90;
                                break;
                            case 90:
                                $wrapper.removeClass("FastCameraRotate90");
                                newRotation = 180;
                                break;
                            case 180:
                                $wrapper.removeClass("FastCameraRotate180");
                                newRotation = 270;
                                break;
                            case 270:
                                $wrapper.removeClass("FastCameraRotate270");
                                newRotation = 0;
                                break;
                        }

                        if (newRotation)
                        {
                            $wrapper.addClass("FastCameraRotate" + newRotation);
                        }

                        _fwdc.editJsonCookie("camerainput", function (settings)
                        {
                            settings.defaultRotation = newRotation;
                        });

                        _fwdc.sizeCameraInputVideo($video);
                    },
                    RotateCameraInputImageCCW: function (event, $button)
                    {
                        var $element = $button.parent().parent();
                        var fieldId = $element.attr("data-field-id");
                        var $video = $element.findElementById("vid_" + fieldId);
                        var $wrapper = $video.parent();

                        var newRotation = 0;
                        switch (_fwdc.getCameraInputRotation($video))
                        {
                            case 0:
                                newRotation = 270;
                                break;
                            case 90:
                                $wrapper.removeClass("FastCameraRotate90");
                                newRotation = 0;
                                break;
                            case 180:
                                $wrapper.removeClass("FastCameraRotate180");
                                newRotation = 90;
                                break;
                            case 270:
                                $wrapper.removeClass("FastCameraRotate270");
                                newRotation = 180;
                                break;
                        }

                        if (newRotation)
                        {
                            $wrapper.addClass("FastCameraRotate" + newRotation);
                        }

                        _fwdc.editJsonCookie("camerainput", function (settings)
                        {
                            settings.defaultRotation = newRotation;
                        });

                        _fwdc.sizeCameraInputVideo($video);
                    },
                    CameraToggleAdvanced: function (event, $button)
                    {
                        if (_busy()) { return false; }

                        $button.parent().findElementsByClassName("FastCameraAdvanced").toggleClass("CameraShowAdvanced");

                        return false;
                    },
                    ReloadCamera: function (event, $link)
                    {
                        var $field = $link.closest(".FastCameraInputImage");
                        _fwdc.Init.camerainputimage($field);
                    },
                    ViewMediaError: function (event, $link)
                    {
                        FWDC.messageBox({
                            message: _fwdc.lastMediaError,
                            icon: FWDC.MessageBoxIcon.Error,
                            buttons: FWDC.MessageBoxButton.Ok
                        });
                    },

                    EditSignature: function (event, $link)
                    {
                        if (_busy()) { return false; }

                        var fieldId = $link.attr("data-linkid");

                        _fwdc.loadSignaturePad(function ()
                        {
                            _fwdc.getData("", "SignatureEditor", fieldId, "html", true, null, function (content)
                            {
                                var $content = $(content);
                                var $modal = $('<div id="SignatureDialog" class="FastDialogElement" style="display:none"></div>');
                                if ($content.attr("title"))
                                {
                                    $modal.attr("title", $content.attr("title"));
                                    $content.removeAttr("title", "");
                                }
                                $modal.append($content);
                                _fwdc.$body().append($modal);

                                var $signatureForm;

                                $modal.dialog({
                                    modal: true,
                                    draggable: false,
                                    resizable: false,
                                    width: "auto",
                                    height: "auto",
                                    position: { my: "center", at: "center", collision: "none" },
                                    dialogClass: "SignatureDialog FastModal FastPanelDialog",
                                    closeOnEscape: false,
                                    closeText: _fwdc.getCloseText(),
                                    open: function ()
                                    {
                                        this.$accessKeyElements = _fwdc.disableAccessKeys();
                                        $signatureForm = $modal.find("#SignatureDialogForm");

                                        var signatureData = $signatureForm.data("signature");

                                        var signatureVersion = signatureData.version || _signaturePadDefaultVersion;

                                        switch (signatureVersion)
                                        {
                                            case 1:
                                                {
                                                    // Signature-Pad v1
                                                    var lineTop = parseInt($signatureForm.find("canvas").height() * 0.80, 10);
                                                    var options = { drawOnly: true, lineTop: lineTop };

                                                    if ($signatureForm.length > 0)
                                                    {

                                                        if (signatureData && signatureData.penColor)
                                                        {
                                                            options.penColour = signatureData.penColor
                                                        }

                                                        if (signatureData && signatureData.penWidth)
                                                        {
                                                            options.penWidth = signatureData.penWidth
                                                        }
                                                    }

                                                    $signatureForm.signaturePad(options);
                                                }
                                                break;

                                            case 2:
                                                {
                                                    // Signature_Pad v2
                                                    _setupSignaturePad2($signatureForm, signatureData);
                                                }
                                                break;

                                            default:
                                                _fwdc._error("Unsupported signature version: " + signatureVersion);
                                        }
                                    },
                                    close: function ()
                                    {
                                        $modal.remove();
                                        $modal.tryDestroyDialog();
                                        _fwdc.restoreAccessKeys(this.$accessKeyElements);
                                    }
                                });
                            });
                        });
                    },
                    AcceptSignatureDialog: function (event, $button)
                    {
                        if (_busy()) { return false; }

                        var targetData = $button.data("target");
                        var control = targetData.docId;
                        var fieldId = targetData.fieldId;

                        var $signatureForm = $("#SignatureDialogForm");

                        var signatureData = $signatureForm.data("signature");

                        var signatureVersion = signatureData.version || _signaturePadDefaultVersion;

                        var signatureData;

                        switch (signatureVersion)
                        {
                            case 1:
                                var signaturePad = $signatureForm.signaturePad();
                                signatureData = signaturePad.getSignatureString();
                                break;

                            case 2:
                                var signaturePad = signatureData.signaturePad
                                signatureData = JSON.stringify(signaturePad.toData());
                                break;
                        }

                        _fwdc.setPropertiesInternal(null, control, "Signature", fieldId, true, { jsonData: signatureData });
                        $("#SignatureDialog").dialog("close");

                        return false;
                    },
                    CancelSignatureDialog: function (event, $button)
                    {
                        if (_busy()) { return false; }
                        $("#SignatureDialog").dialog("close");
                        return false;
                    },

                    // WebAuthN
                    WebAuthNRegister: function (event, $button)
                    {
                        _fwdc.WebAuthN.register($button.attr("data-control-id"), $button.attr("data-linkid") || $button.attr("id"));
                    },
                    WebAuthNLogin: function (event, $button)
                    {
                        _fwdc.WebAuthN.login($button.attr("data-control-id"), $button.attr("data-linkid") || $button.attr("id"));
                    },

                    // Chat
                    ChatTextLinkClick: function (event, $link)
                    {
                        if (_busy()) { return false; }

                        var chatData = $link.data("chatdata");
                        _fwdc.resetChatFocus();

                        var conversationId = chatData.conversationId;
                        var chatToken = chatData.token;
                        var messageData = chatData.data;

                        _fwdc.setConfirmCallback(function ()
                        {
                            _fwdc.setProperties(event,
                                {
                                    control: "MANAGER__",
                                    type: "ChatTextLinkClick",
                                    target: conversationId,
                                    busy: true,
                                    properties: { token: chatToken, data: messageData },
                                    extraData: { CLOSECONFIRMED__: true }
                                });
                        });

                        _fwdc.setProperties(event,
                            {
                                control: "MANAGER__",
                                type: "ChatTextLinkClick",
                                target: conversationId,
                                busy: true,
                                properties: { token: chatToken, data: messageData }
                            });
                    },

                    // Attachment Fields
                    UploadFieldAttachment: function (event, $target)
                    {
                        _fwdc.stopEvent(event);

                        if (_busy()) { return false; }

                        var $field = $target.parent();

                        var formInfo = _createFieldAttachmentForm($field.attr("id"), $field.data("attach-config").accept);

                        _acceptFieldAttachment(formInfo);

                        return false;
                    },
                    PreviewFieldAttachment: function (event, $button)
                    {
                        _fwdc.stopEvent(event);

                        if (_busy()) { return false; }

                        var $field = $button.parent().parent();
                        var fieldId = $field.attr("id");

                        _fwdc.setPropertiesInternal(event, "", "PreviewFieldAttachment", fieldId, true);
                    },
                    RemoveFieldAttachment: function (event, $button)
                    {
                        _fwdc.stopEvent(event);

                        if (_busy()) { return false; }

                        var decodes = $button.data("decodes");

                        FWDC.messageBox({
                            message: decodes.confirmText,
                            caption: decodes.confirmTitle,
                            okDecode: decodes.confirmRemove,
                            icon: FWDC.MessageBoxIcon.Question,
                            buttons: FWDC.MessageBoxButton.OkCancel,
                            callback: function ($modal, tag, result)
                            {
                                if (result === FWDC.MessageBoxResult.Ok)
                                {
                                    var $field = $button.parent().parent();

                                    var fieldId = $field.attr("id");

                                    _fwdc.setPropertiesInternal(event, "", "RemoveFieldAttachment", fieldId, true);
                                }
                            }
                        });

                        return false;
                    }
                },

                StandardDialogSubmit:
                {
                    submit: function (event)
                    {
                        _fwdc.stopEvent(event);

                        if (_busy())
                        {
                            return false;
                        }

                        var dialogClosed = $(event.currentTarget).data("dialog-closed");
                        if (dialogClosed)
                        {
                            return;
                        }

                        var dialogType = $(event.currentTarget).attr("data-dialog");

                        if (!dialogType)
                        {
                            _fwdc._error("Missing data-dialog: ", event.currentTarget);
                            return;
                        }

                        var onsubmit = _fwdc.Events.StandardDialogSubmit[dialogType];
                        if (!onsubmit)
                        {
                            _fwdc._error("Unhandled standard dialog submit: " + dialogType);
                            return;
                        }

                        var result = onsubmit.call(this, event, $(this));

                        if (result === true)
                        {
                            _fwdc.closeStandardDialog(event);
                        }
                        else if (result && result.done)
                        {
                            $(event.currentTarget).addClass("Submitted");
                            result.done(function ()
                            {
                                _fwdc.closeStandardDialog(event);
                            });
                        }

                        return;
                    },
                    Confirmation: function (event, $form)
                    {
                        //password, actionId, type, field
                        var confirmedCallback = $form.data("fast-confirmed-callback");
                        var postParameters = $form.serialize() + "&CLOSECONFIRMED__=true";

                        var captchaId = $form.data("fast-captcha-id");
                        var captcha = captchaId !== undefined;

                        var confirmationData = $form.data("confirmation");
                        //var password = confirmationData.password;
                        var actionId = confirmationData.action;
                        var type = confirmationData.type;
                        var field = confirmationData.field;

                        function formHasFocus()
                        {
                            return !!$form.find($(document.activeElement)).length;
                        }

                        function restoreFocus()
                        {
                            if (!formHasFocus())
                            {
                                $form.find("input:last").focus();
                            }
                        }

                        if (confirmedCallback)
                        {
                            confirmedCallback(_fwdc.getDocPostParameters({ CLOSECONFIRMED__: true }, null, $form), function (result)
                            {
                                if (result !== FWDC.ActionResult.ConfirmationFailure)
                                {
                                    _fwdc.closeStandardDialog(event);
                                }
                                else
                                {
                                    restoreFocus();

                                    if (captcha)
                                    {
                                        _captchaApi.reset(captchaId);
                                    }
                                }
                            });
                        }
                        else if (actionId !== null && actionId !== undefined)
                        {
                            _fwdc.ajax({
                                url: 'ExecuteAction',
                                data: postParameters + "&DOC_MODAL_ID__=" + encodeURIComponent(_fwdc.currentModalId()) + "&ACTION_ID__=" + encodeURIComponent(actionId) + "&TYPE__=" + encodeURIComponent(type),
                                success: function (data, status, request)
                                {
                                    if (_fwdc.handleActionResult(data, { actionId: actionId, type: type }) !== FWDC.ActionResult.ConfirmationFailure)
                                    {
                                        _fwdc.closeStandardDialog(event);
                                    }
                                    else
                                    {
                                        restoreFocus();

                                        if (captcha)
                                        {
                                            _captchaApi.reset(captchaId);
                                        }
                                    }
                                }
                            });
                        }
                        else
                        {
                            _fwdc.ajax({
                                url: 'EventOccurred',
                                data: postParameters + "&DOC_MODAL_ID__=" + encodeURIComponent(_fwdc.currentModalId()) + "&EVENT__=" + encodeURIComponent(field),
                                success: function (data, status, request)
                                {
                                    if (_fwdc.handleActionResult(data, { field: field }) !== FWDC.ActionResult.ConfirmationFailure)
                                    {
                                        _fwdc.closeStandardDialog(event);
                                    }
                                    else
                                    {
                                        restoreFocus();

                                        if (captcha)
                                        {
                                            _captchaApi.reset(captchaId);
                                        }
                                    }
                                }
                            });
                        }
                    },
                    TablePage: function (event, $form)
                    {
                        var data = $form.data("page");
                        var $field = $form.find("#TABLE_PAGE__");
                        var page = $field.val();

                        return _fwdc.selectTablePage(data.table, page);
                    },
                    AutoRefresh: function (event, $form)
                    {
                        var data = $form.data("autorefresh");
                        var $field = $form.find("#AUTO_REFRESH__");
                        var time = $field.val();

                        return _fwdc.setProperties(event, {
                            type: "AutoRefresh",
                            target: data.field,
                            properties: { value: time }
                        });
                    },
                    MaxRowsForm: function (event, $form)
                    {
                        var $field = $form.find("#MaxRows");
                        var data = $form.data("maxrows");

                        return _fwdc.ajax({
                            url: 'SelectMaxRows',
                            data: $.param({ DOC__: data.doc, ROWS__: $field.val() }),
                            commitEdits: false,
                            success: function (data, status, request)
                            {
                                _fwdc.handleActionResult(data);
                                _fwdc.closeStandardDialog(event);
                            }
                        });
                    },
                    CredentialNameForm: function (event, $form)
                    {
                        var registration = $form.data("fast-dialog-data");
                        registration.name = $form.findElementById("CredentialName").val();
                        var control = $form.findElementById("Control").val();

                        if (!registration.name)
                        {
                            $form.findElementById("CredentialName").focus();
                            return false;
                        }

                        return _fwdc.WebAuthN.submitCredential(control, registration);
                    }
                },

                SliceForm:
                {
                    submit: function (event)
                    {
                        var $form = $(this);
                        var postParameters = $form.serialize() + "&XHR__=true";

                        _fwdc.ajax({
                            url: 'SelectSlice',
                            ignoreReady: true,
                            method: 'POST',
                            data: postParameters,
                            beforeRequest: function (args)
                            {
                                args = postParameters.slice.length > 30;
                            },
                            success: function (data, status, request)
                            {
                                if (data.ok)
                                {
                                    FWDC.openUrl(null, data.redirect);
                                }
                                else
                                {
                                    FWDC.messageBox({ icon: FWDC.MessageBoxIcon.Error, message: data.error });
                                }
                            }
                        });

                        return _fwdc.stopEvent(event);
                    }
                }
            };

            _fwdc.base64url = {
                encode: function (bytes)
                {
                    var b64 = base64js.fromByteArray(bytes);
                    return b64.replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
                },
                decode: function (encoded)
                {
                    var b64 = encoded.replaceAll("-", "+").replaceAll("_", "/");
                    var pad = b64.length % 4;
                    if (pad !== 0)
                    {
                        switch (4 - pad)
                        {
                            case 1:
                                b64 += "=";
                                break;
                            case 2:
                                b64 += "==";
                                break;
                            case 3:
                                b64 += "===";
                                break;
                        }
                    }

                    return base64js.toByteArray(b64);
                }
            };

            _fwdc.timeoutPromise = function (promise, timeout, timeoutText)
            {
                if (!timeout)
                {
                    return promise;
                }

                var name = "Promise Timeout: " + timeoutText;
                var timeoutId;
                return Promise.race(
                    [
                        promise,
                        new Promise(function (resolve, reject)
                        {
                            timeoutId = _fwdc.setTimeout(
                                name,
                                function ()
                                {
                                    reject(timeoutText);
                                },
                                timeout);
                        })
                    ])
                    .then(function (result)
                    {
                        _fwdc.clearTimeout(name, timeoutId);
                        return result;
                    });
            };

            var _webAuthNAbortController;
            var _webAuthNOperationId = 0;
            var _webAuthNConditionalRetry = false;
            var _webAuthNCurrentPromise = window.Promise ? Promise.resolve("no current process") : null;
            var _webAuthNCurrentOperationId = -1;
            var _webAuthNDebugToast = false;

            _fwdc.WebAuthN = {
                abort: function ()
                {
                    if (_webAuthNAbortController)
                    {
                        if (_webAuthNDebugToast)
                            _fwdc._devToast("Aborting existing WebAuthN operation " + _webAuthNCurrentOperationId);
                        try
                        {
                            _webAuthNAbortController.abort();
                            return true;
                        }
                        catch (ex)
                        {
                            if (_webAuthNDebugToast)
                                _fwdc._devToast("Error aborting existing WebAuthN operation " + _webAuthNCurrentOperationId + ": " + ex);
                            throw ex;
                        }
                    }

                    return false;
                },
                register: function (control, fieldId)
                {
                    if (_fwdc.busy())
                    {
                        return false;
                    }

                    if (!navigator.credentials)
                    {
                        _fwdc._error("WebAuthN.register: navigator.credentials not available");

                        FWDC.messageBox({
                            message: _fwdc.getDecode("WebAuthNNotAvailable"),
                            icon: FWDC.MessageBoxIcon.Error,
                            buttons: FWDC.MessageBoxButton.Ok
                        });

                        return false;
                    }

                    _fwdc.WebAuthN.abort();

                    var abortController = new AbortController();
                    _webAuthNAbortController = abortController;

                    var busyId = _fwdc.busy.show("WebAuthN.register");

                    if (_fwdc.stopAutoRefresh)
                        _fwdc.stopAutoRefresh();

                    function registerDone()
                    {
                        if (_webAuthNAbortController === abortController)
                        {
                            _webAuthNAbortController = null;
                        }

                        _fwdc.busy.hide(busyId);
                        FWDC.resumeAutoRefresh(true);
                    }

                    var registration = null;

                    _fwdc.setProperties(null,
                        {
                            control: control,
                            type: "WebAuthNChallenge",
                            target: fieldId,
                            action: false,
                            busy: false,
                            checkBusy: false,
                        })
                        .then(function (credentialOptions)
                        {
                            if (!credentialOptions || credentialOptions.status !== "ok")
                            {
                                return;
                            }

                            credentialOptions.challenge = _fwdc.base64url.decode(credentialOptions.challenge);
                            credentialOptions.user.id = _fwdc.base64url.decode(credentialOptions.user.id);

                            if (credentialOptions.excludeCredentials)
                            {
                                for (var ii = 0; ii < credentialOptions.excludeCredentials.length; ++ii)
                                {
                                    credentialOptions.excludeCredentials[ii].id = _fwdc.base64url.decode(credentialOptions.excludeCredentials[ii].id);
                                }
                            }

                            var timeout = credentialOptions.timeout;
                            if (timeout)
                            {
                                // Fuzz the timeout a bit for our hard stop timeout
                                timeout += 10000;
                            }

                            var createOptions = {
                                publicKey: credentialOptions,
                                signal: abortController.signal
                            };

                            var credentialPromise = navigator.credentials.create(createOptions);

                            // Use a timeout limiter to prevent issues with browsers like the stable Android Firefox from stalling this process indefinitely
                            return _fwdc.timeoutPromise(credentialPromise, timeout, "Timeout");
                        })
                        .then(function (credential)
                        {
                            if (!credential)
                            {
                                return;
                            }

                            registration = {
                                type: credential.type,
                                clientWhen: _fwdc.now(),
                                id: _fwdc.base64url.encode(new Uint8Array(credential.rawId)),
                                // Capture the full origin for the relaying party origin check
                                origin: window.location.origin,
                                // Capture the hostname as we may use it as the relaying party ID
                                domain: window.location.hostname,
                                // Transports is extra data to use to hint at later credential usage getTranports is not supported by all user agents.
                                transports: credential.response.getTransports ? JSON.stringify(credential.response.getTransports()) : "[]",
                                response: {
                                    // The attestation object is a raw byte array of serialized data, just base64 encode it
                                    attestationObject: _fwdc.base64url.encode(new Uint8Array(credential.response.attestationObject)),
                                    // The client data JSON element is in byte array form.
                                    clientDataJSON: _fwdc.base64url.encode(new Uint8Array(credential.response.clientDataJSON))
                                },
                                clientExtensionResults: credential.getClientExtensionResults && credential.getClientExtensionResults(),
                                authenticatorAttachment: credential.authenticatorAttachment
                            };

                            return _fwdc.setProperties(null, {
                                control: control,
                                type: "WebAuthNVerifyRegistration",
                                action: false,
                                busy: false,
                                checkBusy: false,
                                target: JSON.stringify(registration)
                            });
                        })
                        .then(function (verifyResponse)
                        {
                            registerDone();

                            if (!verifyResponse)
                            {
                                _fwdc._error("WebAuthN.register: Unknown error occurred - no verifyResponse received.");
                                throw "Unknown error occurred";
                            }

                            if (verifyResponse.status === "ok")
                            {
                                _fwdc.showStandardDialog(null, {
                                    dialog: "WebAuthNCredentialName",
                                    data: { TARGET__: control },
                                    dialogData: registration
                                });

                                return;
                            }

                            FWDC.messageBox({
                                message: verifyResponse.error,
                                icon: FWDC.MessageBoxIcon.Error,
                                buttons: FWDC.MessageBoxButton.OK
                            });
                        })
                        .catch(function (error)
                        {
                            registerDone();

                            _fwdc._error("WebAuthN.register: ", error);

                            var errorText = _fwdc.getDecode("WebAuthNFailed");
                            if (_fwdc.development && error)
                            {
                                errorText = errorText + "\r\n\r\n[Development Info]:\r\n" + error;
                            }

                            FWDC.messageBox({
                                message: errorText,
                                icon: FWDC.MessageBoxIcon.Error,
                                buttons: FWDC.MessageBoxButton.Ok
                            });
                        });
                },

                submitCredential: function (control, registration)
                {
                    return _fwdc.setProperties(null,
                        {
                            control: control,
                            type: "WebAuthNRegisterCredential",
                            target: JSON.stringify(registration),
                            busy: true,
                            checkBusy: false
                        });
                },

                login: function (control, fieldId, tryConditional)
                {
                    function loginInternal(control, fieldId, tryConditional)
                    {
                        if (_fwdc.busy())
                        {
                            return Promise.resolve(false);
                        }

                        var operationId = ++_webAuthNOperationId;
                        var operation = "Operation " + operationId + ": ";

                        if (!navigator.credentials)
                        {
                            if (!tryConditional)
                            {
                                _fwdc._error(operation + "WebAuthN.login: navigator.credentials not available");

                                FWDC.messageBox({
                                    message: _fwdc.getDecode("WebAuthNNotAvailable"),
                                    icon: FWDC.MessageBoxIcon.Error,
                                    buttons: FWDC.MessageBoxButton.Ok
                                });
                            }

                            return Promise.resolve(false);
                        };

                        function performLogon(conditional)
                        {
                            var stage = operation + "performLogon";
                            var busyId = _fwdc.busy.show("WebAuthN.logon");

                            var abortController = new AbortController();
                            _webAuthNAbortController = abortController;
                            _webAuthNCurrentOperationId = operationId;

                            function loginDone()
                            {
                                if (_webAuthNAbortController === abortController)
                                {
                                    _webAuthNAbortController = null;
                                    _webAuthNCurrentOperationId = -1;
                                }

                                _fwdc.busy.hide(busyId);
                                FWDC.resumeAutoRefresh(true);
                            }

                            if (_fwdc.stopAutoRefresh)
                                _fwdc.stopAutoRefresh();

                            stage = operation + "WebAuthNCredentialRequest";
                            var promise = _fwdc.setProperties(null,
                                {
                                    control: control,
                                    type: "WebAuthNCredentialRequest",
                                    target: fieldId,
                                    action: false,
                                    busy: false,
                                    checkBusy: false,
                                    properties: { conditional: !!conditional }
                                })
                                .then(function (credentialRequest)
                                {
                                    if (!credentialRequest || !credentialRequest.challenge)
                                    {
                                        return;
                                    }

                                    credentialRequest.challenge = _fwdc.base64url.decode(credentialRequest.challenge);

                                    if (conditional)
                                    {
                                        delete credentialRequest.allowCredentials;
                                    }
                                    else
                                    {
                                        var allowCredentials = credentialRequest.allowCredentials;
                                        if (allowCredentials)
                                        {
                                            for (var ii = 0; ii < allowCredentials.length; ++ii)
                                            {
                                                allowCredentials[ii].id = _fwdc.base64url.decode(allowCredentials[ii].id);
                                                allowCredentials[ii].transports = JSON.parse(allowCredentials[ii].transports);
                                            }
                                        }
                                    }

                                    var getRequest = {
                                        publicKey: credentialRequest,
                                        signal: abortController.signal
                                    };

                                    if (conditional)
                                    {
                                        stage = "navigator.credentials.get(conditional)";
                                        getRequest.mediation = "conditional";
                                        _fwdc.busy.hide(busyId);
                                        if (_webAuthNDebugToast)
                                            _fwdc._devToast(operation + "Starting conditional credentials.get call...");
                                    }
                                    else
                                    {
                                        stage = "navigator.credentials.get(standard)";
                                        if (_webAuthNDebugToast)
                                            _fwdc._devToast(operation + "Starting standard credentials.get call...");
                                    }

                                    return navigator.credentials.get(getRequest);
                                })
                                .then(function (credential)
                                {
                                    if (!credential)
                                    {
                                        return;
                                    }

                                    if (conditional)
                                    {
                                        if (_webAuthNDebugToast)
                                            _fwdc._devToast(operation + "Conditional get call got credential.");
                                    }
                                    else
                                    {
                                        if (_webAuthNDebugToast)
                                            _fwdc._devToast(operation + "Standard get call got credential.");
                                    }

                                    stage = "WebAuthNVerifyCredential";
                                    return _fwdc.setProperties(null,
                                        {
                                            control: control,
                                            type: "WebAuthNVerifyCredential",
                                            target: JSON.stringify({
                                                type: credential.type,
                                                id: _fwdc.base64url.encode(new Uint8Array(credential.rawId)),
                                                // Capture the full origin for the relaying party origin check
                                                origin: window.location.origin,
                                                // Capture the hostname as we may use it as the relaying party ID
                                                domain: window.location.hostname,
                                                response: {
                                                    authenticatorData: _fwdc.base64url.encode(new Uint8Array(credential.response.authenticatorData)),
                                                    clientDataJSON: _fwdc.base64url.encode(new Uint8Array(credential.response.clientDataJSON)),
                                                    signature: _fwdc.base64url.encode(new Uint8Array(credential.response.signature)),
                                                    userHandle: credential.response.userHandle ? _fwdc.base64url.encode(new Uint8Array(credential.response.userHandle)) : null
                                                }
                                            }),
                                            // Conditional logins are idling in the background and need to re-flag Busy here.
                                            // Non-conditional logins will already be busy from the parent call that retrieved the credential challenge.
                                            busy: !!conditional,
                                            checkBusy: false
                                        });
                                })
                                .then(function ()
                                {
                                    stage = "Credential Verified";
                                    // If we got here we were successful.
                                    if (_webAuthNDebugToast)
                                        _fwdc._devToast(operation + "Credential Verified");
                                    loginDone();
                                    return true;
                                })
                                .catch(function (error)
                                {
                                    if (_webAuthNDebugToast)
                                        _fwdc._devToast(operation + (conditional ? "CONDITIONAL " : "STANDARD ") + " WebAuthN.login ERROR: " + error + "\r\nAt Stage: " + stage);

                                    //_fwdc._devToast("name: " + error.name + ", message: " + error.message + ", code: " + error.code);

                                    if (abortController)
                                    {
                                        abortController.abort();
                                    }

                                    loginDone();

                                    // iOS Safari through at least 16.2 has a bug where having an existing background call causes future calls to fail with this NotAllowedError: OperationFailed.
                                    // For now we'll catch that error and allow a re-start of the call if appropriate.
                                    if (error.name === "NotAllowedError" && error.message === "Operation failed." && !_webAuthNConditionalRetry)
                                    {
                                        _webAuthNConditionalRetry = true;
                                        if (conditional)
                                        {
                                            if (_webAuthNDebugToast)
                                                _fwdc._devToast(operation + "Signalling start of a RETRY conditional background call");
                                            _fwdc.busy.done(_fwdc.WebAuthN.startConditionalMediation, true);
                                        }
                                        else
                                        {
                                            if (_webAuthNDebugToast)
                                                _fwdc._devToast(operation + "Signalling start of a RETRY login call");
                                            _fwdc.busy.done(function () { _fwdc.WebAuthN.login(control, fieldId, false); }, true);
                                        }
                                        return error;
                                    }

                                    if (!conditional)
                                    {
                                        if (_webAuthNDebugToast)
                                            _fwdc._devToast(operation + "Signalling start of a new conditional background call");
                                        _fwdc.busy.done(_fwdc.WebAuthN.startConditionalMediation, true);
                                    }

                                    if (error && error.name === "AbortError")
                                    {
                                        _webAuthNConditionalRetry = false;
                                        if (_webAuthNDebugToast)
                                            _fwdc._devToast(operation + "WebAuthN.login aborted");
                                        return error;
                                    }

                                    if (!conditional)
                                    {
                                        var errorText = _fwdc.getDecode("WebAuthNFailed");
                                        if (_fwdc.development && error)
                                        {
                                            errorText = errorText + "\r\n\r\n[Development Info]:\r\n" + error;
                                        }

                                        // We do not want to show popups during conditional mediation, as this is a background process.
                                        FWDC.messageBox({
                                            message: errorText,
                                            icon: FWDC.MessageBoxIcon.Error,
                                            buttons: FWDC.MessageBoxButton.Ok
                                        });
                                    }
                                    return error;
                                });
                            //.always(function (result)
                            //{
                            //    //_webAuthNCurrentPromise = Promise.resolve(false);
                            //    return result;
                            //});

                            promise.finally = promise.always;

                            return promise;
                        }

                        function startLogonProcess(tryConditional)
                        {
                            if (!tryConditional)
                            {
                                return performLogon();
                            }

                            if (window.PublicKeyCredential && window.PublicKeyCredential.isConditionalMediationAvailable)
                            {
                                //_fwdc._devToast(operation + "Attempting conditional mediation...");
                                return window
                                    .PublicKeyCredential
                                    .isConditionalMediationAvailable()
                                    .then(function (conditionalAvailable)
                                    {
                                        if (conditionalAvailable)
                                        {
                                            //_fwdc._devToast(operation + "Conditional mediation is available, starting auth process...");
                                            return _fwdc.busy.promise().then(function ()
                                            {
                                                return performLogon(true);
                                            });
                                        }
                                        else
                                        {
                                            //_fwdc._devToast(operation + "Conditional mediation is unavailable.");
                                            return Promise.resolve(false);
                                        }
                                    });
                            }

                            //_fwdc._devToast(operation + "Browser does not support conditional mediation."
                            return Promise.resolve(false);

                        }

                        //if (_fwdc.WebAuthN.abort())
                        //{
                        //    _fwdc._devToast(operation + "Delaying login operation due to prior abort");
                        //    window.setTimeout(startLogonProcess, 1000);
                        //}
                        //else
                        //{
                        //    _fwdc._devToast(operation + "Running login directly");
                        //    startLogonProcess();
                        //}

                        //_fwdc.WebAuthN.abort();

                        _webAuthNCurrentPromise = startLogonProcess(tryConditional);
                        return _webAuthNCurrentPromise;
                    }

                    _fwdc.WebAuthN.abort();

                    // TODO - This logic forces the call instead of using the promise logic below
                    // which causes iOS to properly force the existing operation to continue/fail.  Simply
                    // aborting it does not properly trigger it to end.
                    if (_webAuthNDebugToast)
                        _fwdc._devToast("Forcing start of a new login");
                    loginInternal(control, fieldId, tryConditional);

                    //return _webAuthNCurrentPromise = _webAuthNCurrentPromise
                    //    .then(function (result)
                    //    {
                    //        _fwdc._devToast("Promised login got result: " + result);
                    //        loginInternal(control, fieldId, tryConditional);
                    //    })
                    //    .catch(function (error)
                    //    {
                    //        _fwdc._devToast("Promised login got error: " + error);
                    //        loginInternal(control, fieldId, tryConditional);
                    //    });

                    // We can't rely on finally, as it is not part of jQuery's fake Promise structure from ajax()
                    //.finally(function ()
                    //{
                    //    //_fwdc._devToast("Promised login got data: " + data);
                    //    loginInternal(control, fieldId, tryConditional);
                    //});
                },

                startConditionalMediation: function ()
                {
                    if (!navigator.credentials)
                    {
                        return;
                    }

                    //_fwdc._devToast("startConditionalMediation is disabled");
                    //return;

                    var $button = _fwdc.currentDocumentContainer().findElementsByClassName("WebAuthNLoginTarget").filterVisible();
                    if ($button.length === 1)
                    {
                        _fwdc.WebAuthN.login($button.attr("data-control-id"), $button.attr("data-linkid") || $button.attr("id"), true);
                    }
                }
            };

            var $body;
            _fwdc.$body = function ()
            {
                return $body || ($body = $("body"));
            };

            var $html;
            _fwdc.$html = function ()
            {
                return $html || ($html = $(document.documentElement || "html"));
            };

            _fwdc.setupSkipToMain = function ()
            {
                if (!_fwdc.autoFocusMode)
                {
                    //var $container = $.findElementById("MANAGER_CONTAINER__0");
                    var $container = _fwdc.$body();
                    var $skipToMain = $container.findElementsByClassName("SkipToMain");

                    if (!$skipToMain.length)
                    {
                        // Create a skip content link that targets the base manager's control container.
                        $skipToMain = $($.parseHTML('<a class="SkipToMain" href="#MANAGER_CONTENT__0"></a>')).text(_fwdc.standardDecode("SkipToContent")).prependTo($container);
                    }
                    //else
                    //{
                    //    //$skipToMain.remove();
                    //}
                }
            };

            _fwdc.cancelAutoRevealBody = function ()
            {
                if (_fwdc.autoShowBodyHandle)
                {
                    _fwdc.clearTimeout("AutoRevealBody", _fwdc.autoShowBodyHandle);
                    _fwdc.autoShowBodyHandle = null;
                }
            };

            _fwdc.autoRevealBody = function (delay)
            {
                if (_fwdc.bodyHidden)
                {
                    _fwdc.cancelAutoRevealBody(_fwdc.autoShowBodyHandle);
                    _fwdc.autoShowBodyHandle = _fwdc.setTimeout("AutoRevealBody", _fwdc.revealBody, delay || 2000);
                }
            };

            _fwdc.revealBody = function ()
            {
                _fwdc.cancelAutoRevealBody();

                //_fwdc.setTimeout("test delay reveal", function ()
                //{
                if (_fwdc.bodyHidden)
                {
                    _fwdc.bodyHidden = false;
                    _fwdc.$html().removeClass("Loading").addClass("Loaded");

                    _fwdc.setupSkipToMain();
                }
                //}, 5000);
            };

            //function _onUnload(event)
            //{
            //    _fwdc.pauseActivityCheck();
            //}

            _fwdc.initialize = function ()
            {
                _onInitialize.fire();

                $(window)
                    // The unload event is deprecated, and may not fire anyway.  Pausing the activity check should not be necessary if we're leaving the page.
                    //.on("unload", _onUnload)
                    .keydown(function (event)
                    {
                        _fwdc.ctrlDown = event.ctrlKey;
                    })
                    .keyup(function (event)
                    {
                        _fwdc.ctrlDown = event.ctrlKey;
                    })
                    .blur(function (event)
                    {
                        _fwdc.ctrlDown = false;
                    });
            };

            //_fwdc.proxyFunctions = function (obj)
            //{
            //    $.each(obj, function (name, property)
            //    {
            //        if (name !== "jQuery" && obj.hasOwnProperty(name) && typeof property === "function")
            //        {
            //            obj[name] = function ()
            //            {
            //                try
            //                {
            //                    return property.apply(this, arguments);
            //                }
            //                catch (ex)
            //                {
            //                    throw ex;
            //                }
            //            }
            //        }
            //    });
            //};

            return this;
        }

        var _fwdc = FWDC._fwdc = new FWDCPrivate(window, jQuery),
            _busy = _fwdc.busy;

        _toolTipSettings = _fwdc.toolTipSettings;

        function _seal()
        {
            delete FWDC._fwdc;
        }

        //var _snapScrollTimeoutHandle = null;
        function _checkSnapScrolling($container, contentChanged)
        {
            _applySnapScrolling($container, contentChanged);
        }

        function _applySnapScrolling($container, force)
        {
            ($container || _fwdc.currentDocumentContainer()).find(".SnapScrollTop").each(function ()
            {
                var $container = $(this);
                if ($container.closest(".ui-dialog").length)
                {
                    return;
                }

                var $scrollContainer = _fwdc.findScrollableParent($container);
                if (!$scrollContainer)
                {
                    return;
                }

                var scrollContainerOffset = $scrollContainer.offset().top;
                var snapped = $container.hasClass("SnapScrollSnapped");
                var scrollContainerScroll = $scrollContainer.scrollTop();
                var minSnapScroll = $container.data("min-snap-scroll");
                var allowSnap = _fwdc.isLargeScreen();
                var shouldSnap = allowSnap && (scrollContainerScroll > minSnapScroll);
                var spacing = 20; // Not font size specific in 21.
                var snaptop = scrollContainerOffset + spacing;

                var scrollTop = $container.scrollTop();

                // Clear the container max-height as this may clamp the Control Container size, which would affect the outcome.
                $container.css("max-height", "");

                // Set a max height on snap scroll panels.  Use the window height if it is smaller than the actual scroll container.
                // This particularly happens when the html/body are the scroll containers.
                var $controlContainer = $container.closest(".ControlContainer");
                var controlContainerBottom = 100000;
                if ($controlContainer.length)
                {
                    // If the snap element is inside a control container then it should be capped at the bottom of that element.
                    controlContainerBottom = $controlContainer.displayBoundingBox().bottom - scrollContainerOffset;
                }

                var $actionBar = $scrollContainer.findElementsByClassName("ActionBar");
                var actionBarHeight = 0;
                if ($actionBar && $actionBar.length && $actionBar.isVisible())
                {
                    actionBarHeight = $actionBar.outerHeight();
                    if (actionBarHeight)
                    {
                        actionBarHeight += spacing;
                    }
                }

                var scrollHeight = $scrollContainer.height();
                var maxHeight =
                    Math.min(
                        _fwdc.windowHeight - actionBarHeight,
                        scrollHeight - actionBarHeight,
                        controlContainerBottom) // Do not exclude the action bar from the control container, it does not need this.
                    - (spacing * 2);

                if (!force
                    && minSnapScroll !== undefined
                    && snapped === shouldSnap)
                {
                    // Recalculate max height as it may depend on the scroll position of the container.
                    $container
                        .css("max-height", maxHeight + "px")
                        .scrollTop(scrollTop);

                    return;
                }

                var $wrapper = $container.parent();
                var containerScrollTop = $container.scrollTop();

                if (snapped)
                {
                    $container
                        .removeClass("SnapScrollSnapped SnapScrollOversize");
                    $wrapper
                        .removeClass("SnapScrollSnappedWrapper")
                        .css("min-height", "");
                }

                // Evaluate the minimum snap scroll position if forced or if it isn't known yet.
                if (force || minSnapScroll === undefined)
                {
                    var displayOffset = $container.displayContentOffset($scrollContainer);
                    if (!displayOffset)
                    {
                        return;
                    }

                    minSnapScroll = displayOffset.top - spacing;

                    // Page-level scrolling should be ignored when calculating minSnapScroll.
                    var isPageElement = $scrollContainer.is("html,body");
                    if (!isPageElement)
                    {
                        minSnapScroll += scrollContainerScroll;
                    }

                    $container.data("min-snap-scroll", minSnapScroll);
                }

                if (allowSnap && scrollContainerScroll > minSnapScroll)
                {
                    // SNAP
                    var containerWidth = $container.outerWidth();

                    $wrapper
                        .addClass("SnapScrollSnappedWrapper")
                        .css("min-height", scrollHeight + "px");

                    $container
                        .addClass("SnapScrollSnapped")
                        .css({
                            "max-height": maxHeight + "px",
                            "top": (snaptop) + "px"
                        })
                        .outerWidth(containerWidth)
                        .scrollTop(scrollTop);

                    if (containerScrollTop)
                    {
                        $container.scrollTop(containerScrollTop);
                    }
                }
                else
                {
                    // Remove the height of the application header for non-snapped elements so they stay fully on-screen in Page scroll mode.
                    if ($scrollContainer.tagIs("html") && $scrollContainer.hasClass("ScrollStylePage"))
                    {
                        var $applicationHeader = $.findElementsByClassName("ApplicationHeaderContainer");
                        if ($applicationHeader.length)
                        {
                            maxHeight -= $applicationHeader.outerHeight();
                        }
                    }

                    $container
                        .css({
                            "max-height": maxHeight + "px"
                        })
                        .scrollTop(scrollTop);
                }

                FWDC.checkFieldTipPositions();
            });
        }

        function _setCurrentField(field, $field, value, text, cell)
        {
            if (field !== _currentField && field !== undefined)
            {
                _currentField = field;
                _$currentField = $field || $(field);
                _lastFieldText = null;
                _lastFieldValue = null;
                _currentFieldCell = cell;
            }

            if (value !== undefined)
            {
                _setLastValue(field, value, text);
            }
        }

        function _setLastValue(field, value, text)
        {
            if (field && field === _currentField)
            {
                if (text === undefined) { text = value; }

                if (value !== undefined)
                {
                    _lastFieldValue = value;
                }
                if (text !== undefined)
                {
                    _lastFieldText = text;
                }

                return true;
            }

            return false;
        }

        function _clearCurrentField(field)
        {
            if (field === undefined || field === true || field === _currentField)
            {
                _currentField = null;
                _lastFieldText = null;
                _lastFieldValue = null;
                _currentFieldCell = false;

                return true;
            }

            return false;
        }

        function _fieldViewEnabled($field)
        {
            return $field.closest(".DocViewLayout").hasClass("DocViewEnabled");
        }

        var _monitoringBrowserResizeHandle;
        var _monitoringBrowserStartHeight;
        var _monitoringBrowserStartWidth;
        function _onWindowSizeChanged()
        {
            var $window = _fwdc.$window;
            var newHeight = $window.height();
            var newWidth = $window.width();

            if (_fwdc.windowWidth !== newWidth || _fwdc.windowHeight !== newHeight)
            {
                _fwdc.windowWidth = newWidth;
                _fwdc.windowHeight = newHeight;
                _fwdc.calculateScreenWidth();
                _fwdc.resizeElements();
                FWDC.checkFieldTipPositions();

                $.findElementsByClassName("FastModalDialog").each(function ()
                {
                    _fwdc.evaluateDialogScreenSize($(this));
                });

                _fwdc.updateChatWindowOffset();
            }

            if (_fwdc.monitoringConfigJson)
            {
                if (_fwdc.monitoringConfigJson.Browser && _fwdc.monitoringConfigJson.Browser.Enabled === true)
                {
                    if (_monitoringBrowserResizeHandle)
                    {
                        _fwdc.clearTimeout("Monitor browser resizing", _monitoringBrowserResizeHandle);
                    }
                    _monitoringBrowserResizeHandle = _fwdc.setTimeout("Monitor browser resizing", function monitorBrowserResize()
                    {
                        var sizeData = { "oldHeight": _monitoringBrowserStartHeight, "oldWidth": _monitoringBrowserStartWidth, "newHeight": $window.height(), "newWidth": $window.width() };
                        _monitoringBrowserStartHeight = $window.height();
                        _monitoringBrowserStartWidth = $window.width();
                        _fwdc.submitMonitoringBrowserEvent("Resize", sizeData);
                    }, 1500);
                }

            }
        }

        function _evaluateBaseManagerAboveFold()
        {
            var $mgr = $.findElementById("MANAGER_CONTAINER__0");
            var $ctl = $.findElementById("CONTROL_CONTAINER__0");

            if (!$mgr.length || !$ctl.length)
            {
                return;
            }

            var $actions = $mgr.findElementsByClassName("ActionBarBottom");
            var box = $ctl.displayBoundingBox();
            var height = _fwdc.windowHeight;

            if ($actions && $actions.length)
            {
                height -= $actions.outerHeight();
            }

            var currentFold = $mgr.data("above-fold");

            if (!box || box.bottom > height)
            {
                if (currentFold !== false)
                {
                    // Extends below window
                    $mgr.addClass("BelowFold").removeClass("AboveFold");
                    $mgr.data("above-fold", false);
                }
            }
            else
            {
                if (currentFold !== true)
                {
                    // Fits in window
                    $mgr.addClass("AboveFold").removeClass("BelowFold");
                    $mgr.data("above-fold", true);
                }
            }
        }

        function _repositionComboboxes()
        {
            $.findElementsByClassName("FastComboboxOpen").autocomplete("reposition");
        }

        function _onStructureScroll(event)
        {
            _checkSnapScrolling($(event.target));
            _fwdc.updateScrollPanels(null, false);
            _evaluateBaseManagerAboveFold();
            _repositionComboboxes();
            FWDC.checkFieldTipPositions(true);
        }

        function _currentDocModal()
        {
            if (_fwdc.modalDocCount > 0)
            {
                return $("#MODAL_DOC_DIALOG_" + _fwdc.modalDocCount);
            }
            else
            {
                return null;
            }
        }

        function _resizeControlGrids($container)
        {
            return ($container ? $container.find("div.ControlGridContainer") : $("div.ControlGridContainer")).each(function ()
            {
                var $controlGridContainer = $(this);
                var $controlGridLayout = $controlGridContainer.parent(".ControlGridLayout");
                if (!$controlGridLayout.length || $controlGridLayout.hasClass("CGFlex")) { return; }

                var responsive = !$controlGridLayout.hasClass("DocViewNotResponsive");

                var height = 0;
                var width = 0;
                $controlGridContainer
                    .children("div")
                    .each(function ()
                    {
                        var $div = $(this);
                        if ($div.css("display") !== "none" && !$div.hasClass("Hidden"))
                        {
                            var top = parseInt($div.css("top").replace("px", ""), 10);
                            if (isNaN(top)) { top = 0; }

                            var bottom = ($div.outerHeight(true) + top);
                            if (bottom > height)
                            {
                                height = bottom;
                            }

                            if (!responsive)
                            {
                                var left = parseInt($div.css("left").replace("px", ""), 10);
                                if (isNaN(left)) { left = 0; }

                                var right = ($div.outerWidth(true) + left);
                                if (right > width)
                                {
                                    width = right;
                                }
                            }
                        }
                    });

                $controlGridContainer.height(height);
                if (!responsive) { $controlGridContainer.width(width); }
            });
        }

        function _sizeFieldPopupCodeMirror($field, editor)
        {
            editor = editor || $field.data("fast-code-mirror-editor");
            var $editor = $(editor.getWrapperElement());
            var $cmContainer = $(editor.getScrollerElement());
            $cmContainer.height($editor.height());
            editor.refresh();
        }

        function _datepickerRegionalData()
        {
            if (!_datepickerRegional)
            {
                if ($.datepicker.regional[_fwdc.language])
                {
                    _datepickerRegional = $.datepicker.regional[_fwdc.language];
                }
                else
                {
                    var container = _fwdc.currentDocumentContainer();
                    if (container && container.length)
                    {
                        var regionCode = _fwdc.regionCode || container.attr("data-region-code") || "";
                        var regionSubCode = _fwdc.languageCode || (regionCode.indexOf("-") < 0 ? "" : regionCode.substring(0, regionCode.indexOf("-")));
                        _datepickerRegional = (regionCode ? ($.datepicker.regional[regionCode] || $.datepicker.regional[regionSubCode]) : null) || $.datepicker.regional[""];
                    }
                }
            }

            return _datepickerRegional;
        }

        /*function _setupPageSliders()
        {
            _fwdc.currentDocumentContainer().find(".TablePageSlider").each(function ()
            {
                var $this = $(this);
                if (!$this.hasClass("ui-slider"))
                {
                    $this.slider({
                        min: 1,
                        max: $this.data("pages"),
                        value: $this.data("current-page"),
                        stop: function (event, ui)
                        {
                            if (ui.value !== $this.data("current-page"))
                            {
                                FWDC.selectTablePage(null, $this.data("target-table"), ui.value);
                            }
                        }
                    });
                }
            });
        }*/

        function _setupTextareaPopups($container, $field, cancelCallback)
        {
            if (_fwdc.tap)
            {
                return;
            }

            ($field || ($container || _fwdc.currentDocumentContainer()).find("textarea")).each(function ()
            {
                var $field = $(this);
                if ($field.hasClass("TextareaPopup") || $field.hasClass("DocRichTextBox") || $field.hasClass("DocSqlBox")) { return; }

                var $button = $("<button type='button' class='FieldHeaderTool FastFieldPopupButton' tabIndex='-1'></button>");
                $button.click(function ()
                {
                    if (_busy()) { return false; }
                    _endEditCell(false, false);
                    _fwdc.showFieldPopup($field, { cancelCallback: cancelCallback });
                });

                var $image = $("<div></div>").addClass("FastFieldPopupButtonImage");
                $button.append($image);
                var $indicator = $field.parent().find(".FI");
                if ($indicator && $indicator.length)
                {
                    $indicator.before($button);
                }
                else
                {
                    $button.appendTo($field.parent());
                }

                $field.addClass("TextareaPopup");
            });
        }

        function _clearHelpElementClickHandlers($container)
        {
            return ($container || _fwdc.currentDocumentContainer()).find(".DocHelpElement[onclick],.DocHelpElement [onclick],.DocDecodeElement[onclick], .DocDecodeElement [onclick]").removeAttr("onclick");
        }

        function _fadeInMessages($container)
        {
            ($container || _fwdc.currentManagerContainer()).find(".MessagePanelNew").removeClass("MessagePanelNew").hide().fadeIn(500);
        }

        function _setupNoPaste($container)
        {
            ($container || _fwdc.$body()).find(".FastNoPaste input,input.FastNoPaste").each(function ()
            {
                var $input = $(this);
                // FastNoPasteReady class added for other logic to take advantage of if the existing NoPaste handler can't stop the event.
                $input.addClass("FastNoPasteReady").removeClass("FastNoPaste").closest(".FastNoPaste").removeClass("FastNoPaste");

                $input.bind("paste", function (event)
                {
                    event.preventDefault();
                    return false;
                });
            });
        }

        function _scrollContainers()
        {
            return $("#MANAGER_CONTENT__0,.ViewScrollContainer,.DocScrollContainer .DataDocWrapper,.DocTableMobileScroll");
        }

        function _setupStepLists($container)
        {
            var $containers = ($container || _fwdc.currentDocumentContainer()).find(".StepInfoContainer,.StageStepInfoContainer,.PathListContainer").not(".StepSelectorDocGroupStyle");
            $containers.each(function ()
            {
                var $container = $(this);
                //var preferCurrent = $container.hasClass("StepInfoContainer");

                var $wrapper = $container.children(".StepInfoStepsWrapper,.StageStepInfoStepsWrapper").removeClass("Overflown OverflownFuture");
                if (!$wrapper.length) { $wrapper = $container; }

                var $steps = $wrapper.children(".StepInfoSteps,.StageStepInfoSteps,.PathListPath").removeClass("Overflown OverflownFuture").css("margin-left", "");
                if ($steps.length)
                {
                    var $last = $steps.children().filterNotHasClassName("clearer").last();
                    if ($last.length)
                    {
                        var containerWidth = $wrapper.innerWidth();
                        var lastPosition = $last.relativeOffset($wrapper);
                        var lastRight = lastPosition.left + $last.outerWidth();
                        var $current = $steps.children(".StepInfoCurrentStep,.StepInfoButtonWrapper,.StageStepInfoCurrentStep,.StageInfoButtonWrapper,.PathListEntry").last();

                        // Center the current step if there are future steps, and they are not buttons.
                        var centerCurrent = $wrapper.hasClass("StepInfoStepsWrapper")
                            && !$last.equals($current)
                            && $current.length
                            && !$last.hasClass("StepInfoButtonWrapper");
                        var currentPosition = $current.relativeOffset($wrapper);

                        var overflow = 0;

                        if (centerCurrent)
                        {
                            var currentWidth = $current.outerWidth();
                            var targetLeft = (containerWidth / 2) - (currentWidth / 2) - currentPosition.left;
                            var maxLeft = containerWidth - lastRight - _fwdc.fontSize;

                            targetLeft = Math.max(targetLeft, maxLeft);

                            if (targetLeft < 0)
                            {
                                $steps.css("margin-left", targetLeft);
                                $wrapper.addClass("Overflown");
                                $steps.addClass("Overflown");
                            }
                        }
                        else
                        {
                            // Shift to ensure the right-most element is visible.
                            if (lastRight + _fwdc.fontSize > containerWidth)
                            {
                                $wrapper.addClass("Overflown");
                                $steps.addClass("Overflown");

                                // Re-measure offsets in case the overflown class caused a change.
                                lastPosition = $last.relativeOffset($wrapper);
                                lastRight = lastPosition.left + $last.outerWidth();

                                overflow = containerWidth - lastRight - _fwdc.fontSize;
                                if (overflow < 0)
                                {
                                    $steps.css("margin-left", overflow);
                                }
                            }

                            // Shift back to the left if the current item is not visible.
                            if ($current.length)
                            {
                                currentPosition = $current.relativeOffset($wrapper);

                                if (currentPosition && currentPosition.left < _fwdc.fontSize)
                                {
                                    overflow -= (currentPosition.left - _fwdc.fontSize);

                                    // Do not push to the right of the standard positioning.
                                    overflow = Math.min(overflow, 0);

                                    $steps.css("margin-left", overflow);
                                }
                            }
                        }

                        lastPosition = $last.relativeOffset($wrapper);
                        lastRight = lastPosition.left + $last.outerWidth();

                        // Mark the container as overflown to the right if the last item is not entirely visible.
                        if ((lastRight - _fwdc.fontSize) > containerWidth)
                        {
                            $wrapper.addClass("OverflownFuture");
                            $steps.addClass("OverflownFuture");
                        }
                    }
                }
            });

            var $navigationEntries = ($container || _fwdc.currentDocumentContainer()).find(".ManagerNavigationHeader .SidebarNavigationEntries");
            if ($navigationEntries.length)
            {
                var $navContainer = $navigationEntries.removeClass("Overflown").parent(".SidebarGroup");
                if ($navContainer.length)
                {
                    if ($navigationEntries.outerWidth() > $navContainer.innerWidth())
                    {
                        $navigationEntries.addClass("Overflown");
                    }
                    else
                    {
                        $navigationEntries.removeClass("Overflown");
                    }
                }
            }
        }

        function _setComboboxData(field, value, text)
        {
            if (typeof field === "string") { field = _fwdc.formField(field); }

            var $field = $(field);

            $field.data("fast-combo-value", value);
            $field.data("fast-combo-text", text);
        }

        function _checkComboText($field, recalc)
        {
            if ($field.val() !== $field.data("fast-combo-text"))
            {
                if (!recalc)
                {
                    _setComboboxData($field, $field.data("fast-combo-value"), $field.data("fast-combo-text"));
                    $field.val($field.data("fast-combo-text"));
                }
                return true;
            }

            return false;
        }

        function _generateS4()
        {
            var min = 0x1000;
            var max = 0xFFFF;
            var range = max - min;

            return (Math.floor(Math.random() * range) + min).toString(16);
        }

        function _generateWindowId()
        {
            return _generateS4() + "-" + _generateS4() + "-" + _generateS4();
        }

        function _onDocumentInitialized()
        {
            _fwdc.runFingerprinting();

            document.removeEventListener("DOMContentLoaded", _onDocumentInitialized);
            window.removeEventListener("load", _onDocumentInitialized);

            var isIOSSafari = /iP(ad|hone|od).+Version\/[\d\.]+.*Safari/i.test(navigator.userAgent);
            if (isIOSSafari)
            {
                var $metaViewport = $("#MetaViewport");
                var content = $metaViewport.attr("content") + ", maximum-scale=1.0";
                $metaViewport.attr("content", content);
            }

            _busy.initialize();

            _fwdc.$body().append('<input id="virtualbufferupdate" name="virtualbufferupdate" type="hidden" value="0">');

            _fwdc.calculateScreenSizes();

            if (_fwdc.exporting)
            {
                _fwdc.setupControls(_fwdc.$body());
                _fwdc.resizeElements();
                _fwdc.sizeContentModals();
            }

            _onWindowSizeChanged();

            $(window).bind("beforeunload", function (event)
            {
                if (_fwdc.settingHistory)
                {
                    return;
                }

                _busy.showUnloading();
                window.setTimeout(function ()
                {
                    _busy.hideUnloading();
                }, 1000);
            });

            if (_fwdc.exporting)
            {
                var $html = $("html");
                var settings = $html.attr("data-app-settings");
                if (settings)
                {
                    $html.removeAttr("data-app-settings");
                    _fwdc.setSettings(JSON.parse(settings));
                }
            }
            else if (_fwdc.fastApp)
            {
                _fwdc.$html().addClass("Loading");

                _fwdc.bodyHidden = true;

                //_fwdc.autoShowBodyHandle = _fwdc.setTimeout("AutoRevealBody", _fwdc.revealBody, 2000);
                _fwdc.autoRevealBody(500);
            }

            var $returnLink = $("a.SessionMessageReturn");
            if ($returnLink.length) { $returnLink.focus(); }
        }

        function _fastPrompt(caption, inputType, callback)
        {
            var $accessKeyElements = _fwdc.disableAccessKeys();
            var $body = _fwdc.$body();
            var $modal = $('<div id="PROMPT_DIALOG" class="FastDialogElement" style="display:none"></div>');
            $modal.append("<label for='PROMPT_INPUT'>" + caption + "</label>");
            var $input = $("<input type='" + inputType + "' id='PROMPT_INPUT' class='Field FieldEnabled'>");
            $modal.append($input);
            $body.append($modal);
            $modal.css("overflow", "hidden");

            $modal.dialog({
                autoOpen: true,
                modal: true,
                dialogClass: _fwdc.getFastModalClass(),
                closeText: _fwdc.getCloseText(),
                buttons: {
                    "Ok": function ()
                    {
                        var $this = $(this);
                        var val = $this.find("input").val();
                        $this.tryDestroyDialog();

                        if (callback) { callback(val); }
                    },
                    "Cancel": function ()
                    {
                        $(this).tryDestroyDialog();
                    }
                },
                open: function ()
                {
                    _fwdc.showCurrentFieldTip();
                },
                close: function ()
                {
                    _fwdc.restoreAccessKeys($accessKeyElements);
                    _fwdc.showCurrentFieldTip();
                }
            });

            $input.keydown(function (event)
            {
                if (event.which === _fwdc.keyCodes.ENTER)
                {
                    var val = $(event.target).val();
                    $modal.tryDestroyDialog();

                    if (callback) { callback(val); }
                }
            });
        }

        var _ignoreHashChange = false;
        function _onHashChange(event)
        {
            var hash = window.location.hash;

            if (hash === "" || hash === null || hash === undefined) { hash = "#"; }

            hash = hash.substr(1);

            if (_fwdc.runUrlFragment(hash))
            {
                return;
            }

            hash = parseInt(hash, 10);

            if (isNaN(hash))
            {
                _fwdc.initHistoryHash();
                return;
            }
            else if (_ignoreHashChange)
            {
                _fwdc.setHistoryStep(_fwdc.currentHash);
                return;
            }

            if (_fwdc.currentHash === hash) { return; }

            var oldHash = _fwdc.currentHash;
            _fwdc.currentHash = hash;

            _fwdc.onHashChange(oldHash, hash);
        }

        var _fastWindowNameRegex = /<fwdc>(FWDC\.WND-\w{4}-\w{4}-\w{4})<\/fwdc>/;
        _fwdc.getFastWindowName = function ()
        {
            var windowName = window.name;

            if (windowName)
            {
                var m = windowName.match(_fastWindowNameRegex);
                if (m && m[1])
                {
                    return m[1];
                }
            }

            var fastName = "FWDC.WND-" + _generateWindowId();
            window.name += "<fwdc>" + fastName + "</fwdc>";

            return fastName;
        };

        _fwdc.getCurrentAssistantDocForm = function ($relativeSource)
        {
            $relativeSource = $relativeSource || _fwdc.currentDocumentContainer();

            var $baseManagerContent = $relativeSource.closest("#MANAGER_CONTENT__0");
            if ($baseManagerContent.length)
            {
                var $assistantForm = $baseManagerContent.findElementsByClassName("AssistantDocumentForm");

                if ($assistantForm && $assistantForm.length)
                {
                    return $assistantForm;
                }
            }

            return null;
        };

        _fwdc.getDocPostParameters = function (extraParams, filter, $form, ignoreRelated)
        {
            if (filter === undefined || filter === null) { filter = "input,select,textarea,.FastInputField"; }
            var postParameters = null;

            var $source = ($form || _fwdc.currentDocumentContainer());
            $source.find(filter).each(function ()
            {
                var $field = $(this);
                var $richTextContainer = $field.closest(".DocCaptionRichText,.FastHtmlLabel");
                var name = $field.attr("data-name") || $field.attr('name');

                // Do not ignore DocCaptionRichText if it's the proper wrapper for the field. Fixes the Doc Editor's rich text caption editor.
                if (name
                    && !$field.data("fast-recalc-ignore")
                    && !$field.hasClass("TDI") // Exclude radios and checkboxes that are cell inputs
                    && (!$richTextContainer.length || ($richTextContainer.attr("id") === "fc_" + name)))
                {
                    var value = _fwdc.getFieldValue(this);

                    if (value !== undefined)
                    {
                        if (!postParameters) { postParameters = {}; }
                        if (value === null)
                        {
                            postParameters[name] = "";
                        }
                        else
                        {
                            postParameters[name] = value;
                        }
                    }
                }
            });

            var assistantData;
            if (!ignoreRelated)
            {
                var $assistantForm = _fwdc.getCurrentAssistantDocForm($source);
                if ($assistantForm)
                {
                    assistantData = _fwdc.getDocPostParameters(null, null, $assistantForm, true);
                }
            }

            // Put assistant fields first so they can be overwritten by real doc parameters.
            return $.extend({}, assistantData, postParameters, extraParams);
        };

        function _closeModals()
        {
            FWDC.hideViewMenus();
            $("div.FastDialogElement").tryDestroyDialog();
            $("div.FastComboMenu").tryDestroyDialog();
            FWDC.closeFieldPopup(null, true);
            _destroyMessageBoxes();
            $.datepicker._hideDatepicker();
        }

        function _closeBasicDialogs()
        {
            FWDC.hideViewMenus();
            $(".FastBasicDialog").tryDestroyDialog();
            $("div.FastComboMenu").tryDestroyDialog();
            _closeFieldPopup(true);
            _destroyMessageBoxes();
            $.datepicker._hideDatepicker();
        }

        function _destroyMessageBoxes()
        {
            $("div.FastDialogElement.FastMessageBox").tryDestroyDialog();
        }

        function _submitMessageBox(event, $modal, source, tag, result, callback)
        {
            if (_busy() || _fwdc.transitionStopEvent(event)) { return false; }
            if (!source) { source = ""; }

            _fwdc.stopEvent(event);

            $modal
                .closest(".ui-dialog")
                .find("button")
                .attr("disabled", "disabled");

            if (tag)
            {
                _fwdc.ajax({
                    url: 'SubmitMessageBox',
                    data: $.param({ SOURCE__: source, RESULT__: result, TAG__: tag }),
                    success: function (data, status, request)
                    {
                        $modal.dialog("close");

                        _fwdc.handleActionResult(data);

                        if (callback)
                        {
                            callback($modal, tag, result);
                        }
                    }
                });
            }
            else
            {
                $modal.dialog("close");

                if (callback)
                {
                    callback($modal, tag, result);
                }
            }
        }

        function _onDocViewModalClosing(event, element, confirmed, force)
        {
            if (_docModalClosing || _errorOccurred || _refreshingWindowContent) { return true; }

            if (!force && !confirmed && _busy()) { return false; }

            _fwdc.commitEdits("DocViewModalClosing");

            force = !!force;
            confirmed = !!confirmed || force;

            var accept = (_fwdc.getModalState() === "OK");

            _fwdc.ajax({
                url: (accept ? 'AcceptModal' : 'CancelModal'),
                async: !force,
                data: $.param({ DOC_MODAL_ID__: _fwdc.currentModalId(), CONFIRMED__: confirmed }),
                error: function (request, status, error)
                {
                    _fwdc.setModalState("Cancel");

                    _fwdc.onAjaxError("_onDocViewModalClosing", request.responseText);
                },
                success: function (data, status, request)
                {
                    _fwdc.handleActionResult(data);
                }
            });

            return false;
        }

        function _destroyDocModal()
        {
            FWDC.hideViewMenus();
            var $dialog = _currentDocModal();
            if ($dialog)
            {
                //_fwdc.destroyRichElements();
                //$dialog.tryDestroyDialog().remove();
                //_fwdc.modalDocCount -= 1;
                $dialog.dialog("close");
            }
            else
            {
                _fwdc._warn("No doc modal to destroy!");
            }
        }

        function _modalPosition(openPosition)
        {
            switch (openPosition)
            {
                case "top":
                    return { my: "top+50", at: "top", of: window };

                case "center":
                default:
                    return { my: "center", at: "center", of: window };
            }
        }

        function _openModalViewDialog(content, noFocus)
        {
            _fwdc.modalDocCount += 1;

            var $accessKeyElements = _fwdc.disableAccessKeys();

            var $modal = $('<div id="MODAL_DOC_DIALOG_' + _fwdc.modalDocCount + '" class="FastDialogElement FastModalDialog DocModalContainer" style="display:none"></div>').attr("tabindex", "-1");

            var $content = $($.parseHTML(content, true));

            var colorClass = _fwdc.getColorClass($content);
            var id = _fwdc.getDocContainerId($content);

            var appendContent = false;

            if ($content.attr("title"))
            {
                $modal.attr("title", $content.attr("title"));
                $content.removeAttr("title");
            }

            $modal.append($content);

            var contextMenu = $content.hasClass("DocViewContextMenu");
            var panelContextMenu = contextMenu && _fwdc.isSinglePanelContent($content, false);
            var resizable = !contextMenu && !_fwdc.embedded;

            var cssMaxWidth = $content.css("max-width");
            if (cssMaxWidth && cssMaxWidth !== "none")
            {
                resizable = false;
            }

            var cssClass = "DocModalDialog ContainerModal " + colorClass;
            if (panelContextMenu)
            {
                cssClass += " FastPanel SingleFastPanel";
            }
            else if (_fwdc.embedded)
            {
                cssClass += " FastModalFullDisplay";
            }

            var position;

            if (!_fwdc.embedded)
            {
                position = _modalPosition($content.attr("data-open-position"));
            }

            var width = "auto";
            var height = "auto";

            // Capture the top scroll position incase the modal opening or appending shifts it.
            var scrollPositions = _fwdc.saveScrollPositions();
            if (contextMenu)
            {
                cssClass = cssClass + " ContextMenuModal DocViewContextMenu";

                position = _fwdc.contextMenuPosition($content);

                appendContent = false;
            }
            else
            {
                width = "auto";
                height = "auto";
            }

            _fwdc.restoreScrollPositions(scrollPositions);
            _fwdc.minimizeChatDialog();

            $modal.dialog({
                modal: true,
                draggable: !contextMenu && !_fwdc.embedded,
                resizable: resizable,
                title: $content.attr('data-modal-title') || "",
                minWidth: 100,
                minHeight: 50,
                width: width,
                height: height,
                dialogClass: cssClass + " " + _fwdc.getFastModalClass(),
                closeOnEscape: contextMenu,
                closeText: _fwdc.getCloseText(),
                position: position,
                opening: function (event, ui)
                {
                    _fwdc.setupControls($content);
                    _fwdc.resizeElements($content);
                },
                open: function (event, ui)
                {
                    var $this = $(this);

                    _fwdc.setDocContainer($content, id);

                    FWDC.hideViewMenus();

                    _fwdc.setupModalOverlay($this, contextMenu);

                    if (resizable) { $modal.addClass("ModalResizable"); }

                    if (appendContent) { $modal.append($content); }

                    _fwdc.restoreScrollPositions(scrollPositions);

                    _fwdc.checkModalsOpen();

                    _fwdc.sizeContentModals($modal);

                    _fwdc.updateScreenReader();

                    _fixModalOrder();

                    _fwdc.evaluateDialogScreenSize($this);

                    FWDC.resumeAutoRefresh();

                    if (!noFocus)
                    {
                        window.setTimeout(function ()
                        {
                            _fwdc.focusCurrentField();
                            _fwdc.showCurrentFieldTip();
                        }, 100);
                    }
                },
                beforeClose: _onDocViewModalClosing,
                drag: function () { FWDC.checkFieldTipPositions(); },
                hiding: function ()
                {
                    _fwdc.modalDocCount -= 1;
                    _fwdc.clearDocContainer($modal.find(".DocumentContainer").first(), id);
                },
                close: function ()
                {
                    FWDC.hideViewMenus();
                    _fwdc.hideToolTips();
                    _fwdc.closeComboboxes();
                    _fwdc.destroyRichElements(false, $modal);
                    $modal.remove();
                    _fwdc.restoreAccessKeys($accessKeyElements);
                    _fwdc.showCurrentFieldTip();
                    _fwdc.checkModalsOpen();
                },
                resizeStart: function (ui)
                {
                    $modal.closest(".ui-dialog").addClass("ModalResized");
                },
                resize: _fwdc.evaluateDialogScreenResize
            });
        }

        function _showModalView(newModalId)
        {
            _errorOccurred = false;

            _fwdc.ajax({
                url: 'OpenModal',
                async: false,
                busy: false,
                data: function ()
                {
                    return _fwdc.getDocPostParameters({ DOC_MODAL_ID__: newModalId || 0 }, "input[type='hidden']");
                },
                success: function (data, status, request)
                {
                    _openModalViewDialog(data.dochtml, true);
                }
            });
        }

        function _setRecalcResizeRequired()
        {
            if (!_recalcResizeRequired)
            {
                _recalcResizeRequired = true;
                _recalcScrollPositions = _fwdc.saveScrollPositions();
            }
        }

        function _updateDocGroup(update)
        {
            var groupId = update.group;
            var groupSelector = groupId.replace(/@/g, "\\@");
            var $groupElement = _fwdc.formField(groupSelector);

            if (!$groupElement) { return; }

            if (update.caption !== undefined)
            {
                var $caption = _fwdc.formField("caption_" + groupSelector);
                if ($caption)
                {
                    $caption.html(update.caption);
                    _recalcHtmlUpdated = true;
                }
            }

            if (update.selected !== undefined)
            {
                if (update.selected)
                {
                    $groupElement.addClass("GroupSelected");
                }
                else
                {
                    $groupElement.removeClass("GroupSelected");
                }
            }

            if (update.visible !== undefined)
            {
                if (update.visible)
                {
                    $groupElement.removeClass("Hidden");
                }
                else
                {
                    $groupElement.addClass("Hidden");
                }
            }

            if (update.inerror !== undefined)
            {
                if (update.inerror)
                {
                    if ($groupElement.hasClass("TabSetGood"))
                    {
                        $groupElement.removeClass("TabSetGood").addClass("TabSetError");
                    }
                }
                else
                {
                    if ($groupElement.hasClass("TabSetError"))
                    {
                        $groupElement.removeClass("TabSetError").addClass("TabSetGood");
                    }
                }
            }
        }

        function _updateDocView(update)
        {
            var viewId = update.view;
            var viewSelector = viewId.replace(/@/g, "\\@");
            var $viewElement = _fwdc.formField(viewSelector);

            if (!$viewElement) { return; }

            if (update.caption !== undefined)
            {
                var $caption = _fwdc.formField("caption_" + viewSelector);
                if ($caption)
                {
                    $caption.html(update.caption);
                    _recalcHtmlUpdated = true;
                }
            }

            if (update.selected !== undefined)
            {
                if (update.selected)
                {
                    $viewElement.addClass("ViewSelected");
                    $viewElement.removeClass("ViewNotSelected");
                }
                else
                {
                    $viewElement.addClass("ViewNotSelected");
                    $viewElement.removeClass("ViewSelected");
                }
            }

            if (update.visible !== undefined)
            {
                if (update.visible)
                {
                    $viewElement.removeClass("Hidden");
                }
                else
                {
                    $viewElement.addClass("Hidden");
                }
                _recalcVisibleViewsUpdated = true;
            }

            if (update.inerror !== undefined)
            {
                if (update.inerror)
                {
                    if ($viewElement.hasClass("TabSetGood"))
                    {
                        $viewElement.removeClass("TabSetGood").addClass("TabSetError");

                        if ($viewElement.hasClass("TabSetActive"))
                        {
                            _fwdc.updateSelectorUnderlines($viewElement.parent());
                        }
                    }
                }
                else
                {
                    if ($viewElement.hasClass("TabSetError"))
                    {
                        $viewElement.removeClass("TabSetError").addClass("TabSetGood");

                        if ($viewElement.hasClass("TabSetActive"))
                        {
                            _fwdc.updateSelectorUnderlines($viewElement.parent());
                        }
                    }
                }
            }
        }

        function _updateDocRowSelector(update)
        {
            var rowSelectorId = update.row;
            var rowSelectorSelector = rowSelectorId.replace(/@/g, "\\@");
            var $rowSelectorElement = _fwdc.formField(rowSelectorSelector);

            if (!$rowSelectorElement) { return; }

            if (update.header !== undefined)
            {
                var $captionElement = _fwdc.formField("caption_" + rowSelectorId);
                if ($captionElement)
                {
                    $captionElement.text(update.header);
                    _setRecalcResizeRequired();
                }
            }

            if (update.description !== undefined)
            {
                var $description = $rowSelectorElement.closest(".TableRowContainer").parent().find(".ControlGridRowHeader > .RecordCaption");
                if ($description.length)
                {
                    $description = $description.first().text(update.description);
                }
            }

            if (update.selected !== undefined)
            {
                if (update.selected)
                {
                    $rowSelectorElement.addClass("TabSetActive").attr("aria-selected", "true");
                }
                else
                {
                    $rowSelectorElement.removeClass("TabSetActive").removeAttr("aria-selected");
                }
            }

            if (update.inerror !== undefined)
            {
                var $statusElement = _fwdc.formField("img_" + rowSelectorSelector);
                if (update.inerror)
                {
                    $rowSelectorElement.removeClass("TabSetGood").addClass("TabSetError");
                    $statusElement.removeClass("TabSetGood").addClass("TabSetError");
                }
                else
                {
                    $rowSelectorElement.removeClass("TabSetError").addClass("TabSetGood");
                    $statusElement.removeClass("TabSetError").addClass("TabSetGood");
                }
            }
        }

        function _updateDocImage(update)
        {
            var imageId = update.image;
            var imageSelector = imageId.replace(/@/g, "\\@");
            var $image = _fwdc.formField("image_" + imageSelector);

            if (!$image) { return; }

            if (update.visible !== undefined)
            {
                if (update.visible)
                {
                    $image.show();
                }
                else
                {
                    $image.hide();
                }
            }
        }

        function _getFicElement($field)
        {
            if ($field && $field.tagIs("TD"))
            {
                return $field.findElementsByClassName("FIC");
            }

            return $field;
        }

        _fwdc.fieldAttributeUpdates =
        {
            "dp-mindate": function ($field, attr, value)
            {
                $field.attr("data-dp-mindate", value);
                if ($field.hasClass("hasDatepicker"))
                {
                    $field.datepicker("option", "minDate", value);
                }
            },
            "dp-maxdate": function ($field, attr, value)
            {
                $field.attr("data-dp-maxdate", value);
                if ($field.hasClass("hasDatepicker"))
                {
                    $field.datepicker("option", "maxDate", value);
                }
            },
            "fic-src": function ($field, attr, value)
            {
                _getFicElement($field).children(".FICImg").attr("src", value);
            },
            "fic-srcset": function ($field, attr, value)
            {
                _getFicElement($field).children(".FICImg").attr("srcset", value);
            },
            "fic-alt": function ($field, attr, value)
            {
                _getFicElement($field).children(".FICImg").attr("alt", value);
            },
            "fic-title": function ($field, attr, value)
            {
                _getFicElement($field).attr("title", value);
            },
            "fic-iconfont": function ($field, attr, value)
            {
                $field = _getFicElement($field);

                var currentFont = $field.attr("data-iconfont");
                if (currentFont !== value)
                {
                    $field.attr("data-iconfont", value);
                    $field.removeClass("FICF_" + currentFont);

                    if (value)
                    {
                        if (!currentFont)
                        {
                            $field.addClass("FICF").removeClass("FICI");
                        }
                        $field.addClass("FICF_" + value);
                    }
                    else
                    {
                        $field.removeClass("FICF").addClass("FICI");
                    }
                }
            },
            "fic-icon": function ($field, attr, value)
            {
                _getFicElement($field).attr("data-icon", value);
            },
            "fic-iconstatus": function ($field, attr, value)
            {
                $field = _getFicElement($field);

                var currentStatus = $field.attr("data-iconstatus");
                if (currentStatus !== value)
                {
                    $field.attr("data-iconstatus", value);
                    $field.removeClass("FICFT" + currentStatus).addClass("FICFT" + value);
                }
            },
            "aria-description": function ($field, attr, value)
            {
                var $element = $field;

                if ($element.hasClass("TCE"))
                {
                    // Table cells with a link
                    var $link = $element.findElementById("l_" + $element.attr("id"));
                    if ($link.length)
                    {
                        $element = $link;
                    }
                    else
                    {
                        // Table cells with a raw input
                        var $input = $element.findElementById("i_" + $element.attr("id"));
                        if ($input.length)
                        {
                            $element = $input;
                        }
                    }
                }
                else if ($element.hasClass("LBW"))
                {
                    // Flex grid links.  The ID points to the wrapper.
                    var $link = $element.findElementById("cl_" + $element.attr("id"));
                    if ($link.length)
                    {
                        $element = $link;
                    }
                }

                if (value)
                {
                    $element.attr(attr, value);
                }
                else
                {
                    $element.removeAttr(attr);
                }
            },
            unknown: function ($field, attr, value)
            {
                _fwdc._warn("Unhandled data attribute update: ", attr, " = ", value, ": ", $field[0]);
            }
        };

        function _updateDocField(update)
        {
            var fieldId = update.field;
            var fieldSelector = fieldId.replace(/@/g, "\\@");
            var $field = _fwdc.formField(fieldSelector) || _fwdc.formField(update.container);
            if (!$field) { return; }

            //var $indicator = _fwdc.formField("indicator_" + fieldSelector);
            var $indicator;
            var $fieldContainerElement;
            var cm;
            if (update.istable)
            {
                $fieldContainerElement = _fwdc.formField(update.container);
                if ($fieldContainerElement)
                {
                    _setRecalcResizeRequired();
                    _recalcTableUpdate = true;

                    var $new = $($.parseHTML(update.value));
                    // Cross transitioning here can be tricky with tables that may not have backgrounds.
                    // This doesn't look great with the doc editor in particular.
                    //_fwdc.crossTransition($fieldContainerElement, $new, null, "UpdateDocField.Table");

                    $fieldContainerElement.replaceWith($new);

                    // Prefer instant updates as opposed to delayed updates that can be masked by transitions.
                    _fwdc.initElements($new, true);

                    _recalcHtmlUpdated = true;

                    if (update.visible !== undefined)
                    {
                        if (update.visible)
                        {
                            $fieldContainerElement.show();
                            $new.show();
                        }
                        else
                        {
                            $fieldContainerElement.hide();
                            $new.hide();
                        }
                    }

                    _fwdc.updateScrollPanels($new);
                }
                return;
            }

            var isCell = $field.is(".DocTable td");
            if (isCell)
            {
                $indicator = $field.find(".FI");
            }
            else
            {
                $indicator = _fwdc.formField("indicator_" + fieldSelector);
            }

            var $bgElement = _fwdc.formField("bg_" + fieldSelector) || $field;
            $fieldContainerElement = (update.container && _fwdc.formField(update.container)) || _fwdc.formField("fc_" + fieldSelector) || $field;

            if (update.mask !== undefined)
            {
                $field.clearMask();
                var mask = update.mask;
                if (mask) { $field.setMask(mask); }
            }

            if (update.comboitems && !isCell)
            {
                if ($field.is("select"))
                {
                    var watermark = $field.data('fast-watermark');
                    $field.empty();
                    $.each(update.comboitems, function (index, item)
                    {
                        var $item = $("<option></option>").attr("value", item.value).text(item.label);
                        if (item.selected) { $item.attr("selected", "selected"); }
                        if (item.empty || !item.label) { $item.addClass("BlankOption"); }
                        if (item.class)
                        {
                            $item.addClass(item.class);
                        }
                        $field.append($item);
                    });
                    if (watermark) { FWDC.watermark($field, watermark); }
                }
                else if ($field.data("uiAutocomplete"))
                {
                    $field.autocomplete("option", "source", update.comboitems);
                }
                else
                {
                    _fwdc._warn("Attempted to set combobox items to non-combobox field: " + fieldId, $field);
                }
            }

            if (update.combobuttonset !== undefined)
            {
                //_fwdc.setupButtonSets(null, $field.html(update.combobuttonset));
                _fwdc.setButtonSetButtons($field, update.combobuttonset);
                _recalcHtmlUpdated = true;
            }
            else if (update.comboradiobuttons !== undefined)
            {
                //_fwdc.setButtonSetButtons($field, update.comboradiobuttons);
                $field.children(".FCBRadios").html(update.comboradiobuttons);
                _recalcHtmlUpdated = true;
            }

            if (update.value !== undefined)
            {
                if (isCell)
                {
                    var $cellContent = _fwdc.formField(fieldSelector + "_c")
                        || _fwdc.formField("l_" + fieldSelector)
                        || _fwdc.formField("c_" + fieldSelector)
                        || $field;

                    if (update.indicatorclass === undefined)
                    {
                        $indicator = $cellContent.children(".FI").remove();
                    }

                    if ($field.hasClass("CellCheckbox") || $field.hasClass("CellRadioButton"))
                    {
                        $cellContent.find("input").prop("checked", update.value === true || update.value === "true");
                    }
                    else if ($field.hasClass("CellImage"))
                    {
                        var $img = $cellContent.children("img");
                        $img.attr("src", update.value);
                    }
                    else if ($field.hasClass("CellBar"))
                    {
                        $cellContent.html(update.value);
                        _recalcHtmlUpdated = true;
                    }
                    else if ($field.hasClass("CellTextRichText"))
                    {
                        $cellContent.html(update.value);
                    }
                    else if ($field.hasClass("CellToken"))
                    {
                        _fwdc.formField("tkb_" + fieldId).replaceWith($.parseHTML(update.tkb));
                        _fwdc.formField("tkd_" + fieldId).replaceWith($.parseHTML(update.tkd));
                        _recalcHtmlUpdated = true;
                    }
                    else if (update.text !== undefined)
                    {
                        $cellContent.text(update.text);
                    }
                    else
                    {
                        $cellContent.text(update.value);
                    }

                    if ($indicator && $indicator.length)
                    {
                        $indicator.appendTo($cellContent);
                    }
                }
                else if ($field.hasClass("FCBRBS"))
                {
                    var radioVal = update.value.toLowerCase();
                    $field.find("input").each(function ()
                    {
                        var $radio = $(this);
                        $radio.prop("checked", $radio.attr("value").toLowerCase() === radioVal);
                    });

                    if (update.combobuttonset === undefined)
                    {
                        _fwdc.animateSelectorUnderline($field);
                    }
                }
                else if ($field.is(":checkbox") && !$field.hasClass("FastSelectAllInputCheckbox") || $field.is(":radio"))
                {
                    $field.prop("checked", update.value === true || update.value === "true");
                    if ($field.data("uiCheckboxradio")) { $field.checkboxradio("updateState"); }
                }
                else if ($field.is(":checkbox") && $field.hasClass("FastSelectAllInputCheckbox"))
                {
                    switch (update.value)
                    {
                        case "checked":
                            $field.attr("checked", "checked");
                            $field.removeClass("FastIndeterminateInput");
                            break;
                        case "indeterminate":
                            $field.removeAttr("checked");
                            $field.addClass("FastIndeterminateInput");
                            break;
                        default:
                            $field.removeAttr("checked");
                            $field.removeClass("FastIndeterminateInput");
                            break;
                    }
                }
                else if ($field.data("fast-mask"))
                {
                    $field.val($.fastMask.maskString($field.data("fast-mask").mask, update.value));
                }
                else if ($field.is("img"))
                {
                    $field.attr("src", update.value);
                }
                else if ($field.is("select"))
                {
                    $field.val(update.value);
                }
                else if (_fwdc.isCombobox($field))
                {
                    $field.val(update.text);
                    _setComboboxData($field, update.value, update.text);
                }
                else if ($field.hasClass("DocRichTextBox"))
                {
                    _fwdc.setRichTextValue($field, update.value);
                }
                else if ($field.hasClass("DocControlToken"))
                {
                    _fwdc.formField("tkb_" + fieldId).replaceWith($.parseHTML(update.tkb));
                    _fwdc.formField("tkd_" + fieldId).replaceWith($.parseHTML(update.tkd));
                    _recalcHtmlUpdated = true;
                }
                else if ($field.is("audio,video"))
                {
                    try
                    {
                        var source = update.value;
                        var type = "";

                        var mediaElement = $field.get(0);
                        if (mediaElement && mediaElement.pause)
                        {
                            mediaElement.pause();
                        }

                        var split = source.indexOf(";");
                        if (split > 0)
                        {
                            type = "".substring(split + 1);
                            source = source.substring(0, split);
                        }

                        //.attr("type", type) - Skip Type attribute to keep IE9 happy.
                        $field.find("source").attr("src", source);

                        if (mediaElement && mediaElement.load)
                        {
                            mediaElement.load();
                        }
                    }
                    catch (ex)
                    {
                        _fwdc._warn(ex);
                    }
                }
                else if ($field.is(".FGNVV"))
                {
                    var $content = $field.children(".FGNVT");
                    $content.text(update.value);
                }
                else if ($field.hasClass("DocControlDatepicker") || $field.hasClass("DocControlDatepickerCombo"))
                {
                    var focus = !!$(document.activeElement).closest($field).length;
                    $field.datepicker("setDate", update.value);
                    if (focus)
                    {
                        $field.querySelectorAll(".ui-datepicker-current-day a").focus();
                    }
                }
                else
                {
                    cm = $field.data("fast-code-mirror-editor");
                    if (cm)
                    {
                        var scrollInfo = cm.getScrollInfo();
                        var selections = cm.listSelections();
                        cm.fastSetValue(update.value);
                        cm.save();
                        if (selections && selections.length)
                        {
                            cm.setSelections(selections);
                        }
                        cm.scrollTo(scrollInfo.left, scrollInfo.top);
                    }
                    else
                    {
                        if ($field.hasClass("DocControlEmail"))
                        {
                            // Email fields can ignore some value changes such as whitespace-only, so we'll clear and reset it so it is forced to update. (SQR 58876)
                            $field.val("");
                        }

                        $field.val(update.value);
                        if ($field.length)
                        {
                            _setLastValue($field.get(0), update.value);
                        }
                    }
                }
            }

            if (update.fieldclass !== undefined)
            {
                $field.removeClass("Field FieldDisabled FieldRequired FieldEnabled FieldError FieldCorrectableError FieldCheck FieldCorrected FieldReview FieldReviewed").addClass(update.fieldclass);
                if (!$field.equals($bgElement))
                {
                    $bgElement.removeClass("Field FieldDisabled FieldRequired FieldEnabled FieldError FieldCorrectableError FieldCheck FieldCorrected FieldReview FieldReviewed").addClass(update.fieldclass);
                }
                if (!$field.equals($fieldContainerElement))
                {
                    $fieldContainerElement.removeClass("Field FieldDisabled FieldRequired FieldEnabled FieldError FieldCorrectableError FieldCheck FieldCorrected FieldReview FieldReviewed").addClass(update.fieldclass);
                }

                if ($field.hasClass("FieldRequired"))
                {
                    $field.attr("aria-required", "true");
                }
                else
                {
                    $field.removeAttr("aria-required");
                }
            }

            if (update.indicatorclass !== undefined)
            {
                if (update.indicatorclass && isCell && (!$indicator || !$indicator.length))
                {
                    var $indicatorContainer = $field.children(".DCR");
                    if (!$indicatorContainer.length)
                    {
                        $indicatorContainer = $field;
                    }
                    $indicator = $($.parseHTML("<div></div>")).attr("id", "indicator_" + fieldId).attr("class", "FI").appendTo($indicatorContainer);
                }

                if ($indicator && $indicator.length)
                {
                    $indicator.removeClass("FIFieldDisabled FIFieldRequired FIFieldEnabled FIFieldError FIFieldCheck FIFieldCorrected FIFieldReview FIFieldReviewed");
                    if (update.indicatorclass)
                    {
                        $indicator.addClass("FI" + update.indicatorclass);
                    }
                }
            }

            if (update.enabled !== undefined)
            {
                if (isCell)
                {
                    if (update.enabled)
                    {
                        if (!$field.hasClass("CellEditable"))
                        {
                            $field.addClass("CellEditable");
                        }

                        if ($field.hasClass("CellCheckbox") || $field.hasClass("CellRadioButton"))
                        {
                            $field.find("input").removeAttr("disabled");
                        }
                    }
                    else
                    {
                        $field.removeClass("CellEditable");
                        if ($field.hasClass("CellCheckbox") || $field.hasClass("CellRadioButton"))
                        {
                            $field.find("input").attr("disabled", "disabled");
                        }
                    }
                }
                else
                {
                    if (update.enabled)
                    {
                        if ($field.hasClass("FCBRBS"))
                        {
                            $field.find("input").removeAttr("disabled");
                        }
                        else if ($field.is("select"))
                        {
                            $field.removeAttr("disabled");
                        }
                        else if ($field.is(".FastCheckboxButton,.FastRadioButtonButton"))
                        {
                            $field.removeAttr("disabled");
                        }
                        else if ($field.is(":checkbox,:radio"))
                        {
                            if (_fwdc.tap)
                            {
                                $field.removeAttr("disabled");
                            }
                        }
                        else if ($field.hasClass("DocControlSlider"))
                        {
                            $field.removeAttr("disabled");
                        }
                        else if ($field.hasClass("DocControlDatepicker") || $field.hasClass("DocControlDatepickerCombo"))
                        {
                            $field.datepicker("option", "disabled", !update.enabled);
                        }
                        else
                        {
                            if (_fwdc.tap)
                            {
                                $field.removeAttr("disabled");
                            }
                            else
                            {
                                $field.removeAttr("readonly");
                            }
                        }
                    }
                    else
                    {
                        if ($field.hasClass("FCBRBS"))
                        {
                            $field.find("input").attr("disabled", "disabled");
                        }
                        else if ($field.is("select"))
                        {
                            $field.attr("disabled", "disabled");
                        }
                        else if ($field.is(".FastCheckboxButton,.FastRadioButtonButton"))
                        {
                            $field.attr("disabled", "disabled");
                        }
                        else if ($field.is(":checkbox,:radio"))
                        {
                            if (_fwdc.tap)
                            {
                                $field.attr("disabled", "disabled");
                            }
                        }
                        else if ($field.hasClass("DocControlSlider"))
                        {
                            $field.attr("disabled", "disabled");
                        }
                        else if ($field.hasClass("DocControlDatepicker") || $field.hasClass("DocControlDatepickerCombo"))
                        {
                            $field.datepicker("option", "disabled", !update.enabled);
                        }
                        else
                        {
                            if (_fwdc.tap)
                            {
                                $field.attr("disabled", "disabled");
                            }
                            else
                            {
                                $field.attr("readonly", "readonly");
                            }
                        }
                    }

                    if ($field.hasClass("FastCodeMirrorBox"))
                    {
                        cm = $field.data("fastCodeMirrorEditor");
                        if (cm && cm.options)
                        {
                            cm.options.readOnly = !update.enabled;
                        }
                    }
                }

                if ($field.data("uiControlgroup"))
                {
                    $field.buttonset("refresh");
                }
                else if ($field.hasClass("FCBRBS"))
                {
                    var $buttonset = $field.children(".fast-ui-buttonset");
                    if ($buttonset && $buttonset.length && $buttonset.data("uiButtonset"))
                    {
                        $buttonset.buttonset("refresh");
                    }
                }
                else if ($field.data("uiButton"))
                {
                    $field.button("refresh");
                }
                else if ($field.data("uiCheckboxradio"))
                {
                    $field.checkboxradio("refresh");
                }
                else if ($field.hasClass("DocAttachmentInput") || $field.hasClass("CellAttachment"))
                {
                    var $upload = $field.find(".DocAttachmentUpload");
                    if (update.enabled)
                    {
                        $upload.removeAttr("disabled");
                    }
                    else
                    {
                        $upload.attr("disabled", "disabled");
                    }
                }
            }

            if (update.tabindex !== undefined)
            {
                var $tabElement = $field;
                if ($field.hasClass("FCBRBS"))
                {
                    $field.find("input").attr("tabindex", update.tabindex);
                }
                else
                {
                    if ($field.is("label,div,span"))
                    {
                        $tabElement = $field.find("input,select,textarea,a");
                    }
                    $field.attr("tabindex", update.tabindex);
                }
            }

            if (update.linkenabled !== undefined)
            {
                var $link = ($field && $field.length && $field.is("button"))
                    ? $field
                    : _fwdc.currentDocumentContainer().find("#l_" + fieldSelector + ",#cl_" + fieldSelector);

                var fieldIsLink = $field.equals($link);
                if ($link && $link.length > 0)
                {
                    if (update.linkenabled)
                    {
                        $link.removeClass("DisabledLink EnabledLink").addClass("EnabledLink");

                        if ($link.attr("data-tabindex"))
                        {
                            $link.attr("tabindex", $link.attr("data-tabindex"));
                            $link.removeAttr("data-tabindex");
                        }
                        //else
                        //{
                        //    $link.removeAttr("tabindex");
                        //}

                        //if ($link.attr("data-role"))
                        //{
                        //    $link.attr("role", $link.attr("data-role"));
                        //    $link.removeAttr("data-role");
                        //}
                        //else if ($link.attr("role") === "presentation")
                        //{
                        //    $link.removeAttr("role");
                        //}

                        if ($link.attr("data-href"))
                        {
                            $link.attr("href", $link.attr("data-href"));
                            $link.removeAttr("data-href");
                        }

                        if (!fieldIsLink && $field.hasClass("DisabledLink")) { $field.removeClass("DisabledLink").addClass("EnabledLink"); }
                    }
                    else
                    {
                        $link.removeClass("DisabledLink EnabledLink").addClass("DisabledLink");

                        if ($link.attr("tabindex"))
                        {
                            $link.attr("data-tabindex", $link.attr("tabindex"));
                            $link.removeAttr("tabindex");
                        }

                        //if ($link.attr("role"))
                        //{
                        //    $link.attr("data-role", $link.attr("role"));
                        //}
                        //$link.attr("role", "presentation");

                        if ($link.attr("href"))
                        {
                            $link.attr("data-href", $link.attr("href"));
                            $link.removeAttr("href");
                        }

                        if (!fieldIsLink && $field.hasClass("EnabledLink")) { $field.removeClass("EnabledLink").addClass("DisabledLink"); }
                    }

                    if ($link.is("button"))
                    {
                        if (update.linkenabled)
                        {
                            $link.removeAttr("disabled");
                        }
                        else
                        {
                            $link.attr("disabled", "disabled");
                        }
                    }
                    else if ($link.data("uiButton"))
                    {
                        $link.button("refresh");
                    }
                }
                else if ($field && $field.length && $field.is("button"))
                {
                    if (update.linkenabled)
                    {
                        $fieldContainerElement.css("display", "");
                    }
                    else
                    {
                        $fieldContainerElement.css("display", "none");
                    }
                }
            }

            if (update.visible !== undefined)
            {
                _setRecalcResizeRequired();

                if ($fieldContainerElement)
                {
                    if (update.visible)
                    {
                        $fieldContainerElement.removeClass("Hidden");
                    }
                    else
                    {
                        $fieldContainerElement.addClass("Hidden");
                    }

                    var $flexgrid = $fieldContainerElement.closest(".FlexGridContainer");
                    if ($flexgrid.length)
                    {
                        _fwdc.checkFlexGridRowVisibility($flexgrid);
                    }
                }

                if (update.visible)
                {
                    if ($field.hasClass("FCBRBS"))
                    {
                        if (_fwdc.setupButtonSets(null, $field))
                        {
                            _recalcHtmlUpdated = true;
                        }
                    }
                    else if ($fieldContainerElement.hasClass("VSView"))
                    {
                        _fwdc.setupViewStacks();
                        var $cmFields = $field.find(".FastCodeMirrorBox");
                        $cmFields.each(function (index, cmField)
                        {
                            cm = $(cmField).data("fast-code-mirror-editor");
                            if (cm)
                            {
                                cm.fast_refresh(true);
                            }
                        });

                        var $richText = $field.find(".HasCKEditor");
                        $richText.each(function (index, rtField)
                        {
                            var richTextBox = $(rtField).ckeditorGet();
                            richTextBox.fwdc_resetSize();
                        });

                        if (_fwdc.setupButtonSets($fieldContainerElement))
                        {
                            _recalcHtmlUpdated = true;
                        }

                        if (_fwdc.setupCheckboxButtons($fieldContainerElement))
                        {
                            _recalcHtmlUpdated = true;
                        }

                        //_fwdc.setupTableStickyElements($fieldContainerElement);
                    }
                    else if ($field.hasClass("FastCodeMirrorBox"))
                    {
                        cm = $field.data("fast-code-mirror-editor");
                        if (cm)
                        {
                            cm.fast_refresh(true);
                        }
                    }
                    else if ($field.hasClass("HasCKEditor"))
                    {
                        var richTextBox = $field.ckeditorGet();
                        richTextBox.fwdc_resetSize();
                    }
                    else if ($field.is("input.FastCheckboxButton,input.FastRadioButtonButton"))
                    {
                        if (_fwdc.setupCheckboxButtons($fieldContainerElement))
                        {
                            _recalcHtmlUpdated = true;
                        }
                    }
                }
                else
                {
                    // If the focused element has been hidden because of a visibility toggle, attempt to move the focus to the next input field.
                    if (window && window.document && window.document.activeElement && !$(window.document.activeElement).is(":visible"))
                    {
                        $(window.document.activeElement).focusNextInputField();
                    }
                }
            }

            if (update.caption1 !== undefined)
            {
                var fieldCaption1Element = _fwdc.formField("caption1_" + fieldSelector);
                if (fieldCaption1Element)
                {
                    fieldCaption1Element.html(update.caption1);
                    _recalcHtmlUpdated = true;
                }
            }

            if (update.caption2 !== undefined)
            {
                var fieldCaption2Element = _fwdc.formField("caption2_" + fieldSelector);
                if (fieldCaption2Element)
                {
                    //var syntaxHighlight = fieldCaption2Element.hasClass("FastSyntaxHighlighted");
                    var syntaxHighlightMode = fieldCaption2Element.data("fast-higlighted-mode");
                    fieldCaption2Element.html(update.caption2);

                    if (syntaxHighlightMode)
                    {
                        _fwdc.setupSyntaxHighlight(fieldId, syntaxHighlightMode);
                    }

                    if (fieldCaption2Element.parent(".CGVAlignStretch").length)
                    {
                        _setRecalcResizeRequired();
                    }
                    _recalcHtmlUpdated = true;
                }
                else if ($field && $field.data("fast-caption-watermark"))
                {
                    FWDC.watermark($field, update.caption2);
                }
                else if ($field && $field.data("watermark"))
                {
                    $field.watermark(update.caption2 + "  ");
                }

                var $fieldAccessibleCaption = _fwdc.formField("ca_" + fieldSelector);
                if ($fieldAccessibleCaption)
                {
                    $fieldAccessibleCaption.html(update.caption2);
                }

                if ($field && $field.attr("aria-label") !== undefined)
                {
                    $field.attr("aria-label", _fwdc.htmlToText(update.caption2));
                }
            }

            if ((update.message !== undefined) || (update.messageclass !== undefined))
            {
                var fieldMessageElement = _fwdc.formField("msg_" + fieldSelector);
                if (fieldMessageElement)
                {
                    if (update.message !== undefined)
                    {
                        fieldMessageElement.text(update.message);
                    }
                    if (update.messageclass !== undefined)
                    {
                        fieldMessageElement.attr('class', update.messageclass);
                    }
                }
            }

            if (update.tooltip !== undefined)
            {
                $field.attr("title", update.tooltip);
                if ($bgElement !== $field) { $bgElement.attr("title", update.tooltip); }
                if ($indicator) { $indicator.attr("title", update.tooltip); }
                if ($field.data("ui-button"))
                {
                    $field.button("widget").attr("title", update.tooltip);
                }

                if (isCell && !$field.hasClass("DCT"))
                {
                    $field.querySelectorAll(".DCT").attr("title", update.tooltip);
                }
            }

            if (update.statuscolor !== undefined)
            {
                var $statusElement = $field.tagIs("button") ? $field : $fieldContainerElement;

                var fieldClasses = $statusElement.attr("class") || "";

                fieldClasses = fieldClasses.replace(/\bFastStatusColor\w+\s*/, "") + " FastStatusColor" + update.statuscolor;

                $statusElement.attr("class", fieldClasses);
            }

            if (update.watermark !== undefined && $field && !$field.data("fast-caption-watermark"))
            {
                FWDC.watermark($field, update.watermark);
            }

            if (update.attributes)
            {
                $.each(update.attributes, function (attr, val)
                {
                    var func = _fwdc.fieldAttributeUpdates[attr] || _fwdc.fieldAttributeUpdates.unknown;
                    //$field.attr("data-" + attr, val);
                    func($field, attr, val);
                });
            }
        }

        function _getQTipCloseButton()
        {
            // Build a tooltip-less QTip2 close button.
            return $('<button></button>', {
                'class': 'qtip-close qtip-icon'
                //'aria-label': _fwdc.getDecode("Close")
            }).text(_fwdc.getDecode("Close"));
        }

        function _showDecodeTip(element, code)
        {
            var $element = $(element);

            _fwdc.ajax({
                url: '../StandardDecode/' + encodeURIComponent(code),
                type: 'GET',
                success: function (response, status, request)
                {
                    if (response.caption)
                    {
                        if ($element.data("qtip"))
                        {
                            $element.qtip("destroy");
                        }
                        $element.data("fast-decode-tip-" + code, true);
                        $element.qtip({
                            content:
                            {
                                text: response.caption
                            },
                            container: _fwdc.$window,
                            style: { classes: "DecodeTip" + code },
                            events: {
                                hide: function (event, api)
                                {
                                    $element.removeData("fast-decode-tip-" + code);
                                    api.destroy();
                                }
                            }
                        }).qtip("show");

                    }
                }
            });

            return false;
        }

        function _recalc(options)
        {
            _inRecalc = true;
            _recalcResizeRequired = false;
            _recalcScrollPositions = null;

            options = options || {};

            var sourceId = "";
            if (options.source)
            {
                sourceId = _getFieldId(options.source);
            }

            var $form = null;
            if (sourceId && sourceId.startsWith("CTX-"))
            {
                $form = $("#CONTEXT_LOG_CONTAINER__").find(".ContextLogDocumentForm");
            }

            var extraData = options.extraData;
            var data = (options.data || _fwdc.getDocPostParameters(extraData, null, $form));

            var trigger = "";

            if (options.trigger)
            {
                trigger += options.trigger;
            }

            var result = _fwdc.ajax({
                url: 'Recalc',
                async: !!options.async,
                busy: !!options.async,
                checkBusy: true,
                commitEdits: false,
                data: data,
                trigger: trigger,
                //sender: options.source,
                sourceId: sourceId,
                success: function (data, status, request)
                {
                    _handleRecalcUpdates(data);
                },
                complete: function ()
                {
                    _inRecalc = false;

                    if (options.callback) { options.callback(); }
                }
            });

            if (!result)
            {
                _inRecalc = false;
            }

            return !!result;
        }

        _fwdc.recalc = _recalc;

        function _handleRecalcUpdates(data, callback)
        {
            _recalcHtmlUpdated = false;
            _recalcVisibleViewsUpdated = false;
            _recalcDocUpdated = false;
            _fwdc.runResponseFunctions(data, false);
            //_fwdc.saveScrollPositions();
            if (data.ChangeView)
            {
                _fwdc.viewLinkClicked({ fieldId: data.ChangeView, force: true, server: true, trigger: "RecalcUpdates.ChangeView" });
            }
            else if (data.html)
            {
                _recalcHtmlUpdated = true;
                _recalcDocUpdated = true;
                _fwdc.setCurrentManagerHtml(data.html, false, false, true, true);
                _fwdc.focusCurrentField();
            }
            else if (data.dochtml)
            {
                _recalcHtmlUpdated = true;
                _recalcDocUpdated = true;
                _fwdc.setCurrentDocHtml(data.dochtml, true, true);
                _fwdc.focusCurrentField();
            }
            else
            {
                var updates = data.Updates;
                if (updates)
                {
                    var ii;
                    if (updates.GroupUpdates)
                    {
                        for (ii = 0; ii < updates.GroupUpdates.length; ii++)
                        {
                            _updateDocGroup(updates.GroupUpdates[ii]);
                        }
                    }

                    if (updates.ViewUpdates)
                    {
                        for (ii = 0; ii < updates.ViewUpdates.length; ii++)
                        {
                            _updateDocView(updates.ViewUpdates[ii]);
                        }
                    }

                    if (updates.RowSelectorUpdates)
                    {
                        for (ii = 0; ii < updates.RowSelectorUpdates.length; ii++)
                        {
                            _updateDocRowSelector(updates.RowSelectorUpdates[ii]);
                        }
                    }

                    if (updates.ImageUpdates)
                    {
                        for (ii = 0; ii < updates.ImageUpdates.length; ii++)
                        {
                            _updateDocImage(updates.ImageUpdates[ii]);
                        }
                    }

                    if (updates.FieldUpdates)
                    {
                        $.watermark.hideAll();
                        $.watermark.locked = true;
                        for (ii = 0; ii < updates.FieldUpdates.length; ii++)
                        {
                            _updateDocField(updates.FieldUpdates[ii]);
                        }
                        $.watermark.locked = false;
                        $.watermark.showAll(true);
                    }

                    if (updates.ResetSqlFields && _fwdc.resetSqlField)
                    {
                        for (ii = 0; ii < updates.ResetSqlFields.length; ii++)
                        {
                            _fwdc.resetSqlField(updates.ResetSqlFields[ii]);
                        }
                    }
                }

                if (data.Message)
                {
                    setTimeout(function () { FWDC.messageBox(data.Message); }, 1);
                }
            }
            _fwdc.runResponseFunctions(data, true);

            if (data.Updates && data.Updates.RecalcScripts)
            {
                _fwdc.currentDocumentContainer().append(data.Updates.RecalcScripts);
            }

            if (_recalcVisibleViewsUpdated)
            {
                /* Do not allow this to be updated real-time.  It relies on some specific configuration and should not be used on dynamically changing views.
         
                var $groupedTabSets = _fwdc.currentDocumentContainer().find(".InnerTabSet");
         
                $groupedTabSets.each(function ()
                {
                    var $viewTabSet = $(this);
                    var $tabContainer = $viewTabSet.parent();
         
                    var $visibleViews = $viewTabSet.children(".ViewSelector").not(".ViewHidden");
         
                    if ($visibleViews.length)
                    {
                        $tabContainer.removeClass("DocSingleGroupView");
                    }
                    else
                    {
                        $tabContainer.addClass("DocSingleGroupView");
                    }
                });*/

                _recalcVisibleViewsUpdated = false;
            }

            if (_recalcTableUpdate || _recalcResizeRequired)
            {
                _fwdc.setupControls(null, true);
            }

            if (_recalcTableUpdate)
            {
                _setupSortableTables();
                _recalcTableUpdate = false;
            }

            if (_recalcResizeRequired)
            {
                _fwdc.resizeElements();
                _fwdc.sizeContentModals();
                FWDC.checkFieldTipPositions(true);
                _fwdc.restoreScrollPositions(_recalcScrollPositions);
                _recalcScrollPositions = null;
                _recalcHtmlUpdated = true;
            }

            _fwdc.showCurrentFieldTip(true);

            if (_recalcHtmlUpdated)
            {
                _fwdc.updateScreenReader();
                _fwdc.checkHeaderLinks(true);
            }

            if (FWDC.resumeAutoRefresh)
            {
                FWDC.resumeAutoRefresh();
            }

            if (callback) { callback(); }
        }

        function _editingCell()
        {
            return _$currentEditCell && _$currentEditor && true;
        }

        function _endEditCell(commit, checkbox)
        {
            if (_$currentEditCell && _$currentEditor)
            {
                //console.trace("_endEditCell", _$currentEditCell[0]);

                //_clearCurrentField(_$currentEditor[0]);
                var $currentEditor = _$currentEditor;
                var $currentEditContents = _$currentEditContents;
                var $currentEditCell = _$currentEditCell;
                var $currentEditCellContainer = _$currentEditCellContainer;
                var currentCellType = _currentCellType;

                _$currentEditor = null;
                _$currentEditContents = null;
                _$currentEditCell = null;
                _currentCellElement = null;
                _$currentEditCellContainer = null;

                //$currentEditCellContainer.removeClass("HasEditor");
                $currentEditCell.removeClass("CellEditing CellHasEditor");
                $currentEditor.removeClass("CellEditing");

                var mask = $currentEditor.data("fast-mask");
                if (mask) { mask = mask.mask; }
                var value;
                var text;
                switch (currentCellType)
                {
                    case "CellCheckbox":
                    case "CellRadioButton":
                        value = $currentEditor.is(":checked");
                        if (!checkbox)
                        {
                            return true;
                        }
                        break;

                    case "CellAttachment":
                        value = "";
                        return true;

                    case "CellCombobox":
                        if (_mobileBrowser || _tabletBrowser)
                        {
                            value = $currentEditor.val();
                            text = $currentEditor.children(":selected").first().text();

                            if (value === null) { value = ""; }
                            if (text === null) { text = ""; }
                        }
                        else
                        {
                            value = $currentEditor.data("fast-combo-value");
                            text = $currentEditor.data("fast-combo-text");
                            if ($currentEditor.data("uiAutocomplete"))
                            {
                                $currentEditor.autocomplete("destroy");
                            }
                            $currentEditor.val(text);
                        }
                        break;

                    case "CellTextMultiline":
                        value = _fwdc.textToHtml($currentEditor.val()).replace(/\r\n|\r|\n/gi, "<br>");
                        text = $currentEditor.val();
                        break;

                    case "CellTextRichText":
                        var editor = $currentEditor.ckeditorGet();
                        editor.updateElement();
                        value = $currentEditor.val();
                        text = value;
                        editor.destroy();
                        break;

                    default:
                        if (currentCellType === "CellMask")
                        {
                            $currentEditor.clearMask();
                        }
                        value = $currentEditor.val();
                        text = $currentEditor.val();
                }

                if (!checkbox)
                {
                    // Prevent a crash issue in IE11 and Edge that
                    // can be caused by the Spell Checker sending
                    // events to an element that has been removed.
                    $currentEditor.blur().attr("disabled", "disabled").remove();

                    //// The new focus edit model is tricky in IE, we delay removing the field to let focus move first.
                    //var $remove = $currentEditor;
                    //window.setTimeout(function ()
                    //{
                    //    $remove.remove();
                    //}, 0);
                }

                if (text === undefined || text === null) { text = ""; }
                if (value === undefined || value === null) { value = ""; }

                var $indicator = $currentEditCellContainer.childrenWithClass("FI").remove();

                var id = $currentEditCell.attr("id");

                if (id && commit && (value !== _lastFieldValue || text !== _lastFieldText))
                {
                    switch (currentCellType)
                    {
                        case "CellCheckbox":
                        case "CellRadioButton":
                            break;

                        case "CellCombobox":
                            $currentEditContents.text(text);
                            break;

                        case "CellTextMultiline":
                            $currentEditContents.html(value);
                            value = text;
                            break;

                        case "CellTextRichText":
                            $currentEditContents.html(value);
                            break;

                        default:
                            $currentEditContents.text(value);
                            break;
                    }

                    if ($indicator && $indicator.length)
                    {
                        $indicator.appendTo($currentEditContents);
                    }

                    var recalcData = {};

                    // SQL Fields have a JSON data format - This should probably be centralized.
                    if ($currentEditCell.hasClass("CellTextSql"))
                    {
                        recalcData[id] = JSON.stringify({
                            "value": value
                        });
                    }
                    else
                    {
                        recalcData[id] = value;
                    }

                    recalcData = _fwdc.getDocPostParameters(recalcData, "input[type='hidden']");
                    _recalc({ 'data': recalcData, 'source': $currentEditCell, 'trigger': 'EndEditCell' });

                    switch (currentCellType)
                    {
                        case "CellCheckbox":
                        case "CellRadioButton":
                        case "CellAttachment":
                            break;
                        default:
                            if (mask)
                            {
                                $currentEditContents.text($.fastMask.maskString(mask, $currentEditCell.text(), true));

                                if ($indicator && $indicator.length)
                                {
                                    $indicator.appendTo($currentEditContents);
                                }
                            }
                            $currentEditCell.css('padding', '');
                            $currentEditCellContainer.css('padding', '');
                    }
                }
                else
                {
                    switch (currentCellType)
                    {
                        case "CellCheckbox":
                        case "CellRadioButton":
                        case "CellAttachment":
                            break;

                        case "CellCombobox":
                            $currentEditContents.text(_lastFieldText);
                            $currentEditCell.css('padding', '');
                            $currentEditCellContainer.css('padding', '');
                            break;

                        case "CellTextMultiline":
                            $currentEditContents.html(_lastFieldValue);
                            $currentEditCell.css('padding', '');
                            $currentEditCellContainer.css('padding', '');
                            break;

                        case 'CellTextRichText':
                            $currentEditContents.html(_lastFieldValue);
                            $currentEditCell.css('padding', '');
                            $currentEditCellContainer.css('padding', '');
                            break;

                        default:
                            $currentEditContents.text(_lastFieldValue);
                            $currentEditCell.css('padding', '');
                            $currentEditCellContainer.css('padding', '');
                            break;
                    }

                    if ($indicator && $indicator.length)
                    {
                        $indicator.appendTo($currentEditContents);
                    }
                }

                $currentEditCellContainer.remove();

                _clearCurrentField($currentEditor[0]);

                _fwdc.showCurrentFieldTip();

                return true;
            }

            return false;
        }

        function _onHelpElementMouseDown(event)
        {
            if (_busy() || !event || event.which !== 1) { return false; }

            var $element = $(event.target);
            if (!$element.hasClass("DocHelpElement"))
            {
                $element = $element.closest(".DocHelpElement");
                if ($element.length === 0) { return true; }
            }

            event.stopPropagation();
            event.preventDefault();
            event.stopImmediatePropagation();

            _fwdc.getData("", "Help", $element.attr("data-help-id") || $element.attr("data-id") || $element.attr("id"), "json", true, null, function (data)
            {
                if (data)
                {
                    try
                    {
                        $element.qtip({
                            content:
                            {
                                text: data.tip,
                                title:
                                {
                                    text: data.caption,
                                    button: _getQTipCloseButton()
                                }
                            },
                            container: _fwdc.$window,
                            position:
                            {
                                target: [event.pageX, event.pageY]
                            },
                            events:
                            {
                                hide: function (event, api)
                                {
                                    api.destroy();
                                }
                            }
                        }).qtip("show");
                    }
                    catch (ex)
                    {
                        /* This can fail in IE <9 */
                    }
                }
            });

            return false;
        }

        function _onTableFocused(event)
        {
            var $target = $(event.target);

            if (!_fwdc.ignoreTableFocus && $target.is("tbody.DocTableBody") && (_keyEvent || _setFocus))
            {
                if (_$currentEditor && _$currentEditor.closest($target).equals($target))
                {
                    _$currentEditor.focus();
                    return true;
                }

                var $cell = _filterEditFocusCells($target.findElementsByClassName("TCE"));

                if ($cell && $cell.length)
                {
                    if (_focusBackwards)
                    {
                        $cell = $cell.last();
                    }
                    else
                    {
                        $cell = $cell.first();
                    }

                    // Work around an issue where sometimes the focus logic continues and re-focuses the tbody after the cell editor is started.
                    _fwdc.setTimeout("Delayed table focus", function ()
                    {
                        _fwdc.beginEditCell($cell[0], true);
                    });

                    return _fwdc.stopEvent(event);
                }
            }
        }

        function _onMaxlengthTextareaKeypress(event)
        {
            var key = event.which;

            //all keys including return.
            if (key >= 32 || key === 13)
            {
                var textarea = event.target;
                var $textarea = $(event.target);

                var maxLength = $textarea.attr("data-maxlength");
                var length = textarea.value.length;
                if (length >= maxLength)
                {
                    event.preventDefault();
                }
            }
        }

        function _onMaxlengthTextareaPaste(event)
        {
            setTimeout(function ()
            {
                var $textarea = $(event.target);
                var maxLength = $textarea.attr("data-maxlength");
                var length = $textarea.val().length;
                if (length > maxLength)
                {
                    $textarea.val($textarea.val().substring(0, maxLength));
                }
            }, 0);
        }

        function _onDocumentKeyDown(event)
        {
            _fwdc.onUserActivity();

            _focusBackwards = event.shiftKey && (event.which === _fwdc.keyCodes.TAB);
            _keyEvent = true;

            if (event.altKey && event.which >= 65 && event.which <= 90)
            {
                var result = false;

                var $searchContainer = _fwdc.currentDialogContainer();
                var isDialog = true;

                if (!$searchContainer || !$searchContainer.length)
                {
                    $searchContainer = _fwdc.$body();
                    isDialog = false;
                }

                var documentContainer = $searchContainer.find(_fwdc.selectors.documentContainer).last();
                if (documentContainer && documentContainer.length)
                {
                    if (_fwdc.onMnemonicKeyDown(event, documentContainer[0]))
                    {
                        result = true;
                    }
                    else
                    {
                        var managerContainer = $searchContainer.find(".ManagerContainer").last();
                        if (managerContainer && managerContainer.length)
                        {
                            if (_fwdc.onMnemonicKeyDown(event, managerContainer[0]))
                            {
                                result = true;
                            }
                        }
                    }
                }

                if (result)
                {
                    event.preventDefault();
                    event.stopImmediatePropagation();
                    return result;
                }
            }

            if (event.which === 27)
            {
                $(".qtip").qtip("hide", event);
            }
        }

        function _onDocumentMouseDown(event)
        {
            _focusBackwards = false;
            _keyEvent = false;

            if (_busy(true))
            {
                return false;
            }

            _fwdc.onUserActivity({ event: "DocumentMouseDown" });

            var $element = $(event.target);

            var $cell = $element.closest("td.CellEditable♠");
            var blnCellEditor = !!$element.closest(".CellEditorContainer").length;
            var blnCell = $cell.length === 1;
            var blnDatepicker = $element.closest(".ui-datepicker").length > 0;
            var isComboItem = $element.closest(".ui-autocomplete").length > 0;
            var editorDialog = $element.closest(".cke_dialog").length > 0;
            var fieldTip = $element.closest(".FieldTipIcon").length > 0;
            var endedEdit = false;

            if ($element.attr("tagName") !== "OPTION"
                && !blnDatepicker
                && !isComboItem
                && !editorDialog
                && !blnCellEditor
                && !fieldTip
                && (!blnCell
                    || !_$currentEditCell
                    || !$cell.equals(_$currentEditCell)))
            {
                endedEdit = _endEditCell(true);
            }

            if ($element.closest("#FlowMenu").length === 0)
            {
                _hideFlowMenu();
            }

            // Forced focus workaround for IE 11 failing to focus the cell on click when clearing editing another cell.
            if (endedEdit
                && document.activeElement !== event.target
                && $element.tagIs("TD")
                && $element.hasClass("TCE"))
            {
                $element.focus();
                // We need to stop the event so it doesn't complete a click and move the selection inside the input after the editor is created.
                if ($element.equals(_$currentEditCell))
                {
                    return _fwdc.stopEvent(event);
                }
            }
        }

        //var _inEditableCellClick;
        //function _onEditableCellClick(event)
        //{
        //    if (_inEditableCellClick) { return; }

        //    if (_busy())
        //    {
        //        return _fwdc.stopEvent(event);
        //    }

        //    if (!_fwdc.isNormalClick(event)) { return; }

        //    var $target = $(event.target);
        //    if ($target.hasClass("FastToggleDisplay"))
        //    {
        //        //$target = $target.parent();
        //        _fwdc.beginEditCell($target.closest("td"));
        //        event.stopImmediatePropagation();
        //        return;
        //    }

        //    var $input;
        //    if (($target.is("input[type='checkbox'],input[type='radio']") && ($input = $target)) ||
        //        ($target.is("label") && ($input = $target.find("input[type='checkbox'],input[type='radio']")) && $input.length))
        //    {
        //        var $cell = $target.closest("td");
        //        var enabled = $cell.is(".FieldEnabled");

        //        if (enabled && !$target.is("input"))
        //        {
        //            //var id = $cell.attr("id");
        //            _fwdc.stopEvent(event);
        //            _inEditableCellClick = true;
        //            $input.click();
        //            _inEditableCellClick = false;
        //            //_fwdc.beginEditCell(_fwdc.formField(id, true));

        //        }
        //        else if ($cell.length)
        //        {
        //            _fwdc.beginEditCell($cell);
        //        }
        //        return;
        //    }

        //    if (_fwdc.beginEditCell(event.currentTarget))
        //    {
        //        _fwdc.stopEvent(event);
        //    }
        //}

        function _onPasswordKeyPress(event)
        {
            var chr = String.fromCharCode(event.which);
            var $input = $(event.currentTarget);

            var shift = event.shiftKey;

            if ((!shift && chr.toUpperCase() === chr && chr.toLowerCase() !== chr) || (shift && chr.toLowerCase() === chr && chr.toUpperCase() !== chr))
            {
                if (!$input.data("qtip"))
                {
                    _showDecodeTip($input, "CapsLockOn");
                }
            }
            else if ($input.data("fast-decode-tip-CapsLockOn"))
            {
                $input.qtip("destroy");
            }
        }

        function _onPasswordLostFocus(event)
        {
            _fwdc.showCurrentFieldTip();
        }

        function _setCurrentRow($row)
        {
            /*if (!_$currentRow || !_$currentRow.equals($row))
            {
                if (_highlightUserSelectedRow($row))
                {
                    //_$currentRow = $row;
                    return true;
                }
            }*/

            return _highlightUserSelectedRow($row, false);
        }

        var _highlightUserSelectedRowHandle = null;
        function _highlightUserSelectedRow($row, async)
        {
            if (_highlightUserSelectedRowHandle)
            {
                _fwdc.clearTimeout("highlightUserSelectedRow", _highlightUserSelectedRowHandle);
                _highlightUserSelectedRowHandle = null;
            }

            var $table = $row.closest("table");
            if (!$table.hasClass("UserSelectable"))
            {
                return false;
            }

            // Template rows should adjust the TableHighlightCell class instead of the TableHighlightRow class.
            if ($row.hasClass("TTDR"))
            {
                var $tbody = $table.childrenWithClass("DocTableBody"); // Could return multiple body elements for outlined tables.

                _highlightUserSelectedRowHandle = _fwdc.setTimeout("highlightUserSelectedRow", function ($tbody, $row)
                {
                    $tbody.childrenWithClass("TTDR").childrenWithClass("TableHighlightCell").removeClass("TableHighlightCell");
                    $row.children().addClass("TableHighlightCell");
                }, async ? 200 : -1, $tbody, $row);

                return true;
            }
            else if (!$row.hasClass("TableHighlightRow"))
            {
                var $tbody = $table.childrenWithClass("DocTableBody"); // Could return multiple body elements for outlined tables.

                _highlightUserSelectedRowHandle = _fwdc.setTimeout("highlightUserSelectedRow", function ($tbody, $row)
                {
                    $tbody.childrenWithClass("TableHighlightRow").removeClass("TableHighlightRow");
                    $row.addClass("TableHighlightRow");
                }, async ? 200 : -1, $tbody, $row);

                return true;
            }

            return false;
        }

        /*function _onCellEditorFocus(event)
        {
            _setCurrentRow($(event.target).closest("tr"));
        }*/

        function _lockColumnWidths($container, $cols, unit)
        {
            var widths = {};

            var cssWidths = $cols.colsCssWidths();

            var $table = $container.findElementsByClassName("DocTable");

            $cols.each(function (ii)
            {
                var colClass = $(this).attr("data-colcls");
                var cssWidth = cssWidths[ii];
                // Prefer the existing pixel CSS if it exists, as outerWidth can be off by a pixel or two compared to the CSS.
                if (cssWidth.endsWith("px"))
                {
                    widths[colClass] = parseInt(cssWidth, 10); //$("th." + colClass, $container).outerWidth();
                }
                else
                {
                    // Use the column header from the table as the first one might be the sticky header version that could be hidden.
                    widths[colClass] = $("th." + colClass, $table).outerWidth();
                }
            });

            $.each(widths, function (colClass, width)
            {
                var $cols = $("col." + colClass, $container);
                $cols.css("width", width + _default(unit, "px"));
            });
        }

        function _startColumnResize(gripElement)
        {
            var $grip = $(gripElement);
            var colClass = $grip.attr("data-colcls");
            var $container = $grip.closest(".TableContainer");
            var $table = $container.find(".DocTable").not(".DocTableVirtualHeaders").first();
            var $virtualTable = $container.find(".DocTableVirtualHeaders").first();
            var $virtualTableContainer = $virtualTable.parent();
            var tableWidth = $table.outerWidth();
            var $th = $table.find("th." + colClass);
            var width = $th.outerWidth();

            if (isNaN(width) || isNaN(tableWidth)) { return false; }

            var $resizeTargetCols = $container.find("col." + colClass);
            var $modal = $container.closest(_fwdc.selectors.modalContainers);
            if (!$modal.length) { $modal = null; }

            if (!$resizeTargetCols || !$resizeTargetCols.length) { return false; }

            var $tableCols = $table.children("colgroup").children("col");

            var originalWidthsRaw = $tableCols.colsCssWidths();

            var originalStyles = {};
            var originalWidths = {};
            $tableCols.each(function (ii)
            {
                var $col = $(this);
                originalStyles[$col.attr("data-colcls")] = $col.attr("style");
                originalWidths[$col.attr("data-colcls")] = originalWidthsRaw[ii];
            });

            var $virtualCols = $container.children(".DocTableStickyHeader").children(".DocTableVirtualHeadersContainer").find("col");
            var $tableCol = $tableCols.filter("." + colClass);
            var resizeColIndex = $tableCol.index();

            var responsive = $table.hasClass("DocTableResponsive");

            var $pctCols = _fwdc.resetColumnPercentWidths($tableCols);
            _fwdc.resetColumnPercentWidths($virtualCols);

            var $adjustCols;
            var adjustHeaders;
            var adjustColsRatios;
            var adjustColsWidths;

            var originalWidth = width;

            if ($pctCols && $pctCols.length)
            {
                /*var $fixCols = $tableCols.slice(0, resizeColIndex + 1);
                _lockColumnWidths($container, $fixCols);*/

                $adjustCols = $tableCols.slice(resizeColIndex + 1);

                var $pctAdjustCols = _fwdc.findPercentColumns($adjustCols, true).$percentCols;
                if ($pctAdjustCols && $pctAdjustCols.length)
                {
                    $adjustCols = $pctAdjustCols;
                }

                _lockColumnWidths($container, $tableCols);

                if ($adjustCols.length)
                {
                    adjustHeaders = {};
                    adjustColsRatios = {};
                    adjustColsWidths = {};
                    var totalWidth = 0;
                    $adjustCols.each(function ()
                    {
                        var $col = $(this);
                        var colClass = $col.attr("data-colcls");
                        var $th = $col.closest("table").find("th." + colClass);
                        var width = $th.outerWidth();
                        adjustHeaders[colClass] = $th;
                        adjustColsRatios[colClass] = width;
                        adjustColsWidths[colClass] = width;
                        totalWidth += width;
                    });

                    $.each(adjustColsRatios, function (index, width)
                    {
                        if (totalWidth)
                        {
                            adjustColsRatios[index] = width / totalWidth;
                        }
                        else
                        {
                            adjustColsRatios[index] = 1 / $adjustCols.length;
                        }
                    });
                }

                _fwdc.resetColumnPercentWidths($tableCols.slice(resizeColIndex + 1));
                _fwdc.resetColumnPercentWidths($virtualCols.slice(resizeColIndex + 1));
            }

            return {
                $grip: $grip,
                colClass: colClass,
                $container: $container,
                $table: $table,
                responsive: responsive,
                tableWidth: tableWidth,
                $th: $th,
                originalWidth: originalWidth,
                originalStyles: originalStyles,
                originalWidths: originalWidths,
                $resizeTargetCols: $resizeTargetCols,
                resizeColIndex: resizeColIndex,
                $pctCols: $pctCols,
                $tableCols: $tableCols,
                $virtualTable: $virtualTable,
                $virtualTableContainer: $virtualTableContainer,
                $virtualCols: $virtualCols,
                $adjustCols: $adjustCols,
                adjustHeaders: adjustHeaders,
                adjustColsRatios: adjustColsRatios,
                adjustColsWidths: adjustColsWidths
            };
        }

        _fwdc.devGetTableColumnSizes = function ($element)
        {
            var $container = $element.closest(".TableContainer");
            var $table = $container.find(".DocTable").first();
            var $cols = $table.children("colgroup").children("col");

            var widths = {};
            var physicalWidths = {};

            var totalPercent = 0;
            var totalPx = 0;
            var totalPhysical = 0;

            $cols.each(function ()
            {
                var $col = $(this);

                var width = widths[$col.attr("data-colcls")] = $col.cssWidth();
                if (width.endsWith("%"))
                {
                    totalPercent += parseFloat(width);
                }
                else if (width.endsWith("px"))
                {
                    totalPx += parseFloat(width);
                }

                var physicalWidth = physicalWidths[$col.attr("data-colcls")] = $table.find("th." + $col.attr("data-colcls")).outerWidth();
                totalPhysical += physicalWidth;
            });

            return {
                cssWidths: widths,
                physicalWidths: physicalWidths,
                tableWidth: $table.outerWidth(true),
                totalPercent: totalPercent,
                totalPx: totalPx,
                totalPhysical: totalPhysical
            };
        };

        function _applyColumnWidthChange(resizeInfo, newWidth)
        {
            var dWidth = newWidth - resizeInfo.originalWidth;
            var newTableWidth = resizeInfo.tableWidth + dWidth;

            var widthPx = newWidth + "px";
            resizeInfo.$resizeTargetCols.css({
                width: widthPx
            });

            if (!resizeInfo.responsive)
            {
                resizeInfo.$table.css("width", newTableWidth + "px");
                resizeInfo.$virtualTable.css("width", newTableWidth + "px");
            }

            if (resizeInfo.$adjustCols && resizeInfo.$adjustCols.length)
            {
                var availableWidth = dWidth;

                //var adjustments = { "Total": dWidth };
                for (var ii = 0; ii < resizeInfo.$adjustCols.length; ++ii)
                {
                    var $adjustCol = $(resizeInfo.$adjustCols[ii]);
                    var adjustClass = $adjustCol.attr("data-colcls");
                    var adjustWidth = resizeInfo.adjustColsWidths[adjustClass];
                    var adjustRatio = resizeInfo.adjustColsRatios[adjustClass];

                    var adjustment = 0;
                    if (ii === resizeInfo.$adjustCols.length - 1)
                    {
                        adjustment = availableWidth;
                        adjustWidth -= availableWidth;
                        availableWidth = 0;
                    }
                    else
                    {
                        adjustment = Math.ceil(adjustRatio * dWidth);
                        adjustWidth -= adjustment;
                        availableWidth -= adjustment;
                    }

                    //adjustments[adjustClass] = adjustRatio.toFixed(2) + ": " + adjustment;
                    resizeInfo.$container.find("col." + adjustClass).css("width", adjustWidth + "px");

                    if (availableWidth === 0)
                    {
                        break;
                    }
                }
            }

            if (resizeInfo.$virtualTableContainer && resizeInfo.$virtualTableContainer.length)
            {
                _fwdc.resizeVirtualHeaderRow(resizeInfo.$virtualTableContainer); //DocTableVirtualHeadersContainer
            }

            if (resizeInfo.$modal)
            {
                _fwdc.sizeContentModals(resizeInfo.$modal);
            }
        }

        function _applyTableResize(resizeInfo)
        {
            var newWidth = resizeInfo.$th.outerWidth();
            if (!isNaN(newWidth) && (resizeInfo.originalWidth !== newWidth))
            {
                if (resizeInfo.responsive)
                {
                    if (resizeInfo.$pctCols.length)
                    {
                        _lockColumnWidths(resizeInfo.$container, resizeInfo.$pctCols, "%");
                        _fwdc.resetColumnPercentWidths(resizeInfo.$tableCols);
                        _fwdc.resetColumnPercentWidths(resizeInfo.$virtualCols);
                    }

                    var widths = {};

                    var $cols = resizeInfo.$table.children("colgroup").children("col");
                    var colWidths = $cols.colsCssWidths();
                    $cols.each(function (ii)
                    {
                        var $col = $(this);
                        var colClass = $col.attr("data-colcls");
                        var $th = resizeInfo.$table.find("th." + colClass);

                        var style = $col.attr("style");
                        var originalStyle = resizeInfo.originalStyles[colClass];
                        var originalWidthCss = resizeInfo.originalWidths[colClass];
                        var newWidthCss = colWidths[ii];

                        // Submit the column width if it's the one being resized, the style attribute changed, the new CSS width is percentage, or the width has changed.
                        if (colClass === resizeInfo.colClass
                            || (style && style.indexOf("width") > -1 && originalStyle && style !== originalStyle)
                            || (newWidthCss && (newWidthCss.indexOf("%") > -1 || newWidthCss !== originalWidthCss)))
                        {
                            widths[$th.attr("data-id")] = newWidthCss;
                        }
                    });

                    //var thId = resizeInfo.$th.attr("id");
                    _fwdc.setPropertiesInternal(null, "", "ColumnSizes", resizeInfo.$th.attr("data-id"), true, { widths: JSON.stringify(widths) }, function ()
                    {
                    });

                    return true;
                }
                else
                {
                    //FWDC.setProperties("", "ColumnSize", resizeInfo.$th.attr("id"), { Width: Math.round(newWidth) });

                    _fwdc.setPropertiesInternal(null, "", "ColumnSize", resizeInfo.$th.attr("data-id"), true, { Width: Math.round(newWidth) });
                    return true;
                }
            }

            $.each(resizeInfo.originalStyles, function (colClass, style)
            {
                if (style)
                {
                    resizeInfo.$container.find("col." + colClass).attr("style", style);
                }
                else
                {
                    resizeInfo.$container.find("col." + colClass).removeAttr("style");
                }
            });
        }

        function _onColumnResizeMouseDown(event)
        {
            if (event.which !== 1) { return; }

            var resizeInfo;

            _fwdc.$document.on("mouseup.columnresize", function (event)
            {
                _fwdc.$body().removeClass("FastResizing");
                _fwdc.$document.off(".columnresize");

                if (resizeInfo)
                {
                    _applyTableResize(resizeInfo);
                }
            });

            var width;
            var minWidth;
            var mouseX = event.pageX;
            var eventTarget = event.currentTarget;

            _fwdc.$document.on("mousemove.columnresize", function (event)
            {
                if (!resizeInfo)
                {
                    resizeInfo = _startColumnResize(eventTarget);
                    width = resizeInfo.originalWidth;
                    minWidth = Math.min(resizeInfo.originalWidth, 25);
                    _fwdc.$body().addClass("FastResizing");
                }

                var dX = event.pageX - mouseX;
                if (dX !== 0)
                {
                    mouseX = event.pageX;

                    var newWidth = width + dX;
                    if (newWidth < minWidth)
                    {
                        dX += (minWidth - newWidth);
                        newWidth = minWidth;
                    }

                    width = Math.round(newWidth);

                    _applyColumnWidthChange(resizeInfo, width);
                }
            });

            _fwdc.stopEvent(event);
        }

        function _onColumnResizeDoubleClick(event)
        {
            if (event.which !== 1) { return; }

            var resizeInfo = _startColumnResize(event.currentTarget);
            if (!resizeInfo) { return; }

            var minWidth = Math.min(resizeInfo.originalWidth, 25);

            var $rows = resizeInfo.$table.children("tbody").children("tr.TDR,tr.OutlineHeader");
            var $cells = $rows.map(function ()
            {
                return $(this).children("td").get(resizeInfo.resizeColIndex);
            }).add(resizeInfo.$th);

            var newWidth = minWidth;

            $cells.each(function ()
            {
                var $cell = $(this);

                var sizes = _getCellContentSize($cell);

                // Currently doesn't make sense to modify the content structure to accommodate this special case.,
                // as _getCellContentSize is expecting to only find and calculate one item in the cell contents.
                // For now, this can be calculated separately from _getCellContentSize.
                var $contents = $cell.find(".SelectAllWrapper");
                if ($contents && $contents.length)
                {
                    sizes.contentWidth += $contents.outerWidth();
                }

                newWidth = Math.max(sizes.contentWidth + 7, newWidth);
            });

            newWidth = Math.round(Math.min(newWidth, Math.max(1000, resizeInfo.originalWidth)));

            if (newWidth !== resizeInfo.originalWidth)
            {
                /*var dX = newWidth - resizeInfo.originalWidth;
                resizeInfo.$resizeTargetCols.css({ width: newWidth + "px" });
         
                if (!resizeInfo.responsive)
                {
                    var newTableWidth = resizeInfo.tableWidth + dX;
                    resizeInfo.$table.css("width", newTableWidth + "px");
                    resizeInfo.$virtualTable.css("width", newTableWidth + "px");
                }*/

                _applyColumnWidthChange(resizeInfo, newWidth);

                _applyTableResize(resizeInfo);

                //FWDC.setProperties("", "ColumnSize", $th.attr("id"), { Width: newWidth });
            }

            event.preventDefault();
            event.stopPropagation();
        }

        function _getCellContentSize($cell)
        {
            var $contents = $cell.find(".DCL,.DSC,.DTColText");
            if (!$contents.length) { $contents = $cell; }

            return _fwdc.getElementContentSize($contents, $cell, true);
        }

        function _copyTextCss($source, $dest, structure, clear)
        {
            if (clear)
            {
                $dest.attr("style", "");
            }

            if (structure)
            {
                $dest.css("white-space", $source.css("white-space"));
                $dest.css("word-wrap", $source.css("word-wrap"));
                $dest.css("word-break", $source.css("word-break"));
            }

            $dest.css("font-family", $source.css("font-family"));
            $dest.css("font-size", $source.css("font-size"));
            $dest.css("font-weight", $source.css("font-weight"));
            $dest.css("font-style", $source.css("font-style"));
            $dest.css("text-align", $source.css("text-align"));
        }

        var _$cellMouseMeasurer;
        var _$cellMouseMeasurerContent;
        _fwdc.getElementContentSize = function ($contents, $container, includeContentSpace)
        {
            if (!_$cellMouseMeasurer)
            {
                _$cellMouseMeasurer = $('<div id="CellMouseMeasurer__"></div>').appendTo(_fwdc.supportElementsContainer());
                _$cellMouseMeasurerContent = $("<div></div>").appendTo(_$cellMouseMeasurer);
            }

            $container = $container || $contents;

            var whiteSpace = ($contents.css("white-space") || "normal").toLowerCase();

            var wrap = whiteSpace == "normal" || whiteSpace == "pre-wrap";

            var containerWidth = $container.innerWidth();

            var maxWidth = wrap ? (containerWidth + "px") : "none";

            _copyTextCss($contents, _$cellMouseMeasurerContent, true, true);
            if (includeContentSpace)
            {
                // Explicitly map all of the directional values as IE11 fails to report padding properly directly.
                _$cellMouseMeasurerContent.css({
                    "margin-top": $contents.css("margin-top"),
                    "margin-right": $contents.css("margin-right"),
                    "margin-bottom": $contents.css("margin-bottom"),
                    "margin-left": $contents.css("margin-left"),
                    "padding-top": $contents.css("padding-top"),
                    "padding-right": $contents.css("padding-right"),
                    "padding-bottom": $contents.css("padding-bottom"),
                    "padding-left": $contents.css("padding-left"),
                    "max-width": maxWidth,
                    "box-sizing": "border-box", // We need to be sure maxWidth doesn't go beyond existing content+padding
                    "white-space": whiteSpace
                });
            }
            else
            {
                _$cellMouseMeasurerContent.css({
                    "margin": "",
                    "padding": "",
                    "max-width": maxWidth,
                    "box-sizing": "border-box", // We need to be sure maxWidth doesn't go beyond existing content+padding
                    "white-space": whiteSpace
                });
            }

            _$cellMouseMeasurerContent.html($contents.html());

            var size = {
                contentWidth: _$cellMouseMeasurerContent.outerWidth(true),
                contentHeight: _$cellMouseMeasurerContent.outerHeight(true),
                cellWidth: containerWidth,
                cellHeight: $container.innerHeight(),
                wrap: wrap
            };

            // THIS MUST BE PUT BACK AFTER TESTING - WITHOUT THIS, REMAINING CONTENT CAN BE INPUTS OR OTHER PROBLEMATIC FIELDS.
            _$cellMouseMeasurerContent.empty();

            return size;
        };

        var _$largeCell;
        var _cellMouseEnterHandle;
        function _onCellMouseEnter(event)
        {
            if (_cellMouseEnterHandle)
            {
                _fwdc.clearTimeout("OnCellMouseEnter", _cellMouseEnterHandle);
                _cellMouseEnterHandle = null;
            }

            _cellMouseEnterHandle = _fwdc.setTimeout("OnCellMouseEnter", function (cell)
            {
                _cellMouseEnterHandle = null;

                var $cell = $(cell);

                if ($cell.attr("title")) { return; }

                // Use our .innerText instead of .text() so we can get newlines from the data.
                var text = $cell.innerText();

                if (text && text.length > 1)
                {
                    text = $.trim(text);
                    var sizes = _getCellContentSize($cell, text);

                    if (sizes.contentWidth > sizes.cellWidth)
                    {
                        _$largeCell = $cell.attr("title", text);
                    }
                }
            }, 10, event.currentTarget);
        }

        function _onCellMouseLeave(event)
        {
            if (_cellMouseEnterHandle)
            {
                _fwdc.clearTimeout("OnCellMouseLeave", _cellMouseEnterHandle);
                _cellMouseEnterHandle = null;
            }

            if (_$largeCell)
            {
                _$largeCell.removeAttr("title");
                _$largeCell = null;
            }
        }

        function _destroyTemporaryQtips(immediate)
        {
            var $tips = $(".qtip:not(.fast-qtip-persistent)");
            if ($tips && $tips.length)
            {
                // Disable links on the tip to prevent access while the tool tip animates away.
                _fwdc.disableChildLinks($tips);
                $tips.qtip("destroy", immediate);

                // Clear any existing tooltip fields.
                _toolTipFields = {};
                _toolTipTargets = {};
            }
        }

        function _getFieldId(field)
        {
            if (typeof field === "string")
            {
                return field;
            }

            var $field;
            if (field instanceof jQuery)
            {
                $field = field;
            }
            else
            {
                $field = $(field);
            }

            return $field.data("data-field-id") || $field.attr("id");
        }

        function _getFieldProperty(field, property, dataType, contents, values)
        {
            var value;
            var data = { FIELD__: field, PROPERTY__: property };
            if (contents !== undefined) { data.CONTENTS__ = contents; }
            if (values) { data.VALUES__ = values; }
            _fwdc.ajax({
                url: 'FieldProperty',
                async: false,
                busy: false,
                commitEdits: false,
                data: function ()
                {
                    return _fwdc.getDocPostParameters(data, "input[type='hidden']");
                },
                dataType: dataType || "json",
                hideErrors: true,
                success: function (data, status, request)
                {
                    value = data;
                }
            });

            return value;
        }

        var _beginEditSetCurrentRowHandle;

        function _onEditCellFocus(event)
        {
            var $cell = $(event.target);

            if ($cell.tagIs("td"))
            {
                _fwdc.beginEditCell($cell);
            }
        }

        function _repositionCellEditor()
        {
            //if (_$currentEditCellContainer && _$currentEditCell)
            //{
            //    var offset = _$currentEditCell.position();

            //    _$currentEditCellContainer
            //        .css({
            //            "top": Math.ceil(offset.top) + "px",
            //            "left": Math.ceil(offset.left) + "px"
            //        });
            //}
        }

        function _captureEditCellInfo($cell)
        {
            var cell = $cell[0];
            if (_currentCellElement === cell || !cell)
            {
                return;
            }

            //console.trace("_captureEditCellInfo", cell);

            _$currentEditCell = $cell;
            _currentCellElement = cell;

            // Cell IDs are expected to be docid-columnid-rownum
            var cellIdSplit = $cell.attr("id").split("-");

            // Assume the last piece is the row number. Prepend TC for the column class.
            _currentColumnId = cellIdSplit.slice(0, -1).join("-");
            _currentColumnClass = "TC-" + _currentColumnId;
            _currentDataRowNumber = parseInt(cellIdSplit[cellIdSplit.length - 1], 10);

            var cellClass = $cell.attr("class");

            _$currentTable = $cell.closest("table");
            _currentTableId = _$currentTable.attr("id");

            // Extract the row number from the cell table+row class (TR-TableID-RowNumber).
            var tableRowRegex = new RegExp("\\bTR-" + _currentTableId + "-(\\d+)\\b");
            var tableRowClassMatch = cellClass.match(tableRowRegex);
            _currentRowClass = tableRowClassMatch[0];
            _currentRowNumber = parseInt(tableRowClassMatch[1], 10);

            _$currentTableCells = _$currentTable.findElementsByAnyClassName("TCE");
            _currentTableCellIndex = _$currentTableCells.index(_currentCellElement);
            _currentTableInverted = _$currentTable.hasClass("DocTableInverted");
            _$currentRowCells = _$currentTableCells.filterHasClassName(_currentRowClass);
            _currentRowCellIndex = _$currentRowCells.index(_currentCellElement);
            _$currentColumnCells = _$currentTableCells.filterHasClassName(_currentColumnClass);
            _currentColumnCellIndex = _$currentColumnCells.index(_currentCellElement);
        }

        _fwdc.beginEditCell = function (cell, resume)
        {
            if (!cell) { return false; }

            var $cell = $(cell);
            if (!_fwdc.elementOnCurrentModal($cell))
            {
                return false;
            }

            if ($cell.equals(_$currentEditCell)) { return true; }

            if (_editingCell())
            {
                if (!_endEditCell(true))
                {
                    return false;
                }
            }
            else
            {
                _fwdc.commitEdits("beginEditCell", true);
            }

            if ($cell.hasClass("TDOV"))
            {
                return false;
            }

            //console.trace("beginEditCell", cell);

            _captureEditCellInfo($cell);

            var $link = $cell.findElementsByClassName("DCL");
            if ($link.length > 0)
            {
                $link.focusNative();
                return true;
            }

            //var $input = $cell.findElementsByClassName("TDI");
            //if ($input.length > 0)
            //{
            //    $input.focusNative();
            //    return true;
            //}

            //var $currentTableContainer = _$currentTable.parent();

            if ($cell.hasClass("CellEditable"))
            {
                if (_$currentEditCellContainer)
                {
                    _$currentEditCellContainer.remove();
                    _$currentEditCellContainer = null;
                }

                _$currentEditCellContainer = $($.parseHTML('<div class="CellEditorContainer"></div>'));

                var createdEditor = true;

                //_$currentEditCellContainer = $cell.children(".DTC");
                _$currentEditContents = $cell.hasClass("TDS") ? $cell : _fwdc.formField("c_" + $cell.attr("id"));

                var $row = $cell.parent("tr");

                if ($row.hasClass("TableInsertionRow"))
                {
                    _$currentEditCellContainer.addClass("InsertionRowEditor").removeClass("ExistingRowEditor");
                }
                else
                {
                    _$currentEditCellContainer.removeClass("InsertionRowEditor").addClass("ExistingRowEditor");
                }

                if (!_currentTableInverted)
                {
                    if (_setCurrentRow($row))
                    {
                        if (_beginEditSetCurrentRowHandle)
                        {
                            _fwdc.clearTimeout("BeginEditCellSelectRow", _beginEditSetCurrentRowHandle);
                            _beginEditSetCurrentRowHandle = null;
                        }

                        _beginEditSetCurrentRowHandle = _fwdc.setTimeout("BeginEditCellSelectRow", function ($row)
                        {
                            _fwdc.setUserSelectedRow($row, { force: true });
                            _beginEditSetCurrentRowHandle = null;
                        }, 0, $row);
                    }
                }

                var lastValue;
                var lastText;

                //var cellWidth = _$currentEditContents.innerWidth();
                var cellHeight = _$currentEditContents.innerHeight();

                if (_$currentEditContents.text() === "")
                {
                    // There might not be any content to prop up a wrapper span or div
                    var $spacer = $("<span>&nbsp;</span>").appendTo(_$currentEditContents);
                    cellHeight = _$currentEditContents.innerHeight();
                    $spacer.remove();
                }

                var cellPadding = _$currentEditContents.css("padding");
                var $indicator = $cell.findElementsByClassName("FI");

                var maxLength = $cell.attr("data-mxl");

                var maskProperties;
                if ($cell.hasClass("CellMask"))
                {
                    maskProperties = _getFieldProperty($cell.attr("id"), "mask");
                }

                $cell.addClass("CellEditing");

                if ($cell.hasClass("CellCheckbox") || $cell.hasClass("CellRadioButton"))
                {
                    _currentCellType = ($cell.hasClass("CellCheckbox") ? "CellCheckbox" : "CellRadioButton");
                    _$currentEditor = $cell.find("input").focusNative();
                    lastValue = _$currentEditor.is(":checked");
                    createdEditor = false;
                }
                else if ($cell.hasClass("CellAttachment"))
                {
                    _currentCellType = "CellAttachment";
                    _$currentEditor = $cell.find(".DocAttachmentCellInput");
                    lastValue = "";
                    createdEditor = false;
                }
                else if ($cell.hasClass("CellCombobox") || $cell.hasClass("CellUser"))
                {
                    _currentCellType = "CellCombobox";
                    lastValue = _$currentEditContents.text();
                    lastText = lastValue;

                    var data = _getFieldProperty($cell.attr("id"), "comboitems");
                    var items = (data && data.items) || [];
                    var hasDescription = data && data.hasDescription;
                    var value = "";
                    var text = "";

                    if (_mobileBrowser || _tabletBrowser)
                    {
                        _$currentEditor = $('<select></select>');

                        if (items)
                        {
                            $.each(items, function (index, item)
                            {
                                var $item = $("<option></option>").attr("value", item.value).text(item.label);
                                _$currentEditor.append($item);

                                if (item.selected)
                                {
                                    $item.attr("selected", "selected");
                                    lastValue = item.value;
                                    lastText = item.label;
                                    value = item.value;
                                    text = item.label;
                                }

                            });
                        }

                        _$currentEditCellContainer.empty().append(_$currentEditor);

                        _$currentEditor.change(function (sender, event)
                        {
                            _endEditCell(true, false);
                            _$currentTable = _fwdc.currentDocumentContainer().find("#" + _currentTableId);
                            _currentTableInverted = _$currentTable.hasClass("DocTableInverted");
                            _$currentRowCells = _$currentTable.find("td." + _currentRowClass);
                            _$currentColumnCells = _$currentTable.find("td." + _currentColumnClass);
                            var $newCell = _$currentRowCells.slice(_currentRowCellIndex, _currentRowCellIndex + 1);
                            _fwdc.beginEditCell($newCell, true);
                        });
                    }
                    else
                    {
                        _$currentEditor = $('<input type="text">').val(lastValue);

                        if (items)
                        {
                            var ii;
                            for (ii = 0; ii < items.length; ii++)
                            {
                                var item = items[ii];
                                if (item.selected)
                                {
                                    lastValue = item.value;
                                    lastText = item.label;
                                    value = item.value;
                                    text = item.label;
                                }
                            }
                        }

                        _$currentEditCellContainer.empty().append(_$currentEditor);

                        FWDC.setupCombobox({
                            field: _$currentEditor,
                            items: items,
                            value: value,
                            text: text,
                            hasDescription: hasDescription,
                            fieldId: _$currentEditCell.attr("id"),
                            isCell: true,
                            onSelect: function (event, ui)
                            {
                                if (event && event.originalEvent && event.originalEvent.originalEvent && event.originalEvent.originalEvent.type === "keydown")
                                {
                                    var keyEvent = event.originalEvent.originalEvent;
                                    if (keyEvent.keyCode === _fwdc.keyCodes.TAB)
                                    {
                                        return;
                                    }
                                }

                                _pendingFocusChange = true;
                                try
                                {
                                    _endEditCell(true, false);
                                    _$currentTable = _fwdc.currentDocumentContainer().find("#" + _currentTableId);
                                    _currentTableInverted = _$currentTable.hasClass("DocTableInverted");
                                    _$currentRowCells = _$currentTable.find("td." + _currentRowClass);
                                    _$currentColumnCells = _$currentTable.find("td." + _currentColumnClass);
                                    var $newCell = _$currentRowCells.slice(_currentRowCellIndex, _currentRowCellIndex + 1);
                                    _fwdc.beginEditCell($newCell, true);
                                }
                                finally
                                {
                                    _pendingFocusChange = false;
                                }
                            }
                        });
                    }
                }
                else if ($cell.hasClass("CellMask"))
                {
                    _currentCellType = "CellMask";
                    lastValue = _$currentEditContents.text();
                    lastText = lastValue;
                    _$currentEditor = $('<input type="text">')
                        .val(lastValue)
                    /*.css({
                        'font-size': 'inherit',
                        'text-align': $cell.css('text-align'),
                        "min-height": "0"
                    })*/;

                    if (maxLength) { _$currentEditor.attr("maxLength", maxLength); }

                    _$currentEditor.setMask(maskProperties.mask);

                    _$currentEditCellContainer.empty().append(_$currentEditor);
                }
                else if ($cell.hasClass("CellTextMultiline"))
                {
                    _currentCellType = "CellTextMultiline";
                    lastValue = _$currentEditContents.html();
                    lastText = _htmlToText(lastValue.replace(/<br>/gi, '\r\n'));
                    _$currentEditor = $('<textarea>')
                        .val(lastText)
                        .attr({
                            'data-field-id': _$currentEditCell.attr("id"),
                            'spellcheck': $cell.hasClass("SpCk"),
                            'rows': '1'
                        })
                    /*.css({
                        'text-align': $cell.css('text-align')
                    })*/;

                    if (_$currentEditCell.hasClass("CustomFieldPopup"))
                    {
                        _$currentEditor.addClass("CustomFieldPopup");
                    }

                    if (maxLength) { _$currentEditor.attr("data-maxlength", maxLength); }

                    _$currentEditCellContainer.empty().append(_$currentEditor);



                    _setupTextareaPopups(null, _$currentEditor,
                        function ($editor)
                        {
                            if (_fwdc.beginEditCell(cell, false))
                            {
                                _$currentEditor.val($editor.val());
                            }
                        });
                }
                else if ($cell.hasClass("CellTextRichText") && _fwdc.createRichTextBox)
                {
                    _currentCellType = 'CellTextRichText';
                    lastValue = _$currentEditContents.html();
                    lastText = lastValue;

                    //var $oldContent = _$currentEditContents.children();

                    var classes = $cell.attr('class').split(' ');
                    var iClass = 0;
                    var classCount = classes.length;

                    var richTextClass = 'CellTextRichText';
                    for (iClass = 0; iClass < classCount; iClass++)
                    {
                        var cssClass = classes[iClass];
                        if (cssClass.indexOf('RichText') > 0)
                        {
                            richTextClass = richTextClass + ' ' + cssClass;
                        }
                    }

                    _$currentEditor = $('<textarea>')
                        .addClass("CellEditorRichTextData")
                        .attr('data-field-id', _$currentEditCell.attr('id'))
                        .val(lastText)
                    /*.css({
                        'font-size': 'inherit',
                        'text-align': $cell.css('text-align'),
                        'min-height': '0',
                        'padding': '2px'
                    })*/
                    _$currentEditCellContainer.empty().append(_$currentEditor);

                    _fwdc.createRichTextBox($cell.attr('id'), _$currentEditor, richTextClass, true,
                        function ($field, editor)
                        {
                            //$oldContent.remove();
                            editor.updateElement();
                        },
                        function ($field, editor)
                        {
                            _endEditCell(true, false);
                        });

                    _setupTextareaPopups(null, _$currentEditor,
                        function ($editor)
                        {
                            if (_fwdc.beginEditCell(cell, false))
                            {
                                _fwdc.setRichTextValue(_$currentEditor, _fwdc.getFieldValue("", $editor));
                            }
                        });
                }
                else
                {
                    _currentCellType = "CellText";
                    lastValue = _$currentEditContents.text();
                    lastText = lastValue;
                    _$currentEditor = $('<input type="text">')
                        .val(lastValue)
                        //.css('font-size', 'inherit')
                        //.css('text-align', $cell.css('text-align'))
                        //.css('text-transform', $cell.css('text-transform'))
                        .attr('spellcheck', $cell.hasClass("SpCk"));
                    _$currentEditCellContainer.empty().append(_$currentEditor);

                    if ($cell.hasClass("CellDate"))
                    {
                        _$currentEditor.datepicker($.extend({
                            beforeShow: function (input, picker)
                            {
                                if (_$currentEditor)
                                {
                                    _$currentEditor.addClass("DatePickerOpen");

                                    var $dpDiv = $(picker.dpDiv);
                                    if ($dpDiv)
                                    {
                                        var dpDivHeight = $dpDiv.outerHeight();
                                        var $input = $(this);
                                        var bottom = $input.offset().top + $input.outerHeight() + dpDivHeight;
                                        var viewportHeight = window.document.documentElement.clientHeight + _fwdc.$document.scrollTop();

                                        if (viewportHeight >= bottom)
                                        {
                                            var qtipApi;
                                            if ((qtipApi = _$currentEditor.data("qtip")) && qtipApi.fastIsTableField)
                                            {
                                                qtipApi.set("position.my", "bottom center");
                                                qtipApi.set("position.at", "top center");
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    return false;
                                }
                            },
                            onSelect: function (input, picker)
                            {
                                _pendingFocusChange = true;
                                try
                                {
                                    _endEditCell(true, false);
                                    _navigateCellEditor(CellNavigation.Current);
                                }
                                finally
                                {
                                    _pendingFocusChange = false;
                                }
                            },
                            onClose: function (dateText, picker)
                            {
                                if (_$currentEditor)
                                {
                                    _$currentEditor.removeClass("DatePickerOpen");

                                    var qtipApi;
                                    if ((qtipApi = _$currentEditor.data("qtip")) && qtipApi.fastIsTableField)
                                    {
                                        qtipApi.set("position.my", "top center");
                                        qtipApi.set("position.at", "bottom center");
                                    }
                                }
                            }
                        },
                            _datepickerRegionalData(),
                            _datepickerSettings));
                    }
                    else if ($cell.hasClass("CellEmail"))
                    {
                        _$currentEditor.attr("type", "email");
                    }

                    if (maxLength) { _$currentEditor.attr("maxLength", maxLength); }
                }

                if (createdEditor)
                {
                    $cell.addClass("CellHasEditor");

                    _$currentEditContents.empty();

                    var fieldClasses = $cell.attr("class").match(/\bField\w*\b/g);
                    fieldClasses.push("CellEditor");

                    if ($cell.hasClass("Uppercase"))
                    {
                        fieldClasses.push("Uppercase");
                    }
                    else if ($cell.hasClass("Lowercase"))
                    {
                        fieldClasses.push("Lowercase");
                    }

                    //var cellOffset = $cell.offset();
                    //var tableOffset = $currentTableContainer.offset();

                    _$currentEditor
                        .addClass(fieldClasses.join(" "))
                        .attr('title', $cell.attr('title'))
                        .css("padding", cellPadding)
                        .attr("data-focus-id", $cell.attr("id"));

                    if (_currentCellType === "CellCombobox")
                    {
                        _$currentEditor.css("padding-right", "");
                    }

                    _copyTextCss($cell, _$currentEditor);

                    //var offset = $cell.position();

                    _$currentEditCellContainer
                        .addClass("HasEditor")
                        .css({
                            //"width": cellWidth, // Let the width be auto so it automatically fills without requiring explicit sets
                            "height": cellHeight
                        })
                        .appendTo(_$currentEditContents);
                    //    .css({
                    //        /*"top": cellOffset.top - tableOffset.top + "px",
                    //        "left": cellOffset.left - tableOffset.left + "px"*/
                    //        "top": offset.top + "px",
                    //        "left": offset.left + "px"
                    //    });

                    _repositionCellEditor();

                    if (_$currentEditor.hasClass("FieldRequired"))
                    {
                        _$currentEditor.attr("aria-required", "true");
                    }


                    $indicator.remove().appendTo(_$currentEditCellContainer);
                }

                // We don't want to apply the description to the field as it means screen readers read the cell's version, then read the editor version.
                // Ideally we'd ignore the cell and only read the editor, but currently it has no caption or anything.
                //_$currentEditor.attr("aria-description", _$currentEditCell.attr("aria-description"));
                _$currentEditor.addClass("CellEditing").focus();
                _$currentEditor.data("fast-editing-cell", _$currentEditCell);
                _setCurrentField(_$currentEditor[0], _$currentEditor, lastValue, lastText, true);
                //_fwdc.ensureElementVisible(_$currentEditor.add(_$currentEditCell), false, _$currentEditor.closest(".PanelScrollContainer"), 10, true);
                //_fwdc.ensureElementVisible(_$currentEditCell, false, _$currentEditor.closest(".PanelScrollContainer"), 10, true);
                _fwdc.scrollIntoView(_$currentEditor.add(_$currentEditCell));

                _fwdc.showCurrentFieldTip();

                switch (_currentCellType)
                {
                    case "CellMask":
                        setTimeout(function ()
                        {
                            _$currentEditor.focus().select();
                        }, 0);
                        _$currentEditor.select();
                        break;
                    case "CellText":
                    case "CellTextMultiline":
                        _$currentEditor.select();

                        //Determine overflow height                        
                        var $tableBody = $cell.closest(".DocTableBody");
                        if ($tableBody.length)
                        {
                            //Only care about doc tables with a scroll panel, since scroll panels do not allow table fields to overflow on top of them
                            //Non-scroll panel tables can just let the field overflow
                            var panelContainer = $tableBody.closest(".PanelScrollContainer");
                            if (panelContainer.length)
                            {
                                var tableHeight = $tableBody.height();
                                var editorHeight = _$currentEditor.outerHeight(true);
                                var shiftUp = 0;

                                var displayOffset = cell.displayContentOffset($tableBody);
                                if (displayOffset && displayOffset.top > 0)
                                {
                                    //Too tall, slide up
                                    if (editorHeight > tableHeight)
                                    {
                                        shiftUp = -displayOffset.top;
                                    }
                                    else
                                    {
                                        //Add 2 pixels so the focus outline can be shown at the bottom of the cell
                                        shiftUp = Math.floor(tableHeight - (displayOffset.top + editorHeight + 2));
                                        //Never shift down
                                        if (shiftUp > 0) { shiftUp = 0; }
                                    }
                                }

                                var maxHeight = 0;
                                if (editorHeight > tableHeight)
                                {
                                    //Factor in 2 pixels so the focus outline can be shown at the bottom of the cell
                                    maxHeight = tableHeight - 2;
                                }

                                if (maxHeight > 0)
                                {
                                    _$currentEditor.css("top", shiftUp + "px")
                                        .css("max-height", maxHeight + "px")
                                        .css("min-height", maxHeight + "px");
                                }
                                else
                                {
                                    _$currentEditor.css("top", shiftUp + "px");
                                }
                            }
                        }

                        break;
                    case "CellCombobox":
                        _$currentEditor.select();
                        if (!_keyEvent && !resume)
                        {
                            if (!_$currentEditor.is("select"))
                            {
                                _$currentEditor.autocomplete("search", "");
                            }
                        }
                        else
                        {
                            setTimeout(function ()
                            {
                                if (_$currentEditor)
                                {
                                    _$currentEditor.focus().select();
                                }
                            }, 0);
                        }
                        break;
                    case "CellCheckbox":
                    case "CellRadioButton":
                        if (_$currentEditor)
                        {
                            setTimeout(function ()
                            {
                                if (_$currentEditor)
                                {
                                    _$currentEditor.focus();
                                }
                            }, 0);
                        }
                        break;
                }

                //_setCurrentRow(_$currentEditor.closest("tr"));

                return true;
            }
            else if ($cell.hasClass("TCE"))
            {
                $cell.focusNative();
            }

            return false;
        };

        function _filterEditFocusCells($cells)
        {
            return _fwdc.autoFocusMode
                ? $cells.filterHasClassName("CellEditable")
                : $cells;
        }

        function _navigateCellEditor(direction, invert)
        {
            _$currentTable = _fwdc.currentDocumentContainer().find("#" + _currentTableId);
            _currentTableInverted = _$currentTable.hasClass("DocTableInverted");

            if (!invert && _currentTableInverted)
            {
                switch (direction)
                {
                    case CellNavigation.Down:
                        return _navigateCellEditor(CellNavigation.Right, true);
                    case CellNavigation.Up:
                        return _navigateCellEditor(CellNavigation.Left, true);
                    case CellNavigation.Right:
                        return _navigateCellEditor(CellNavigation.Down, true);
                    case CellNavigation.Left:
                        return _navigateCellEditor(CellNavigation.Up, true);
                }
            }

            _$currentTableCells = _$currentTable.findElementsByClassName("TCE");
            _$currentRowCells = _$currentTableCells.filterHasClassName(_currentRowClass);
            _$currentColumnCells = _$currentTableCells.filterHasClassName(_currentColumnClass);

            if (_$currentRowCells.length === 0 && _currentDataRowNumber === 0)
            {
                if (_currentTableInverted)
                {
                    var $rows = _$currentTable.find("tbody tr");
                    _$currentRowCells = $rows.map(function ()
                    {
                        var $firstCell = $(this).children(".TDC,.TDS");

                        if ($firstCell.length)
                        {
                            return $firstCell[0];
                        }

                        return null;
                    });
                }
                else
                {
                    _$currentRowCells = _$currentTable.find("tbody tr").slice(-2, -1).findElementsByClassName("TCE");
                    if (_$currentRowCells.length === 0)
                    {
                        _$currentRowCells = _$currentTable.find("tbody tr").slice(0, 1).findElementsByClassName("TCE");
                    }
                    if (_$currentRowCells.length === 0)
                    {
                        _$currentRowCells = _$currentTable.findElementsByClassName(_currentTableId + "_" + 0);
                    }
                }
                _currentColumnCellIndex = 0;
            }

            // Re-determine the current cell index in the row, as it could have been offset by the copy/delete links appearing during an add.
            var $currentCell = _$currentRowCells.filterHasClassName(_currentColumnClass);
            _currentRowCellIndex = _$currentRowCells.index($currentCell[0]);

            var $nextCell;
            var $rowCells = _$currentRowCells;
            var rowNumber = _currentRowNumber;
            var rowClass = _currentRowClass;

            switch (direction)
            {
                case CellNavigation.Tab:
                    $nextCell = _filterEditFocusCells($rowCells.slice(_currentRowCellIndex + 1)).first();

                    do
                    {
                        if ($nextCell && $nextCell.length > 0)
                        {
                            _fwdc.beginEditCell($nextCell);
                            return true;
                        }
                        else
                        {
                            rowNumber++;
                            rowClass = "TR-" + _currentTableId + "-" + rowNumber;
                            $rowCells = _$currentTableCells.filter("td." + rowClass);
                            $nextCell = _filterEditFocusCells($rowCells).first();
                        }
                    }
                    while ($rowCells && $rowCells.length);

                    _$currentTable.children("tbody").last().focusNextInputField();

                    return;

                case CellNavigation.ReverseTab:
                    $nextCell = _filterEditFocusCells($rowCells.slice(0, _currentRowCellIndex)).last();

                    do
                    {
                        if ($nextCell && $nextCell.length > 0)
                        {
                            _fwdc.beginEditCell($nextCell);
                            return true;
                        }
                        else
                        {
                            rowNumber--;
                            rowClass = "TR-" + _currentTableId + "-" + rowNumber;
                            $rowCells = _$currentTableCells.filter("td." + rowClass);
                            $nextCell = _filterEditFocusCells($rowCells).last();
                        }
                    }
                    while ($rowCells && $rowCells.length);

                    _$currentTable.children("tbody").focusNextInputField(true);

                    return;

                case CellNavigation.Down:
                    $nextCell = _filterEditFocusCells(_$currentColumnCells.slice(_currentColumnCellIndex + 1)).first();
                    if ($nextCell.length === 0)
                    {
                        $nextCell = _$currentColumnCells.slice(_currentColumnCellIndex, _currentColumnCellIndex + 1);
                    }
                    if ($nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                case CellNavigation.Up:
                    if (_currentColumnCellIndex > 0)
                    {
                        $nextCell = _filterEditFocusCells(_$currentColumnCells.slice(0, _currentColumnCellIndex)).last();
                        if ($nextCell.length === 0)
                        {
                            $nextCell = _$currentColumnCells.slice(_currentColumnCellIndex, _currentColumnCellIndex + 1);
                        }
                    }
                    else
                    {
                        $nextCell = _$currentColumnCells.slice(0, 1);
                    }

                    if ($nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                case CellNavigation.Right:
                    $nextCell = _filterEditFocusCells(_$currentRowCells.slice(_currentRowCellIndex + 1)).first();
                    if ($nextCell.length === 0)
                    {
                        $nextCell = _$currentRowCells.slice(_currentRowCellIndex, _currentRowCellIndex + 1);
                    }

                    if ($nextCell && $nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                case CellNavigation.Left:
                    $nextCell = _filterEditFocusCells(_$currentRowCells.slice(0, _currentRowCellIndex)).last();
                    if ($nextCell.length === 0)
                    {
                        $nextCell = _$currentRowCells.slice(_currentRowCellIndex, _currentRowCellIndex + 1);
                    }

                    if ($nextCell && $nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                case CellNavigation.Current:
                    $nextCell = _$currentRowCells.slice(_currentRowCellIndex, _currentRowCellIndex + 1);

                    if ($nextCell && $nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                case CellNavigation.RowStart:
                    $nextCell = _filterEditFocusCells(_$currentRowCells).first();

                    if ($nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                case CellNavigation.RowEnd:
                    $nextCell = _filterEditFocusCells(_$currentRowCells).last();

                    if ($nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                case CellNavigation.ColumnStart:
                    $nextCell = _filterEditFocusCells(_$currentColumnCells).first();

                    if ($nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                case CellNavigation.ColumnEnd:
                    $nextCell = _filterEditFocusCells(_$currentColumnCells).last();

                    if ($nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                case CellNavigation.TableStart:
                    $nextCell = _filterEditFocusCells(_$currentTableCells).first();

                    if ($nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                case CellNavigation.TableEnd:
                    //$nextCell = _$currentTableCells.filter("td.CellEditable").last();
                    // Jump to the first editable field in the final table row instead of the last cell.
                    $nextCell = _filterEditFocusCells(_$currentTable.find(".TDR,.TableInsertionRow").last().findElementsByClassName("TCE")).first();

                    if ($nextCell.length > 0)
                    {
                        _fwdc.beginEditCell($nextCell);
                        return true;
                    }
                    break;

                default:
                    _fwdc._warn("Unhandled cell navigation: " + direction);
            }
        }

        function _onTableCheckboxChange(event, checkbox)
        {
            checkbox = checkbox || event.currentTarget;
            var $checkbox = $(checkbox);

            // Forcibly cancel queued current row set calls.
            _fwdc.clearTimeout("onTableCheckboxChange.beginEditSetCurrentRow", _beginEditSetCurrentRowHandle);
            _beginEditSetCurrentRowHandle = null;

            // Set the client-side current row display.
            _setCurrentRow($checkbox.closest("tr"));
            _fwdc.beginEditCell($checkbox.closest("td.CellEditable"));
            _setLastValue(checkbox, !($checkbox.is(":checked")));
            _endEditCell(true, true);

            _$currentTable = _fwdc.currentDocumentContainer().find("#" + _currentTableId);
            _currentTableInverted = _$currentTable.hasClass("DocTableInverted");
            _$currentRowCells = _$currentTable.find("td." + _currentRowClass);
            _$currentColumnCells = _$currentTable.find("td." + _currentColumnClass);
            var $newCell = _$currentRowCells.slice(_currentRowCellIndex, _currentRowCellIndex + 1);
            $newCell.find("input").focus();

            event.stopPropagation();
            event.stopImmediatePropagation();
        }

        function _onCellEditorKeydown(event)
        {
            var $target = $(event.target);

            if ($target.hasClass("TDOV"))
            {
                return;
            }

            var pos;
            var length;
            _keyEvent = true;
            try
            {
                switch (event.keyCode)
                {
                    case _fwdc.keyCodes.TAB:
                        // Delay tab handling to prevent issues with Firefox moving focus during ajax calls.
                        setTimeout(function ()
                        {
                            _pendingFocusChange = true;
                            try
                            {
                                if (_$currentEditor)
                                {
                                    if (_$currentEditor.hasClass("FastComboboxOpen"))
                                    {
                                        _setComboboxData(_$currentEditor, _$currentEditor.data("fast-combo-focus-value"), _$currentEditor.data("fast-combo-focus-text"));
                                    }
                                }
                                _endEditCell(true);

                                if (event.shiftKey)
                                {
                                    _navigateCellEditor(CellNavigation.ReverseTab);
                                }
                                else
                                {
                                    _navigateCellEditor(CellNavigation.Tab);
                                }
                            }
                            finally
                            {
                                _pendingFocusChange = false;
                            }
                        }, 1);

                        return _fwdc.stopEvent(event);

                    case _fwdc.keyCodes.ENTER:
                        _pendingFocusChange = true;
                        if (_$currentEditor)
                        {
                            if (_$currentEditor.is("textarea") || _$currentEditor.hasClass("FastComboboxOpen")) { return true; }
                        }
                        _endEditCell(true);
                        _navigateCellEditor(CellNavigation.Tab);

                        return _fwdc.stopEvent(event);

                    case _fwdc.keyCodes.ESCAPE:
                        _pendingFocusChange = true;
                        if (_$currentEditor)
                        {
                            if (_$currentEditor.hasClass("DatePickerOpen"))
                            {
                                _$currentEditor.datepicker("hide");
                                return _fwdc.stopEvent(event);
                            }
                        }
                        var $cell = _$currentEditCell;
                        _endEditCell(false);
                        _fwdc.beginEditCell($cell);

                        return _fwdc.stopEvent(event);

                    case _fwdc.keyCodes.SPACE:
                        _pendingFocusChange = true;
                        if (_$currentEditor && _$currentEditor.hasClass("CellCombobox") && !_$currentEditor.hasClass("FastComboboxOpen"))
                        {
                            _$currentEditor.autocomplete("search");

                            return _fwdc.stopEvent(event);
                        }
                        break;

                    case _fwdc.keyCodes.UP:
                        if (event.shiftKey || event.altKey) { return true; }
                        _pendingFocusChange = true;
                        if (_$currentEditor)
                        {
                            if (_$currentEditor.is("textarea") || _$currentEditor.hasClass("FastComboboxOpen")) { return true; }
                        }
                        _endEditCell(true);
                        _navigateCellEditor(event.ctrlKey ? CellNavigation.ColumnStart : CellNavigation.Up);

                        return _fwdc.stopEvent(event);

                    case _fwdc.keyCodes.DOWN:
                        if (event.shiftKey || event.altKey) { return true; }
                        _pendingFocusChange = true;
                        if (_$currentEditor)
                        {
                            if (_$currentEditor.is("textarea") || _$currentEditor.hasClass("FastComboboxOpen")) { return true; }
                        }
                        _endEditCell(true);
                        _navigateCellEditor(event.ctrlKey ? CellNavigation.ColumnEnd : CellNavigation.Down);

                        return _fwdc.stopEvent(event);

                    case _fwdc.keyCodes.LEFT:
                        if (event.shiftKey || event.altKey) { return true; }
                        _pendingFocusChange = true;
                        if (_$currentEditor)
                        {
                            if (_$currentEditor.is("textarea") || _$currentEditor.hasClass("FastComboboxOpen")) { return true; }
                            if (_$currentEditor.is("input[type='text'],input[type='email']") && !_$currentEditor.hasClass("FastComboboxClosed"))
                            {
                                pos = $.fastMask._getCursorPos(_$currentEditor[0]);
                                length = $.fastMask._getSelectionLength(_$currentEditor[0]);

                                if (pos > 0 || length > 0)
                                {
                                    return true;
                                }
                            }
                        }
                        _endEditCell(true);
                        _navigateCellEditor(event.ctrlKey ? CellNavigation.RowStart : CellNavigation.Left);

                        return _fwdc.stopEvent(event);

                    case _fwdc.keyCodes.RIGHT:
                        if (event.shiftKey || event.altKey) { return true; }
                        _pendingFocusChange = true;
                        if (_$currentEditor)
                        {
                            if (_$currentEditor.is("textarea") || _$currentEditor.hasClass("FastComboboxOpen")) { return true; }
                            if (_$currentEditor.is("input[type='text'],input[type='email']") && !_$currentEditor.hasClass("FastComboboxClosed"))
                            {
                                pos = $.fastMask._getCursorPos(_$currentEditor[0]);
                                length = $.fastMask._getSelectionLength(_$currentEditor[0]);

                                if (pos < _$currentEditor.val().length || length > 0)
                                {
                                    return true;
                                }
                            }
                        }
                        _endEditCell(true);
                        _navigateCellEditor(event.ctrlKey ? CellNavigation.RowEnd : CellNavigation.Right);

                        return _fwdc.stopEvent(event);

                    case _fwdc.keyCodes.HOME:
                        if (event.shiftKey || event.altKey) { return true; }
                        _pendingFocusChange = true;
                        if (_$currentEditor)
                        {
                            if (_$currentEditor.is("textarea") || _$currentEditor.hasClass("FastComboboxOpen")) { return true; }
                            if (!event.ctrlKey && _$currentEditor.is("input[type='text'],input[type='email']") && !_$currentEditor.hasClass("FastComboboxClosed"))
                            {
                                pos = $.fastMask._getCursorPos(_$currentEditor[0]);
                                length = $.fastMask._getSelectionLength(_$currentEditor[0]);

                                if (pos > 0 || length > 0)
                                {
                                    return true;
                                }
                            }
                        }
                        _endEditCell(true);
                        if (_navigateCellEditor(event.ctrlKey ? CellNavigation.TableStart : CellNavigation.RowStart))
                        {
                            return _fwdc.stopEvent(event);
                        }
                        break;

                    case _fwdc.keyCodes.END:
                        if (event.shiftKey || event.altKey) { return true; }
                        _pendingFocusChange = true;
                        if (_$currentEditor)
                        {
                            if (_$currentEditor.is("textarea") || _$currentEditor.hasClass("FastComboboxOpen")) { return true; }
                            if (!event.ctrlKey && _$currentEditor.is("input[type='text'],input[type='email']") && !_$currentEditor.hasClass("FastComboboxClosed"))
                            {
                                pos = $.fastMask._getCursorPos(_$currentEditor[0]);
                                length = $.fastMask._getSelectionLength(_$currentEditor[0]);

                                if (pos < _$currentEditor.val().length || length > 0)
                                {
                                    return true;
                                }
                            }
                        }
                        _endEditCell(true);
                        if (_navigateCellEditor(event.ctrlKey ? CellNavigation.TableEnd : CellNavigation.RowEnd))
                        {
                            return _fwdc.stopEvent(event);
                        }
                        break;

                    case _fwdc.keyCodes.SPACE:
                        break;

                    case _fwdc.keyCodes.F9:
                        if (_fwdc.handleF9)
                        {
                            _pendingFocusChange = true;
                            var fieldId = _$currentEditCell.attr("id");

                            _endEditCell(false);

                            _fwdc.correctField(fieldId);

                            _navigateCellEditor(CellNavigation.Tab);

                            return _fwdc.stopEvent(event);
                        }

                        break;

                    case _fwdc.keyCodes.NUM0:
                    case _fwdc.keyCodes.NUMPAD0:
                    case _fwdc.keyCodes.F:
                        if (!_fwdc.tap && _fwdc.noModifiers(event) && _$currentEditor.is(".CellEditable input:checkbox"))
                        {
                            _pendingFocusChange = true;
                            if (_$currentEditor.is(":checked"))
                            {
                                // Explicit change event is fired as it is not normally raised.
                                _$currentEditor.prop("checked", false).change();
                            }
                            _navigateCellEditor(CellNavigation.Tab);

                            return _fwdc.stopEvent(event);
                        }
                        break;

                    case _fwdc.keyCodes.NUM1:
                    case _fwdc.keyCodes.NUMPAD1:
                    case _fwdc.keyCodes.T:
                        if (!_fwdc.tap && _fwdc.noModifiers(event) && _$currentEditor.is(".CellEditable input:checkbox,.CellEditable input:radio"))
                        {
                            _pendingFocusChange = true;
                            if (!_$currentEditor.is(":checked"))
                            {
                                // Explicit change event is fired as it is not normally raised.
                                _$currentEditor.prop("checked", true).change();
                            }
                            _navigateCellEditor(CellNavigation.Tab);

                            return _fwdc.stopEvent(event);
                        }
                        break;
                }
            }
            finally
            {
                _pendingFocusChange = false;
            }
            return true;
        }

        function _onCellEditorKeypress(event)
        {
            if (event.shiftKey || event.ctrlKey || event.altKey) { return true; }

            var $target = $(event.target);

            if ($target.hasClass("TDOV"))
            {
                return;
            }

            switch (event.keyCode)
            {
                case 13:    // Enter
                    if (_$currentEditor && _$currentEditor.is("textarea"))
                    {
                        return true;
                    }
                    return false;
                case 9:     // Tab
                case 27:    // Escape
                    return false;
            }

            return true;
        }

        function _onCellEditorKeyup(event)
        {
            if (event.shiftKey || event.ctrlKey || event.altKey) { return true; }

            var $target = $(event.target);

            if ($target.hasClass("TDOV"))
            {
                return;
            }

            switch (event.keyCode)
            {
                case 13:    // Enter
                    if (_$currentEditor && _$currentEditor.is("textarea"))
                    {
                        return true;
                    }
                    return false;
                case 9:     // Tab
                case 27:    // Escape
                    return false;
            }

            return true;
        }

        // Triggering modifications here can cause Firefox to block checkbox changes.  Not sure what value this function was adding.
        //function _onCellInputFocus(event)
        //{
        //    _fwdc.beginEditCell($(event.target).closest("td"));
        //}

        /*function _onViewTabKeyDown(event)
        {
            if (event.shiftKey || event.ctrlKey || event.altKey) { return; }
         
            var handled;
         
            var $current, $container, $tabs, current;
         
            switch (event.keyCode)
            {
                case _fwdc.keyCodes.LEFT:
                case _fwdc.keyCodes.UP:
                    $current = $(event.currentTarget);
                    $container = $current.closest("ul");
                    $tabs = $container.children("li:visible");
         
                    current = $tabs.index($current);
         
                    if (current > 0)
                    {
                        handled = true;
                        $($tabs.get(current - 1)).find('a').click();
                    }
         
                    break;
         
                case _fwdc.keyCodes.RIGHT:
                case _fwdc.keyCodes.DOWN:
                    $current = $(event.currentTarget);
                    $container = $current.closest("ul");
                    $tabs = $container.children("li:visible");
         
                    current = $tabs.index($current);
         
                    if (current >= 0 && current < $tabs.length - 1)
                    {
                        handled = true;
                        $($tabs.get(current + 1)).find('a').click();
                    }
                    break;
            }
         
            if (handled)
            {
                event.preventDefault();
                event.stopPropagation();
            }
        }*/

        function _onManagerModalClosing(event, element, confirmed)
        {
            if (!_modalManagerClosed && !_errorOccurred && !_refreshingWindowContent)
            {
                _fwdc.navigate(null, "ModalManagerClosing", -1);
                return false;
            }

            //_fwdc.destroyRichElements();
            _modalManagerClosed = false;
            return true;
        }

        function _handleReview(sender, event)
        {
            var $sender = $(sender);
            if (!_fieldViewEnabled($sender)) { return true; }

            var fieldId = $sender.attr("data-name") || $sender.attr("name") || $sender.attr("id");
            _fwdc.correctField(fieldId);
            _setCurrentField(sender, null, _fwdc.getFieldValue(sender));

            _fwdc.hideToolTips();
            _fwdc.closeComboboxes();
            $sender.focusNextInputField(false, true);

            if (event)
            {
                event.stopPropagation();
                event.preventDefault();
                event.stopImmediatePropagation();
            }
        }

        function _raiseGotFocus(fieldId)
        {
            if (!FWDC.fastReady)
            {
                setTimeout(function () { _raiseGotFocus(fieldId); }, 10);
            }
            else
            {
                var $field = _fwdc.formField(fieldId);
                if (_fwdc.currentDocumentContainer().equals(_fwdc.parentDocumentContainer($field)))
                {
                    FWDC.ready(function ()
                    {
                        _fwdc.busy.done(function ()
                        {
                            _fwdc.setLastFocusField(fieldId);

                            _fwdc.ajax({
                                url: 'FieldGotFocus',
                                async: false,
                                busy: false,
                                checkBusy: true,
                                commitEdits: false,
                                data: { DOC_MODAL_ID__: _fwdc.currentModalId(), FIELD__: fieldId },
                                success: function (data, status, request)
                                {
                                    _handleRecalcUpdates(data);
                                }
                            });
                        });


                        /*if (_busy(true))
                        {
                            setTimeout(function () { _raiseGotFocus(fieldId); }, 10);
                            return;
                        }
         
                        _fwdc.ajax({
                            url: 'FieldGotFocus',
                            async: false,
                            busy: false,
                            checkBusy: true,
                            commitEdits: false,
                            data: { DOC_MODAL_ID__: _fwdc.currentModalId(), FIELD__: fieldId },
                            success: function (data, status, request)
                            {
                                _handleRecalcUpdates(data);
                            }
                        });*/


                    });
                }
            }
        }

        function _onInputKeyPress(event)
        {
            var $sender = $(event.target);
            var id = $sender.attr("id");
            if (id)
            {
                _fwdc.onUserActivity({ event: "InputKeyPress", fieldId: id, getValue: function () { return _fwdc.getFieldValue(event.target, $sender); } });
            }
            else
            {
                _fwdc.onUserActivity({ event: "InputKeyPress" });
            }
        }

        function _onSelectTableView(event)
        {
            var $target = $(event.target);

            if ($target.is(":checked"))
            {
                var args = $target.data("fast-tableview");

                _fwdc.animateSelectorUnderline($target.parent());

                FWDC.setTableView(event, args.control, args.tableId, args.view);

                event.preventDefault();
                event.stopPropagation();
                event.stopImmediatePropagation();
            }
        }

        function _onCheckboxChange(event)
        {
            if (_inRecalc) { return false; }

            var $target = $(event.target);

            if ($target.hasClass("FastTableToggleInput"))
            {
                return _onTableCheckboxChange(event);
            }

            if ($target.hasClass("TableViewButton"))
            {
                return;
            }

            var isRadioCombo = $target.hasClass("FCBRB");

            if ($target.is(":enabled") && ($target.hasClass("FastCheckboxButton") || $target.hasClass("FastRadioButtonButton") || isRadioCombo))
            {
                _fwdc.Events.Field.focus(event);

                _setLastValue(event.target, !_fwdc.getFieldValue(event.target));

                _fwdc.checkValueChanged(event.target, "CheckboxChange");

                var isButtonSet = isRadioCombo && $target.hasClass("FastComboButtonRadio");
                if (isButtonSet)
                {
                    _fwdc.animateSelectorUnderline($target.parent());
                }

                return true;
            }

            // Rather than try to prevent the change clientside, let the server fix things.  Otherwise radio buttons don't self-correct

            //if (!$target.hasClass("FieldEnabled"))
            //{
            //    _fwdc.stopEvent(event);
            //    $target.focus();
            //    _setLastValue(event.target, !$target.prop("checked"));
            //    $target.prop("checked", !$target.prop("checked"));
            //    event.preventDefault();
            //    event.stopImmediatePropagation();
            //    event.stopPropagation();
            //    return false;
            //}
            //else
            //{
            _fwdc.Events.Field.focus(event);

            _setLastValue(event.target, !_fwdc.getFieldValue(event.target));

            _fwdc.focus($target);

            _fwdc.checkValueChanged(event.target, "CheckboxClick");
            //}
        }

        function _onDocSliderChange(event)
        {
            if (_inRecalc) { return false; }

            // Force the value changed check as the focus event that sets lastvalue might occur after the field value actually changes
            _fwdc.checkValueChanged(event.target, "DocSliderChange", { force: true });
        }

        function _handleDocResponse(data, status, request)
        {
            /*jshint validthis: true */
            _fwdc.hideToolTips();
            _fwdc.closeComboboxes();
            _fwdc.runResponseFunctions(data, false);
            _fwdc.setActionResponseHtml(data);
            if (data.message) { FWDC.messageBox(data.message); }
            _fwdc.runResponseFunctions(data, true);
        }

        function _hideFlowMenu()
        {
            try
            {
                var $menu = $("#FlowMenu");
                if ($menu.data("uiDialog"))
                {
                    $menu.dialog("close");
                }
            }
            catch (ex)
            {
            }
        }

        function _htmlToText(html)
        {
            return $("<div></div>").html(html).text();
        }

        function _findElementName(element)
        {
            var $element = $(element);
            if ($element.attr("data-name"))
            {
                return $element.attr("data-name");
            }
            else if ($element.attr("name"))
            {
                return $element.attr("name");
            }
            else
            {
                var $nameElement = $element.find("[data-name]");
                if ($nameElement.length > 0 && $nameElement.attr("data-name"))
                {
                    return $nameElement.attr("data-name");
                }

                $nameElement = $element.find("[name]");
                if ($nameElement.length > 0 && $nameElement.attr("name"))
                {
                    return $nameElement.attr("name");
                }
            }

            return null;
        }

        function _dragGridSize($element)
        {
            return $element.attr("data-draggridsize") ? [parseInt($element.attr("data-draggridsize"), 10), parseInt($element.attr("data-draggridsize"), 10)] : false;
        }

        function _setResizable(element, resizeOnly, disableTouch)
        {
            var $element = $(element);
            var handles = "e,s,se";

            if ($element.hasClass("fast-ui-resizable-vertical"))
            {
                handles = "s";
            }
            else if ($element.hasClass("fast-ui-resizable-horizontal"))
            {
                handles = "e";
            }

            var grid = _dragGridSize($element);
            var minSize = 8;

            if ($element.hasClass("FastShapeLineContainer"))
            {
                minSize = 0;
                handles = "se";
            }

            $element.resizable({
                helper: "ui-resizable-helper",
                alsoResize: ".ui-selected",
                handles: handles,
                grid: grid,
                minHeight: minSize,
                minWidth: minSize,
                // disableTouch is True by default on resizable to protect modals, we need to re-enable it.
                disableTouch: _default(disableTouch, false),
                aspectRatio: !!$element.hasClass("FastPreserveAspectRatio"),
                resize: function (e, ui)
                {
                    _resizeControlGrids();
                },
                stop: function (e, ui)
                {
                    var dX = ui.size.width - ui.originalSize.width;
                    var dY = ui.size.height - ui.originalSize.height;

                    if (grid)
                    {
                        var gridSize = parseInt(grid[0], 10);
                        dX = Math.round(dX / gridSize) * gridSize;
                        dY = Math.round(dY / gridSize) * gridSize;
                    }

                    var elements = resizeOnly ? _findElementName(element) : _fwdc.selectedIds().join(",");

                    _fwdc.ajax({
                        url: 'FieldsResized',
                        async: false,
                        commitEdits: false,
                        data: function ()
                        {
                            return _fwdc.getDocPostParameters({ 'SELECTED_FIELDS__': elements, 'DX__': dX, 'DY__': dY }, "input[type='hidden']");
                        },
                        error: function (request, status, error)
                        {
                            _fwdc.onAjaxError("FieldsResized", request.responseText);
                        },
                        success: function (data, status, request)
                        {
                            _fwdc.setActionResponseHtml(data, data.selectedfields);
                        }
                    });
                }
            });
        }

        function _raiseElementsDragged(elements, dX, dY, select, callback, sync)
        {
            return _fwdc.ajax({
                url: 'FieldsDragged',
                async: !sync,
                commitEdits: false,
                data: function ()
                {
                    return _fwdc.getDocPostParameters({ 'SELECTED_FIELDS__': elements, 'DX__': dX, 'DY__': dY, 'SELECT__': select }, "input[type='hidden']");
                },
                error: function (request, status, error)
                {
                    _fwdc.onAjaxError("FieldsDragged", request.responseText);
                },
                success: function (data, status, request)
                {
                    _fwdc.setActionResponseHtml(data, data.selectedfields);
                },
                complete: callback
            });
        }

        var _pendingNudgeHandle = null;
        var _$pendingNudgeElements = null;
        var _pendingNudgeX = 0;
        var _pendingNudgeY = 0;

        function _nudgePendingElements(callback, sync)
        {
            if (_pendingNudgeHandle)
            {
                window.clearTimeout(_pendingNudgeHandle);
                _pendingNudgeHandle = null;
            }

            if (_$pendingNudgeElements)
            {
                if (_pendingNudgeX || _pendingNudgeY)
                {
                    _raiseElementsDragged(_fwdc.selectedIds(_$pendingNudgeElements).join(","), _pendingNudgeX, _pendingNudgeY, true, function ()
                    {
                        _$pendingNudgeElements = null;
                        _pendingNudgeX = 0;
                        _pendingNudgeY = 0;

                        if (callback)
                        {
                            callback();
                        }

                    }, sync);
                }
            }
        }

        function _elementsNudged($elements, dX, dY)
        {
            if (_$pendingNudgeElements)
            {
                if ($elements.equals(_$pendingNudgeElements))
                {
                    window.clearTimeout(_pendingNudgeHandle);
                    _pendingNudgeHandle = null;
                }
                else
                {
                    _nudgePendingElements(null, true);
                }
            }

            _pendingNudgeHandle = window.setTimeout(_nudgePendingElements, 500);
            _$pendingNudgeElements = $elements;
            _pendingNudgeX += dX;
            _pendingNudgeY += dY;
        }

        function _nudgeElements(event, $elements, directionCode)
        {
            if (!$elements || !$elements.length || _fwdc.uiBusy()) { return false; }

            var xAmount = 0;
            var yAmount = 0;

            var distance = 5;
            if (event.shiftKey)
            {
                distance = 1;
            }
            else
            {
                var gridSize = _dragGridSize($elements);
                if (gridSize)
                {
                    distance = gridSize[0];
                }
            }

            switch (directionCode)
            {
                case _fwdc.keyCodes.LEFT:
                    xAmount = -distance;
                    break;
                case _fwdc.keyCodes.UP:
                    yAmount = -distance;
                    break;
                case _fwdc.keyCodes.RIGHT:
                    xAmount = distance;
                    break;
                case _fwdc.keyCodes.DOWN:
                    yAmount = distance;
                    break;

                default:
                    return false;
            }

            if (xAmount)
            {
                $elements.css("left", "+=" + xAmount);
            }
            else if (yAmount)
            {
                $elements.css("top", "+=" + yAmount);
            }

            //_fwdc.ensureElementVisible($elements);
            _fwdc.scrollIntoView($elements);

            _elementsNudged($elements, xAmount, yAmount);

            _resizeControlGrids();
        }

        function _setDraggable($draggables)
        {
            $draggables.one("mouseenter", function ()
            {
                _initDraggable($(this));
            });
        }

        function _initDraggable($element)
        {
            if ($element.hasClass("ui-draggable")) { return false; }

            var element = $element.length ? $element[0] : null;

            var $container = $element.closest(".ControlGridContainer");
            var containerOffset = $container.offset();
            if (containerOffset === null || containerOffset === undefined)
            {
                containerOffset = {
                    left: 0,
                    right: 0
                };
            }

            var $dragKeyBox = $container.data("fastDragKeyBox");
            if (!$dragKeyBox)
            {
                // Use a focusable div instead of a textarea so it does not trigger mobile keyboards
                $dragKeyBox = $($.parseHTML('<div></div>'))
                    .attr("tabindex", -1)
                    .addClass("FastDragKeyBox")
                    .appendTo($container)
                    .focus(function (event)
                    {
                        $dragKeyBox.text("Focused");
                        return _fwdc.stopEvent(event);
                    })
                    .keydown(function (event)
                    {
                        if (!event.altKey && !event.metaKey)
                        {
                            switch (event.which)
                            {
                                case _fwdc.keyCodes.LEFT:
                                    $dragKeyBox.text("LEFT");
                                    _nudgeElements(event, $container.find(".ui-selected"), _fwdc.keyCodes.LEFT);
                                    break;
                                case _fwdc.keyCodes.UP:
                                    $dragKeyBox.text("UP");
                                    _nudgeElements(event, $container.find(".ui-selected"), _fwdc.keyCodes.UP);
                                    break;
                                case _fwdc.keyCodes.RIGHT:
                                    $dragKeyBox.text("RIGHT");
                                    _nudgeElements(event, $container.find(".ui-selected"), _fwdc.keyCodes.RIGHT);
                                    break;
                                case _fwdc.keyCodes.DOWN:
                                    $dragKeyBox.text("DOWN");
                                    _nudgeElements(event, $container.find(".ui-selected"), _fwdc.keyCodes.DOWN);
                                    break;
                                case _fwdc.keyCodes.F5:
                                    return;
                            }

                            return _fwdc.stopEvent(event);
                        }
                    })
                    .blur(function (event)
                    {
                        $dragKeyBox.text("Blurred");
                        return _fwdc.stopEvent(event);
                    });
                $container
                    .data("fastDragKeyBox", $dragKeyBox)
                    /*.on("focus", "*", function (event)
                    {
                        $dragKeyBox.focus();
                    })*/
                    .on("click", function (event)
                    {
                        _fwdc.saveScrollPositions();
                        $dragKeyBox.focus();
                        _fwdc.restoreScrollPositions();
                    })
                    .on("fastfieldsselected", function (event)
                    {
                        _fwdc.saveScrollPositions();
                        $dragKeyBox.focus();
                        _fwdc.restoreScrollPositions();
                    });
            }

            var dragOnly = !$element.hasClass("ui-selectee");

            var axis = false;
            if ($element.hasClass("fast-ui-draggable-vertical"))
            {
                axis = "y";
            }
            else if ($element.hasClass("fast-ui-draggable-horizontal"))
            {
                axis = "x";
            }

            var selectAfter = false;
            $element.draggable({
                containment: [containerOffset.left, containerOffset.top, 10000, 100000],
                cancel: "",
                grid: _dragGridSize($element),
                axis: axis,
                // disableTouch is True by default on draggable to protect modals, we need to re-enable it.
                disableTouch: false,
                start: function (e, ui)
                {
                    selectAfter = false;
                    if (!dragOnly)
                    {
                        var $this = $(this);
                        $this.data("fast-dragged", true);
                        if (!$this.hasClass("ui-selected"))
                        {
                            _fwdc.clearSelected();
                            $this.closest(".ui-selectable").children(".ui-selected").removeClass("ui-selected");
                            $this.addClass("ui-selected");
                            selectAfter = true;
                        }
                    }
                },
                drag: function (e, ui)
                {
                    if (ui.position.left < 0) { ui.position.left = 0; }
                    if (ui.position.top < 0) { ui.position.top = 0; }

                    var gridSize = _dragGridSize($element);
                    var gridDX = 0;
                    var gridDY = 0;
                    if (gridSize)
                    {
                        var originalLeft = ui.position.left;
                        var originalTop = ui.position.top;
                        ui.position.left = Math.floor(ui.position.left / gridSize[0]) * gridSize[0];
                        ui.position.top = Math.floor(ui.position.top / gridSize[1]) * gridSize[1];
                        gridDX = originalLeft - ui.position.left;
                        gridDY = originalTop - ui.position.top;
                    }

                    FWDC.hideViewMenus();
                    _fwdc.hideToolTips();

                    var dragElement = this;
                    var $this = $(dragElement);
                    var position = $this.position();

                    var dX = ui.position.left - position.left;
                    var dY = ui.position.top - position.top;

                    if (!dragOnly)
                    {
                        var $dragElements = $this.closest(".ui-selectable").children(".ui-selected");
                        $dragElements.each(function ()
                        {
                            if (this !== dragElement)
                            {
                                var $element = $(this);
                                var offset = $element.offset();
                                offset.top += dY;
                                offset.left += dX;
                                $element.offset(offset);
                            }
                        });
                    }

                    _resizeControlGrids();
                },
                stop: function (e, ui)
                {
                    var dX = ui.position.left - ui.originalPosition.left;
                    var dY = ui.position.top - ui.originalPosition.top;

                    var elements = dragOnly ? _findElementName(element) : _fwdc.selectedIds().join(",");

                    _raiseElementsDragged(elements, dX, dY, !dragOnly);
                }
            }).click(function (event)
            {
                var $this = $(this);
                if (!$this.data("fast-dragged") && $this.hasClass("ui-selectee") && !$this.hasClass("ui-selected"))
                {
                    if (!event.ctrlKey)
                    {
                        _fwdc.clearSelected();
                    }
                    $this.addClass("ui-selected");
                    _fwdc.raiseSelected();

                    return _fwdc.stopEvent(event);
                }
            }).find("a,button").each(_fwdc.disableClick);

            return true;
        }

        function _onSelectionOptionClick(event)
        {
            var $link = $(event.target);
            var $field = $link.closest(".fast-ui-selectable");

            var fieldName = _findElementName($field);

            var option;
            if ($link.hasClass("FastSelectionProperties"))
            {
                option = "Properties";
            }
            else if ($link.hasClass("FastSelectionDelete"))
            {
                option = "Delete";
            }

            FWDC.setProperties("", "SelectionOption", fieldName, { "Option": option });

            return _fwdc.stopEvent(event);
        }

        function _setSelectedFields(selectedFields)
        {
            if (!selectedFields) { return; }

            var $container = _fwdc.currentDocumentContainer();

            var $currentSelected = $container.find(".ui-selected");

            $currentSelected.each(function ()
            {
                var $field = $(this);
                var id = _findElementName($field);
                if (!id || selectedFields.indexOf(id) < 0)
                {
                    $field.removeClass("ui-selected");
                }
            });

            $container.find(".ui-selectee").filter(":NOT(.ui-selected)").find(".ui-resizable").addBack(".ui-resizable").resizable("destroy");

            var $dragContainer;

            var $blurField;

            var ii;
            for (ii = 0; ii < selectedFields.length; ii++)
            {
                var $field = _fwdc.formField(selectedFields[ii]);
                if ($field)
                {
                    var $selectee = $field.closest(".ui-selectee");
                    $selectee.addClass("ui-selected");

                    $selectee.find("a,button").each(_fwdc.disableClick);

                    if ($selectee.hasClass("fast-ui-resizable")) { _setResizable($selectee); }

                    var draggable = $selectee.hasClass("fast-ui-draggable");
                    if (draggable)
                    {
                        _initDraggable($selectee);
                    }

                    if (!$dragContainer && $selectee.hasClass("fast-ui-draggable"))
                    {
                        $dragContainer = $selectee.closest(".ControlGridContainer");
                        if (!$dragContainer.length)
                        {
                            $dragContainer = null;
                        }
                    }

                    if ($field.is(":focus")) { $blurField = $field; }
                }
            }

            if ($blurField)
            {
                window.setTimeout(function () { $blurField.blur(); }, 1);
            }

            if ($dragContainer)
            {
                window.setTimeout(function ()
                {
                    $dragContainer.trigger("fastfieldsselected");
                }, 1);
            }
        }

        function _setupSortableTables($container)
        {
            $container = $container || _fwdc.currentDocumentContainer();
            var $sortable = $container.find("tbody.TableSortable");
            if ($sortable && $sortable.length)
            {
                var startIndex = -1;
                var sourceTable = null;
                var received = false;

                $sortable.each(function ()
                {
                    var $this = $(this);

                    var sortGroup = $this.attr("data-fast-sortgroup");
                    var connectWith;

                    if (sortGroup)
                    {
                        connectWith = "#" + _fwdc.parentDocumentContainer($this).attr("id") + " [data-fast-sortgroup='" + sortGroup + "']";
                    }

                    var hasHandle = !!$this.findElementsByClassName("FastSortableHandle").length;

                    $this.sortable({
                        connectWith: connectWith,
                        //appendTo: _fwdc.parentDocumentContainer($this),
                        cancel: "tr.TableTotal,.CellEditable",
                        items: "tr.TDR:not(.fast-nosort)",
                        placeholder: "fast-sort-drop-placeholder",
                        forcePlaceholderSize: true,
                        handle: (hasHandle ? ".FastSortableHandle" : false),
                        helper: function (e, $tr)
                        {
                            var $helper = $tr.clone();

                            var $rowCells = $tr.children();
                            var $helperCells = $helper.children();

                            for (var ii = 0; ii < $helperCells.length; ++ii)
                            {
                                $($helperCells[ii])
                                    .width($($rowCells[ii]).width())
                                    .height($($rowCells[ii]).height());
                            }

                            $helper
                                .addClass("fast-sort-dragging")
                                .appendTo(_fwdc.parentDocumentContainer($this));

                            //tr.remove().appendTo(_fwdc.parentDocumentContainer($this));

                            return $helper;
                        },
                        start: function (event, ui)
                        {
                            var $item = ui.item;
                            startIndex = $item.parent().children().index($item);
                            sourceTable = $this.attr("data-table-id");
                            received = false;

                            $(connectWith).addClass("fast-sorting");

                            ui.placeholder.append('<td class="fast-sort-drop-placeholder" colspan="' + $item.children().length + '"><div class="fast-sort-drop-placeholder">&nbsp;</div></td>');

                            // Re-evaluate size of connected tables.  Fixes an issue where connected tables were zero height if they had no rows.
                            $(this).sortable("refreshPositions");
                        },
                        receive: function (event, ui)
                        {
                            received = true;
                            var $item = ui.item;
                            var newIndex = $item.parent().children("tr.TDR:not(.fast-nosort)").index($item);
                            FWDC.setProperties($this.attr("data-sort-control"), "SortRow", $this.attr("data-table-id"), { sourceTable: sourceTable, startIndex: startIndex, destIndex: newIndex });
                        },
                        stop: function (event, ui)
                        {
                            if (received) { return; }
                            var $item = ui.item;
                            var newIndex = $item.parent().children("tr.TDR:not(.fast-nosort)").index($item);
                            FWDC.setProperties($this.attr("data-sort-control"), "SortRow", $this.attr("data-table-id"), { sourceTable: sourceTable, startIndex: startIndex, destIndex: newIndex });
                            $(connectWith).removeClass("fast-sorting");
                        }
                    });
                });
            }
        }

        var MatchType = {
            NONE: 0,
            STARTSWITH: 1,
            MATCH: 2
        };

        function containsi(element, filter)
        {
            var result = false;
            if (element instanceof jQuery)
            {
                element.each(function ()
                {
                    if (containsi(this, filter))
                    {
                        result = true;
                    }
                    else
                    {
                        result = false;
                        return false;
                    }
                });

                return result;
            }
            else
            {
                if (!filter) { return true; }

                if (typeof filter === "string")
                {
                    return containsi_s(element.textContent || element.innerText || '', filter);
                }
                else if ($.isArray(filter))
                {
                    return containsi_sa(element.textContent || element.innerText || "", filter);
                }

                return false;
            }
        }

        function containsi_s(string, filterstring)
        {
            if (!filterstring) { return true; }
            return string.toLowerCase().indexOf(filterstring.toLowerCase()) > -1;
        }

        function containsi_sa(string, filters)
        {
            if (filters)
            {
                var filterCount = filters.length;
                for (var ii = 0; ii < filterCount; ii++)
                {
                    if (string.toLowerCase().indexOf(filters[ii].toLowerCase()) < 0)
                    {
                        return false;
                    }
                }
            }

            return true;
        }

        function containsr(element, regex)
        {
            var result = false;
            if (element instanceof jQuery)
            {
                element.each(function ()
                {
                    if (containsr(this, regex))
                    {
                        result = true;
                    }
                    else
                    {
                        result = false;
                        return false;
                    }
                });

                return result;
            }
            else
            {
                if (!regex) { return true; }

                if (regex instanceof RegExp)
                {
                    return !!containsr_s(element.textContent || element.innerText || '', regex);
                }
                else if ($.isArray(regex))
                {
                    return !!containsr_sa(element.textContent || element.innerText || '', regex);
                }

                return false;
            }
        }

        function containsr_s(string, regex)
        {
            if (!regex) { return true; }
            //return string.search(regex) > -1;
            switch (string.search(regex))
            {
                case 0:
                    return MatchType.STARTSWITH;
                case -1:
                    return MatchType.NONE;
            }

            return MatchType.MATCH;
        }

        function containsr_sa(string, regexes)
        {
            var startsWith;
            if (regexes)
            {
                var regexCount = regexes.length;
                for (var ii = 0; ii < regexCount; ii++)
                {
                    if (ii === 0)
                    {
                        switch (string.search(regexes[ii]))
                        {
                            case 0:
                                startsWith = true;
                                break;
                            case -1:
                                return MatchType.NONE;
                        }
                    }
                    else if (string.search(regexes[ii]) < 0)
                    {
                        return MatchType.NONE;
                    }
                }
            }

            return startsWith ? MatchType.STARTSWITH : MatchType.MATCH;
        }

        function _handleTabRecalc(event, sender, $sender)
        {
            if (event)
            {
                event.stopPropagation();
                event.preventDefault();
                event.stopImmediatePropagation();
            }

            $sender = $sender || $(sender);
            var senderId = $sender.attr("id");


            // Push the actual check out of the event to handle Firefox AJAX/KeyDown issue: https://bugzilla.mozilla.org/show_bug.cgi?id=489375
            _fwdc.setTimeout("HandleTabRecalc:" + senderId, function ()
            {
                var valueChanged = _fwdc.checkValueChanged(sender, "HandleTabRecalc", {
                    callback: function ()
                    {
                        var $field = _fwdc.formField(senderId);
                        if ($field)
                        {
                            $field.focusNextInputField(event && (event.which === _fwdc.keyCodes.TAB && event.shiftKey));
                        }
                    }
                });

                if (!valueChanged)
                {
                    $sender.focusNextInputField(event && (event.which === _fwdc.keyCodes.TAB && event.shiftKey));
                }
            });
            return false;
        }

        function _fixModalOrder()
        {
            var $topMostModals = $(".TopMostModal");
            if ($topMostModals.length)
            {
                $topMostModals.each(function ()
                {
                    var dialog = $(this).data("ui-dialog");
                    if (dialog)
                    {
                        dialog.moveToTop();
                    }
                });
            }

            var $messageBoxes = $("div.FastDialogElement.FastMessageBox,div.FastDialogElement.FastBasicDialog");

            $messageBoxes.each(function ()
            {
                var dialog = $(this).data("ui-dialog");
                if (dialog)
                {
                    dialog.moveToTop();
                }
            });

            //var $chatAssistant = $(".ChatAssistantWindow");
            //if ($chatAssistant.length)
            //{
            //    var $fronts = $.findElementsByClassName("ui-front");
            //    if ($fronts && $fronts.length)
            //    {
            //        var zIndices = $fronts.map(function ()
            //        {
            //            return +$(this).css("z-index");
            //        }).get();

            //        var zIndexMax = Math.max(zIndices);

            //        $chatAssistant.css("z-index", zIndexMax);
            //    }
            //    else
            //    {
            //        $chatAssistant.css("z-index", null);
            //    }
            //}
        }

        function _onLinkClick(event)
        {
            var $sender = $(event.currentTarget);

            if (!$sender.attr("onclick"))
            {
                var href = $sender.attr("href") || "";

                if (href && !href.startsWith("#") && !href.startsWith("javascript:") && !href.startsWith("mailto:") && !$sender.attr("target"))
                {
                    if (!(window.location.hash === "error" || _fwdc.currentModalId() < 0))
                    {
                        _fwdc.setPropertiesInternalJson("MANAGER__", "LeavingWindow", "", true, null);
                        //FWDC.setProperties("MANAGER__", "LeavingWindow", "", null, false);
                    }
                }

                if (href && href.startsWith("#") && !isNaN(parseInt(href.slice(1), 10)))
                {
                    _ignoreHashChange = true;
                    _fwdc.setTimeout("IgnoreHashChange", function ()
                    {
                        _ignoreHashChange = false;
                    }, 100);
                }
            }
        }

        function _commitCombobox(field, event)
        {
            if (!field) { return false; }

            var $field = $(field);
            var comboMenu;
            if ($field.hasClass("FastComboboxOpen") && (comboMenu = _getComboMenu($field)) && (comboMenu.active || event))
            {
                comboMenu.select(event);
                return true;
            }

            return false;
        }

        function _ajaxPostFieldAttachment(fieldId, file)
        {
            var formData = new FormData();

            formData.append("AttachmentField", fieldId);
            formData.append("AttachmentFile", file);
            formData.append("AttachmentResponseMode", "Action");
            formData.append("FAST_SCRIPT_VER__", _fwdc.scriptVersion);
            formData.append("FAST_VERLAST__", _fwdc.fastVerLast);
            formData.append("FAST_VERLAST_SOURCE__", _fwdc.fastVerLastSource);
            formData.append("FAST_CLIENT_WINDOW__", _fwdc.getFastWindowName());

            return _fwdc.ajax({
                url: "AddAttachment?AttachmentResponseMode=Action",
                busy: true,
                data: formData,
                // These values are necessary to stop jQuery from interfering with our pre-setup FormData.
                contentType: false,
                processData: false,
                uploadprogress: function (event)
                {
                    _busy.setProgress(event.loaded || event.position || 0, event.total);
                },
                success: function (data, status, request)
                {
                    _fwdc.handleActionResult(data);
                },
                error: function (request)
                {
                    FWDC.attachmentFailed(_fwdc.getDecode("AttachmentError"), null, null, true);
                }
            });
        }

        function _createFieldAttachmentForm(fieldId, accept)
        {
            $("#FAST_FIELD_ATTACHMENT_FORM").remove();

            var $form = $($.parseHTML("<form/>"))
                .attr("method", "post")
                .attr("action", "AddAttachment")
                .attr("id", "FAST_FIELD_ATTACHMENT_FORM")
                .addClass("Hidden TemporaryUploadForm");

            var submitted = false;
            var $file = $($.parseHTML("<input/>"))
                .attr("type", "file")
                .attr("name", "AttachmentFile");

            function submit()
            {
                var files = $file[0].files;

                if (!submitted && files && files.length && files[0])
                {
                    _ajaxPostFieldAttachment(fieldId, files[0]);
                    submitted = true;
                }
            }

            if (accept)
            {
                $file.attr("accept", accept);
            }

            $file
                .change(submit)
                .appendTo($form);

            $form.appendTo(_fwdc.supportElementsContainer());

            return {
                $form: $form,
                $file: $file,
                getSubmitted: function ()
                {
                    return submitted;
                },
                submit: submit
            };
        }

        function _acceptFieldAttachment(formInfo)
        {
            formInfo.$file.click();

            if (!formInfo.getSubmitted() && formInfo.$file.val().length)
            {
                formInfo.submit();
            }
        }

        var _capturedFocusId;
        var _capturedFocusChild;
        _fwdc.captureFocus = function ()
        {
            _capturedFocusId = null;
            _capturedFocusChild = null;

            if (document && document.activeElement)
            {
                var $activeElement = $(document.activeElement);
                if ($activeElement && $activeElement.length)
                {
                    var id = $activeElement.attr("id");
                    if (id)
                    {
                        _capturedFocusId = id;
                        return _capturedFocusId;
                    }
                    else if ($activeElement.is("a"))
                    {
                        var $parent = $activeElement.closest("[id]");
                        if ($parent && $parent.length)
                        {
                            id = $parent.attr("id");
                            if (id)
                            {
                                _capturedFocusId = id;
                                _capturedFocusChild = "a";
                                return _capturedFocusId;
                            }
                        }
                    }
                }
            }
        };

        _fwdc.restoreFocus = function ()
        {
            if (_capturedFocusId)
            {
                var $element = $('#' + _capturedFocusId);

                var focus = false;
                if ($element && $element.length)
                {
                    if (_capturedFocusChild)
                    {
                        var $child = $element.find(_capturedFocusChild);
                        if ($child)
                        {
                            $element = $child.first();
                        }
                    }

                    if ($element && $element.length && $element.is(":visible"))
                    {
                        $element.focus();
                        focus = true;
                    }
                }

                _capturedFocusId = null;

                return focus;
            }

            return false;
        };

        var CellNavigation = {
            Tab: 1,
            ReverseTab: 2,
            Down: 3,
            Up: 4,
            Left: 5,
            Right: 6,
            Current: 7,
            RowStart: 8,
            RowEnd: 9,
            ColumnStart: 10,
            ColumnEnd: 11,
            TableStart: 12,
            TableEnd: 13
        };

        FWDC.ActionResult = {
            OK: 0,
            Modal: 1,
            ConfirmationRequired: 3,
            ConfirmationFailure: 4,
            NoAction: 5,
            CallFunction: 9,
            CloseWindow: 10,
            Navigated: 11,
            Closed: 12
        };

        FWDC.MessageBoxButton = {
            Ok: 0,
            OkCancel: 1,
            YesNoCancel: 3,
            YesNo: 4
        };

        FWDC.MessageBoxIcon = {
            None: 0,
            Error: 16,
            Information: 64,
            Question: 32,
            Warning: 48
        };

        FWDC.MessageBoxResult = {
            None: 0,
            Ok: 1,
            Cancel: 2,
            Yes: 6,
            No: 7
        };

        //FWDC.ready = _fwdc.$document.ready;
        //var _preReady = [];
        FWDC.ready = function (callback)
        {
            //_preReady.push(callback);
            _fwdcReadyCallbacks.add(callback);
        };

        FWDC.setMask = function (fieldId, mask)
        {
            var $field = _fwdc.formField(fieldId);
            if ($field) { $field.setMask(mask); }
        };

        FWDC.watermark = function (fieldOrId, watermark)
        {
            var $field = (typeof fieldOrId === "string" ? _fwdc.formField(fieldOrId) : fieldOrId);
            if ($field)
            {
                if ($field.is("select"))
                {
                    $field.data('fast-watermark', watermark);
                    var $blankOption = $field.children("option.watermark,option.BlankOption").first();
                    if ($blankOption && $blankOption.length && ($blankOption.hasClass("watermark") || !($blankOption.text() || "").trim()))
                    {
                        $blankOption.addClass("watermark").text(watermark);
                        _fwdc.onDocSelectChange($field.get(0), null, true);
                    }
                }
                else
                {
                    var focus = $field.is('input[type="password"]:focus');
                    if (focus)
                    {
                        $field.blur();
                    }

                    if (_fwdc.isCombobox($field))
                    {
                        // Workaround for IE10/11 focus + placeholder bug that opens the dropdown due to the input event being raised when the placeholder changes:
                        _suppressComboboxInput($field);
                    }

                    $field.data("fast-watermark", watermark);
                    //.attr("placeholder", watermark)
                    //.watermark();
                    if (watermark)
                    {
                        if ($field.is("input[type='email']"))
                        {
                            $field.watermark(watermark);
                        }
                        else if (Modernizr.placeholder)
                        {
                            $field.watermark(watermark);
                        }
                        else
                        {
                            // Workaround for IE input event on placeholder bug.
                            $field.watermark(watermark + "   ");
                        }
                    }
                    else
                    {
                        $field.watermark("");
                    }
                    //$field.attr("placeholder", watermark);
                    if (focus)
                    {
                        $field.focus();
                    }
                }
            }
        };

        function _tryFocus($elements, ignoreTabIndex, defaultFocus)
        {
            if ($elements && $elements.length)
            {
                var focused = false;
                $elements.each(function ()
                {
                    var $this = $(this);
                    // Not excluding DCC elements allows auto-focusing random checkboxes internally.
                    //if (!$this.closest(".fast-ui-selectable").length && _fwdc.focus("_tryFocus", $this, { checkTabIndex: !ignoreTabIndex, defaultFocus: defaultFocus }))
                    if (!$this.closest(".fast-ui-selectable,.NoAutoFocus").length
                        && (!$this.is("input") || !$this.closest(".DCC").length)
                        && _fwdc.focus("_tryFocus", $this, { checkTabIndex: !ignoreTabIndex, defaultFocus: defaultFocus }))
                    {
                        $this.removeClass("TempAutoFocus");

                        focused = true;
                        return false;
                    }
                });

                if (focused) { return true; }
            }

            return false;
        }

        function _tryFocusContainer($container, inputsOnly, defaultFocus)
        {
            var $elements;
            if (!_fwdc.autoFocusMode && defaultFocus)
            {
                return _tryFocus($elements = $container.find(inputsOnly ? "input,textarea,select" : "input,textarea,select,a,button").filter(":visible"), false, defaultFocus);
            }

            return _tryFocus($container.find(".TempAutoFocus"), true, defaultFocus)
                || _tryFocus($container.find("input,textarea,select").filter(":visible:enabled:not([readonly]):not(.FieldDisabled):not(.FastTableToggleInput)").add($container.find(".FastFocusable").filter(":visible")), false, defaultFocus)
                || _tryFocus($container.find("table.DocEditableTable tbody"), false, defaultFocus)
                || _tryFocus($elements = $container.find(inputsOnly ? "input,textarea,select" : "input,textarea,select,a,button").filter(":visible"), false, defaultFocus)
                || _tryFocus($elements, true, defaultFocus)
                || (!inputsOnly
                    && _tryFocus($container.find("tbody.DocTableBody"), false, defaultFocus));
        }

        FWDC.acceptFieldPopup = function (event)
        {
            var $dialog = $(event.target).closest(".FastFieldPopupDialog");
            var $modal = $dialog.find(".FastFieldPopup").data("fast-dialog-accepted", true);
            var $textArea = $modal.find("textarea").first();
            if ($textArea && $textArea.length)
            {
                var cm = $textArea.data("fast-code-mirror-editor");
                if (cm)
                {
                    cm.toTextArea();
                }
                else
                {
                    var cke = $textArea.data("fast-ckeditor-instance");
                    if (cke)
                    {
                        cke.updateElement();
                        cke.destroy();
                    }
                }

                _fwdc.setLastFocusField("");

                var recalcData = { 'DOC_MODAL_ID__': _fwdc.currentModalId() };
                recalcData[$textArea.attr("id")] = _fwdc.getFieldValue(null, $textArea);
                _recalc({ 'data': recalcData, 'source': $textArea.attr("id"), 'trigger': 'AcceptFieldPopup' });
            }

            return FWDC.closeFieldPopup(event);
        };

        function _closeFieldPopup(destroy)
        {
            var $dialogs = $("div.FastFieldPopup");
            if (destroy)
            {
                $dialogs.tryDestroyDialog();
            }
            else
            {
                $dialogs.dialog("close");
            }
        }

        FWDC.closeFieldPopup = function (event, destroy)
        {
            _closeFieldPopup(destroy);
            return _fwdc.stopEvent(event);
        };

        FWDC.setTableFilterBox = function (elementOrId, containerId, rowFilter)
        {
            var $filter = (typeof elementOrId === "string") ? $("#" + elementOrId) : elementOrId;
            var $container = typeof containerId === "string" ? $("#" + containerId) : $(containerId);

            $filter.watermark($filter.attr("title") + "  ");
            $filter.attr("title", "");

            $filter.keyup(function (event)
            {
                var filter = $filter.val();

                var $rows = $container.find("tbody tr");
                if (rowFilter) { $rows = $rows.filter(rowFilter); }
                $rows.css("display", "");
                if (filter)
                {
                    $rows.not(":containsi('" + filter.replace("'", "\\'") + "')").css("display", "none");
                }

                if (event.keyCode === _fwdc.keyCodes.ENTER)
                {
                    $rows = $container.find("tbody tr:visible");
                    if ($rows.length === 1)
                    {
                        var $link = $rows.find("a");
                        if ($link && $link.length === 1)
                        {
                            $link.click();
                        }
                    }
                }
            });

            return $filter;
        };

        function _getComboMenu($field)
        {
            var data = $field.data("ui-autocomplete");
            return data && data.menu;
        }

        function _suppressComboboxInput($field, uiAutocomplete)
        {
            uiAutocomplete = uiAutocomplete || $field.data("ui-autocomplete");

            if (uiAutocomplete && !$field.is(":focus") && !uiAutocomplete._fastSuppressInput)
            {
                uiAutocomplete._fastSuppressInput = true;
                uiAutocomplete.element.one("focus", function (event)
                {
                    _fwdc.setTimeout("unsuppressCombobox", function ()
                    {
                        uiAutocomplete._fastSuppressInput = false;
                    }, 1);
                });
            }
        }

        FWDC.setupCombobox = function (config)
        {
            var fieldId = config.fieldId;
            var $field = (config.field || _fwdc.formField(fieldId));
            if (!$field) { return; }

            var items = config.items;
            var value = config.value;
            var text = config.text;
            var hasDescription = config.hasDescription;
            var enterEvent = config.enterEvent;
            var onSelect = config.onSelect;
            var isCell = config.isCell;
            var isInput = $field.is("input");

            if (isInput)
            {
                $field.attr("spellcheck", "false");
            }

            var uiAutocomplete;
            var menu;

            _setComboboxData($field, value, text);

            var fieldElement = $field[0];
            if (fieldElement === _currentField)
            {
                _setLastValue(fieldElement, _fwdc.getFieldValue(fieldElement, $field));
            }

            var $container = $field.parent();

            $field.keydown(function (event)
            {
                if (event.ctrlKey || event.altKey || event.metaKey) { return; }

                if (event.keyCode === _fwdc.keyCodes.ENTER)
                {
                    if (!$field.hasClass("FastComboboxOpen"))
                    {
                        if (_checkComboText($field, true) && enterEvent === true)
                        {
                            $field.autocomplete("search"); // Force a search event here to prevent delay issues.
                        }
                        else if (enterEvent === true)
                        {
                            $field.focusNextInputField(false, true, false, true);
                            _fwdc.stopEvent(event);
                        }
                        else if (enterEvent)
                        {
                            FWDC.eventOccurred(event, { field: enterEvent, eventType: _fwdc.EventType.Enter, trigger: "Combobox.keydown.Enter", sourceId: enterEvent });
                        }
                    }
                }
                else if (event.keyCode === _fwdc.keyCodes.ESCAPE)
                {
                    $field.val($field.data("fast-combo-text"));
                    $field.autocomplete("close");
                    event.stopImmediatePropagation();
                    return false;
                }
                else if (event.keyCode === _fwdc.keyCodes.UP)
                {
                    if (!$field.hasClass("FastComboboxOpen"))
                    {
                        event.stopImmediatePropagation();
                    }
                }
                else if (event.keyCode === _fwdc.keyCodes.DOWN)
                {
                    if (!$field.hasClass("FastComboboxOpen") && !$field.is("[readonly]"))
                    {
                        $field.autocomplete("search", "").focus();
                        event.stopImmediatePropagation();
                        return false;
                    }
                }
                else if (_fwdc.handleF9 && (event.keyCode === _fwdc.keyCodes.F9))
                {
                    if (!isCell)
                    {
                        _commitCombobox($field, event);
                        /*if ($field.hasClass("FastComboboxOpen"))
                        {
                            menu.select(event);
                        }*/
                        //_checkComboText($field, true);
                        _handleReview($field[0]);
                        event.stopImmediatePropagation();
                        return false;
                    }
                }
                /*else if (event.keyCode === 16 || event.keyCode === 17 || event.keyCode === 18 || event.altKey || event.ctrlKey || event.metaKey) // Shift, Ctrl, Alt
                {
                    event.stopImmediatePropagation();
                }*/
            });

            $field.blur(function (event)
            {
                _checkComboText($field);
            });

            var autocomplete = $field.autocomplete($.extend(_autocompleteOptions, {
                //appendTo: _fwdc.closestScrollContainer($field, _fwdc.supportElementsContainer()),
                appendTo: _fwdc.supportElementsContainer(),
                source: items,
                minLength: 0,
                autoFocus: true,
                delay: 0,
                maxHeight: 300,
                zIndex: 3,
                select: function (event, ui)
                {
                    var keyEvent = event && event.originalEvent && event.originalEvent.originalEvent;
                    if (keyEvent && !/^key/.test(keyEvent.type))
                    {
                        keyEvent = null;
                    }

                    var mouseEvent = event && event.originalEvent && event.originalEvent.originalEvent;
                    if (mouseEvent && !/^mouse|^click/.test(mouseEvent.type))
                    {
                        mouseEvent = null;
                    }

                    var isEnterTrigger = keyEvent && (keyEvent.keyCode === _fwdc.keyCodes.ENTER || keyEvent.keyCode === _fwdc.keyCodes.NUMPAD_ENTER);
                    var isMouseTrigger = !!mouseEvent && _fwdc.isNormalClick(mouseEvent);

                    _fwdc.Events.Field.focus(fieldElement);

                    if (ui.item.moreItemsOption)
                    {
                        if (isEnterTrigger || isMouseTrigger)
                        {
                            var text = $field.val();
                            _endEditCell(false);
                            //FWDC.setProperties = function (control, type, target, properties, async, extraData, confirmResultCallback)
                            setTimeout(function () { FWDC.setProperties("", "ComboMoreItems", fieldId, { "moreComboText": text }); }, 1);
                        }
                        return false;
                    }

                    var self = this;

                    $field.val(ui.item.label);
                    _setComboboxData($field, ui.item.value, ui.item.label);

                    var commitEdits;

                    if (onSelect)
                    {
                        onSelect(event, ui);
                    }
                    else
                    {
                        if (_fwdc.checkValueChanged(self, "autocomplete.onSelect", { test: true }))
                        {
                            var isKeyEvent = keyEvent && /^key/.test(keyEvent.type);

                            if (isKeyEvent && ((keyEvent.keyCode === _fwdc.keyCodes.TAB) || ((keyEvent.keyCode === _fwdc.keyCodes.ENTER) && enterEvent === true)))
                            {
                                _handleTabRecalc(keyEvent, self, $field);
                                return false;
                            }
                            /*else if (isKeyEvent && (keyEvent.keyCode === _fwdc.keyCodes.ENTER) && enterEvent === true)
                            {
                                $field.focusNextInputField(false, true, false, true);
                                return;
                            }*/
                            else
                            {
                                _fwdc.checkValueChanged(self, "autocomplete.onSelect");
                                commitEdits = false;
                            }
                        }
                    }

                    if (isEnterTrigger && enterEvent)
                    {
                        if (enterEvent === true)
                        {
                            $field.focusNextInputField(false, true, false, true);
                        }
                        else
                        {
                            FWDC.eventOccurred(event, { field: enterEvent, eventType: _fwdc.EventType.Enter, trigger: "Combobox.autocomplete.select", sourceId: enterEvent, commitEdits: commitEdits });
                        }
                    }
                    return false;
                },
                focus: function (event, ui)
                {
                    if (!event.originalEvent.originalEvent || !/^mouseenter/.test(event.originalEvent.originalEvent.type))
                    {
                        $field.data("fast-combo-focus-value", ui.item.value);
                        $field.data("fast-combo-focus-text", ui.item.label);

                        if (isInput && event.originalEvent.originalEvent && /^key/.test(event.originalEvent.originalEvent.type))
                        {
                            $field.val(ui.item.label);
                            if ($field[0].select)
                            {
                                $field[0].select();
                            }
                        }
                    }
                    return false;
                },
                search: function (event, ui)
                {
                    var $window = _fwdc.$window;
                    var windowOffset = $field.offset().top + $field.outerHeight() - $window.scrollTop();
                    if (($window.height() - windowOffset) < 300)
                    {
                        $field.autocomplete("option", "position", { my: "left bottom", at: "left top" });
                    }
                    else
                    {
                        $field.autocomplete("option", "position", { my: "left top", at: "left bottom" });
                    }
                },
                open: function (event, ui)
                {
                    _fwdc.Events.Field.focus(fieldElement, true);

                    //menu.widget().css("zIndex", _fwdc.containerZIndex($field) + 10);

                    // Ensure autocomplete menus appear above qtip tooltips
                    if ($.fn && $.fn.qtip && $.fn.qtip.zindex)
                    {
                        menu.widget().css("zIndex", $.fn.qtip.zindex + 100);
                    }

                    $field.removeClass("FastComboboxClosed").addClass("FastComboboxOpen");
                    $container.attr("aria-expanded", "true");
                    //$field.autocomplete("widget").zIndex($field.zIndex() + 10);
                    var $current;
                    var value = _fwdc.getFieldValue($field);
                    var text = $field.val();
                    var $textCurrent;

                    if (text === $field.data("fastComboText"))
                    {
                        $field.autocomplete("widget").find(".ui-menu-item").each(function ()
                        {
                            var $item = $(this);

                            if ($item.data("uiAutocompleteItem").value === value)
                            {
                                $current = $item;
                                return false;
                            }
                            if ($item.text() === text)
                            {
                                $textCurrent = $item;
                            }
                        });

                        $current = $current || $textCurrent;

                        var comboMenu;
                        if ($current && (comboMenu = _getComboMenu($field)))
                        {
                            comboMenu.focus(event, $current);
                        }
                    }

                    if (isCell)
                    {
                        var qtipApi;
                        var myPosition = $field.autocomplete("option", "position.my");
                        var topPosition = myPosition.indexOf("top") > -1;
                        if ((qtipApi = $field.data("qtip")) && qtipApi.fastIsTableField && topPosition)
                        {
                            qtipApi.set("position.my", "bottom center");
                            qtipApi.set("position.at", "top center");
                        }
                    }
                },
                close: function (event, ui)
                {
                    $field.removeClass("FastComboboxOpen").addClass("FastComboboxClosed");
                    $container.attr("aria-expanded", "false");
                    if (isCell)
                    {
                        var qtipApi;
                        if ((qtipApi = $field.data("qtip")) && qtipApi.fastIsTableField)
                        {
                            qtipApi.set("position.my", "top center");
                            qtipApi.set("position.at", "bottom center");
                        }
                    }
                }
            }));

            uiAutocomplete = $field.data("ui-autocomplete");

            // Workaround for IE10/11 Unicode oninput bug:
            // http://connect.microsoft.com/IE/feedback/details/816137/ie-11-ie-10-input-elements-with-unicode-entity-character-values-cause-oninput-events-to-be-fired-on-page-load
            _suppressComboboxInput($field, uiAutocomplete);

            menu = uiAutocomplete.menu;
            menu.widget()
                .css("font-family", $field.css("font-family"))
                .css("font-size", $field.css("font-size"))
                .css("text-align", $field.css("text-align"));

            // Remove base UI Menu mouseenter and mouseleave logic.
            /*$field.autocomplete("widget")
                .off("mouseenter", ".ui-menu-item")
                .off("mouseleave")
                .on("mouseenter", ".ui-menu-item", function (event)
                {
                    var $item = $(event.target);
                    $item.addClass("fast-ui-state-active");
                })
                .on("mouseleave", ".ui-menu-item", function (event)
                {
                    var $item = $(event.target);
                    $item.removeClass("fast-ui-state-active");
                })
                .on("mousedown", ".ui-menu-item", function (event)
                {
                    var $item = $(event.target).closest(".ui-menu-item");
                    if ($item && $item.length)
                    {
                        menu.focus(event, $item);
                    }
                });*/

            var menuId = $field.autocomplete("widget").attr("id");

            $field
                .addClass("FastComboboxClosed")
                .attr("aria-autocomplete", "inline")
                .attr("aria-controls", menuId);

            $container
                .attr("role", "combobox")
                .attr("aria-expanded", "false")
                .attr("aria-owns", menuId)
                .attr("aria-haspopup", "listbox");

            var $button = $('<button type="button" class="FastInputButton FastComboboxButton" tabIndex="-1"></button>');
            $button.click(function (event)
            {
                if (_busy()) { return false; }
                if (!$field.is("[readonly]"))
                {
                    if ($field.hasClass("FastComboboxOpen"))
                    {
                        $field.autocomplete("close").focus();
                    }
                    else
                    {
                        menu.fastClicking = true;
                        $field.autocomplete("search", "").focus();
                    }
                }
            })
                .attr("aria-controls", menuId);

            if (!menu.collapseAllOriginal)
            {
                menu.collapseAllOriginal = menu.collapseAll;
                menu.collapseAll = function (event, all)
                {
                    if (!this.fastClicking)
                    {
                        this.collapseAllOriginal(event, all);
                    }
                    this.fastClicking = false;
                };
            }

            var $image = $("<div></div>")
                .addClass("FastComboboxButtonImage")
                .text(_fwdc.getDecode("ToggleCombobox", "Toggle Combobox"));
            $button.append($image);
            $field.after($button);

            if (hasDescription)
            {
                FWDC.setupComboboxDescriptions(fieldId, $field);
            }

            return autocomplete;
        };

        FWDC.setupComboboxDescriptions = function (fieldId, $field)
        {
            if (!$field)
            {
                $field = _fwdc.formField(fieldId);
            }

            if ($field)
            {
                var $button = $('<button type="button" class="FieldHeaderTool FastFieldPopupButton FastComboboxMenuButton"></button>')
                    .text(_fwdc.getDecode("OpenComboboxMenu", "Open Combobox Descriptions"))
                    .click(function (event)
                    {
                        if (_busy()) { return false; }
                        _fwdc.showComboboxMenu(fieldId, $field);
                    });

                if (_fwdc.autoFocusMode)
                {
                    $button.attr("tabindex", "-1");
                }

                $button.appendTo($field.parent());

                $field.addClass("HasMenuButton");
            }
        };

        FWDC.refreshManager = function (verLast, verLastSource)
        {
            if (verLast)
            {
                FWDC.setVerLast(verLast, verLastSource);
            }
            if (!FWDC.setProperties("MANAGER__", "Refresh", ""))
            {
                setTimeout(FWDC.refreshManager, 500);
            }
        };

        FWDC.messageBox = function (options)
        {
            _fwdc.onContentReady(function () { _messageBox(options); });
        };

        function _messageBox(options)
        {
            var $activeElement = $(document.activeElement);
            var focusId = $activeElement.attr("data-focus-id") || $activeElement.attr("id");

            if (typeof options === "string")
            {
                options = { message: options };
            }

            var $accessKeyElements = _fwdc.disableAccessKeys();

            var $body = _fwdc.$body();
            var $modal = $('<div class="FastDialogElement FastMessageBox" style="display:none"></div>');
            //$modal.css("overflow", "hidden");

            if (options.icon && options.icon !== FWDC.MessageBoxIcon.None)
            {
                var $icon = $($.parseHTML('<div class="FastMessageBoxIcon" aria-hidden="true"></div>'));

                switch (options.icon)
                {
                    case FWDC.MessageBoxIcon.Error:
                        $icon.addClass("FastMessageBoxIconError");
                        break;
                    case FWDC.MessageBoxIcon.Information:
                        $icon.addClass("FastMessageBoxIconInformation");
                        break;
                    case FWDC.MessageBoxIcon.Question:
                        $icon.addClass("FastMessageBoxIconQuestion");
                        break;
                    case FWDC.MessageBoxIcon.Warning:
                        $icon.addClass("FastMessageBoxIconWarning");
                        break;
                }

                $modal.append($icon);
            }

            //$modal.append('<div class="FastMessageBoxCaption">' + options.message + '</div>');
            var $content = options.html ? $('<div class="FastMessageBoxCaption">' + options.html + '</div>') : $('<div class="FastMessageBoxCaption"></div>').text(options.message);
            $modal.append($content);

            var colorClass = options.colorClass; _fwdc.getCurrentManagerColor();
            if (colorClass)
            {
                colorClass = " " + colorClass;
            }

            if (options.callback && typeof options.callback === "string")
            {
                options.callback = _fwdc.Events.MessageBox[options.callback];
            }

            var standardDecodes = _fwdc.standardDecodes();

            var buttons = [];
            switch (options.buttons ? options.buttons : FWDC.MessageBoxButton.Ok)
            {
                case FWDC.MessageBoxButton.Ok:
                    buttons.push({
                        "text": options.okDecode || standardDecodes.MsgBoxOk,
                        //"classes": "FastMessageBoxButtonOk",
                        "class": "FastMessageBoxButtonOk",
                        "click": function (event) { _submitMessageBox(event, $modal, options.source, options.tag, FWDC.MessageBoxResult.Ok, options.callback); }
                    });
                    break;

                case FWDC.MessageBoxButton.OkCancel:
                    buttons.push({
                        "text": standardDecodes.MsgBoxCancel,
                        //"classes": { "ui-button": "FastMessageBoxButtonCancel" },
                        "class": "FastMessageBoxButtonCancel",
                        "click": function (event) { _submitMessageBox(event, $modal, options.source, options.tag, FWDC.MessageBoxResult.Cancel, options.callback); }
                    });
                    buttons.push({
                        "text": options.okDecode || standardDecodes.MsgBoxOk,
                        //"classes": "FastMessageBoxButtonOk",
                        "class": "FastMessageBoxButtonOk",
                        "click": function (event) { _submitMessageBox(event, $modal, options.source, options.tag, FWDC.MessageBoxResult.Ok, options.callback); }
                    });
                    break;

                case FWDC.MessageBoxButton.YesNo:
                    buttons.push({
                        "text": standardDecodes.MsgBoxNo,
                        //"classes": { "ui-button": "FastMessageBoxButtonNo" },
                        "class": "FastMessageBoxButtonNo",
                        "click": function (event) { _submitMessageBox(event, $modal, options.source, options.tag, FWDC.MessageBoxResult.No, options.callback); }
                    });
                    buttons.push({
                        "text": standardDecodes.MsgBoxYes,
                        //"classes": "FastMessageBoxButtonYes",
                        "class": "FastMessageBoxButtonYes",
                        "click": function (event) { _submitMessageBox(event, $modal, options.source, options.tag, FWDC.MessageBoxResult.Yes, options.callback); }
                    });
                    break;

                case FWDC.MessageBoxButton.YesNoCancel:
                    buttons.push({
                        "text": standardDecodes.MsgBoxCancel,
                        //"classes": "FastMessageBoxButtonCancel",
                        "class": "FastMessageBoxButtonCancel",
                        "click": function (event) { _submitMessageBox(event, $modal, options.source, options.tag, FWDC.MessageBoxResult.Cancel, options.callback); }
                    });
                    buttons.push({
                        "text": standardDecodes.MsgBoxNo,
                        //"classes": "FastMessageBoxButtonNo",
                        "class": "FastMessageBoxButtonNo",
                        "click": function (event) { _submitMessageBox(event, $modal, options.source, options.tag, FWDC.MessageBoxResult.No, options.callback); }
                    });
                    buttons.push({
                        "text": standardDecodes.MsgBoxYes,
                        //"classes": "FastMessageBoxButtonYes",
                        "class": "FastMessageBoxButtonYes",
                        "click": function (event) { _submitMessageBox(event, $modal, options.source, options.tag, FWDC.MessageBoxResult.Yes, options.callback); }
                    });
                    break;

                default:
            }

            var position = { my: "center", at: "center", collision: "none", of: window };
            var minWidth = 300;
            var minHeight = 100;
            var maxWidth = Math.min(950, _fwdc.windowWidth - 20);
            var maxHeight = Math.min(700, _fwdc.windowHeight - 20);
            var show;
            var hide;
            var width = "auto";

            if (_fwdc.screenWidth < _fwdc.ScreenWidths.Medium)
            {
                width = "95%";
            }

            $body.append($modal);

            var titleClass = options.caption ? "" : " BlankTitle";

            $modal.dialog({
                modal: true,
                title: options.caption,
                draggable: true,
                resizable: false,
                width: width,
                minWidth: minWidth,
                minHeight: minHeight,
                maxWidth: maxWidth,
                maxHeight: maxHeight,
                dialogClass: "FastMessageBox FastPanelDialog " + _fwdc.getFastModalClass() + colorClass + titleClass,
                closeOnEscape: false,
                closeText: _fwdc.getCloseText(),
                position: position,
                show: show,
                hide: hide,
                describedByContent: true, // Custom option that enables the aria-describedby to read the full dialog content.
                open: function (event, ui)
                {
                    _endEditCell(false);
                    FWDC.hideViewMenus();
                    _fwdc.hideToolTips();
                    _fwdc.closeComboboxes();
                    //$(".ui-dialog-titlebar-close", $modal.dialog("widget")).hide();
                    _fixModalOrder();
                    _fwdc.updateScreenReader();
                    _fwdc.showCurrentFieldTip();
                },
                initFocus: function ()
                {
                    var uiDialog = $(this).data("uiDialog");
                    if (uiDialog)
                    {
                        uiDialog.uiDialogButtonPane.find("button").last().focus();
                    }
                },
                drag: function () { FWDC.checkFieldTipPositions(); },
                close: function ()
                {
                    _fwdc.restoreAccessKeys($accessKeyElements);
                    FWDC.hideViewMenus();
                    _fwdc.hideToolTips();
                    _fwdc.closeComboboxes();
                    $modal.remove();

                    if (document.activeElement === document.body && focusId)
                    {
                        var $field = _fwdc.formField(focusId);
                        if ($field)
                        {
                            _fwdc.cancelPendingFocus();
                            _fwdc.focus("MessageBox.Close", $field);
                        }
                    }

                    _fwdc.showCurrentFieldTip();
                },
                buttons: buttons
            });
        };

        FWDC.showVersion = function (doc, version, compare)
        {
            return _fwdc.ajax({
                url: 'ShowVersion',
                data: function ()
                {
                    return _fwdc.getDocPostParameters({ DOC__: doc, VERSION__: version, COMPARE__: !!compare }, "input[type='hidden']");
                },
                success: function (data, status, request)
                {
                    _fwdc.handleActionResult(data);
                }
            });
        };

        function _showTip(element, content, panel)
        {
            var $element = $(element);

            if ($element.data("qtip"))
            {
                $element.qtip("destroy");
            }

            var $tipText = $($.parseHTML(content.tipHtml))
                .attr("tabindex", "0")
                .addClass("FastShowTipContent");

            var strFocusGuardClass = "FastShowTipFocusGuard";

            var $container = $element.closest(".ui-dialog");
            if (!$container.length)
            {
                $container = _fwdc.$body();
            }

            var options = {
                content:
                {
                    text: $tipText,
                    title:
                    {
                        text: content.captionHtml,
                        button: _getQTipCloseButton()
                    }
                },
                role: "dialog",
                position:
                {
                    viewport: _fwdc.$window,
                    container: $container,
                    my: 'top center',
                    at: 'bottom center',
                    adjust:
                    {
                        method: "shift flip"
                    }
                },
                style:
                {
                    classes: 'FastSoloTip FastInfoTip'
                },
                show:
                {
                    autofocus: ".FastShowTipContent"
                },
                events:
                {
                    show: function (event, api)
                    {
                        _fwdc.showCurrentFieldTip();
                    },
                    render: function (event, api)
                    {
                        if (content.captionHtml)
                        {
                            api.elements.tooltip.attr("aria-describedby", api.elements.tooltip.attr("id") + "-title");
                        }
                        else
                        {
                            api.elements.tooltip.removeAttr("aria-describedby");
                        }

                        // Attach focus guards to the tooltip's root element so they can manage keeping focus inside the "tooltip".
                        $("<div/>",
                            {
                                "class": strFocusGuardClass,
                                "tabindex": "0"
                            })
                            .on("focus", function ()
                            {
                                $(this)
                                    .closest(".qtip")
                                    .find(":focusable")
                                    .filterNotHasClassName(strFocusGuardClass)
                                    .last()
                                    .focus();
                            })
                            .prependTo(api.elements.tooltip);

                        $("<div/>",
                            {
                                "class": strFocusGuardClass,
                                "tabindex": "0"
                            })
                            .on("focus", function ()
                            {
                                $(this)
                                    .closest(".qtip")
                                    .find(":focusable")
                                    .filterNotHasClassName(strFocusGuardClass)
                                    .first()
                                    .focus();
                            })
                            .appendTo(api.elements.tooltip);
                    },
                    hide: function (event, api)
                    {
                        _fwdc.showCurrentFieldTip();
                        api.destroy(true);

                        if (event
                            && event.originalEvent
                            && ((event.originalEvent.type === "keydown" && event.originalEvent.which === _fwdc.keyCodes.ESCAPE)
                                || (event.originalEvent.target && $(event.originalEvent.target).hasClass("qtip-close"))))
                        {
                            $element.focus();
                        }
                    }
                }
            };

            if (panel)
            {
                $.extend(options,
                    {
                        position:
                        {
                            my: 'top right',
                            at: 'bottom right'
                        }
                    });
            }

            $element.qtip(options).qtip("show");
        }

        FWDC.raiseStandardEvent = function (event, data)
        {
            return FWDC.setProperties("", "StandardEvent", event, data);
        };

        FWDC.moreHelp = function (target)
        {
            return FWDC.raiseStandardEvent("ViewHelp", { field: target });
        };

        function _verLastNumber(verlast)
        {
            var parts = verlast.split(".", 2);
            if (parts.length < 2) { return -1; }

            var num = parseInt(parts[0], 10);
            if (isNaN(num)) { return -1; }

            return num;
        }

        FWDC.setVerLast = function (verlast, source, force)
        {
            var currentNumber = _verLastNumber(_fwdc.fastVerLast);
            var newNumber = _verLastNumber(verlast);

            if (force || newNumber > currentNumber)
            {
                _fwdc.fastVerLast = verlast;
                _fwdc.fastVerLastSource = source;
                //_fwdc.applyVerLast();
            }
            else if (newNumber < currentNumber)
            {
                _fwdc._warn("Ignoring lower new ver last: " + verlast + " vs. " + _fwdc.fastVerLast);
            }

            FWDC.fastReady = !_fwdc.exporting;
        };

        function _getMobileModalDialogPosition()
        {
            //return { my: "top center", at: "top center", collision: "fit", of: _fwdc.window };
            //return { my: "center top", at: "center top", collision: "none", of: $(".ManagerMobileHeader") };
            return { my: "center top", at: "center top", collision: "none", of: _fwdc.window };
        }

        FWDC.loadManager = function (trigger, copy)
        {
            //_fwdc._log("Waiting for condUI promise to load content");
            //condUIPromise.finally(function ()
            //{
            //    _fwdc._log("CondUI promise finished.  Loading content...");
            //    _fwdc.cancelAutoRevealBody();
            //    _fwdc.$document.ready(function () { _fwdc.loadManager(trigger, { noRefresh: false, copy: copy, initial: true }); });
            //});

            _fwdc.cancelAutoRevealBody();
            _fwdc.$document.ready(function () { _fwdc.loadManager(trigger, { noRefresh: false, copy: copy, initial: true }); });
        };

        FWDC.importFailed = function (messageBox, fastverlast, fastverlastsource, refresh)
        {
            if (fastverlast) { FWDC.setVerLast(fastverlast, fastverlastsource); }

            if (typeof messageBox === "string")
            {
                messageBox = { message: messageBox, icon: FWDC.MessageBoxIcon.Error };
            }

            if (refresh)
            {
                messageBox.callback = function ()
                {
                    _fwdc.refreshPage("importFailed");
                };
            }

            _busy.hide();

            FWDC.messageBox(messageBox);
        };

        FWDC.importAccepted = function (verLast)
        {
            $("#IMPORT_DIALOG").tryDestroyDialog();
            _fwdc.refreshWindowContent(verLast, undefined, undefined, "ImportAccepted", true);
        };

        FWDC.viewAttachment = function (options)
        {
            if (typeof options === "string")
            {
                window.open("ViewAttachment?Key=" + encodeURIComponent(options) + "&FAST_SCRIPT_VER__=" + encodeURIComponent(_fwdc.scriptVersion) + "&FAST_VERLAST__=" + encodeURIComponent(_fwdc.fastVerLast));
            }
            else
            {
                options.FAST_SCRIPT_VER__ = _fwdc.scriptVersion;
                options.FAST_VERLAST__ = _fwdc.fastVerLast;
                window.open("ViewAttachment?" + $.param(options));
            }
        };

        FWDC.removeAttachment = function (key, message, caption)
        {
            if (_busy()) { return false; }

            FWDC.messageBox({
                message: message,
                caption: caption,
                buttons: FWDC.MessageBoxButton.YesNo,
                icon: FWDC.MessageBoxIcon.Question,
                callback: function ($modal, tag, result)
                {
                    if (result === FWDC.MessageBoxResult.Yes)
                    {
                        _fwdc.ajax({
                            url: 'RemoveAttachment',
                            data: $.param({ KEY__: key }),
                            commitEdits: false,
                            success: function (data, status, request)
                            {
                                _fwdc.handleActionResult(data);
                            }
                        });
                    }
                }
            });
        };

        FWDC.attachmentFailed = function (error, fastverlast, fastverlastsource, refresh)
        {
            $("#AttachmentForm").find(".DialogProgressBar").progressbar("value", 0);
            if (fastverlast) { FWDC.setVerLast(fastverlast, fastverlastsource); }
            if (refresh)
            {
                if (typeof error === "string")
                {
                    error = { message: error, icon: FWDC.MessageBoxIcon.Error };
                }
                error.callback = function ()
                {
                    _fwdc.refreshWindowContent();
                };
            }
            FWDC.messageBox(error);

            // Wait to hide the busy indicator until everything is processed so anything queued up doesn't happen with bad verlast info/etc
            _busy.hide();
        };

        FWDC.attachmentAccepted = function (verLast, verLastSource)
        {
            $("#AttachmentForm").find(".DialogProgressBar").progressbar("value", 100);
            $("#ATTACHMENT_DIALOG").tryDestroyDialog();
            _fwdc.refreshWindowContent(verLast, verLastSource, undefined, "AttachmentAccepted", true);
        };

        FWDC.acceptAttachmentDialog = function (event)
        {
            _fwdc.stopEvent(event);
            $("#AttachmentForm").submit();
        };

        FWDC.cancelAttachmentDialog = function (event, reload)
        {
            _fwdc.stopEvent(event);
            $("#ATTACHMENT_DIALOG").dialog("close");
            if (reload)
            {
                _fwdc.refreshPage("cancelAttachmentDialog");
            }
        };

        FWDC.runClientFunctions = function (functions)
        {
            _fwdc.runResponseFunctions(functions, false);
            _fwdc.runResponseFunctions(functions, true);
        };

        FWDC.eventOccurred = function (browserEvent, options)
        {
            var ctrl = false;
            if (browserEvent && !options)
            {
                options = browserEvent;
                browserEvent = null;
                ctrl = _fwdc.ctrlDown;
            }
            else if (browserEvent)
            {
                ctrl = (options.eventType === _fwdc.EventType.CtrlClick) || browserEvent.ctrlKey;
                _fwdc.stopEvent(browserEvent);
            }
            else
            {
                ctrl = _fwdc.ctrlDown;
            }

            if (typeof options === "string")
            {
                options = { field: options };
            }

            /*field, docAction, eventType, confirmed, successCallback*/
            options.eventType = options.eventType || _fwdc.EventType.Standard;
            var event = options.event || (ctrl && options.ctrlField ? (options.event = options.ctrlField) : options.field);

            var eventSource = { field: options.field || options.elementId, element: options.elementId || options.field, sourceChart: options.sourceChart };

            var busySource = _fwdc.eventBusySource(event) || _fwdc.eventBusySource(browserEvent);

            return _fwdc.ajax({
                event: browserEvent,
                url: 'EventOccurred',
                busySource: busySource,
                trigger: options.trigger,
                sourceId: options.sourceId,
                commitEdits: options.commitEdits,
                ignoreActivityCheck: options.eventType === _fwdc.EventType.AutoRefresh,
                data: function ()
                {
                    return _fwdc.getDocPostParameters({ EVENT__: event, TYPE__: options.eventType, CLOSECONFIRMED__: !!options.confirmed, SCREENWIDTH__: _fwdc.screenWidth });
                },
                beforeRequest: function (args)
                {
                    _linkSourceInfo = eventSource;
                    _fwdc.setConfirmCallback(function ()
                    {
                        options.confirmed = true;
                        FWDC.eventOccurred(null, options);
                    });
                },
                success: function (data, status, request)
                {
                    _fwdc.handleActionResult(data, $.extend({}, options, { sourceInfo: eventSource }));
                }
            });
        };

        FWDC.graphEventOccurred = function (field, ctrlField, sourceChart)
        {
            return FWDC.eventOccurred(null, { field: field, ctrlField: ctrlField, sourceChart: sourceChart });
        };

        FWDC.executeFlow = function (flow, confirmed)
        {
            return _fwdc.ajax({
                url: 'ExecuteFlow',
                data: $.param({ FLOW__: flow, CLOSECONFIRMED__: !!confirmed }),
                beforeRequest: function (args)
                {
                    _fwdc.setConfirmCallback(function ()
                    {
                        FWDC.executeFlow(flow, true);
                    });
                },
                success: function (data, status, request)
                {
                    _fwdc.handleActionResult(data);
                }
            });
        };

        FWDC.home = function (event, ignoreState)
        {
            _fwdc.navigate(event, "Home", -2, '', '', false, false, ignoreState);
        };

        FWDC.showBasicDialog = function (event, dialog, target, options)
        {
            _fwdc.stopEvent(event);

            if ((!options || !options.force) && _busy()) { return false; }

            var params = { TARGET__: target };

            if (options.params)
            {
                params = $.extend(params, options.params);
            }

            return _fwdc.ajax({
                url: 'Dialog/' + dialog,
                type: 'GET',
                data: $.param(params),
                dataType: "html",
                busy: !options.force,
                checkBusy: !options.force,
                success: function (data, status, request)
                {
                    _fwdc.stopAutoRefresh();
                    var $accessKeyElements = _fwdc.disableAccessKeys();
                    var $body = _fwdc.$body();
                    var $modal = $($.parseHTML('<div id="' + dialog + '_Dialog" class="FastDialogElement FastStandardDialog" style="display:none"></div>'));
                    var $content = $($.parseHTML(request.responseText));
                    if ($content.attr("title"))
                    {
                        $modal.attr("title", $content.attr("title"));
                        $content.removeAttr("title", "");
                    }

                    $body.append($modal);
                    $modal.dialog({
                        modal: true,
                        draggable: true,
                        resizable: false,
                        minHeight: 100,
                        width: "auto",
                        position: { my: "center", at: "center", collision: "none" },
                        dialogClass: "FastBasicDialog " + dialog + "ModalDialog " + _fwdc.getFastModalClass(),
                        closeOnEscape: false,
                        closeText: _fwdc.getCloseText(),
                        open: function ()
                        {
                            $modal.append($content);
                            $content.find("input:enabled:visible").first().focus().select();
                            if (options && options.formData)
                            {
                                $content.data("fast-form-data", options.formData);
                            }
                        },
                        drag: function ()
                        {
                            FWDC.checkFieldTipPositions();
                        },
                        close: function ()
                        {
                            $modal.remove();
                            $modal.tryDestroyDialog();
                            _fwdc.restoreAccessKeys($accessKeyElements);
                            if (options && options.close)
                            {
                                options.close.call(this);
                            }
                            FWDC.resumeAutoRefresh();
                        }
                    });
                }
            });
        };

        FWDC.acceptBasicDialog = function (event, formId, closeOnly)
        {
            _fwdc.stopEvent(event);
            if (!closeOnly && _busy()) { return false; }
            if (closeOnly)
            {
                $("#" + formId + "_Dialog").dialog("close");
            }
            else
            {
                $("#" + formId + "_Form").submit();
            }
        };

        FWDC.cancelBasicDialog = function (event, formId)
        {
            _fwdc.stopEvent(event);
            if (_busy()) { return false; }
            $("#" + formId + "_Dialog").dialog("close");
        };

        var _viewMenusVisible = false;
        FWDC.toggleViewMenus = function (event)
        {
            _fwdc.stopEvent(event);

            var $links = _fwdc.currentDocumentContainer().find("div.HiddenExportLink");
            if (!_viewMenusVisible)
            {
                var viewport = {
                    top: _fwdc.$window.scrollTop(),
                    left: _fwdc.$window.scrollLeft(),
                    height: _fwdc.$window.height(),
                    width: _fwdc.$window.width(),
                    bottom: 0,
                    right: 0
                };

                viewport.bottom = viewport.top + viewport.height;
                viewport.right = viewport.left + viewport.width;

                $links.each(function ()
                {
                    var $link = $(this);
                    var $container = $link.closest(".TableContainer");
                    if ($container && $container.length)
                    {
                        var containerBounds = $container.offset();
                        if (containerBounds)
                        {
                            containerBounds.height = $container.outerHeight();
                            containerBounds.width = $container.outerWidth();
                            containerBounds.bottom = containerBounds.top + containerBounds.height;
                            containerBounds.right = containerBounds.left + containerBounds.width;

                            var visibleBounds = {
                                top: Math.max(viewport.top, containerBounds.top),
                                left: Math.max(viewport.left, containerBounds.left),
                                bottom: Math.min(viewport.bottom, containerBounds.bottom),
                                right: Math.min(viewport.right, containerBounds.right),
                                width: 0,
                                height: 0
                            };

                            visibleBounds.width = visibleBounds.right - visibleBounds.left;
                            visibleBounds.height = visibleBounds.bottom - visibleBounds.top;

                            if (visibleBounds.width > 0 && visibleBounds.height > 0)
                            {
                                var scrollAdjustment = {
                                    top: containerBounds.top < 0 ? -containerBounds.top : 0,
                                    left: containerBounds.left < 0 ? -containerBounds.left : 0
                                };

                                $link.css({ "left": visibleBounds.width / 2 - 10 + scrollAdjustment.left, "top": visibleBounds.height / 2 - 10 + scrollAdjustment.top });
                            }
                            else
                            {
                                $link.css({ "left": containerBounds.width / 2 - 10, "top": containerBounds.height / 2 - 10 });
                            }
                        }
                    }
                });
            }

            _viewMenusVisible = !_viewMenusVisible;

            $links.fadeToggle();
        };

        FWDC.hideViewMenus = function ()
        {
            _viewMenusVisible = false;
            $("div.HiddenExportLink").fadeOut();
        };

        FWDC.setupFlowMenu = function ()
        {
            $(".FlowMenuDialog > .FlowMenu").tryDestroyDialog();
            $("#FlowMenu").dialog({
                modal: true,
                draggable: true,
                resizable: false,
                autoOpen: false,
                width: "auto",
                dialogClass: "FlowMenuDialog",
                closeOnEscape: true,
                closeText: _fwdc.getCloseText(),
                open: function (event, ui)
                {
                    this.$accessKeyElements = _fwdc.disableAccessKeys();
                    FWDC.hideViewMenus();
                    _fwdc.hideToolTips();
                    _fwdc.closeComboboxes();
                    _fwdc.updateScreenReader();
                },
                close: function ()
                {
                    FWDC.hideViewMenus();
                    _fwdc.restoreAccessKeys(this.$accessKeyElements);
                }
            });
        };

        FWDC.showFlowMenu = function (event, raiseEvent)
        {
            if (raiseEvent)
            {
                _fwdc.setPropertiesInternal(event, "MANAGER__", "FlowMenu", "", true);
            }
            else
            {
                $("#FlowMenu").dialog("option", { position: { my: "right top", of: event, collision: "flipfit" } }).dialog("open");
            }
        };

        FWDC.createModalButton = function ($container, buttonClass, tiptext, manager, callback, retry)
        {
            /*$container = typeof $container === "string" ? $("#" + $container) : $container;
            var $titlebar = $container.closest(".ui-dialog").children(".ui-dialog-titlebar");
         
            if (!$titlebar || !$titlebar.length)
            {
                if (!retry)
                {
                    setTimeout(function () { FWDC.createModalButton($container, buttonClass, tiptext, manager, callback, true); }, 100);
                }
                return;
            }
         
            if (!$titlebar.find("." + buttonClass).length)
            {
                var $button = $("<a href='#' class='FastTitlebarButton ui-corner-all " + buttonClass + "' role='button'><span class='FastTitlebarButton ui-icon " + buttonClass + "'></span></a>");
                if (tiptext) { $button.attr("title", tiptext); }
                $titlebar.append($button);
                $button.click(callback);
            }*/
        };

        FWDC.setModalAuditTrail = function (containerId, html, doc, retry)
        {
            var $titlebar = $("#" + containerId).closest(".ui-dialog").children(".ui-dialog-titlebar");

            if (!$titlebar || !$titlebar.length)
            {
                if (!retry)
                {
                    setTimeout(function () { FWDC.setModalAuditTrail(containerId, html, doc, true); }, 100);
                }
                return;
            }

            var $modalAuditTrail = $titlebar.find(".ModalAuditTrail");
            if (html)
            {
                if (!$modalAuditTrail || !$modalAuditTrail.length)
                {
                    $modalAuditTrail = $("<div class='ModalAuditTrail'></div>");
                    var $title = $titlebar.children(".ui-dialog-title");
                    if ($title.length)
                    {
                        $modalAuditTrail.insertAfter($title);
                    }
                    else
                    {
                        $titlebar.prepend($modalAuditTrail);
                    }
                }

                $modalAuditTrail.html(html);
            }
            else if ($modalAuditTrail && $modalAuditTrail.length)
            {
                $modalAuditTrail.remove();
            }
        };

        FWDC.linkSetProperties = function (event, control, type, target, properties, async, extraData, confirmResultCallback)
        {
            event = $.event.fix(event);
            var $link = $(event.target).closest("a");
            var fieldId = $link.attr("id");
            if (fieldId)
            {
                _linkSourceInfo = { field: fieldId };
            }

            return FWDC.setProperties(control, type, target, properties, async, extraData, confirmResultCallback);
        };

        FWDC.setProperties = function (control, type, target, properties, async, extraData, confirmResultCallback)
        {
            var data = { DOC_MODAL_ID__: _fwdc.currentModalId(), CONTROL__: control, TYPE__: type, TARGET__: target, VALUES: properties };

            if (extraData)
            {
                data = $.extend(data, extraData);
            }

            return _fwdc.ajax({
                url: 'SetProperties',
                data: data,
                async: async !== false,
                error: function (request)
                {
                    _fwdc.onAjaxError("setProperties", request.responseText);
                },
                success: function (data, status, request)
                {
                    _fwdc.handleActionResult(data, {
                        type: "SetProperties",
                        confirmedCallback: function (confirmedArgs, confirmResultCallback)
                        {
                            FWDC.setProperties(control, type, target, properties, async, confirmedArgs, confirmResultCallback);
                        },
                        confirmResultCallback: confirmResultCallback
                    });
                },
                complete: function ()
                {
                    FWDC.resumeAutoRefresh();
                }
            });
        };

        FWDC.setupFramedManager = function ()
        {
            var $managerContainer = _fwdc.currentManagerContainer();
            while (!$managerContainer.parent().is("body"))
            {
                $managerContainer.unwrap();
            }
        };

        FWDC.checkFieldTipPositions = function (scrolling)
        {
            if (scrolling)
            {
                $(".qtip").each(function ()
                {
                    var qtip = $(this).data("qtip");
                    if (qtip && qtip.rendered)
                    {
                        qtip.reposition(null, false);
                    }
                });
            }
            else
            {
                _fwdc.showCurrentFieldTip(true);
            }
            /*$(".FastFieldQTip").each(function ()
            {
                var $this = $(this);
                var qtip = $this.qtip('api');
                var $target = $(qtip.target);
                if (!$target.is(":visible"))
                {
                    qtip.hide();
                }
                else
                {
                    qtip.reposition();
                }
            });*/

        };

        FWDC.setSiteHttpHeaders = function (headers)
        {
            _siteHttpHeaders = headers || {};
        };

        var _fwdcInitialized;

        var _fwdcReadyCallbacks = $.Callbacks("once memory");
        //function _fwdcReady(callback)
        //{
        //    _fwdcReadyCallbacks.add(callback);
        //    //return _fwdc.$document.ready(callback);
        //}

        function _onFwdcInitialized()
        {
            //if (!_$cellMouseMeasurer) { _$cellMouseMeasurer = $('<div id="CellMouseMeasurer__"></div>').appendTo("body"); }

            _fwdcReadyCallbacks.fire();

            /*FWDC.ready = _fwdcReady; //_fwdc.$document.ready;
         
            if (_preReady && _preReady.length)
            {
                for (var ii = 0; ii < _preReady.length; ++ii)
                {
                    FWDC.ready(_preReady[ii]);
                }
            }
         
            _preReady = null;*/
        }

        function _setTipField(tipId, $field, $target, updateContent, preserveCurrent)
        {
            if ($field && (!$field.length || !$field.attr("title") || !$field.inDom()))
            {
                $field = null;
            }

            if (!$field && preserveCurrent)
            {
                return false;
            }

            var $currentField = _toolTipFields[tipId];
            var $currentTarget = _toolTipTargets[tipId];

            if ($currentField
                && (!$currentField.equals($field)
                    || ($currentTarget
                        && !$currentTarget.equals($target))))
            {
                var data;
                if (!$currentField.inDom())
                {
                    data = $currentField.data('qtip');
                    if (data)
                    {
                        $currentField.qtip("destroy");
                    }
                    if ($currentField.equals(_toolTipFields[tipId]))
                    {
                        _toolTipFields[tipId] = null;
                        _toolTipTargets[tipId] = null;
                    }
                }
                else if (!$currentField.equals($field))
                {
                    data = $currentField.data('qtip');
                    if (data && data.fastTipId === tipId)
                    {
                        $currentField.qtip("hide");
                    }
                    if ($currentField.equals(_toolTipFields[tipId]))
                    {
                        _toolTipFields[tipId] = null;
                        _toolTipTargets[tipId] = null;
                    }
                }
            }

            if ($field && $field.inDom())
            {
                return !!_fwdc.showFieldQTip(tipId, $field, $target, updateContent);
            }

            return false;
        }

        var _errorFieldClassFilter = ".FieldRequired,.FieldError,.FieldReview,.FieldCheck";
        var _hardErrorFieldClassFilter = ".FieldError,.FieldReview,.FieldCheck";
        function _filterErrorFields($container, ignoreRequired)
        {
            return $container
                .find(ignoreRequired ? _hardErrorFieldClassFilter : _errorFieldClassFilter)
                .filter("[title]:visible,div:visible>textarea.FastCodeMirrorBox[title]");
        }

        FWDC.resumeAutoRefresh = function (continueDelay)
        {
            if (_fwdc.fastAutoRefreshElements)
            {
                $.each(_fwdc.fastAutoRefreshElements, function (elementId, autoRefreshInfo)
                {
                    _fwdc.autoRefresh(autoRefreshInfo.displayElementId,
                        ((continueDelay || autoRefreshInfo.useEndDate) && autoRefreshInfo.lastTimeout ? autoRefreshInfo.lastTimeout : autoRefreshInfo.timeout),
                        autoRefreshInfo.callback);
                });
            }
        };

        //FWDC.autoRefreshDialog = function (event, fieldId)
        //{
        //    FWDC.showBasicDialog(event, "AutoRefresh", fieldId);
        //};

        FWDC.makeLine = function (fieldId)
        {
            var $field = _fwdc.formField(fieldId);

            if ($field && $field.hasClass("FastShapeLine") && !$field.hasClass("RenderedLine"))
            {
                $field.addClass("RenderedLine");
                var color = $field.css("border-top-color");
                var thickness = $field.css("border-top-width");
                $field.css("border", "none");
                var height = $field.height();
                var width = $field.width();
                var length = Math.sqrt(height * height + width * width);

                var angle = -Math.acos(height / length);
                var angleDeg = 180 / Math.PI * angle;
                var rotate = "rotate(" + angleDeg + "deg)";

                var thicknessInt = parseInt(thickness, 10);
                if (isNaN(thicknessInt)) { thicknessInt = 1; }

                var offsetX = thicknessInt / -2 * Math.cos(angle);
                var offsetY = thicknessInt / -2 * Math.sin(angle);
                if (thicknessInt === 1) { offsetX = 0; offsetY = 0; }

                var origin = "0 0";

                $field.css({
                    "height": length,
                    "width": thickness,
                    "left": offsetX,
                    "top": offsetY,
                    "border": "none",
                    "background": color,
                    "-webkit-transform": rotate,
                    "-webkit-transform-origin": origin,
                    "-moz-transform": rotate,
                    "-moz-transform-origin": origin,
                    "-o-transform": rotate,
                    "-o-transform-origin": origin,
                    "-ms-transform": rotate,
                    "-ms-transform-origin": origin,
                    "transform": rotate,
                    "transform-origin": origin
                });

                $field.parent().addClass("FastShapeLineContainer");
            }
        };

        FWDC.openUrl = function (event, url)
        {
            if (!url) { url = event; event = null; }
            if (!url) { return; }

            if (url && !url.toLowerCase().startsWith("javascript:") && !url.toLowerCase().startsWith("#"))
            {
                _fwdc.stopEvent(event);
                if (_fwdc.busy(true))
                {
                    _openingUrl = true;
                    _stayBusy = true;
                    setTimeout(function ()
                    {
                        _openingUrl = false;
                        _stayBusy = false;
                        _fwdc.busy.hide();
                    }, 1000);
                }
            }

            _fwdc._log("Opening URL: [" + url + "] at " + _fwdc.nowString());
            window.location = url;
        };

        FWDC.openWindow = function (event, url)
        {
            if (!url) { url = event; event = null; }
            _fwdc.stopEvent(event);
            _fwdc._log("Opening URL in new window: [" + url + "] at " + _fwdc.nowString());
            var newWindow = window.open(url);
            if (!newWindow || newWindow.closed || typeof newWindow.closed === "undefined")
            {
                FWDC.messageBox({ message: _fwdc.getDecode("PopupBlocked"), icon: FWDC.MessageBoxIcon.Information, buttons: FWDC.MessageBoxButton.Ok });
            }
        };

        FWDC.openTemporaryUrl = function (event, url)
        {
            _fwdc.stopEvent(event);
            _fwdc._log("Opening Temporary URL: " + url);
            window.location = url;
        };

        var _fusionChartsInit = false, _fusionChartsReady = $.Callbacks("once unique memory");

        var _fusionChartId = 1;

        function _createFusionChart(chartConfig)
        {
            if (!_fusionChartsInit)
            {
                _fusionChartsInit = true;

                var scripts = [
                    'fusioncharts.js',
                    'fusioncharts.charts.js',
                    'fusioncharts.powercharts.js',
                    'fusioncharts.widgets.js',
                    'fusioncharts.zoomline.js',
                    'fusioncharts.zoomscatter.js',
                    'fusioncharts.theme.fast.js',
                    'fusioncharts.overlappedcolumn2d.js',
                    'fusioncharts.overlappedbar2d.js',
                    'fusioncharts.timeseries.js',
                    'fusioncharts.maps.js'
                ];

                _fwdc.loadScripts(scripts, function ()
                {
                    _fwdc.FusionCharts = window.FusionCharts;

                    _fwdc.FusionCharts.options.license({
                        //key: "4cE2orxG1H4G1B3A2C3A2E2F3D4F3H3B-22ffF4E2D3nD2G1B6cfqB2E3C1C-7yhB1E4B1suwA33A8B14C5D7A2D5G2H4B3B2hbbA3C4IA2rveA4ED3D2B-9xiF1C10B8C4A3C3C2H4I2J2C10D3B2B5q==",
                        key: "hzH5vmaD8A1C5D2A1G1A1G1B4A1A3B1B3fqyH2B7C-16xvhyA2E1lduC7E2B4E2F2G2C1B10C2D2E6C1D1E3E1G2c1D-16yC2A3E2yD1J2B3lozD1B1G4da1wB9B6C6dG-10A-8D3J2A9B1A8C7E1E5A2A1A1sB-22uE2D6G1F1H-8H-7lB8A5C7epG4d1I3B8lnE-13F4E2D3F1H4A10D8C1C5B5B1F4D3E1g==",
                        creditLabel: false
                    });

                    _fusionChartsReady.fire();
                });
            }

            _fusionChartsReady.add(function ()
            {
                if (chartConfig && chartConfig.fcConfig && chartConfig.fcConfig.fastConfig)
                {
                    chartConfig.fcConfig = $.extend(chartConfig.fcConfig, chartConfig.fcConfig.fastConfig);
                }

                _busy.done(function ()
                {
                    var $field = _fwdc.formField(chartConfig.fcConfig.renderAt);
                    if ($field)
                    {
                        chartConfig.fcConfig.renderAt = $field[0];

                        chartConfig.fcConfig.id = "fc_" + _fusionChartId;
                        _fusionChartId++;

                        var oldChart = $field.data("fast-fc");
                        if (oldChart)
                        {
                            oldChart.dispose();
                        }

                        if ($field.data("fast-fc"))
                        {
                            $field.children("button.FastChartAction").remove();
                        }

                        if (chartConfig.fcConfig.dataSource && chartConfig.fcConfig.isGauge)
                        {
                            // Since gauges don't have .dataSource.data or .dataSource.dataset, the resize logic ignores them even in 3.18.0.
                            // We'll provide a hacky value here just to force the logic to fire.
                            chartConfig.fcConfig.dataSource.data = true;
                        }

                        if (chartConfig.fcConfig.timeseries && chartConfig.fcConfig.timeseriesData)
                        {
                            //Timeseries charts have to setup the datatable to render

                            var schema = chartConfig.fcConfig.timeseries.schema;
                            var data = chartConfig.fcConfig.timeseriesData.data;

                            var fusionTable = new FusionCharts.DataStore().createDataTable(data, schema);
                            chartConfig.fcConfig.dataSource.data = fusionTable;
                        }

                        var chart = new _fwdc.FusionCharts(chartConfig.fcConfig);
                        $field
                            .addClass("DocTableGraphContainerFC")
                            .data("fast-fc", chart);

                        if (chartConfig.decodes)
                        {
                            $.each(chartConfig.decodes, function (index, value)
                            {
                                chart.configure(index, value);
                            });
                        }

                        chart.render();

                        if (chartConfig.fcConfig.fastActions)
                        {
                            var $buttonContainer = $($.parseHTML("<div></div>")).addClass("FastChartActions").appendTo($field);
                            $.each(chartConfig.fcConfig.fastActions, function (action, onclick)
                            {
                                $($.parseHTML('<button type="button"></button>'))
                                    .text(action)
                                    .attr("onclick", onclick)
                                    .addClass("FastChartAction")
                                    .appendTo($buttonContainer);
                            });
                        }

                        $field.mousedown(function (event)
                        {
                            $field.data("fast-mousedown-pos",
                                {
                                    pageX: event.pageX,
                                    pageY: event.pageY,
                                    offsetX: event.offsetX,
                                    offsetY: event.offsetY
                                });
                        });
                    }
                });
            });
        }

        FWDC.createChart = function (chartConfig)
        {
            _createFusionChart(chartConfig);
        };

        FWDC.printElement = function (event, $element)
        {
            if (typeof $element === "string")
            {
                $element = _fwdc.formField($element);
            }

            if ($element)
            {
                $element.addClass("PrintTarget");
                var $parents = $element.parents().addClass("PrintTargetParent");
                _fwdc.$body().addClass("PrintingTarget");

                try
                {
                    if (_fwdc.pausePush) { _fwdc.pausePush(); }
                    window.print();
                    if (_fwdc.resumePush) { _fwdc.resumePush(); }
                }
                catch (ignore)
                {
                }

                $element.removeClass("PrintTarget");
                $parents.removeClass("PrintTargetParent");
                _fwdc.$body().removeClass("PrintingTarget");
            }
        };

        FWDC.printPage = function (event)
        {
            _fwdc.stopEvent(event);

            window.print();
        };

        FWDC.viewSupportId = function (event, confirm)
        {
            if (_busy()) { return false; }

            _fwdc.stopEvent(event);

            _fwdc.setPropertiesInternalJson("MANAGER__", "ViewSupportId", (confirm ? "confirm" : ""), true, null, function (response)
            {
                if (response.messageBox)
                {
                    FWDC.messageBox(response.messageBox);
                }
            });
        };

        var _initialized = false;
        FWDC.initialize = function (options)
        {
            if (_initialized) { return; }

            _initialized = true;

            _seal();

            _fwdc.initOptions = options;

            if (options)
            {
                _fwdc.standardDecodes(options.standardDecodes);
            }

            var $html = $("html");
            if ($html.hasClass("Export"))
            {
                _fwdc.exporting = true;
            }
            else if ($html.hasClass("SimplePage"))
            {
                _fwdc.simplePage = true;
            }
            else
            {
                $html.addClass("FastApp");
                _fwdc.fastApp = true;
            }

            document.addEventListener("DOMContentLoaded", _onDocumentInitialized);
            window.addEventListener("load", _onDocumentInitialized);

            var $document = _fwdc.$document;
            $document.mousedown(_onDocumentMouseDown);
            $document.bind("touchstart", _onDocumentMouseDown);
            $document.keydown(_onDocumentKeyDown);

            var $window = $(window);

            if (!_fwdc.exporting)
            {
                //$document.on("focus", ".DocControlPassword", logPasswordFieldEvent);
                //$document.on("blur", ".DocControlPassword", logPasswordFieldEvent);
                //$document.on("input", ".DocControlPassword", logPasswordFieldEvent);
                //$document.on("change", ".DocControlPassword", logPasswordFieldEvent);

                $window.on("focus", _fwdc.Events.BrowserWindow.focus);
                $window.on("blur", _fwdc.Events.BrowserWindow.blur);

                $document.on("submit", "#SelectSliceForm", _fwdc.Events.SliceForm.submit);

                $document.on("click", ".FastTransitioning a,.FastTransitioning input,.FastTransitioning button", _fwdc.blockTransitionClick);
                $document.on("click", ".DisabledAccessKey", _fwdc.onBlockedMnemonicClick);

                $document.on("mousedown", "button,.DFL,.FRC,.LinkButton", _fwdc.Events.Field.rippleMouseDown);

                $document.on("mousedown", "input,textarea,a,button", _fwdc.Events.Document.scrollmousedown);
                $document.on("focusin", _fwdc.Events.Document.scrollfocusin);

                // Disable keypress pending a better way to manage repeating events.
                //$document.on("keypress", "button,.DFL,.FRC,.LinkButton", _fwdc.Events.Field.rippleKeyPress);

                $document.on("click", "a,button", _fwdc.setLastFocusClick);

                $document.on("click", "a", _onLinkClick);

                $document.on("keypress", "input,textarea,select", _onInputKeyPress);
                $document.on("paste", ".FastNoPaste input,input.FastNoPaste", function (event)
                {
                    event.preventDefault();
                    return false;
                });

                $document.on("click", "input.TableViewButton[type='radio']", _onSelectTableView);
                $document.on("change", "input[type='checkbox']", _onCheckboxChange);
                $document.on("change", "input[type='radio']", _onCheckboxChange);
                $document.on("change", ".DocControlSlider", _onDocSliderChange);

                $document.on("mousedown", ".FastEvt", _fwdc.Events.standardmousedown);
                $document.on("click", ".FastEvt", _fwdc.Events.standardclick);
                $document.on("submit", ".FastBasicDialogCustomForm", _fwdc.Events.StandardDialogSubmit.submit);
                $document.on("submit", ".FastBasicDialogForm", _fwdc.Events.BasicForm.submitted);

                $document.on("click", "button.FastEvtExecuteAction,a.FastEvtExecuteAction", _fwdc.Events.Action.click);

                $document.on("keydown", ".FastEvtEnterSubmitForm", _fwdc.Events.Interface.enterSubmitForm);

                $document.on("click", ".FastEvtAcceptDialog", _fwdc.Events.Interface.acceptDialog);
                $document.on("click", ".FastEvtCancelDialog", _fwdc.Events.Interface.cancelDialog);

                $document.on("click", ".DocUploadLink", _fwdc.Events.Field.uploadclick);
                $document.on("click", "tr.TDR .DFL", _fwdc.Events.Table.linkclick);
                $document.on("mousedown", "tr.TDR .DFL", _fwdc.Events.Table.linkmousedown);
                $document.on("click", ".DFB,.StepInfoStepListLink,.StageStepInfoStepListLink,.PathListEntryLink,.OutlineValueLink", _fwdc.Events.Field.linkclick);
                $document.on("mousedown", ".DFL,.DFB", _fwdc.Events.Field.linkmousedown);
                $document.on("click", "a.DTColText", _fwdc.Events.Table.columnheaderclick);
                $document.on("click", ".FastEvtTablePage", _fwdc.Events.Table.pageclick);
                $document.on("click", ".FastEvtTablePageMenu", _fwdc.Events.Table.pagemenuclick);

                $document.on("focus", ".DTColText", _fwdc.Events.Table.columnlinkfocus);
                $document.on("blur", ".DTColText", _fwdc.Events.Table.columnlinkblur);

                $document.on("mousedown", ".FastEvtRichTextLink", _fwdc.Events.Field.richtextlinkmousedown);
                $document.on("click", ".FastEvtRichTextLink", _fwdc.Events.Field.richtextlinkclick);

                $document.on("click", ".FastEvtSelectView", _fwdc.Events.ViewSelector.tabClicked);
                $document.on("keydown", ".TabSetLink", _fwdc.Events.ViewSelector.tabkeydown);

                $document.on("keydown", ".CellEditor,.TDI", _onCellEditorKeydown);
                $document.on("keypress", ".CellEditor,.TDI", _onCellEditorKeypress);
                $document.on("keyup", ".CellEditor,.TDI", _onCellEditorKeyup);
                $document.on("focus", ".TCE", _onEditCellFocus);
                //$document.on("focus", ".TDI", _onCellInputFocus);
                //$document.on("click", ".TCE", _onEditableCellClick);

                // Touch Start here causes instant editing to begin when trying to swipe to scroll lists.
                //$document.on("touchstart", "td.CellEditable", _onEditableCellClick);

                $document.on("mousedown", ".DocHelpElement", _onHelpElementMouseDown);

                $document.on("keypress", "textarea[data-maxlength]", _onMaxlengthTextareaKeypress);
                $document.on("paste", "textarea[data-maxlength]", _onMaxlengthTextareaPaste);
                $document.on("keydown", "div.DocumentContainer,div.ManagerContainer,.ui-dialog", _fwdc.onMnemonicKeyDown);
                $document.on("keypress", "input[type='password']", _onPasswordKeyPress);
                $document.on("blur", "input[type='password']", _onPasswordLostFocus);

                $document.on("focus", ".DocTableBody", _onTableFocused);

                $document.on("mousedown", "div.ColumnResizeGrip", _onColumnResizeMouseDown);
                $document.on("dblclick", "div.ColumnResizeGrip", _onColumnResizeDoubleClick);

                $document.on("mousedown", ".DocMenu", false);

                $document.on("click", "tr.TDR", _fwdc.Events.Table.datarowclick);

                $document.on("click", "a.FastSelectionOption", _onSelectionOptionClick);

                $document.on("touchend", ".FastEvtFieldFocus", _fwdc.Events.Field.touchend);
                $document.on("focus", ".FastEvtFieldFocus", _fwdc.Events.Field.focus);
                $document.on("blur", ".FastEvtFieldFocus", _fwdc.Events.Field.blur);
                $document.on("keydown", ".FastEvtFieldKeyDown", _fwdc.Events.Field.keydown);
                $document.on("drop", ".FastEvtFieldKeyDown", _fwdc.Events.Field.drop);
                $document.on("click", "input.FastEvtFieldFocus", _fwdc.Events.Field.inputclick);
                $document.on("change", "select.FastEvtFieldKeyDown", _fwdc.Events.Field.selectchange);
                $document.on("click", "input.DocControlFile.FieldEnabled", _fwdc.Events.Field.fileclick);
                $document.on("click", "button.FastEvtLinkClick,a.FastEvtLinkClick", _fwdc.Events.Field.linkclick);

                //$document.on("click", ".FastEvtTableSelectRow", _fwdc.Events.Table.selectTableRow);
                $document.on("click", "table.DocTable", _fwdc.Events.Table.click);
                $document.on("click", "a.TableMenuLink", _fwdc.Events.Table.showTableMenu);

                $document.on("click", "a.ChatLink", _fwdc.Events.Chat.chatlinkclick);

                $document.on("click", "li.FastTab > a", _fwdc.Events.FastTabs.click);

                $document.on("mouseenter", "th.TCH, td.TDC, td.TDS, .TLI", _onCellMouseEnter);
                $document.on("mouseleave", "th.TCH, td.TDC, td.TDS, .TLI", _onCellMouseLeave);

                $document.on("scroll", ".ManagerContentContainer", _onStructureScroll);
                // Content-only scrolling
                $document.on("scroll", ".ManagerControlsContainer", _onStructureScroll);

                $document.on("click", "a.DocTableMobileScrollLeft,a.DocTableMobileScrollRight", _fwdc.Events.Table.mobileScrollLinkClick);

                $document.on("mouseenter", "a.SidebarNavigationLink", _fwdc.Events.Navigation.linkMouseEnter);

                $document.on("click", "a.MessagePanelLink", _fwdc.Events.MessagePanel.linkclick);
                $document.on("click", "a.MessagePanelCloseLink", _fwdc.Events.MessagePanel.closeclick);

                $document.on("click", "a.FastEvtToggleManagerMenu", _fwdc.Events.Manager.menuclick);
                //$document.on("click", "a.ManagerLogonOptionLinkSettings,a.MenuLinkSettings,a.SidebarBasicActionsLinkSettings", _fwdc.Events.Manager.settingsclick);
                $document.on("click", "a.FastEvtLogOff", _fwdc.Events.Manager.logoffclick);
                //$document.on("click", "a.ManagerLogonOptionLinkHelp,a.SidebarBasicActionsLinkHelp", _fwdc.Events.Manager.helpclick);
                $document.on("click", "a.SwitchToDesktop", _fwdc.Events.Interface.switchToDesktopClick);
                $document.on("click", ".FastEvtSetAppFontSize", _fwdc.Events.Interface.setAppFontSize);

                $document.on("click", ".HelpRichText a", _fwdc.Events.Field.helprichtextlinkclick);

                // Fix an IE issue where textareas do not receive focus if the DOM is modified during a focus-related click.
                $document.on("click", "textarea", _fwdc.Events.Field.textareaClickFix);

                $document.on("focus", ".BasicRequiredField", _fwdc.Events.BasicForm.requiredfocus);
                $document.on("blur", ".BasicRequiredField", _fwdc.Events.BasicForm.requiredblur);
                $document.on("change", ".BasicRequiredField", _fwdc.Events.BasicForm.requiredchange);
                $document.on("keydown", ".BasicRequiredField", _fwdc.Events.BasicForm.requiredkeydown);
                $document.on("keydown", ".FastBasicDialogForm .BasicField", _fwdc.Events.BasicForm.inputkeydown);

                $document.on("focus", ".TableStandardFilter", _fwdc.Events.Table.filterfocus);
                $document.on("blur", ".TableStandardFilter", _fwdc.Events.Table.filterblur);
                $document.on("keydown", ".TableStandardFilter", _fwdc.Events.Table.filterkeydown);

                $document.on("click", ".FastTransitioning", _fwdc.Events.FastTransition.click);

                $document.on("mousedown", ".DocDecodeElement", _onDecodableElementMouseDown);
                $document.on("click", ".DocDecodeElement", function () { return false; });
                $document.on("mouseup", ".DocDecodeElement", function () { return false; });

                $document.on("change", ".DocAttachmentFieldFile", _fwdc.Events.AttachmentField.change);

                $document.on("dragover", ".DocAttachmentDropTarget", _fwdc.Events.AttachmentField.uploadDragOver);
                $document.on("dragenter", ".DocAttachmentDropTarget", _fwdc.Events.AttachmentField.uploadDragEnter);
                $document.on("dragleave", ".DocAttachmentDropTarget", _fwdc.Events.AttachmentField.uploadDragLeave);
                $document.on("drop", ".DocAttachmentDropTarget", _fwdc.Events.AttachmentField.uploadDrop);

                $document.on("dragover", _fwdc.Events.Document.dragover);

                function logPasswordFieldEvent(event)
                {
                    console.log(event);
                }
            }

            _fwdc.$window.resize(_onWindowSizeChanged);
            _fwdc.$window.scroll(_onStructureScroll);
            _fwdc.$window.hashchange(_onHashChange);

            $.datepicker.setDefaults($.extend({
                constrainInput: false,
                showOn: "button",
                dateFormat: "yy-mm-dd",
                buttonText: _fwdc.textToHtml(_fwdc.getDecode("ToggleDatePicker", "Toggle Date Picker")),
                changeMonth: true,
                changeYear: true,
                yearRange: "1901:+50",
                showButtonPanel: true
            }, $.datepicker.regional[""]));

            $.watermark.options.hideBeforeUnload = false;

            $.fn.qtip.defaults = $.extend(true, {}, $.fn.qtip.defaults, {
                content: {
                    title: {
                        button: true
                    }
                },
                show: {
                    event: false,
                    solo: true,
                    effect: false
                },
                hide: {
                    event: 'unfocus',
                    effect: false
                },
                position: {
                    my: "left center",
                    at: "right center",
                    viewport: true
                },
                suppress: false
            });

            _fwdc.initialize();

            $document.on("dragstart", "a", function ()
            {
                var href = $(this).attr("href");
                return href !== "javascript:;" && href !== "#";
            });

            $document.on("click", "a", function ()
            {
                return $(this).attr("href") !== "javascript:;";
            });
        };

        function _onDecodableElementMouseDown(event)
        {
            if (_busy() || !event || event.which !== 1)
            {
                return _fwdc.stopEvent(event);
            }

            var $element = $(event.target).closest('.DocDecodeElement');
            if ($element.length === 0)
            {
                return _fwdc.stopEvent(event);
            }

            var rowData = $element.data("row");
            var parentViewId = $element.attr("data-parent-view") || (rowData && rowData.view) || "";

            var targetId = $element.attr('data-decode-id') || $element.attr('data-help-id') || $element.attr("data-id") || $element.attr('id');
            if (!targetId)
            {
                // Check if this is a child of a proper DocDecodeElement.
                $element = $element.parent().closest(".DocDecodeElement");
                if ($element.length)
                {
                    targetId = $element.attr('data-decode-id') || $element.attr('data-help-id') || $element.attr("data-id") || $element.attr('id');
                }
            }

            if (targetId)
            {
                _fwdc.getData('', 'DecodeInfo', targetId, 'json', true, { ParentView: parentViewId }, function (data)
                {
                    if (data)
                    {
                        $element.qtip({
                            content:
                            {
                                text: data.tip,
                                title:
                                {
                                    text: data.caption
                                }
                            },
                            style:
                            {
                                classes: 'fast-qtip-decode-info'
                            },
                            position:
                            {
                                my: 'top left',
                                target: 'mouse',
                                adjust: { mouse: false, method: 'flip' },
                                container: _fwdc.supportElementsContainer(),
                                viewport: _fwdc.$window
                            },
                            events:
                            {
                                hide: function (event, api)
                                {
                                    api.destroy();
                                }
                            }
                        }).qtip('show', event);
                    }
                });
            }

            return _fwdc.stopEvent(event);
        }

        //// Google maps ////

        function _delayDisplayAddresses(map, bounds, addresses, index, progressCallback, finishedCallback, overLimit, delay)
        {
            window.setTimeout(function ()
            {
                _displayAddresses(map, bounds, addresses, index, progressCallback, finishedCallback, overLimit);
            }, delay);
        }

        function _geocodeAddress(address, map, bounds, addresses, index, progressCallback, finishedCallback, overLimit)
        {
            _geocoder.geocode({ address: address.address }, function (results, status)
            {
                switch (status)
                {
                    case google.maps.GeocoderStatus.OK:
                        var location = results[0].geometry.location;

                        address.geocoded = _geocoderCache[address.address] = { location: location, formatted_address: results[0].formatted_address };

                        bounds = _displayGoogleMapMarker(address, map, bounds);
                        if (!bounds)
                        {
                            return;
                        }

                        break;

                    case google.maps.GeocoderStatus.ZERO_RESULTS:
                        address.geocoded = _geocoderCache[address.address] = null;

                        FWDC.messageBox({ message: _fwdc.getDecode("Google.Maps.Geocoder." + status) + "\n\n" + address.address, icon: FWDC.MessageBoxIcon.Warning });
                        break;

                    default:
                        if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT && overLimit < 5)
                        {
                            _delayDisplayAddresses(map, bounds, addresses, index, progressCallback, finishedCallback, overLimit + 1, overLimit ? overLimit * 2000 : 2000);
                        }
                        else
                        {
                            FWDC.messageBox({ message: _fwdc.getDecode("Google.Maps.Geocoder." + status), icon: FWDC.MessageBoxIcon.Warning });
                            if (finishedCallback) { finishedCallback(); }
                        }
                        return;
                }

                _delayDisplayAddresses(map, bounds, addresses, index + 1, progressCallback, finishedCallback, overLimit ? 1 : 0, overLimit ? 500 : 150);
            });
        }

        function _displayAddresses(map, bounds, addresses, index, progressCallback, finishedCallback, overLimit)
        {
            while (index < addresses.length)
            {
                if (progressCallback)
                {
                    progressCallback(index, addresses.length);
                }

                var address = addresses[index];
                address.geocoded = address.geocoded || _geocoderCache[address.address];

                if (address.geocoded)
                {
                    bounds = _displayGoogleMapMarker(address, map, bounds);
                    if (!bounds)
                    {
                        return;
                    }
                    ++index;
                }
                else if (!address.address || address.geocoded === null)
                {
                    // Skip blank addresses.
                    ++index;
                }
                else
                {
                    overLimit = overLimit || 0;
                    _geocodeAddress(address, map, bounds, addresses, index, progressCallback, finishedCallback, overLimit);

                    return;
                }
            }

            if (finishedCallback) { finishedCallback(); }
        }

        function _displayGoogleMapMarker(address, map, bounds)
        {
            if (!map || map.fastDestroyed || !map.fastMarkers)
            {
                return false;
            }

            var location = address.geocoded.location;

            var markerOptions = {
                position: location,
                map: map
            };

            if (address.iconUrl)
            {
                markerOptions.icon = address.iconUrl;
            }
            if (address.highlight === true)
            {
                markerOptions.icon = _mapIconSelected;
            }
            else if (address.highlight === false)
            {
                markerOptions.icon = _mapIconUnselected;
            }

            var marker = new google.maps.Marker(markerOptions);
            marker.fastToolTip = _fwdc.textToHtml(_getMarkerTip(address, map));
            marker.fastAddress = address;

            map.fastMarkers.push(marker);

            if (address.linkId)
            {
                map.fastEvents.push(google.maps.event.addListener(marker, 'click', function ()
                {
                    FWDC.eventOccurred({ field: address.linkId, eventType: _fwdc.EventType.Standard, trigger: "MapMarkerClick", sourceId: address.linkId });
                }));
            }
            else if (address.selectId)
            {
                map.fastEvents.push(google.maps.event.addListener(marker, 'click', function ()
                {
                    var recalcData = {};
                    recalcData[address.selectId] = !address.highlight;
                    recalcData = _fwdc.getDocPostParameters(recalcData, "input[type='hidden']");
                    if (_fwdc.recalc({ 'data': recalcData, 'source': address.id }))
                    {
                        address.highlight = !address.highlight;
                        if (address.highlight)
                        {
                            this.setIcon(_mapIconSelected);
                        }
                        else
                        {
                            this.setIcon(_mapIconUnselected);
                        }
                    }
                }));
            }

            map.fastEvents.push(google.maps.event.addListener(marker, "mouseover", function (event)
            {
                var position = _getLatLngPoint(event.latLng, map);

                var qtip = map.$fastToolTip.qtip("api");

                if (qtip && qtip.elements && qtip.elements.tooltip)
                {
                    qtip.elements.tooltip.stop(1, 1);
                }

                qtip.set("position.target", [position.x, position.y]);
                qtip.set("content.text", this.fastToolTip);
                qtip.show();
            }));

            map.fastEvents.push(google.maps.event.addListener(marker, "mouseout", function ()
            {
                map.$fastToolTip.qtip("hide");
            }));

            if (!bounds)
            {
                bounds = new google.maps.LatLngBounds(location, location);
                // Expand the bounds by a little to prevent super-zooming on a single location
                var extension = 0.002;
                var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + extension, bounds.getNorthEast().lng() + extension);
                var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - extension, bounds.getNorthEast().lng() - extension);
                bounds.extend(extendPoint1);
                bounds.extend(extendPoint2);
            }
            else
            {
                bounds.extend(location);
            }

            map.fitBounds(bounds);

            return bounds;
        }

        function _getMarkerTip(addressObject, map)
        {
            if (map.fastGeocode)
            {
                var formattedAddress = _mapOptions.displayedDecode + "\n" + addressObject.geocoded.formatted_address;
                return _mapOptions.originalDecode + "\n" + addressObject.address + "\n\n" + (addressObject.toolTip ? formattedAddress + "\n\n" + addressObject.toolTip : formattedAddress);
            }

            return addressObject.toolTip;
        }

        // Adapted from: http://jsfiddle.net/svigna/VzYF6/
        function _getLatLngPoint(latLng, map)
        {
            var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
            var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
            var scale = Math.pow(2, map.getZoom());
            var worldPoint = map.getProjection().fromLatLngToPoint(latLng);

            var mapOffset = map.$element.offset();

            return { x: mapOffset.left + (worldPoint.x - bottomLeft.x) * scale, y: mapOffset.top + (worldPoint.y - topRight.y) * scale };
        }

        //function _destroyMaps()
        //{
        //    if (_maps)
        //    {
        //        var deleteMaps = $.extend({}, _maps);
        //        $.each(deleteMaps, _destroyMap);
        //    }
        //}

        function _destroyMap(mapId, map)
        {
            map = map || _maps[mapId];

            if (map)
            {
                try
                {
                    map.fastDestroyed = true;
                    if (_maps[mapId])
                    {
                        delete _maps[mapId];
                    }

                    if (map.fastEvents)
                    {
                        $.each(map.fastEvents, function (index, listener)
                        {
                            google.maps.event.removeListener(listener);
                        });
                        delete map.fastEvents;
                    }
                    delete map.fastMarkers;

                    if (map.$element)
                    {
                        map.$element.qtip("destroy");
                        map.$element.removeClass("HasMap");
                        map.$element.data("fast-map-id", null);
                        map.$element.empty();
                        delete map.$element;
                    }

                    if (map.$directionsElement)
                    {
                        map.$directionsElement.empty();
                        map.$directionsElement.removeClass("HasDirections");
                        delete map.$directionsElement;
                    }

                    if (map.fastDirectionsRenderer)
                    {
                        map.fastDirectionsRenderer.setMap(null);
                        delete map.fastDirectionsRenderer;
                    }
                }
                catch (ignore)
                {
                }
            }
        }

        FWDC.initMaps = function (options)
        {
            if (!_mapsInitialized && !_fwdc.exporting)
            {
                _mapsInitialized = true;
                _mapOptions = options.mapOptions;

                _fwdc.ajax({
                    url: options.apiUrl + "&callback=FWDC.onGoogleMapsInitialized",
                    method: "GET",
                    cache: true,
                    busy: false,
                    dataType: "script",
                    success: function ()
                    {
                    },
                    error: function (request, status, error)
                    {
                        FWDC.messageBox(error);
                    }
                });
            }
        };

        FWDC.onGoogleMapsInitialized = function ()
        {
            if (!_googleMapsInitialized)
            {
                _googleMapsInitialized = true;
                _mapOptions = $.extend({ zoom: 8, mapTypeId: google.maps.MapTypeId.ROADMAP, scaleControl: true }, _mapOptions);
                _geocoder = new google.maps.Geocoder();
                _directionsService = new google.maps.DirectionsService();
                _mapInfoWindow = new google.maps.InfoWindow({ disableAutoPan: true });
                _mapsReady.fire();

                $(window)
                    .keydown(function (event)
                    {
                        if (event.which === _fwdc.keyCodes.SHIFT)
                        {
                            _mapsShiftModifier = true;
                        }
                    })
                    .keyup(function (event)
                    {
                        if (event.which === _fwdc.keyCodes.SHIFT)
                        {
                            _mapsShiftModifier = false;
                        }
                    });
            }
        };

        var _mapId = 0;
        FWDC.renderMap = function (options)
        {
            function RenderMapInternal()
            {
                var mapOptions = $.extend({}, _mapOptions, options.mapOptions);
                var $mapElement = _fwdc.formField(options.mapId, true);

                if (!$mapElement || !$mapElement.length)
                {
                    _fwdc._warn("Map element not found: " + options.mapId);
                    return;
                }
                else if (!$mapElement.inDom())
                {
                    _fwdc._warn("Map element not connected: " + options.mapId);
                    return;
                }

                var mapId = $mapElement.data("fast-map-id") || ++_mapId;

                _destroyMap(mapId);

                var map;
                try
                {
                    map = _maps[mapId] = new google.maps.Map($mapElement.get(0), mapOptions);
                }
                catch (ex)
                {
                    _fwdc._warn(ex);
                    return;
                }
                $mapElement.addClass("HasMap").data("fast-map-id", mapId);

                map.fastMapId = mapId;
                map.fastGeocode = options.geocode;
                map.elementId = options.mapId;
                map.$element = $mapElement;
                map.fastMarkers = [];
                map.fastEvents = [];

                var $dialog = $mapElement.closest(".ui-dialog");
                var inModal = !!$dialog.length;
                var $container = _fwdc.$body();
                var $modalViewport = inModal ? $mapElement.closest(".DocumentForm") : null;

                map.$fastToolTip = $mapElement.qtip({
                    overwrite: false,
                    content:
                    {
                        text: "",
                        title:
                        {
                            button: false
                        }
                    },
                    position:
                    {
                        container: $container,
                        viewport: true,
                        my: "top left",
                        at: "bottom center",
                        adjust:
                        {
                            x: 0,
                            method: "flipinvert none"
                        }
                    },
                    show:
                    {
                        event: false,
                        ready: false,
                        solo: false
                    },
                    hide:
                    {
                        fixed: true,
                        event: 'click'
                    },
                    style:
                    {
                        classes: 'MapMarkerQTip'
                    },
                    events:
                    {
                        move: function (event, api, eventData)
                        {
                            if (inModal)
                            {
                                var viewportOffset = $modalViewport.offset();
                                var viewportLeft = viewportOffset.left;
                                var viewportRight = viewportLeft + $modalViewport.width();

                                if (eventData.left < 0)
                                {
                                    eventData.left = 0;
                                }
                                else if (eventData.left > viewportRight)
                                {
                                    eventData.left = viewportRight + 5;
                                }
                            }
                        }
                    }
                });

                var errorOccurred = false;

                if (options.directions)
                {
                    var $directionsElement = map.$directionsElement = _fwdc.formField(options.directionsRendererOptions.panel);
                    var directionsRenderer = map.fastDirectionsRenderer = new google.maps.DirectionsRenderer($.extend({}, options.directionsRendererOptions, { map: map, panel: $directionsElement.get(0) }));
                    $directionsElement.addClass("HasDirections");

                    if (_directionsCache[options.routeId])
                    {
                        directionsRenderer.setDirections(_directionsCache[options.routeId]);
                    }
                    else
                    {
                        _directionsService.route(options.directionsRequest, function (result, status)
                        {
                            if (status === google.maps.DirectionsStatus.OK)
                            {
                                var route = result.routes[0];
                                var legs = route.legs;
                                if (legs && legs.length)
                                {
                                    var waypointOrder = route.waypoint_order;
                                    var waypoints = options.directionsRequest.waypoints;
                                    var fastWaypointData = options.fastWaypointData;
                                    var asMapped = _mapOptions.displayedDecode || "Displayed:";

                                    for (var ii = 0; ii < legs.length - 1; ++ii)
                                    {
                                        legs[ii].end_address = asMapped + "\n" + legs[ii].end_address + "\n\n" + waypoints[waypointOrder[ii]].location;

                                        var toolTip = fastWaypointData[waypointOrder[ii]].toolTip;
                                        if (toolTip)
                                        {
                                            legs[ii].end_address = legs[ii].end_address + "\n\n" + toolTip;
                                        }
                                    }
                                }

                                _directionsCache[options.routeId] = result;
                                directionsRenderer.setDirections(result);
                            }
                            else if (!errorOccurred)
                            {
                                errorOccurred = true;
                                FWDC.messageBox({ message: _fwdc.getDecode("Google.Maps.Directions." + status), icon: FWDC.MessageBoxIcon.Warning });
                            }
                        });
                    }
                }
                else
                {
                    if (options.selectable)
                    {
                        map.fastEvents.push(google.maps.event.addListener(map, "mousedown", function (event)
                        {
                            if (_mapsShiftModifier && !this.fastSelecting)
                            {
                                $.each(this.fastMarkers, function (index, marker)
                                {
                                    marker.setClickable(false);
                                });

                                this.fastSelecting = true;
                                this.fastSelectionOrigin = event.latLng;

                                map.setOptions({ draggable: false });

                                this.fastSelectionRectangle = new google.maps.Rectangle({
                                    map: this,
                                    bounds: new google.maps.LatLngBounds(event.latLng, event.latLng),
                                    fillOpacity: 0.1,
                                    strokeWeight: 1,
                                    clickable: false
                                });
                            }
                        }));
                        map.fastEvents.push(google.maps.event.addListener(map, "mouseup", function (event)
                        {
                            if (this.fastSelecting)
                            {
                                $.each(this.fastMarkers, function (index, marker)
                                {
                                    marker.setClickable(true);
                                });

                                this.fastSelecting = false;

                                var bounds = this.fastSelectionRectangle.getBounds();

                                var recalcData = {};
                                var recalc = false;
                                var highlightMarkers = [];

                                $.each(this.fastMarkers, function (index, marker)
                                {
                                    if (bounds.contains(marker.fastAddress.geocoded.location))
                                    {
                                        highlightMarkers.push(marker);
                                        recalc = true;
                                        recalcData[marker.fastAddress.selectId] = true;
                                    }
                                });

                                this.fastSelectionRectangle.setMap(null);
                                delete this.fastSelectionRectangle;
                                map.setOptions({ draggable: true });

                                if (recalc)
                                {
                                    recalcData = _fwdc.getDocPostParameters(recalcData, "input[type='hidden']");

                                    if (_fwdc.recalc({ 'data': recalcData, 'source': $mapElement.attr("id") + ".MapSelection" }))
                                    {
                                        $.each(highlightMarkers, function (index, marker)
                                        {
                                            marker.fastAddress.highlight = true;
                                            marker.setIcon(_mapIconSelected);
                                        });
                                    }
                                }
                            }
                        }));
                        map.fastEvents.push(google.maps.event.addListener(map, "mousemove", function (event)
                        {
                            if (this.fastSelecting)
                            {
                                var bounds = new google.maps.LatLngBounds();
                                bounds.extend(this.fastSelectionOrigin);
                                bounds.extend(event.latLng);

                                this.fastSelectionRectangle.setBounds(bounds);
                            }
                        }));
                    }

                    var addresses = options.addresses;
                    var bounds;

                    if (addresses.length)
                    {
                        var $busyOverlay = $('<div class="FastBusyOverlay MapBusyOverlay"></div>').appendTo($mapElement);
                        var $busyContainer = $('<div class="FastBusyContainer"></div>').appendTo($busyOverlay);
                        var $busySpinner = $('<div class="FastBusySpinner MapBusySpinner"></div>').html(_fwdc.busySpinnerContent()).appendTo($busyContainer);
                        var $progressBar = $('<div class="FastBusyProgressBar InactiveProgressBar"></div>').appendTo($mapElement).progressbar({ value: 0, max: 1 });
                        _displayAddresses(map, bounds, addresses, 0,
                            function (value, max)
                            {
                                $progressBar.removeClass("InactiveProgressBar").progressbar({ value: value, max: max });
                            },
                            function ()
                            {
                                $busyOverlay.remove();
                                $busySpinner.remove();
                                $progressBar.remove();
                            });
                    }
                }
            }

            _mapsReady.add(function ()
            {
                // Delay the activation of real rendering to make sure this does not happen synchronously with DOM content load.
                // This isn't an ideal approach - it should be done via element init logic.
                _fwdc.setTimeout("RenderMap.Delay", function ()
                {
                    _fwdc.busy.done(function ()
                    {
                        _fwdc.afterCrossTransition(RenderMapInternal);
                    });
                });
            });
        };

        /////////// jQuery Extensions ///////////
        (function ($)
        {
            // Based on Unicode Ll, Lu, Lo categories.
            var _unicodeLetter = /[\u0041-\u005a\u0061-\u007a\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u01c4\u01c6\u01c7\u01c9\u01ca\u01cc-\u01f1\u01f3-\u02af\u037b-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03ce\u03d0-\u03f5\u03f7-\u0481\u048a-\u0513\u0531-\u0556\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0621-\u063a\u0641-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u076d\u0780-\u07a5\u07b1\u07ca-\u07ea\u0904-\u0939\u093d\u0950\u0958-\u0961\u097b-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d60\u0d61\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e45\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0edc\u0edd\u0f00\u0f40-\u0f47\u0f49-\u0f6a\u0f88-\u0f8b\u1000-\u1021\u1023-\u1027\u1029\u102a\u1050-\u1055\u10a0-\u10c5\u10d0-\u10fa\u1100-\u1159\u115f-\u11a2\u11a8-\u11f9\u1200-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u1676\u1681-\u169a\u16a0-\u16ea\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17dc\u1820-\u1842\u1844-\u1877\u1880-\u18a8\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19a9\u19c1-\u19c7\u1a00-\u1a16\u1b05-\u1b33\u1b45-\u1b4b\u1d00-\u1d2b\u1d62-\u1d77\u1d79-\u1d9a\u1e00-\u1e9b\u1ea0-\u1ef9\u1f00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fbb\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcb\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffb\u2071\u207f\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2183\u2184\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2c6c\u2c74-\u2c77\u2c80-\u2ce4\u2d00-\u2d25\u2d30-\u2d65\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3006\u303c\u3041-\u3096\u309f\u30a1-\u30fa\u30ff\u3105-\u312c\u3131-\u318e\u31a0-\u31b7\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fbb\ua000-\ua014\ua016-\ua48c\ua800\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\uac00-\ud7a3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uff6f\uff71-\uff9d\uffa0-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]/;

            // Based on Unicode Nd category.
            var _unicodeNumber = /[\u0030-\u0039\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19d9\u1b50-\u1b59\uff10-\uff19]/;

            function _isLetter(charData, character)
            {
                return charData.unicode ? character.match(_unicodeLetter) : character.match(/[a-zA-Z]/);
            }

            function _isNumber(charData, character)
            {
                return charData.unicode ? character.match(_unicodeNumber) : character.match(/[0-9]/);
            }

            function _maskTouchMode()
            {
                return true; // Enabled permanently pending issues.
            }

            function _mergeNodeLists(nodeLists)
            {
                if (!nodeLists || !nodeLists.length)
                {
                    return null;
                }

                if (nodeLists.length === 1)
                {
                    return nodeLists[0];
                }

                var lengths = 0;
                for (var ii = 0; ii < nodeLists.length; ++ii)
                {
                    lengths += nodeLists[ii].length;
                }

                var data = new Array(lengths);
                var itemIndex = 0;
                for (var jj = 0; jj < nodeLists.length; ++jj)
                {
                    for (var kk = 0; kk < nodeLists[jj].length; ++kk)
                    {
                        data[itemIndex] = nodeLists[jj][kk];
                        itemIndex++;
                    }
                }

                return data;
            }

            function _clampNumber(number, min, max)
            {
                return Math.max(Math.min(number, max), min);
            }

            function _clampRect(rect, container)
            {
                var clamped = {
                    top: _clampNumber(rect.top, container.top, container.bottom),
                    right: _clampNumber(rect.right, container.left, container.right),
                    bottom: _clampNumber(rect.bottom, container.top, container.bottom),
                    left: _clampNumber(rect.left, container.left, container.right)
                };

                clamped.width = clamped.right - clamped.left;
                clamped.height = clamped.bottom - clamped.top;

                return clamped;
            }

            function _isElement(node)
            {
                return node.nodeType === Node.ELEMENT_NODE;
            }

            function _elementDisplayed(element)
            {
                var style = window.getComputedStyle(element);
                return style.display !== "none" && style.visibility !== "hidden";
            }

            /*
            $.qtip.prototype.destroy = _fwdc._logFunction("qtip.destroy", $.qtip.prototype.destroy);
            $.qtip.prototype.hide = _fwdc._logFunction("qtip.hide", $.qtip.prototype.hide);
            $.qtip.prototype.render = _fwdc._logFunction("qtip.render", $.qtip.prototype.render);
            $.qtip.prototype.show = _fwdc._logFunction("qtip.show", $.qtip.prototype.show);
            $.qtip.prototype.toggle = _fwdc._logFunction("qtip.toggle", $.qtip.prototype.toggle);
            _setTipField = _fwdc._logFunction("_setTipField", _setTipField);
            /**/

            $.extend({
                fastMask:
                {
                    set: function (element, mask)
                    {
                        var $fastMask = this,
                            $element = $(element),
                            maskData = new MaskData(mask);

                        return $element.each(function ()
                        {
                            var $this = $(this),
                                data;
                            if (!mask)
                            {
                                $.fastMask.clear(this);
                            }
                            else
                            {
                                data = { mask: maskData, checkInput: true };
                                if (!$this.attr("data-fastmask-maxlength") && $this.attr("maxlength"))
                                {
                                    $this
                                        .attr("data-fastmask-maxlength", $this.attr("maxlength"))
                                        .removeAttr("maxlength");
                                }
                                $this
                                    .attr("autocomplete", "off")
                                    .attr("autocorrect", "off")
                                    .attr("autofill", "off")
                                    .attr("maxlength", maskData.maxLength)
                                    .bind("keydown.fastMask", data, $fastMask._onMaskKeyDown)
                                    .bind("keypress.fastMask", data, $fastMask._onMaskKeyPress)
                                    .bind("input.fastMask", data, $fastMask._onMaskInput)
                                    .bind("keyup.fastMask", data, $fastMask._onMaskKeyUp)
                                    .bind("paste.fastMask", data, $fastMask._onPaste)
                                    .val($.fastMask.maskString(maskData, $this.val()))
                                    .data("fast-mask", data);
                            }
                        });
                    },

                    clear: function (element)
                    {
                        return $(element).each(function ()
                        {
                            var $this = $(this);
                            if ($this.data("fast-mask"))
                            {
                                $this.unbind(".fastMask").data("fast-mask", null).removeAttr("maxlength");
                                if ($this.attr("data-fastmask-maxlength"))
                                {
                                    $this
                                        .attr("maxlength", $this.attr("data-fastmask-maxlength"))
                                        .removeAttr("data-fastmask-maxlength");
                                }
                            }
                        });
                    },

                    maskString: function (mask, value, blanks, trim)
                    {
                        if (!(mask instanceof MaskData))
                        {
                            mask = new MaskData(mask);
                        }

                        if (blanks === undefined) { blanks = true; }

                        var output = "", maskPosition = 0, ii, character, jj, charData;
                        for (ii = 0; ii < value.length; ii++)
                        {
                            character = value.charAt(ii);
                            if (maskPosition >= mask.length)
                            {
                                return trim ? output : value;
                            }

                            for (jj = maskPosition; jj < mask.length; jj++)
                            {
                                charData = mask[jj];
                                if (charData.constant)
                                {
                                    if (character === charData.character)
                                    {
                                        output += character;
                                        maskPosition++;
                                        break;
                                    }
                                    else
                                    {
                                        output += charData.character;
                                        maskPosition++;
                                    }
                                }
                                else if (charData.space && character === " ")
                                {
                                    output += character;
                                    maskPosition++;
                                    break;
                                }
                                else if (charData.hidden && character === "*")
                                {
                                    output += character;
                                    maskPosition++;
                                    break;
                                }
                                else if (charData.alpha && _isLetter(charData, character))
                                {
                                    if (charData.upper)
                                    {
                                        character = character.toUpperCase();
                                    }
                                    else if (charData.lower)
                                    {
                                        character = character.toLowerCase();
                                    }
                                    output += character;
                                    maskPosition++;
                                    break;
                                }
                                else if (charData.numeric && _isNumber(charData, character))
                                {
                                    output += character;
                                    maskPosition++;
                                    break;
                                }
                                else
                                {
                                    return trim ? output : value;
                                }
                            }
                        }

                        return output;
                    },

                    _onMaskKeyDown: function (e)
                    {
                        var $this = $(this),
                            input = e.currentTarget,
                            mask = e.data.mask,
                            position = $.fastMask._getCursorPos(input),
                            length = $.fastMask._getSelectionLength(input),
                            end = position + length,
                            charData,
                            value = $this.val() || "",
                            str1,
                            str2,
                            readonly = $this.attr("readonly");

                        if (readonly) { return; }

                        var which = e.which || e.keyCode;

                        switch (which)
                        {
                            case _fwdc.keyCodes.BACKSPACE: // Backspace
                                if (_maskTouchMode())
                                {
                                    return;
                                }

                                if ($.fastMask._checkMask($(this), e.data.mask))
                                {
                                    $.fastMask._setCursorPos(input, position);
                                }

                                if (length > 0)
                                {
                                    $this.val($.fastMask.maskString(mask, value.substring(0, position) + value.substring(end, value.length), false));
                                }
                                else
                                {
                                    while (position > 0)
                                    {
                                        position--;
                                        charData = mask[position];
                                        if (charData)
                                        {
                                            value = $this.val();
                                            str1 = value.substring(0, position);
                                            str2 = value.substring(position + 1, value.length);
                                            $this.val($.fastMask.maskString(mask, str1 + str2, false));
                                            if (!charData.constant) { break; }
                                        }
                                    }
                                }
                                $.fastMask._setCursorPos(input, position);
                                return false;

                            case _fwdc.keyCodes.DELETE: // Delete
                                if (_maskTouchMode() && position < value.length)
                                {
                                    $this.val(value.substring(0, position));
                                    $.fastMask._setCursorPos(input, position);
                                    return;
                                }

                                if ($.fastMask._checkMask($(this), e.data.mask))
                                {
                                    $.fastMask._setCursorPos(input, position);
                                }

                                if (length > 0)
                                {
                                    $this.val($.fastMask.maskString(mask, value.substring(0, position) + value.substring(end, value.length), false));
                                }
                                else
                                {
                                    if (position > -1)
                                    {
                                        charData = mask[position];
                                        if (charData && !(charData.constant))
                                        {
                                            value = $this.val();
                                            str1 = value.substring(0, position);
                                            str2 = value.substring(position + 1, value.length);
                                            $this.val($.fastMask.maskString(mask, str1 + str2, false));
                                        }
                                    }
                                }
                                $.fastMask._setCursorPos(input, position);
                                return false;

                            case _fwdc.keyCodes.TAB:
                            case _fwdc.keyCodes.ENTER:
                            case _fwdc.keyCodes.END:
                            case _fwdc.keyCodes.HOME:
                            case _fwdc.keyCodes.LEFT:
                            case _fwdc.keyCodes.UP:
                            case _fwdc.keyCodes.RIGHT:
                            case _fwdc.keyCodes.DOWN:
                                if (e.altKey || e.ctrlKey || e.metaKey) { return; }
                                // Allow navigation keys.
                                return true;

                            case _fwdc.keyCodes.SHIFT:
                            case _fwdc.keyCodes.CTRL:
                            case _fwdc.keyCodes.ALT:
                            case _fwdc.keyCodes.CAPSLOCK:
                            case _fwdc.keyCodes.NUMLOCK:
                            case _fwdc.keyCodes.SCROLLLOCK:
                            case _fwdc.keyCodes.INSERT:
                            case _fwdc.keyCodes.WINDOWS_LEFT:
                            case _fwdc.keyCodes.WINDOWS_RIGHT:
                            case _fwdc.keyCodes.SELECT:
                                return true;

                            default:
                                if (which > _fwdc.keyCodes.Z)
                                {
                                    return;
                                }

                                if (e.altKey || e.ctrlKey || e.metaKey) { return; }

                                if (_maskTouchMode())
                                {
                                    if (position < value.length)
                                    {
                                        $this.val(value.substring(0, position));
                                        $.fastMask._setCursorPos(input, position);
                                    }
                                    return;
                                }
                                else if ($.fastMask._checkMask($(this), e.data.mask))
                                {
                                    $.fastMask._setCursorPos(input, position);
                                }

                                return true;
                        }
                    },

                    _applyMaskChar: function (input, mask, character)
                    {
                        var $input = $(input),
                            position = $.fastMask._getCursorPos(input),
                            charData,
                            value,
                            str1,
                            str2,
                            ii;

                        for (ii = position; ii < mask.length; ii++)
                        {
                            if (!mask[ii].constant)
                            {
                                charData = mask[ii];
                                position = ii;
                                break;
                            }
                            else if (mask[ii].character.toLowerCase() === character.toLowerCase())
                            {
                                value = $input.val();
                                if (value.length <= ii)
                                {
                                    str1 = value.substring(0, position);
                                    str2 = value.substring(position + 1, value.length);
                                    $input.val(str1 + mask[ii].character + str2);
                                }
                                $.fastMask._setCursorPos(input, position + 1);
                                return false;
                            }
                            else
                            {
                                value = $input.val();
                                str1 = value.substring(0, position);
                                str2 = value.substring(position + 1, value.length);
                                $input.val(str1 + mask[ii].character + str2);
                                $.fastMask._setCursorPos(input, position + 1);
                                position += 1;
                            }
                        }

                        if (charData)
                        {
                            var success = false;
                            if (charData.space && character === " ")
                            {
                                success = true;
                            }
                            else if (charData.alpha && _isLetter(charData, character))
                            {
                                if (charData.upper)
                                {
                                    character = character.toUpperCase();
                                }
                                else if (charData.lower)
                                {
                                    character = character.toLowerCase();
                                }
                                success = true;
                            }
                            else if (charData.numeric && _isNumber(charData, character))
                            {
                                success = true;
                            }

                            if (success)
                            {
                                value = $input.val();
                                str1 = value.substring(0, position);
                                str2 = value.substring(position + 1, value.length);
                                $input.val(str1 + character + str2);
                                $.fastMask._setCursorPos(input, position + 1);
                            }
                        }
                    },

                    _onMaskKeyPress: function (e)
                    {
                        var $this = $(this),
                            input = e.currentTarget,
                            mask = e.data.mask,
                            readonly = $this.attr("readonly"),
                            keyChar = (e.which || e.charCode || e.keyCode),
                            character;

                        if (readonly || _maskTouchMode()) { return; }

                        e.data.checkInput = false;

                        switch (keyChar)
                        {
                            case 8: // Backspace
                                return false;

                            case 9: // Tab
                            case 13: // Enter
                                // Allow navigation keys.
                                return true;

                            default:
                                if (e.altKey || e.ctrlKey || e.metaKey || _maskTouchMode()) { return; }

                                if (!readonly)
                                {
                                    character = $.fastMask._getKeyChar(e);

                                    _applyMaskChar(input, mask, character);
                                    /*if (character)
                                    {
                                        charData = null;
                                        var ii;
                                        for (ii = position; ii < mask.length; ii++)
                                        {
                                            if (!mask[ii].constant)
                                            {
                                                charData = mask[ii];
                                                position = ii;
                                                break;
                                            }
                                            else if (mask[ii].character.toLowerCase() === character.toLowerCase())
                                            {
                                                value = $this.val();
                                                if (value.length <= ii)
                                                {
                                                    str1 = value.substring(0, position);
                                                    str2 = value.substring(position + 1, value.length);
                                                    $this.val(str1 + mask[ii].character + str2);
                                                }
                                                $.fastMask._setCursorPos(input, position + 1);
                                                return false;
                                            }
                                            else
                                            {
                                                value = $this.val();
                                                str1 = value.substring(0, position);
                                                str2 = value.substring(position + 1, value.length);
                                                $this.val(str1 + mask[ii].character + str2);
                                                $.fastMask._setCursorPos(input, position + 1);
                                                position += 1;
                                            }
                                        }
         
                                        if (charData)
                                        {
                                            var success = false;
                                            if (charData.space && character === " ")
                                            {
                                                success = true;
                                            }
                                            else if (charData.alpha && _isLetter(charData, character))
                                            {
                                                if (charData.upper)
                                                {
                                                    character = character.toUpperCase();
                                                }
                                                else if (charData.lower)
                                                {
                                                    character = character.toLowerCase();
                                                }
                                                success = true;
                                            }
                                            else if (charData.numeric && _isNumber(charData, character))
                                            {
                                                success = true;
                                            }
         
                                            if (success)
                                            {
                                                value = $this.val();
                                                str1 = value.substring(0, position);
                                                str2 = value.substring(position + 1, value.length);
                                                $this.val(str1 + character + str2);
                                                $.fastMask._setCursorPos(input, position + 1);
                                            }
                                        }
                                    }*/
                                }
                                return false;
                        }
                    },

                    _onMaskInput: function (e)
                    {
                        if (e.data.checkInput && _maskTouchMode())
                        {
                            var $this = $(this),
                                input = e.currentTarget,
                                position = $.fastMask._getCursorPos(input),
                                value = $this.val(),
                                readonly = $this.attr("readonly");

                            if (readonly) { return; }

                            var atEnd = position >= value.length;

                            if ($.fastMask._checkMask($this, e.data.mask, true))
                            {
                                if (atEnd) { position = $this.val().length; }
                                $.fastMask._setCursorPos(input, position);
                            }
                        }
                    },

                    _onMaskKeyUp: function (e)
                    {
                        var $this = $(this);
                        if ($this.attr("readonly") || e.altKey || e.ctrlKey || e.metaKey) { return; }

                        if (_maskTouchMode())
                        {
                            switch (e.which || e.keyCode)
                            {
                                case _fwdc.keyCodes.BACKSPACE:
                                case _fwdc.keyCodes.DELETE:
                                case _fwdc.keyCodes.TAB:
                                case _fwdc.keyCodes.ENTER:
                                case _fwdc.keyCodes.END:
                                case _fwdc.keyCodes.HOME:
                                case _fwdc.keyCodes.LEFT:
                                case _fwdc.keyCodes.UP:
                                case _fwdc.keyCodes.RIGHT:
                                case _fwdc.keyCodes.DOWN:
                                case _fwdc.keyCodes.SHIFT:
                                case _fwdc.keyCodes.CTRL:
                                case _fwdc.keyCodes.ALT:
                                    return;

                                default:
                                    if ($.fastMask._checkMask($this, e.data.mask, true))
                                    {
                                        $.fastMask._setCursorPos(e.currentTarget, $this.val().length);
                                    }
                            }
                        }
                        else
                        {
                            return false;
                        }
                    },

                    _onPaste: function (e)
                    {
                        var input = this;
                        if ($(input).hasClass("FastNoPasteReady"))
                        {
                            return _fwdc.stopEvent(e);
                        }

                        var $cell = $target.data("fast-editing-cell");

                        if ($cell
                            && _fwdc.tryPasteTsv
                            && _fwdc.tryPasteTsv(e, $cell))
                        {
                            return _fwdc.stopEvent(e);
                        }

                        var clipboardData = (e && e.originalEvent && e.originalEvent.clipboardData) || window.clipboardData;
                        var hasText = clipboardData && clipboardData.types && clipboardData.types.indexOf && clipboardData.types.indexOf("text/plain") >= 0;
                        var text = hasText && clipboardData.getData && (clipboardData.getData("text/plain") + "");

                        if (text)
                        {
                            for (var ii = 0; ii < text.length; ++ii)
                            {
                                $.fastMask._applyMaskChar(input, e.data.mask, text[ii]);
                            }

                            return _fwdc.stopEvent(e);
                        }
                        else
                        {
                            setTimeout(function () { $.fastMask._applyMask($(input)); }, 0);
                        }
                    },

                    _onChange: function (e)
                    {
                        $.fastMask._checkMask($(this), e.data.mask);
                    },

                    _onBlur: function (e)
                    {
                        var $this = $(this);
                        if ($this.val().length < $this.attr("maxLength"))
                        {
                            $.fastMask._applyMask($this);
                        }
                    },

                    _applyMask: function ($field, mask, force)
                    {
                        if (!mask) { mask = $field.data("fast-mask").mask; }

                        var oldVal = $field.val();
                        var newVal = $.fastMask.maskString(mask, $field.val(), false, true);
                        if (newVal !== oldVal)
                        {
                            $field.val(newVal);
                            return true;
                        }

                        return false;
                    },

                    _checkMask: function ($field, mask, force)
                    {
                        if (!$field.attr("maxLength") || ($field.val().length <= $field.attr("maxLength")))
                        {
                            return $.fastMask._applyMask($field, mask);
                        }

                        return false;
                    },

                    _getKeyChar: function (e)
                    {
                        var keyChar = (e.which || e.charCode || e.keyCode);
                        return String.fromCharCode(keyChar);
                    },

                    _getCursorPos: function (tb)
                    {
                        if (tb.selectionStart > -1)
                        {
                            return tb.selectionStart;
                        }

                        // IE Fallback
                        if (document.selection && tb.createTextRange)
                        {
                            var sel = document.selection;
                            if (sel)
                            {
                                var r1 = tb.createTextRange();
                                var r2 = sel.createRange();
                                r1.setEndPoint("EndToStart", r2);
                                return r1.text.length;
                            }
                        }

                        return -1;
                    },

                    _getSelectionLength: function (tb)
                    {
                        if (tb.selectionStart > -1)
                        {
                            return tb.selectionEnd - tb.selectionStart;
                        }

                        if (document.selection && tb.createTextRange)
                        {
                            var sel = document.selection;
                            if (sel)
                            {
                                var r1 = tb.createTextRange();
                                var r2 = sel.createRange();
                                r1.setEndPoint("EndToEnd", r2);
                                r1.setEndPoint("StartToStart", r2);
                                return r1.text.length;
                            }
                        }
                    },

                    _getSelectionEnd: function (tb)
                    {
                        if (tb.selectionEnd > -1)
                        {
                            return tb.selectionEnd;
                        }

                        if (document.selection && tb.createTextRange)
                        {
                            var sel = document.selection;
                            if (sel)
                            {
                                var r1 = tb.createTextRange();
                                var r2 = sel.createRange();
                                r1.setEndPoint("EndToEnd", r2);
                                return r1.text.length;
                            }
                        }
                    },

                    _setCursorPos: function (tb, pos)
                    {
                        if (tb.selectionStart > -1)
                        {
                            tb.focus();
                            tb.setSelectionRange(pos, pos);
                        }
                        else if (tb.createTextRange)
                        {
                            // IE Mode
                            var range = tb.createTextRange();
                            range.move("character", pos);
                            range.select();
                        }
                    }
                },

                findElementById: function (id, context)
                {
                    var documentContext;
                    if (!context)
                    {
                        context = $(document);
                        documentContext = true;
                    }
                    else if (context.nodeType)
                    {
                        documentContext = context.nodeType === Node.DOCUMENT_NODE;
                        context = $(context);
                    }

                    var element = document.getElementById(id);
                    var $element;
                    if (element)
                    {
                        $element = $(element);

                        if (!documentContext)
                        {
                            // Filter out document, HTML and BODY elements as these would contain "everything".
                            var $closest = context.map(function (ii, element)
                            {
                                if (element.nodeType !== Node.ELEMENT_NODE || !element.tagName || element.tagName === "HTML" || element.tagName === "BODY")
                                {
                                    return null;
                                }

                                return element;
                            });

                            if (context.length && !$element.closest($closest).length)
                            {
                                $element = null;
                            }
                        }
                    }

                    return context.pushStack($element ? $element : $());
                },

                findElementsByClassName: function (classNames, context)
                {
                    if (!context)
                    {
                        context = $(document);
                    }
                    else if (context.nodeType)
                    {
                        context = $(context);
                    }

                    var results;
                    if (classNames)
                    {
                        for (var ii = 0; ii < context.length; ++ii)
                        {
                            var element = context[ii];

                            if (element.nodeType === Node.ELEMENT_NODE || element.nodeType === Node.DOCUMENT_NODE || element.nodeType === Node.DOCUMENT_FRAGMENT_NODE)
                            {
                                var elementResults = element.getElementsByClassName(classNames);
                                if (elementResults && elementResults.length)
                                {
                                    if (results)
                                    {
                                        results.push(elementResults);
                                    }
                                    else
                                    {
                                        results = [elementResults];
                                    }
                                }
                            }
                        }
                    }

                    return context.pushStack(results ? $(_mergeNodeLists(results)) : $());
                },

                findElementsByAnyClassName: function (classNames, context)
                {
                    if (!context)
                    {
                        context = $(document);
                    }
                    else if (context.nodeType)
                    {
                        context = $(context);
                    }

                    classNames = classNames ? classNames.split(",") : [];

                    var results;
                    for (var ii = 0; ii < context.length; ++ii)
                    {
                        var element = context[ii];

                        if (element.nodeType === Node.ELEMENT_NODE || element.nodeType === Node.DOCUMENT_NODE || element.nodeType === Node.DOCUMENT_FRAGMENT_NODE)
                        {
                            for (var jj = 0; jj < classNames.length; ++jj)
                            {
                                var elementResults = element.getElementsByClassName(classNames[jj]);
                                if (elementResults && elementResults.length)
                                {
                                    if (results)
                                    {
                                        results.push(elementResults);
                                    }
                                    else
                                    {
                                        results = [elementResults];
                                    }
                                }
                            }
                        }
                    }

                    return context.pushStack(results ? $(_mergeNodeLists(results)) : $());
                },

                // Wrapper for querySelectorAll for better performance on certain calls than jQuery's .find which can manipulate things.
                querySelectorAll: function (selector, context)
                {
                    if (!context)
                    {
                        context = $(document);
                    }
                    else if (context.nodeType)
                    {
                        context = $(context);
                    }

                    if (selector)
                    {
                        var element;
                        if (context.length > 1)
                        {
                            var results;

                            for (var ii = 0; ii < context.length; ++ii)
                            {
                                element = context[ii];
                                if (element.nodeType === Node.ELEMENT_NODE || element.nodeType === Node.DOCUMENT_NODE || element.nodeType === Node.DOCUMENT_FRAGMENT_NODE)
                                {
                                    var elementResults = element.querySelectorAll(selector);
                                    if (elementResults && elementResults.length)
                                    {
                                        if (results)
                                        {
                                            results.push(elementResults);
                                        }
                                        else
                                        {
                                            results = [elementResults];
                                        }
                                    }
                                }
                            }

                            return context.pushStack(results ? $(_mergeNodeLists(results)) : $());
                        }
                        else
                        {
                            element = context[0];
                            if (element.nodeType === Node.ELEMENT_NODE || element.nodeType === Node.DOCUMENT_NODE || element.nodeType === Node.DOCUMENT_FRAGMENT_NODE)
                            {
                                return context.pushStack($(context[0].querySelectorAll(selector)));
                            }
                        }
                    }
                    return context.pushStack($());
                },

                elementVisible: $.expr.pseudos.visible
            });

            $.fn.extend({
                equals: function ($target)
                {
                    if (!$target || this.length !== $target.length) { return false; }

                    var ii;
                    for (ii = 0; ii < this.length; ii++)
                    {
                        if (this[ii] !== $target[ii]) { return false; }
                    }

                    return true;
                },
                or: function (selectorOrJquery)
                {
                    if (!this.length)
                    {
                        return selectorOrJquery instanceof $ ? selectorOrJquery : $(selectorOrJquery);
                    }

                    return this;
                },

                visible: function ()
                {
                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        var element = this[ii];
                        if ($.elementVisible(element))
                        {
                            return true;
                        }
                    }

                    return false;
                },

                filterVisible: function ()
                {
                    var visibleElements;
                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        var element = this[ii];
                        if ($.elementVisible(element))
                        {
                            if (visibleElements)
                            {
                                visibleElements.push(element);
                            }
                            else
                            {
                                visibleElements = [element];
                            }
                        }
                    }

                    return this.pushStack(visibleElements || []);
                },

                firstVisible: function ()
                {
                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        var element = this[ii];
                        if ($.elementVisible(element))
                        {
                            return this.pushStack([element]);
                        }
                    }

                    return this.pushStack([]);
                },

                filtercontainsi: function (filter)
                {
                    return this.map(function ()
                    {
                        if (containsi(this, filter))
                        {
                            return this;
                        }

                        return null;
                    });
                },
                filtercontainsr: function (regex)
                {
                    return this.map(function ()
                    {
                        if (containsr(this, regex))
                        {
                            return this;
                        }

                        return null;
                    });
                },

                filternotcontainsi: function (filter)
                {
                    return this.map(function ()
                    {
                        if (!containsi(this, filter))
                        {
                            return this;
                        }

                        return null;
                    });
                },

                tag: function ()
                {
                    return (this.prop("tagName") || "").toUpperCase();
                },

                tagIs: function (tagName)
                {
                    if (!this.length) { return false; }

                    tagName = tagName.toUpperCase();

                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        if (!_isElement(this[ii]) || (this[ii].tagName || "").toUpperCase() !== tagName)
                        {
                            return false;
                        }
                    }

                    return true;
                },

                isElement: function ()
                {
                    if (!this.length) { return false; }

                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        if (!_isElement(this[ii]))
                        {
                            return false;
                        }
                    }

                    return true;
                },

                isVisible: function ()
                {
                    var $check = this;

                    while ($check.length && $check.isElement())
                    {
                        for (var ii = 0; ii < $check.length; ++ii)
                        {
                            if (_isElement($check[ii]) && !_elementDisplayed($check[ii]))
                            {
                                return false;
                            }
                        }

                        $check = $check.parent();
                    }

                    return true;
                },

                isActiveElement: function ()
                {
                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        if (this[ii] === document.activeElement)
                        {
                            return true;
                        }
                    }

                    return false;
                },

                hasFocus: function ()
                {
                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        if ($.expr.pseudos.focus(this[ii]))
                        {
                            return true;
                        }
                    }

                    return false;
                },

                childrenWithClass: function (className)
                {
                    return this.children().filter(function (index, element)
                    {
                        return element.nodeType === Node.ELEMENT_NODE && element.classList.contains(className);
                    });
                },

                focusNextInputField: function (backwards, noLinks, fallback, dataDoc)
                {
                    var $focused;
                    this.each(function ()
                    {
                        var source = this;
                        var $source = $(source);

                        if (!$source.inDom())
                        {
                            if ($source.attr("id"))
                            {
                                $source = _fwdc.formField($source.attr("id"));
                                if ($source)
                                {
                                    source = $source[0];
                                }
                            }
                            else
                            {
                                return;
                            }
                        }

                        if (!$source) { return false; }

                        var $container;

                        if (dataDoc)
                        {
                            $container = $source.closest(".DataDocContainer");
                        }

                        if (!($container && $container.length))
                        {
                            $container = $source.closest(".FastDialogElement"); //_fwdc.parentDocumentContainer($source);
                            if (!($container && $container.length))
                            {
                                $container = $source.closest(".ManagerContainer");
                            }

                            if (!($container && $container.length))
                            {
                                $container = $source.closest(_fwdc.selectors.documentContainer);
                            }

                            if (!($container && $container.length))
                            {
                                $container = $source.closest("form,body");
                            }
                        }

                        var filter = fallback ?
                            ":tabbable" :
                            (noLinks ?
                                "input[type!='hidden'],select,button,textarea[name],textarea.FastCodeMirrorBox,textarea.DocRichTextBox,.FastCaptchaField,table.DocEditableTable tbody.DocTableBody" :
                                "input[type!='hidden'],select,button,textarea[name],textarea.FastCodeMirrorBox,textarea.DocRichTextBox,.FastCaptchaField,table.DocEditableTable tbody.DocTableBody,a");

                        // If the source field isn't one of the inputs we could pick, add it to the list so we can use the index.
                        var $fields = $container.find(filter).add(source);

                        if (backwards)
                        {
                            $fields = $fields.reverse();
                            _focusBackwards = true;
                        }

                        var index = $fields.index(source);

                        if (index > -1 && (index + 1) < $fields.length)
                        {
                            $fields.slice(index + 1).each(function ()
                            {
                                var $field = $(this);
                                if (!$field.inDom())
                                {
                                    if ($field.attr("id"))
                                    {
                                        $field = _fwdc.formField($field.attr("id"));
                                        if (!$field) { return; }
                                    }
                                    else
                                    {
                                        return;
                                    }
                                }

                                var tabIndex = _default($field.attr("tabindex"), 0);
                                // Exclude elements with no tab index, or that are inside the source element as we're trying to find something after it.
                                if (tabIndex !== undefined
                                    && tabIndex > -1
                                    && !$field.closest(source).length
                                    && _fwdc.focus($field))
                                {
                                    $focused = $field;
                                    return false;
                                }
                            });

                            if ($focused) { return false; }
                        }

                        if (fallback !== false)
                        {
                            $fields.each(function ()
                            {
                                var $field = $(this);
                                if (!$field.inDom())
                                {
                                    if ($field.attr("id"))
                                    {
                                        $field = _fwdc.formField($field.attr("id"));
                                        if (!$field) { return; }
                                    }
                                    else
                                    {
                                        return;
                                    }
                                }

                                var tabIndex = $field.attr("tabindex");
                                if (tabIndex !== undefined && tabIndex > -1 && _fwdc.focus($field))
                                {
                                    $focused = $field;
                                    return false;
                                }
                            });
                        }

                        if ($focused) { return false; }
                    });

                    return $focused;
                },

                // Added to handle scenarios where calling jQUery's focus() on a child element from within a focus event would not properly move.
                focusNative: function ()
                {
                    var ele = this[0];
                    if (ele && ele.focus)
                    {
                        ele.focus();
                        return this;
                    }

                    return this.focus();
                },

                findElementById: function (id)
                {
                    return $.findElementById(id, this);
                },

                findElementsByClassName: function (classNames)
                {
                    return $.findElementsByClassName(classNames, this, this);
                },

                findElementsByAnyClassName: function (classNames)
                {
                    return $.findElementsByAnyClassName(classNames, this);
                },

                filterHasClassName: function (className)
                {
                    return this.filter(function (index, element)
                    {
                        return element.nodeType === Node.ELEMENT_NODE && element.classList.contains(className);
                    });
                },

                filterNotHasClassName: function (className)
                {
                    return this.filter(function (index, element)
                    {
                        return element.nodeType === Node.ELEMENT_NODE && !element.classList.contains(className);
                    });
                },

                hasAnyClass: function (classNames)
                {
                    if (arguments.length > 1)
                    {
                        classNames = arguments;
                    }
                    else if (typeof classNames === "string")
                    {
                        classNames = classNames.split(",") || [];
                    }

                    if (!classNames || !classNames.length)
                    {
                        return false;
                    }

                    var result = false;

                    this.each(function (index, element)
                    {
                        if (element.nodeType === Node.ELEMENT_NODE)
                        {
                            for (var ii = 0; ii < classNames.length; ++ii)
                            {
                                if (element.classList.contains(classNames[ii]))
                                {
                                    result = true;
                                    return false;
                                }
                            }
                        }
                    });

                    return result;
                },

                // Wrapper for querySelectorAll for better performance on certain calls than jQuery's .find which can manipulate things.
                querySelectorAll: function (selector)
                {
                    return $.querySelectorAll(selector, this);
                },

                setMask: function (mask)
                {
                    return $.fastMask.set(this, mask);
                },
                clearMask: function ()
                {
                    return $.fastMask.clear(this);
                },

                tryDestroyDialog: function ()
                {
                    this.each(function ()
                    {
                        var $dialog = $(this);

                        var dialogData = $dialog.data("ui-dialog");
                        if (dialogData && $dialog.dialog("isOpen"))
                        {
                            $dialog.dialog("close");
                            dialogData = $dialog.data("ui-dialog");
                        }

                        if ($(this).closest(".ui-effects-wrapper").length) { return; }

                        if (dialogData)
                        {
                            $dialog.dialog("destroy").remove();
                        }
                    });

                    return this;
                },

                windowOffset: function (elem)
                {
                    var offset = this.offset();
                    var $window = $(window);

                    return { top: offset.top - $window.scrollTop(), left: offset.left - $window.scrollLeft() };
                },

                inDom: function ()
                {
                    if (!this.length)
                    {
                        return false;
                    }

                    var inDom = true;

                    this.each(function ()
                    {
                        if (!$.contains(window.document.documentElement, this))
                        {
                            inDom = false;
                            return false;
                        }
                    });

                    return inDom;
                },

                cssWidth: function ()
                {
                    if (!this.length)
                    {
                        return "";
                    }

                    var $first = this.length === 1 ? this : $(this[0]);

                    //if (_cssWidthRequiresDisplayNone)
                    {
                        $first.css("display", "none");
                    }

                    var cssWidth = $first.css("width") || "";

                    //if (_cssWidthRequiresDisplayNone)
                    {
                        $first.css("display", "");
                    }

                    return cssWidth.trim();
                },

                cssWidths: function ()
                {
                    if (!this.length)
                    {
                        return [];
                    }

                    var widths = new Array(this.length);

                    //if (_cssWidthRequiresDisplayNone)
                    {
                        this.css("display", "none");
                    }

                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        var $ii = $(this[ii]);
                        widths[ii] = $ii.css("width").trim();
                    }

                    //if (_cssWidthRequiresDisplayNone)
                    {
                        this.css("display", "");
                    }

                    return widths;
                },

                colsCssWidths: function ()
                {
                    if (!this.length)
                    {
                        return [];
                    }

                    var $colgroup = this.parent();

                    //$colgroup.addClass("ColMeasuring");
                    $colgroup.css("display", "none");

                    var widths = new Array(this.length);

                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        // Do not use jQuery's .css for this, as it slowly manipulates some things due to these being <col> elements.
                        widths[ii] = window.getComputedStyle(this[ii]).width;
                    }

                    //$colgroup.removeClass("ColMeasuring");
                    $colgroup.css("display", "");

                    return widths;
                },

                // Native Offset function to get past issues with jQuery's .offset() being affected by transforms.
                nativeOffset: function ()
                {
                    if (!this.length) { return null; }

                    return { left: this[0].offsetLeft, top: this[0].offsetTop };
                },

                nativeOffsetClosest: function (parent)
                {
                    // Parent must be a string or jQuery element.
                    if (!this.length || !parent || !parent.length) { return null; }

                    var $parent = this.closest(parent);
                    if (!$parent.length)
                    {
                        return null;
                    }

                    var $offsetElement = this.length > 1 ? $(this[0]) : this;

                    var offset = { left: 0, top: 0 };

                    while ($offsetElement && $offsetElement.length && !$offsetElement.equals($parent))
                    {
                        offset.left += $offsetElement[0].offsetLeft;
                        offset.top += $offsetElement[0].offsetTop;
                        $offsetElement = $($offsetElement[0].offsetParent);
                    }

                    return offset;
                },

                relativeOffset: function ($relativeTo)
                {
                    if (!this.length || !$relativeTo || !$relativeTo.length) { return null; }

                    var thisOffset = this.offset();

                    var relativeOffset = $relativeTo.offset();

                    return {
                        "top": thisOffset.top - relativeOffset.top,
                        "left": thisOffset.left - relativeOffset.left
                    };
                },

                relativeContentOffset: function ($relativeTo)
                {
                    if (!this.length && !$relativeTo && !$relativeTo.length) { return null; }

                    var thisOffset = this.offset();

                    var relativeOffset = $relativeTo.offset();

                    var borderLeftWidth = $relativeTo.css("border-left-width");
                    var borderTopWidth = $relativeTo.css("border-top-width");

                    if (borderLeftWidth && borderLeftWidth.endsWith("px"))
                    {
                        borderLeftWidth = parseInt(borderLeftWidth, 10);
                        if (isNaN(borderLeftWidth))
                        {
                            borderLeftWidth = 0;
                        }
                    }

                    if (borderTopWidth && borderTopWidth.endsWith("px"))
                    {
                        borderTopWidth = parseInt(borderTopWidth, 10);
                        if (isNaN(borderTopWidth))
                        {
                            borderTopWidth = 0;
                        }
                    }

                    return {
                        "top": thisOffset.top - relativeOffset.top - borderTopWidth,
                        "left": thisOffset.left - relativeOffset.left - borderLeftWidth
                    };
                },

                displayContentOffset: function ($relativeTo)
                {
                    if (!this.length || !$relativeTo || !$relativeTo.length) { return null; }

                    var thisRect = this[0].getClientRects();
                    if (thisRect && thisRect.length)
                    {
                        thisRect = thisRect[0];
                    }
                    else
                    {
                        return null;
                    }

                    var relativeRect = $relativeTo[0].getClientRects();
                    if (relativeRect && relativeRect.length)
                    {
                        relativeRect = relativeRect[0];
                    }
                    else
                    {
                        return null;
                    }

                    var borderLeftWidth = $relativeTo.css("border-left-width");
                    var borderTopWidth = $relativeTo.css("border-top-width");

                    if (borderLeftWidth && borderLeftWidth.endsWith("px"))
                    {
                        borderLeftWidth = parseInt(borderLeftWidth, 10);
                        if (isNaN(borderLeftWidth))
                        {
                            borderLeftWidth = 0;
                        }
                    }

                    if (borderTopWidth && borderTopWidth.endsWith("px"))
                    {
                        borderTopWidth = parseInt(borderTopWidth, 10);
                        if (isNaN(borderTopWidth))
                        {
                            borderTopWidth = 0;
                        }
                    }

                    return {
                        "top": thisRect.y - relativeRect.y - borderLeftWidth,
                        "left": thisRect.x - relativeRect.x - borderTopWidth
                    };
                },

                scrollHeight: function ()
                {
                    if (!this.length) { return 0; }

                    return this[0].scrollHeight;
                },

                scrollWidth: function ()
                {
                    if (!this.length) { return 0; }

                    return this[0].scrollWidth;
                },

                viewportHeight: function ()
                {
                    if (!this.length) { return 0; }

                    return this.is("html") ? _fwdc.$window.height() : this.height();
                },

                displayBoundingBox: function ()
                {
                    if (!this.length) { return null; }

                    var box = { top: 1000000, left: 1000000, bottom: -1000000, right: -1000000, height: 0, width: 0 };
                    var foundVisibleElement;

                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        var clientRects = null;
                        switch (this[ii].nodeType)
                        {
                            case Node.ELEMENT_NODE:
                                clientRects = this[ii].getClientRects();
                                break;

                            case Node.DOCUMENT_NODE:
                                clientRects = [{ top: 0, left: 0, bottom: _fwdc.windowHeight, right: _fwdc.windowWidth }];
                                break;
                        }

                        if (clientRects && clientRects.length)
                        {
                            for (var jj = 0; jj < clientRects.length; ++jj)
                            {
                                foundVisibleElement = true;

                                var elementBox = clientRects[jj];

                                box.top = Math.min(box.top, elementBox.top);
                                box.left = Math.min(box.left, elementBox.left);
                                box.bottom = Math.max(box.bottom, elementBox.bottom);
                                box.right = Math.max(box.right, elementBox.right);
                            }
                        }
                    }

                    if (!foundVisibleElement)
                    {
                        return null;
                    }

                    if (box.top > box.bottom)
                    {
                        box.top = box.bottom;
                    }

                    if (box.left > box.right)
                    {
                        box.left = box.right;
                    }

                    box.width = box.right - box.left;
                    box.height = box.bottom - box.top;

                    return box;
                },

                visibleBoundingBox: function ()
                {
                    var displayBoundingBox = this.displayBoundingBox();

                    if (!displayBoundingBox) { return null; }

                    displayBoundingBox = _clampRect(displayBoundingBox, { top: 0, right: _fwdc.windowWidth, bottom: _fwdc.windowHeight, left: 0 });

                    return displayBoundingBox;
                },

                focusScroll: function (scroll)
                {
                    if (!this.length) { return this; }

                    if (scroll)
                    {
                        return this.focus();
                    }
                    else if (_fwdc.supportsPreventScrollOption)
                    {
                        _ignoreFocusScroll += 1;
                        try
                        {
                            var scrollPositions = _fwdc.saveScrollPositions(true);
                            this[0].focus({ preventScroll: true });
                            _fwdc.restoreScrollPositions(scrollPositions);
                            // Queue an async restore to deal with async post-focus scrolling.
                            // Doing this can cause a huge flicker, but resolves an issue with FF and others where the preventScroll option is ignored
                            // if a DOM change is made in the same synchronous call.
                            //_fwdc.setTimeout("focusScroll.restoreScrollPositions", _fwdc.restoreScrollPositions, 0, scrollPositions);
                        }
                        finally
                        {
                            _ignoreFocusScroll -= 1;
                        }
                    }
                    else
                    {
                        _ignoreFocusScroll += 1;
                        try
                        {
                            var scrollPositions = _fwdc.saveScrollPositions(true);

                            this[0].focus();

                            _fwdc.restoreScrollPositions(scrollPositions);

                            // Queue an async restore to deal with async post-focus scrolling.
                            _fwdc.setTimeout("focusScroll.restoreScrollPositions", _fwdc.restoreScrollPositions, 0, scrollPositions);
                        }
                        finally
                        {
                            _ignoreFocusScroll -= 1;
                        }
                    }

                    return this;
                },

                // Attempts to return the text of an element or set of elements including newlines based on the content.
                // The jQuery version drops what should be newlines based on paragraph structures.
                innerText: function ()
                {
                    if (!this.length) { return ""; }

                    var text = "";

                    for (var ii = 0; ii < this.length; ++ii)
                    {
                        var elem = this[ii];

                        switch (elem.nodeType)
                        {
                            case 1: // Element
                            case 9: // Document
                            case 11: // Document Fragment
                                if (text) text += "\r\n";

                                if (elem.innerText === undefined)
                                {
                                    text += elem.textContent;
                                }
                                else
                                {
                                    text += elem.innerText;
                                }

                                break;

                            case 3: // Text
                            case 4: // CDATA
                                if (text) text += "\r\n";

                                text += elem.nodeValue;
                                break;
                        }
                    }

                    return text ? text.trim() : "";
                }
                /*,
         
                qtip: _fwdc._logFunction("qtip", $.fn.qtip)*/

                //qtip: function (options, notation, newValue)
                //{
                //    console.log("qtip+" + options, notation, newValue, this);
                //    return qtipBase.apply(this, arguments);
                //}
                /*,
         
                // This function doesn't make much sense - seems to return .closest for each item, not the root?
                root: function (filter)
                {
                    return this.map(function ()
                    {
                        if (filter)
                        {
                            var $this = $(this);
                            var $parent = $this.parent();
         
                            while ($parent && $parent.length)
                            {
                                if ($parent.is(filter))
                                {
                                    return $parent[0];
                                }
         
                                $parent = $parent.parent();
                            }
         
                            return null;
                        }
                        else
                        {
                            return this;
                        }
                    });
                }*//*,
         
                setScrollTop: function (top)
                {
                    return this.scrollTop(top);
                }*/
            });

            function filterAutocompleteRegex(array, term)
            {
                if (!term) { return { results: array }; }

                term = term.split(/\s+/);
                var terms = [];
                var termLength = term.length;
                for (var jj = 0; jj < termLength; jj++)
                {
                    if (term[jj])
                    {
                        terms.push(new RegExp($.ui.autocomplete.escapeRegex(term[jj]), "i"));
                    }
                }
                term = terms;

                if (!term.length) { return { results: array }; }

                var matcher;
                if (term.length === 1)
                {
                    term = term[0];
                    matcher = containsr_s;
                }
                else
                {
                    matcher = containsr_sa;
                }

                var results = [];
                var firstMatch;
                var bestElement;

                var arrayLength = array.length;
                for (var ii = 0; ii < arrayLength; ii++)
                {
                    var element = array[ii];
                    var text = (element.label || element.value || "");

                    if (element.moreItemsOption)
                    {
                        firstMatch = firstMatch || element;
                        results.push(element);
                    }
                    else if (!element.empty)
                    {
                        var result = matcher(text, term);

                        switch (result)
                        {
                            case MatchType.STARTSWITH:
                                bestElement = bestElement || element;
                                firstMatch = firstMatch || element;
                                results.push(element);
                                break;
                            case MatchType.MATCH:
                                firstMatch = firstMatch || element;
                                results.push(element);
                        }
                    }
                }

                return { results: results, best: bestElement || firstMatch };
            }

            // Redefining ui.mouse here wipes out any plugins that are already registered by the base jQuery UI script.  We don't need to predefine this value.
            //$.widget("ui.mouse", $.ui.mouse, {
            //    options:
            //    {
            //        disableTouch: false
            //    }
            //});

            $.widget("ui.dialog", $.ui.dialog, {
                _createWrapper: function ()
                {
                    var rtn = this._super();

                    this.element.attr("tabindex", "-1");

                    if (!this.options.describedByContent)
                    {
                        // Remove the aria-describedby that automatically adds the entire dialog content as a description for the dialog.
                        this.uiDialog.removeAttr("aria-describedby");
                    }

                    if (this.options.modal)
                    {
                        this._addClass(this.uiDialog, "ui-dialog", "ui-dialog-modal");
                    }

                    return rtn;
                },

                _allowInteraction: function (event)
                {
                    return this._super(event) || _fwdc.allowDialogInteraction(event);
                },

                _makeResizable: function ()
                {
                    var that = this;
                    this._super();

                    var baseResize = this.uiDialog.data("ui-resizable").options.resize;

                    this.uiDialog.resizable({
                        "resize": function (event, ui)
                        {
                            var returnVal = baseResize.call(this, event, ui);
                            that.uiDialog.fast_resized = true;
                            _fwdc.resizeElements(that.uiDialog);
                            return returnVal;
                        }
                    });
                },

                _createTitlebar: function ()
                {
                    this._super();

                    // Allow regular titlebar to be created, but replace span element with heading level element
                    var $uiDialogTitle = this.uiDialogTitlebar.childrenWithClass("ui-dialog-title").remove();

                    if ($uiDialogTitle.length > 0)
                    {
                        var $headingLevelTitle;
                        if (this.options.titleHeadingLevel && this.options.titleHeadingLevel.length > 0)
                        {
                            $headingLevelTitle = this.options.titleHeadingLevel;
                        }
                        else
                        {
                            $headingLevelTitle = $($.parseHTML('<h2></h2>'));
                        }
                        $headingLevelTitle.addClass($uiDialogTitle[0].className);
                        $headingLevelTitle.attr("id", $uiDialogTitle.attr("id"));
                        $headingLevelTitle.text($uiDialogTitle.text());


                        $headingLevelTitle.prependTo(this.uiDialogTitlebar);

                        if (!$headingLevelTitle.text() || $headingLevelTitle.innerText() == '')
                        {
                            this.uiDialog.removeAttr("aria-labelledby");
                        }
                    }

                },

                // FAST - Added logic to move the corresponding overlay.
                _moveToTop: function (event, silent)
                {
                    var moved = false,
                        zIndices = this.uiDialog.siblings(".ui-front:visible").map(function ()
                        {
                            return +$(this).css("z-index");
                        }).get(),
                        zIndexMax = Math.max.apply(null, zIndices);

                    if (zIndexMax >= +this.uiDialog.css("z-index"))
                    {
                        this.uiDialog.css("z-index", zIndexMax + 1);

                        if (this.overlay)
                        {
                            this.overlay.css("z-index", zIndexMax);
                        }

                        moved = true;
                    }

                    if (moved && !silent)
                    {
                        this._trigger("focus", event);
                    }
                    return moved;
                },

                // Fast - Adapted from jQuery UI 1.11.4 Z-Index modal rearrangement changes.
                open: function ()
                {
                    //return this._super();
                    var that = this;
                    if (this._isOpen)
                    {
                        if (this._moveToTop())
                        {
                            this._focusTabbable();
                        }
                        return;
                    }

                    this._isOpen = true;
                    this.opener = $(this.document[0].activeElement);

                    // Toggle Display so the elements are visible during the opening call.
                    var display = this.uiDialog.css("display");
                    this.uiDialog.css("display", "");
                    this._trigger("opening");
                    this.uiDialog.css("display", display);

                    this._size();
                    this._position();
                    this._addClass(this.uiDialog, "ui-dialog", "fast-ui-dialog-positioned");
                    this._createOverlay();
                    this._moveToTop(null, true);

                    // Ensure the overlay is moved to the top with the dialog, but only when
                    // opening. The overlay shouldn't move after the dialog is open so that
                    // modeless dialogs opened after the modal dialog stack properly.
                    if (this.overlay)
                    {
                        this.overlay.css("z-index", this.uiDialog.css("z-index") - 1);
                    }

                    this._show(this.uiDialog, this.options.show, function ()
                    {
                        // Moved this stuff out to allow focusing to be delayed to the end of transition effects.
                        _fwdc.setTimeout("uiDialogOpenFocus", function ()
                        {
                            //that._focusTabbable();
                            if (that.options.initFocus)
                            {
                                that.options.initFocus.call(that.element[0]);
                            }
                            else
                            {
                                that.focusDialog();
                                //$dialog.children(".ui-dialog-content").focus();
                                _fwdc.focusCurrentField();
                            }
                            that._trigger("focus");
                        }, 1);
                    });

                    this._trigger("open");

                    // Workaround for IE not supporting column flexing properly with max-height but no explicit height.
                    if (Modernizr.flexboxtweener)
                    {
                        this.uiDialog.outerHeight(this.uiDialog.outerHeight());
                    }

                    //this._addClass(this.uiDialog, "ui-dialog", "fast-ui-dialog-open");
                    if (!_fwdc.onTransition("ui.dialog.open", this.uiDialog, "fast-ui-dialog-open", function ()
                    {
                        // Force rich controls to update as they may have improperly reacted to scaling.
                        _fwdc.refreshRichControls(that.uiDialog);
                        // Reposition any table cell editors so they adjust for scaling.
                        _repositionCellEditor();
                        // Re-position/show tooltips after opening
                        _fwdc.showCurrentFieldTip();
                        // Ensure repositioning is done
                        FWDC.checkFieldTipPositions(true);
                    }, true))
                    {
                        this._addClass(this.uiDialog, "ui-dialog", "fast-ui-dialog-open");
                        // Re-position/show tooltips after opening
                        _fwdc.showCurrentFieldTip();
                    }
                },

                _position: function ()
                {
                    //this.uiDialog.css({
                    //    "transform": "none",
                    //    "transition-property": "none"
                    //}).css("transform");

                    if (Modernizr.flexboxtweener && !this.uiDialog.fast_resized && this.uiDialog)
                    {
                        this.uiDialog.css("height", "").outerHeight(this.uiDialog.outerHeight());
                    }

                    var returnVal = this._super();

                    //this.uiDialog.css({
                    //    "transform": "",
                    //    "transition-property": ""
                    //}).css("transform");

                    return returnVal;
                },

                reposition: function ()
                {
                    this._position();
                },

                _hide: function (element, options, callback)
                {
                    this._trigger("hiding");

                    var that = this;
                    if (options === null)
                    {
                        //element.addClass("FastTransitioning");

                        //_fwdc.incrementTransitioning();

                        element.addClass("fast-ui-dialog-hiding");

                        var transitionId = null;

                        var onCssTransition = function ($element, transitionEvent)
                        {
                            delete that.pendingHideTransition;
                            callback(element[0]);
                            // Ensure the callback can't be invoked by the _super call if animations are off.
                            callback = null;
                            $element.removeClass("fast-ui-dialog-closing");

                            if (transitionId)
                            {
                                _fwdc.onCrossTransitionFinished(transitionId);
                            }
                        };

                        if (_fwdc.onTransition("ui.dialog._hide", element, "fast-ui-dialog-closing", onCssTransition, true))
                        {
                            transitionId = _fwdc.onCrossTransitionStarting();
                            //_fwdc._log("Disabling access keys for closing dialog: ", element);
                            _fwdc.disableAccessKeys(element, true);
                            if (that.overlay)
                            {
                                that.overlay.addClass("ui-widget-hiding");
                            }

                            that.pendingHideTransition = element;

                            //_fwdc.decrementTransitioning();
                            return;
                        }
                    }

                    return this._super(element, options, callback);
                },

                /*_destroyOverlay: function()
                {
                    if (!this.options.modal)
                    {
                        return;
                    }
         
                    if (this.overlay)
                    {
                        var overlays = this.document.data("ui-dialog-overlays") - 1;
         
                        if (!overlays)
                        {
                            this._off(this.document, "focusin");
                            this.document.removeData("ui-dialog-overlays");
                        }
                        else
                        {
                            this.document.data("ui-dialog-overlays", overlays);
                        }
         
                        var $oldOverlay = this.overlay;
                        this.overlay = null;
         
                        $oldOverlay.addClass("ui-widget-hiding");
                        _fwdc.onTransition("ui.dialog._destroyOverlay", $oldOverlay, function ()
                        {
                            $oldOverlay.remove();
                        }, true );
                    }
                },*/

                close: function (event)
                {
                    /*_fwdc.saveScrollPositions();
                    var returnVal = this._super(event);
                    _fwdc.restoreScrollPositions();
         
                    this.uiDialog.removeClass("fast-ui-dialog-open");
         
                    return returnVal;*/

                    var that = this;

                    if (!this._isOpen || this._trigger("beforeClose", event) === false)
                    {
                        return;
                    }

                    this._isOpen = false;
                    this._focusedElement = null;

                    this.uiDialog.find("[id]").removeAttr("id");

                    this._hide(this.uiDialog, this.options.hide, function ()
                    {
                        that._destroyOverlay();
                        that._untrackInstance();
                        /*if (!that.opener.filter(":focusable").trigger("focus").length)
                        {
                            // Hiding a focused element doesn't trigger blur in WebKit
                            // so in case we have nothing to focus on, explicitly blur the active element
                            // https://bugs.webkit.org/show_bug.cgi?id=47182
                            $.ui.safeBlur($.ui.safeActiveElement(that.document[0]));
                        }*/

                        // Use our focus logic instead of the native dialog logic.
                        /*if (!_fwdc.focusCurrentField())
                        {
                            $.ui.safeBlur($.ui.safeActiveElement(that.document[0]));
                        }*/

                        // Only attempt to blur if the focused element is in the current dialog.
                        var element = $.ui.safeActiveElement(that.document[0]);
                        if (element && $(element).closest(that.element).length)
                        {
                            $.ui.safeBlur($.ui.safeActiveElement(that.document[0]));
                        }

                        _fwdc.focusCurrentField();

                        that.uiDialog.removeClass("fast-ui-dialog-open");
                        that._trigger("close", event);
                    });
                },

                focusDialog: function ()
                {
                    var activeElement = $.ui.safeActiveElement(this.document[0]);
                    var isActive = this.uiDialog[0] === activeElement || $.contains(this.uiDialog[0], activeElement);
                    if (!isActive)
                    {
                        //this._focusTabbable();
                        this.uiDialog.focus();
                        this.element.focus();
                    }
                },

                _destroy: function ()
                {
                    if (this.pendingHideTransition)
                    {
                        _fwdc.cancelOnTransition("ui.dialog._hide", this.pendingHideTransition);
                    }
                    return this._super();
                }
            });

            $.widget("ui.resizable", $.ui.resizable, {
                // FAST Customization: Disable touch interactions to fix scrollable modals being broken by Touch Punch
                options:
                {
                    disableTouch: true
                }
            });

            $.widget("ui.draggable", $.ui.draggable, {
                // FAST Customization: Disable touch interactions to fix scrollable modals being broken by Touch Punch
                options:
                {
                    disableTouch: true
                }
            });

            $.widget("ui.autocomplete", $.ui.autocomplete, {
                _searchTimeout: function (event)
                {
                    if (event)
                    {
                        // Check if the field is readonly to prevent yet another input event error in IE caused by placeholders.
                        if (event.type === "input" && (!this.element.is(":visible") || this.element.attr("readonly")))
                        {
                            // Received an input event for an invisible field.  Ignore this event.
                            // Caused by placeholders on elements in IE.
                            event.preventDefault();
                            return;
                        }
                        /* Ignoring modified keydown events could block opening with multilingual setups.
                        else if (event.type === "keydown" && (event.ctrlKey || event.altKey))
                        {
                            event.preventDefault();
                            return;
                        }*/
                    }

                    // Workaround for IE10/11 Unicode oninput bug:
                    // http://connect.microsoft.com/IE/feedback/details/816137/ie-11-ie-10-input-elements-with-unicode-entity-character-values-cause-oninput-events-to-be-fired-on-page-load
                    if (event.keyCode === _fwdc.keyCodes.SHIFT || event.keyCode === _fwdc.keyCodes.CTRL || event.keyCode === _fwdc.keyCodes.ALT || this._fastSuppressInput) // Shift, Ctrl, Alt
                    {
                        if (this._fastSuppressInput)
                        {
                            event.preventDefault();
                        }
                        return;
                    }

                    return this._super(event);
                },
                _normalize: function (items)
                {
                    return items;
                },
                _renderItem: function (ul, item)
                {
                    if (item["class"])
                    {
                        return $("<li>")
                            .addClass(item["class"])
                            .attr("aria-label", item.label) // aria-label is used in the background by jQuery UI in generating live region updates
                            .append($("<div>").text(item.label))
                            .appendTo(ul);
                    }
                    else if (item.label)
                    {
                        return $("<li>")
                            .attr("aria-label", item.label)
                            .append($("<div>").text(item.label))
                            .appendTo(ul);
                    }
                    else
                    {
                        return $("<li>")
                            .attr("aria-label", "")
                            .append($("<div>").html("&nbsp;"))
                            .appendTo(ul);
                    }
                },
                // Custom suggest implementation to provide best match functionality.
                _suggest: function (items)
                {
                    var bestMatch = items.bestMatch;
                    if (bestMatch)
                    {
                        delete items.bestMatch;
                    }

                    this._super(items);

                    if (bestMatch)
                    {
                        var menu = this.menu;
                        var $items = menu.activeMenu.find(menu.options.items);
                        if ($items)
                        {
                            $items.each(function ()
                            {
                                var $item = $(this);
                                if ($item.data("uiAutocompleteItem") === bestMatch)
                                {
                                    menu.focus(null, $item);
                                }
                            });
                        }
                    }
                },
                reposition: function ()
                {
                    var ul = this.menu.element;

                    // Size and position menu
                    this._resizeMenu();
                    ul.position($.extend({
                        of: this.element
                    }, this.options.position));
                }
            });

            $.widget("ui.menu", $.ui.menu, {
                _isDivider: function ()
                {
                    return false;
                },
                refresh: function ()
                {
                    var menus, items, newItems, newWrappers,
                        that = this;//,
                    //icon = this.options.icons.submenu;

                    this._toggleClass("ui-menu-icons", null, !!this.element.find(".ui-icon").length);

                    // FAST: Disabled submenus
                    // Initialize nested menus
                    /*newSubmenus = submenus.filter(":not(.ui-menu)")
                        .hide()
                        .attr({
                            role: this.options.role,
                            "aria-hidden": "true",
                            "aria-expanded": "false"
                        })
                        .each(function ()
                        {
                            var menu = $(this),
                                item = menu.prev(),
                                submenuCaret = $("<span>").data("ui-menu-submenu-caret", true);
         
                            that._addClass(submenuCaret, "ui-menu-icon", "ui-icon " + icon);
                            item
                                .attr("aria-haspopup", "true")
                                .prepend(submenuCaret);
                            menu.attr("aria-labelledby", item.attr("id"));
                        });
         
                    this._addClass(newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front");*/

                    //menus = submenus.add(this.element);
                    menus = this.element;
                    items = menus.find(this.options.items);

                    // Initialize menu-items containing spaces and/or dashes only as dividers
                    items.not(".ui-menu-item").each(function ()
                    {
                        var item = $(this);
                        if (that._isDivider(item))
                        {
                            that._addClass(item, "ui-menu-divider", "ui-widget-content");
                        }
                    });

                    // Don't refresh list items that are already adapted
                    newItems = items.not(".ui-menu-item, .ui-menu-divider");
                    newWrappers = newItems.children()
                        .not(".ui-menu")
                        .uniqueId()
                        .attr({
                            tabIndex: -1,
                            role: this._itemRole()
                        });

                    // FAST: Use .addClass instead of _addClass due to huge performance issue.
                    /*this._addClass(newItems, "ui-menu-item")
                        ._addClass(newWrappers, "ui-menu-item-wrapper");*/
                    newItems.addClass("ui-menu-item");
                    newWrappers.addClass("ui-menu-item-wrapper");

                    // Add aria-disabled attribute to any disabled menu item
                    items.filter(".ui-state-disabled").attr("aria-disabled", "true");

                    // If the active item has been removed, blur the menu
                    if (this.active && !$.contains(this.element[0], this.active[0]))
                    {
                        this.blur();
                    }
                }
            });

            $.widget("ui.fastmenu", $.ui.menu, {
                _move: function (direction, filter, event)
                {
                    var next;
                    if (this.active)
                    {
                        if (direction === "first" || direction === "last")
                        {
                            next = this.active
                            [direction === "first" ? "prevAll" : "nextAll"](".ui-menu-item:visible")
                                .eq(-1);
                        }
                        else
                        {
                            next = this.active
                            [direction + "All"](".ui-menu-item:visible")
                                .eq(0);
                        }
                    }
                    if (!next || !next.length || !this.active)
                    {
                        next = this.activeMenu.children(".ui-menu-item:visible")[filter]();
                    }

                    this.focus(event, next);
                },

                _destroy: function ()
                {
                    this.element.empty();
                    this._super();
                },

                // Overridden to count only visible items.
                isFirstItem: function ()
                {
                    return this.active && !this.active.prevAll(".ui-menu-item:visible").length;
                },

                // Overridden to count only visible items.
                isLastItem: function ()
                {
                    return this.active && !this.active.nextAll(".ui-menu-item:visible").length;
                },

                // Overridden to count only visible items.
                nextPage: function (event)
                {
                    var item, base, height;

                    if (!this.active)
                    {
                        this.next(event);
                        return;
                    }
                    if (this.isLastItem())
                    {
                        return;
                    }
                    if (this._hasScroll())
                    {
                        base = this.active.offset().top;
                        height = this.element.height();
                        this.active.nextAll(".ui-menu-item:visible").each(function ()
                        {
                            item = $(this);
                            return item.offset().top - base - height < 0;
                        });

                        this.focus(event, item);
                    } else
                    {
                        this.focus(event, this.activeMenu.children(".ui-menu-item:visible")
                        [!this.active ? "first" : "last"]());
                    }
                },

                // Overridden to count only visible items.
                previousPage: function (event)
                {
                    var item, base, height;
                    if (!this.active)
                    {
                        this.next(event);
                        return;
                    }
                    if (this.isFirstItem())
                    {
                        return;
                    }
                    if (this._hasScroll())
                    {
                        base = this.active.offset().top;
                        height = this.element.height();
                        this.active.prevAll(".ui-menu-item:visible").each(function ()
                        {
                            item = $(this);
                            return item.offset().top - base + height > 0;
                        });

                        this.focus(event, item);
                    }
                    else
                    {
                        this.focus(event, this.activeMenu.children(".ui-menu-item:visible").first());
                    }
                },

                close: function (event)
                {
                    clearTimeout(this.closing);
                    if (this.element.is(":visible"))
                    {
                        this.element.hide();
                        this.blur();
                        this._trigger("close", event);
                    }
                }
            });

            $.widget("ui.checkboxradio", $.ui.checkboxradio, {
                options: {
                    icon: false
                },
                _create: function ()
                {
                    this._super();

                    var id = this.element.attr("id");
                    id = id ? "caption2_" + id : "";
                    this._wrapUiButtonText(this.label, id);

                    if (this.options.appendToggle)
                    {
                        this.label.append('<div class="FastToggle"></div>').addClass("fast-ui-toggle");
                    }

                    var me = this;

                    _fwdc.setTimeout("ui.checkboxradio.ready",
                        function ()
                        {
                            me.label.addClass("fast-ui-animate-ready");
                        }, 1);
                },
                updateState: function ()
                {
                    var checked = this.element[0].checked,
                        isDisabled = this.element[0].disabled;

                    this._updateIcon(checked);
                    this._toggleClass(this.label, "ui-checkboxradio-checked", "ui-state-active", checked);

                    if (isDisabled !== this.options.disabled)
                    {
                        this._setOptions({ "disabled": isDisabled });
                    }
                },
                _updateLabel: function ()
                {
                    this._super();

                    //if(this.options.wrapLabel)
                    //{
                    var id = this.element.attr("id");
                    id = (id && "caption2_" + id) || "";

                    this._wrapUiButtonText(this.label, id);

                    if (this.options.appendToggle)
                    {
                        this.label.append('<div class="FastToggle"></div>').addClass("fast-ui-toggle");
                    }
                },
                _wrapUiButtonText: function ($label, id)
                {
                    var $text = $($.parseHTML('<span class="fast-ui-button-text"></span>')).html($label.html());

                    if (id)
                    {
                        $text.attr("id", id);
                    }

                    return $label.empty().append($text);
                }
            });

            $.widget("ui.buttonset", $.ui.controlgroup, {
                _enhance: function ()
                {
                    var that = this;

                    this._addClass("fast-ui-buttonset");
                    //this.element.append('<div class="SelectorUnderline Init" data-current-selector=".ui-state-active .fast-ui-button-text"></div>');
                    this._super();

                    this._on(this.element, {
                        "change input": function (event)
                        {
                            that.updateSelector();
                        }
                    });
                    //.addClass("fast-ui-buttonset")
                    //.append('<div class="SelectorUnderline Init"></div>');
                },
                refresh: function ()
                {
                    this._super();

                    this.updateSelector(true);

                    //$document.on("change", "input[type='radio']", _onCheckboxChange);
                },
                updateSelector: function (init)
                {
                    //_fwdc.animateSelectorUnderline(this.element, init);
                }
            });

            $.widget("ui.sortable", $.ui.sortable, {
                _setHandleClassName: function ()
                {
                    //var that = this;
                    this._removeClass(this.element.find(".ui-sortable-handle"), "ui-sortable-handle");
                    $.each(this.items, function ()
                    {
                        // Use .AddClass instead of _addClass due to performance problems.
                        // Same issue was encountered in ui.menu.
                        (this.instance.options.handle ?
                            this.item.find(this.instance.options.handle) :
                            this.item).addClass("ui-sortable-handle");
                        //that._addClass(
                        //    this.instance.options.handle ?
                        //        this.item.find(this.instance.options.handle) :
                        //        this.item,
                        //    "ui-sortable-handle"
                        //);
                    });
                }

                //// FAST Customization of UI Sortable Widget - Enable Touch Support
                //// Logic is based on jQuery UI Touch-Punch
                //// MIT Licensed
                //// https://github.com/furf/jquery-ui-touch-punch

                //_mouseInit: function ()
                //{
                //    var rtn = this._super();

                //    if ("ontouchstart" in document)
                //    {
                //        var self = this;
                //        self.element.bind({
                //            touchstart: self._touchStart.bind(self),
                //            touchmove: self._touchMove.bind(self),
                //            touchend: self._touchEnd.bind(self)
                //        });
                //    }

                //    return rtn;
                //},
                //_simulateMouse: function (event, simulatedType)
                //{
                //    // Ignore multi-touch events
                //    if (event.originalEvent.touches.length > 1)
                //    {
                //        return;
                //    }

                //    event.preventDefault();

                //    var touch = event.originalEvent.changedTouches[0];

                //    // Initialize the simulated mouse event using the touch event's coordinates
                //    var simulatedEvent = new MouseEvent(simulatedType, {
                //        screenX: touch.screenX,
                //        screenY: touch.screenY,
                //        clientX: touch.clientX,
                //        clientY: touch.clientY,
                //        ctrlkey: false,
                //        shitKey: false,
                //        altkey: false,
                //        metaKey: false,
                //        button: 0, // 0: Left, 1: middle, 2: Right
                //        buttons: 0, // 0: None, 1: Left, 2: Right, 4: Middle (Bitfield)
                //        relatedTarget: null,
                //        view: window // This doesn't seem to be an option to the MouseEvent constructor, but it did exist on the initMouseEvent function
                //    });

                //    // Dispatch the simulated event to the target element
                //    event.target.dispatchEvent(simulatedEvent);
                //},

                //_touchHandled: false,
                //_touchMoved: false,
                //_touchStart: function (event)
                //{
                //    console.log("_touchStart:", arguments);

                //    var self = this;

                //    if (self._touchhandled || !self._mouseCapture(event.originalEvent.changedTouches[0]))
                //    {
                //        return;
                //    }

                //    self._touchHandled = true;
                //    self._touchMoved = false;

                //    // Simulate the series of events that would've happened with a mouse
                //    self._simulateMouse(event, "mouseover");
                //    self._simulateMouse(event, "mousemove");
                //    self._simulateMouse(event, "mousedown");
                //},
                //_touchMove: function (event)
                //{
                //    console.log("_touchMove:", arguments);

                //    var self = this;

                //    if (!self._touchHandled)
                //    {
                //        return;
                //    }

                //    // If we moved, this isn't a click
                //    self._touchMoved = true;

                //    // Raise the corresponding mousemove event
                //    self._simulateMouse(event, "mousemove");
                //},
                //_touchEnd: function (event)
                //{
                //    console.log("_touchEnd:", arguments);

                //    var self = this;

                //    if (!self._touchHandled)
                //    {
                //        return;
                //    }


                //    self._simulateMouse(event, "mouseup");
                //    self._simulateMouse(event, "mouseout");

                //    if (!self._touchMoved)
                //    {
                //        self._simulateMouse(event, "click");
                //    }

                //    self._touchHandled = false;
                //},
                //_destroy: function ()
                //{
                //    return this._super();
                //}
            });

            $.extend($.ui.autocomplete, {
                // Override the standard filter method for the autocomplete system to not match against the value directly.
                filter: function (array, term)
                {
                    if (!array || !array.length)
                    {
                        return array;
                    }

                    var filterResults = filterAutocompleteRegex(array, term);

                    filterResults.results.bestMatch = filterResults.best;

                    return filterResults.results;
                }
            });

            $.extend($.datepicker, {
                _triggerClass: "ui-datepicker-trigger FastInputButton",

                // Override to add a floating class for CSS.
                _superNewInst: $.datepicker._newInst,
                _newInst: function (target, inline)
                {
                    var ret = $.datepicker._superNewInst.call(this, target, inline);

                    if (!ret.inline)
                    {
                        this.dpDiv.addClass("ui-datepicker-floating");
                    }

                    return ret;
                },

                // Override to attach keydown listener to datepicker itself instead of input field
                _superConnectDatepicker: $.datepicker._connectDatepicker,
                _connectDatepicker: function (target, inst)
                {
                    var input = $(target);
                    inst.append = $([]);
                    inst.trigger = $([]);
                    if (input.hasClass(this.markerClassName))
                    {
                        return;
                    }

                    this._attachments(input, inst);
                    input.addClass(this.markerClassName).on("keypress", this._doKeyPress).on("keyup", this._doKeyUp);

                    if (!$(inst.dpDiv).hasClass("FastDatepickerHandler"))
                    {
                        inst.dpDiv.addClass("FastDatepickerHandler");
                        inst.dpDiv.on("keydown", this._doKeyDown);
                    }

                    this._autoSize(inst);
                    $.data(target, "datepicker", inst);

                    //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
                    if (inst.settings.disabled)
                    {
                        this._disableDatepicker(target);
                    }
                },

                _superDoKeyDown: $.datepicker._doKeyDown,
                _doKeyDown: function (event)
                {
                    var target;
                    var id = $(event.currentTarget).data("fast-datepicker-input"); //update where this is getting set
                    if (id)
                    {
                        target = document.getElementById(id);
                    }

                    if (!target)
                    {
                        return; // Can't find the input field
                    }

                    var onSelect, dateStr, sel,
                        inst = $.datepicker._getInst(target),
                        inline = inst.inline,
                        handled = true,
                        isRTL = inst.dpDiv.is(".ui-datepicker-rtl");

                    if (!$(event.target).hasClass("FastDatepickerDay"))
                    {
                        // Only apply custom key handling for days in datepicker
                        return;
                    }

                    inst._keyEvent = true;
                    if ($.datepicker._datepickerShowing || inline)
                    {
                        switch (event.keyCode)
                        {
                            case _fwdc.keyCodes.ENTER:
                                sel = $(event.target).parent();
                                if (sel[0])
                                {
                                    if (sel.hasClass("ui-datepicker-unselectable"))
                                    {
                                        _fwdc.stopEvent(event);
                                        return false;
                                    }

                                    $.datepicker._selectDay(target, inst.selectedMonth, inst.selectedYear, sel[0]);
                                }

                                onSelect = $.datepicker._get(inst, "onSelect");
                                if (onSelect)
                                {
                                    dateStr = $.datepicker._formatDate(inst);

                                    // trigger custom callback
                                    onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
                                }
                                else if (!inline)
                                {
                                    $.datepicker._hideDatepicker();
                                }


                                return false; // don't submit the form
                            case _fwdc.keyCodes.ESCAPE:
                                $.datepicker._hideDatepicker();
                                break; // hide on escape

                            case _fwdc.keyCodes.PAGE_UP:
                                $.datepicker._adjustDate(target, (event.ctrlKey ?
                                    -$.datepicker._get(inst, "stepBigMonths") :
                                    -$.datepicker._get(inst, "stepMonths")), "M");
                                _fwdc.focusDatepickerSelected(inst.dpDiv);
                                break; // previous month/year on page up/+ ctrl

                            case _fwdc.keyCodes.PAGE_DOWN:
                                $.datepicker._adjustDate(target, (event.ctrlKey ?
                                    +$.datepicker._get(inst, "stepBigMonths") :
                                    +$.datepicker._get(inst, "stepMonths")), "M");
                                _fwdc.focusDatepickerSelected(inst.dpDiv);
                                break; // next month/year on page down/+ ctrl

                            case _fwdc.keyCodes.END:
                                if (event.ctrlKey || event.metaKey)
                                {
                                    $.datepicker._clearDate(target);
                                    _fwdc.focusDatepickerSelected(inst.dpDiv);
                                }
                                handled = event.ctrlKey || event.metaKey;
                                break; // clear on ctrl or command +end

                            case _fwdc.keyCodes.HOME:
                                if (event.ctrlKey || event.metaKey)
                                {
                                    $.datepicker._gotoToday(target);
                                    _fwdc.focusDatepickerSelected(inst.dpDiv);
                                }
                                handled = event.ctrlKey || event.metaKey;
                                break; // current on ctrl or command +home

                            case _fwdc.keyCodes.LEFT:
                                if (event.originalEvent.altKey)
                                {
                                    // next month/year on alt +left
                                    $.datepicker._adjustDate(target, (event.ctrlKey ?
                                        -$.datepicker._get(inst, "stepBigMonths") :
                                        -$.datepicker._get(inst, "stepMonths")), "M");
                                    _fwdc.focusDatepickerSelected(inst.dpDiv);
                                }
                                else if (!event.shiftKey)
                                {
                                    // -1 day on ctrl or command +left
                                    $.datepicker._adjustDate(target, (isRTL ? +1 : -1), "D");
                                    _fwdc.focusDatepickerSelected(inst.dpDiv);
                                }
                                else
                                {
                                    handled = false;
                                }
                                break;

                            case _fwdc.keyCodes.UP:
                                // -1 week on ctrl or command +up
                                if (!event.shiftKey)
                                {
                                    $.datepicker._adjustDate(target, -7, "D");
                                    _fwdc.focusDatepickerSelected(inst.dpDiv);
                                }
                                else
                                {
                                    handled = false;
                                }
                                break;

                            case _fwdc.keyCodes.RIGHT:
                                if (event.originalEvent.altKey)
                                {
                                    // next month/year on alt +right
                                    $.datepicker._adjustDate(target, (event.ctrlKey ?
                                        +$.datepicker._get(inst, "stepBigMonths") :
                                        +$.datepicker._get(inst, "stepMonths")), "M");
                                    _fwdc.focusDatepickerSelected(inst.dpDiv);
                                }
                                else if (!event.shiftKey)
                                {
                                    // +1 day on ctrl or command +right
                                    $.datepicker._adjustDate(target, (isRTL ? -1 : +1), "D");
                                    _fwdc.focusDatepickerSelected(inst.dpDiv);
                                }
                                else
                                {
                                    handled = false;
                                }
                                break;

                            case _fwdc.keyCodes.DOWN:
                                // +1 week on ctrl or command +down
                                if (!event.shiftKey)
                                {
                                    $.datepicker._adjustDate(target, +7, "D");
                                    _fwdc.focusDatepickerSelected(inst.dpDiv);
                                }
                                else
                                {
                                    handled = false;
                                }
                                break;

                            default:
                                handled = false;
                        }
                    }
                    else
                    {
                        handled = false;
                    }

                    if (handled)
                    {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                    //return $.datepicker._superDoKeyDown.call(this, event);
                },
                _gotoToday: function (id)
                {
                    var $target = $(id);
                    var inst = this._getInst($target[0]);
                    var runDate = this._get(inst, "runDate") || new Date();

                    if (runDate)
                    {
                        runDate = this._determineDate(inst, runDate, new Date());

                        inst.selectedDay = runDate.getDate();
                        inst.drawMonth = inst.selectedMonth = runDate.getMonth();
                        inst.drawYear = inst.selectedYear = runDate.getFullYear();

                        this._notifyChange(inst);
                        this._adjustDate($target);

                        this._selectDate(id, this._formatDate(inst, runDate.getDate(), runDate.getMonth(), runDate.getFullYear()));
                    }
                    else
                    {
                        this._super(id);
                    }
                },

                //_selectDate: function (id, dateStr)
                //{
                //    var focus = $(this).

                //    var rtn = this._super(id, dateStr);


                //    return rtn;
                //},

                _superSetDateDatepicker: $.datepicker._setDateDatepicker,
                _setDateDatepicker: function (target, date)
                {
                    var ret = $.datepicker._superSetDateDatepicker.call(this, target, date);

                    if (this._optionDatepicker(target, "disabled"))
                    {
                        this._disableDatepicker(target);
                    }

                    return ret;
                },

                /* Set the date(s) directly. */
                /* Added explicit handling for HighDate */
                _setDate: function (inst, date, noChange)
                {
                    var clear = !date,
                        origMonth = inst.selectedMonth,
                        origYear = inst.selectedYear,
                        newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));

                    inst.selectedDay = inst.currentDay = newDate.getDate();
                    inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
                    inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();

                    if (clear)
                    {
                        delete inst.currentDay;
                        delete inst.currentMonth;
                        delete inst.currentYear;
                    }

                    if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange)
                    {
                        this._notifyChange(inst);
                    }
                    this._adjustInstDate(inst);
                    if (inst.input)
                    {
                        inst.input.val(clear ? "" : this._formatDate(inst));
                    }
                },

                _focusDatepicker: function ()
                {

                },

                /*_superEnableDatepicker: $.datepicker._enableDatepicker,
                _enableDatepicker: function (target)
                {
                    var ret = $.datepicker._superEnableDatepicker.call(this, target);
         
                    var $target = $(target);
                    var inline = $target.children("." + this._inlineClass);
         
                    inline.children().addClass("ui-state-enabled");
                },*/

                /* Provide the configuration settings for formatting/parsing.  Extended to handle parsing arrays for months and days. */
                _getFormatConfig: function (inst)
                {
                    var shortYearCutoff = this._get(inst, "shortYearCutoff");
                    shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
                        new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
                    return {
                        shortYearCutoff: shortYearCutoff,
                        dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
                        monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames"),
                        parseDayNamesShort: this._get(inst, "parseDayNamesShort"), parseDayNames: this._get(inst, "parseDayNames"),
                        parseMonthNamesShort: this._get(inst, "parseMonthNamesShort"), parseMonthNames: this._get(inst, "parseMonthNames")
                    };
                },

                _superShowDatepicker: $.datepicker._showDatepicker,
                _showDatepicker: function (input)
                {
                    var rtn = this._superShowDatepicker(input);
                    var inst = $.datepicker._getInst(input);
                    var dpDiv;
                    if (inst && (dpDiv = inst.dpDiv))
                    {
                        inst.dpDiv.css("z-index", 15000);

                        $(dpDiv).data("fast-datepicker-input", input.id);

                        // Put focus on the selected date or the default 'today' when opening
                        var $today = $(dpDiv).find("." + this._currentClass);
                        if ($today.length === 0)
                        {
                            $today = $(dpDiv).find("." + this._dayOverClass);
                        }

                        var $todayLink;
                        if ($today.length > 0 && ($todayLink = $today.children()))
                        {
                            $todayLink.focus();
                        }
                    }

                    return rtn;
                },

                ///* Extended to support a separate Parsing array for month and day names separate to the display versions. */
                parseDate: function (format, value, settings)
                {
                    if (format === null || value === null)
                    {
                        throw "Invalid arguments";
                    }

                    value = (typeof value === "object" ? value.toString() : value + "");
                    if (value === "")
                    {
                        return null;
                    }

                    var iFormat, dim, extra,
                        iValue = 0,
                        shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
                        shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
                            new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
                        dayNamesShort = (settings ? (settings.parseDayNamesShort || settings.dayNamesShort) : null) || this._defaults.parseDayNamesShort || this._defaults.dayNamesShort,
                        dayNames = (settings ? (settings.parseDayNames || settings.dayNames) : null) || this._defaults.parseDayNames || this._defaults.dayNames,
                        monthNamesShort = (settings ? (settings.parseMonthNamesShort || settings.monthNamesShort) : null) || this._defaults.parseMonthNamesShort || this._defaults.monthNamesShort,
                        monthNames = (settings ? (settings.parseMonthNames || settings.monthNames) : null) || this._defaults.parseMonthNames || this._defaults.monthNames,
                        year = -1,
                        month = -1,
                        day = -1,
                        doy = -1,
                        literal = false,
                        date,
                        // Check whether a format character is doubled
                        lookAhead = function (match)
                        {
                            var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
                            if (matches)
                            {
                                iFormat++;
                            }
                            return matches;
                        },
                        // Extract a number from the string value
                        getNumber = function (match)
                        {
                            var isDoubled = lookAhead(match),
                                size = (match === "@" ? 14 : (match === "!" ? 20 :
                                    (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
                                minSize = (match === "y" ? size : 1),
                                digits = new RegExp("^\\d{" + minSize + "," + size + "}"),
                                num = value.substring(iValue).match(digits);
                            if (!num)
                            {
                                throw "Missing number at position " + iValue;
                            }
                            iValue += num[0].length;
                            return parseInt(num[0], 10);
                        },
                        // Extract a name from the string value and convert to an index
                        getName = function (match, shortNames, longNames)
                        {
                            var index = -1,
                                names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k)
                                {
                                    return [[k, v]];
                                }).sort(function (a, b)
                                {
                                    return -(a[1].length - b[1].length);
                                });

                            $.each(names, function (i, pair)
                            {
                                var name = pair[1];
                                if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase())
                                {
                                    index = pair[0];
                                    iValue += name.length;
                                    return false;
                                }
                            });
                            if (index !== -1)
                            {
                                return index + 1;
                            } else
                            {
                                throw "Unknown name at position " + iValue;
                            }
                        },
                        // Confirm that a literal character matches the string value
                        checkLiteral = function ()
                        {
                            if (value.charAt(iValue) !== format.charAt(iFormat))
                            {
                                throw "Unexpected literal at position " + iValue;
                            }
                            iValue++;
                        };

                    for (iFormat = 0; iFormat < format.length; iFormat++)
                    {
                        if (literal)
                        {
                            if (format.charAt(iFormat) === "'" && !lookAhead("'"))
                            {
                                literal = false;
                            } else
                            {
                                checkLiteral();
                            }
                        } else
                        {
                            switch (format.charAt(iFormat))
                            {
                                case "d":
                                    day = getNumber("d");
                                    break;
                                case "D":
                                    getName("D", dayNamesShort, dayNames);
                                    break;
                                case "o":
                                    doy = getNumber("o");
                                    break;
                                case "m":
                                    month = getNumber("m");
                                    break;
                                case "M":
                                    month = getName("M", monthNamesShort, monthNames);
                                    break;
                                case "y":
                                    year = getNumber("y");
                                    break;
                                case "@":
                                    date = new Date(getNumber("@"));
                                    year = date.getFullYear();
                                    month = date.getMonth() + 1;
                                    day = date.getDate();
                                    break;
                                case "!":
                                    date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
                                    year = date.getFullYear();
                                    month = date.getMonth() + 1;
                                    day = date.getDate();
                                    break;
                                case "'":
                                    if (lookAhead("'"))
                                    {
                                        checkLiteral();
                                    } else
                                    {
                                        literal = true;
                                    }
                                    break;
                                default:
                                    checkLiteral();
                            }
                        }
                    }

                    if (iValue < value.length)
                    {
                        extra = value.substr(iValue);
                        if (!/^\s+/.test(extra))
                        {
                            throw "Extra/unparsed characters found in date: " + extra;
                        }
                    }

                    if (year === -1)
                    {
                        year = new Date().getFullYear();
                    } else if (year < 100)
                    {
                        year += new Date().getFullYear() - new Date().getFullYear() % 100 +
                            (year <= shortYearCutoff ? 0 : -100);
                    }

                    if (doy > -1)
                    {
                        month = 1;
                        day = doy;
                        do
                        {
                            dim = this._getDaysInMonth(year, month - 1);
                            if (day <= dim)
                            {
                                break;
                            }
                            month++;
                            day -= dim;
                        } while (true);
                    }

                    date = this._daylightSavingAdjust(new Date(year, month - 1, day));
                    if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day)
                    {
                        throw "Invalid date"; // E.g. 31/02/00
                    }
                    return date;
                },

                /* Extended to support a separate Parsing array for month and day names separate to the display versions. */
                formatDate: function (format, date, settings)
                {
                    if (!date)
                    {
                        return "";
                    }

                    var iFormat,
                        dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
                        dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
                        monthNamesShort = (settings ? (settings.parseMonthNamesShort || settings.monthNamesShort) : null) || this._defaults.parseMonthNamesShort || this._defaults.monthNamesShort,
                        monthNames = (settings ? (settings.parseMonthNames || settings.monthNames) : null) || this._defaults.parseMonthNames || this._defaults.monthNames,
                        // Check whether a format character is doubled
                        lookAhead = function (match)
                        {
                            var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
                            if (matches)
                            {
                                iFormat++;
                            }
                            return matches;
                        },
                        // Format a number, with leading zero if necessary
                        formatNumber = function (match, value, len)
                        {
                            var num = "" + value;
                            if (lookAhead(match))
                            {
                                while (num.length < len)
                                {
                                    num = "0" + num;
                                }
                            }
                            return num;
                        },
                        // Format a name, short or long as requested
                        formatName = function (match, value, shortNames, longNames)
                        {
                            return (lookAhead(match) ? longNames[value] : shortNames[value]);
                        },
                        output = "",
                        literal = false;

                    if (date)
                    {
                        for (iFormat = 0; iFormat < format.length; iFormat++)
                        {
                            if (literal)
                            {
                                if (format.charAt(iFormat) === "'" && !lookAhead("'"))
                                {
                                    literal = false;
                                } else
                                {
                                    output += format.charAt(iFormat);
                                }
                            } else
                            {
                                switch (format.charAt(iFormat))
                                {
                                    case "d":
                                        output += formatNumber("d", date.getDate(), 2);
                                        break;
                                    case "D":
                                        output += formatName("D", date.getDay(), dayNamesShort, dayNames);
                                        break;
                                    case "o":
                                        output += formatNumber("o",
                                            Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
                                        break;
                                    case "m":
                                        output += formatNumber("m", date.getMonth() + 1, 2);
                                        break;
                                    case "M":
                                        output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
                                        break;
                                    case "y":
                                        output += (lookAhead("y") ? date.getFullYear() :
                                            (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
                                        break;
                                    case "@":
                                        output += date.getTime();
                                        break;
                                    case "!":
                                        output += date.getTime() * 10000 + this._ticksTo1970;
                                        break;
                                    case "'":
                                        if (lookAhead("'"))
                                        {
                                            output += "'";
                                        } else
                                        {
                                            literal = true;
                                        }
                                        break;
                                    default:
                                        output += format.charAt(iFormat);
                                }
                            }
                        }
                    }
                    return output;
                },

                /* Attach an inline date picker to a div. */
                /* Adjusted to not call _setDate for a blank default. */
                /* Adjusted to apply _doKeyDown so the inline version is still keyboard accessible */
                _inlineDatepicker: function (target, inst)
                {
                    var divSpan = $(target);
                    if (divSpan.hasClass(this.markerClassName))
                    {
                        return;
                    }
                    divSpan.addClass(this.markerClassName).append(inst.dpDiv);

                    // Add the standard keyboard handler logic to the div.  The base jQuery UI version doesn't handle this at all.
                    inst.dpDiv.on("keydown", this._doKeyDown);
                    // Associate the input field id to the datepicker div
                    $(inst.dpDiv).data("fast-datepicker-input", target.id);

                    $.data(target, "datepicker", inst);

                    var rawDefault = this._get(inst, "defaultDate");
                    if (rawDefault)
                    {
                        this._setDate(inst, this._getDefaultDate(inst), true);
                    }
                    this._updateDatepicker(inst);
                    this._updateAlternate(inst);

                    //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
                    if (inst.settings.disabled)
                    {
                        this._disableDatepicker(target);
                    }

                    // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
                    // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
                    inst.dpDiv.css("display", "block");
                },

                /* FAST: Override _selectDay to handle parsing the date value from the cell button instead of link */
                _selectDay: function (id, month, year, td)
                {
                    var inst,
                        target = $(id);

                    if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0]))
                    {
                        return;
                    }

                    inst = this._getInst(target[0]);
                    if (!inst)
                    {
                        return;
                    }

                    inst.selectedDay = inst.currentDay = parseInt(($(td).children("button")).attr("data-date"));
                    inst.selectedMonth = inst.currentMonth = month;
                    inst.selectedYear = inst.currentYear = year;
                    this._selectDate(id, this._formatDate(inst,
                        inst.currentDay, inst.currentMonth, inst.currentYear));
                },

                /* Attach the onxxx handlers.  These are declared statically so
                 * they work with static code transformers like Caja.
                 * 
                 * FAST: Overridden so these functions can prevent event propagation as some of the links they were used on are now rendered with href=#
                 */
                _attachHandlers: function (inst)
                {
                    var stepMonths = this._get(inst, "stepMonths"),
                        id = "#" + inst.id.replace(/\\\\/g, "\\");
                    inst.dpDiv.find("[data-handler]").map(function ()
                    {
                        var handler = {
                            prev: function (event)
                            {
                                $.datepicker._adjustDate(id, -stepMonths, "M");
                                _fwdc.focusDatepickerHeaderChanged(inst.dpDiv, "prev");
                                return false;
                            },
                            next: function (event)
                            {
                                $.datepicker._adjustDate(id, +stepMonths, "M");
                                _fwdc.focusDatepickerHeaderChanged(inst.dpDiv, "next");
                                return false;
                            },
                            hide: function (event)
                            {
                                $.datepicker._hideDatepicker();
                                return false;
                            },
                            today: function (event)
                            {
                                $.datepicker._gotoToday(id);
                                return false;
                            },
                            selectDay: function (event)
                            {
                                $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
                                return false;
                            },
                            selectMonth: function (event)
                            {
                                $.datepicker._selectMonthYear(id, this, "M");
                                _fwdc.focusDatepickerHeaderChanged(inst.dpDiv, "month");
                                return false;
                            },
                            selectYear: function (event)
                            {
                                $.datepicker._selectMonthYear(id, this, "Y");
                                _fwdc.focusDatepickerHeaderChanged(inst.dpDiv, "year");
                                return false;
                            }
                        };
                        $(this).on(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
                    });
                },

                // FAST override to setup focus handling on focus guards for datepicker widget
                _superUpdateDatepicker: $.datepicker._updateDatepicker,
                _updateDatepicker: function (inst)
                {
                    var rtn = this._superUpdateDatepicker(inst);

                    var dpDiv;
                    if (inst && (dpDiv = inst.dpDiv))
                    {
                        //$(dpDiv).attr("aria-description", inst.settings.monthNames[inst.selectedMonth] + " " + inst.selectedYear);

                        var $focusDay = _fwdc.getDatepickerDayFocusTarget(dpDiv, true);
                        if ($focusDay)
                        {
                            $focusDay.attr("tabindex", 0);
                        }

                        if (!inst.inline)
                        {
                            var FocusGuardStart = inst.dpDiv.find(".FastDatepickerFocusGuardStart");
                            if (FocusGuardStart && FocusGuardStart.length > 0)
                            {
                                $(FocusGuardStart[0]).on("focus", function ()
                                {
                                    $(this)
                                        .closest(".ui-datepicker")
                                        .find(":focusable")
                                        .filterNotHasClassName("FastFocusGuard")
                                        .last()
                                        .focus();
                                });
                            }

                            var FocusGuardEnd = inst.dpDiv.find(".FastDatepickerFocusGuardEnd");
                            if (FocusGuardEnd && FocusGuardEnd.length > 0)
                            {
                                $(FocusGuardEnd[0]).on("focus", function ()
                                {
                                    $(this)
                                        .closest(".ui-datepicker")
                                        .find(":focusable")
                                        .filterNotHasClassName("FastFocusGuard")
                                        .first()
                                        .focus();
                                });
                            }
                        }
                    }

                    return rtn;
                },

                /* Generate the HTML for the current state of the date picker. */
                /* FAST: Extended to allow forcing 6 week rows for inline rendering */
                _generateHTML: function (inst)
                {
                    var maxDraw, startFocusGuard, prevText, prev, endFocusGuard, nextText, next, currentText, gotoDate,
                        controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
                        monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
                        selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
                        cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
                        printDate, dRow, tbody, daySettings, otherMonth, unselectable, dateText, currentMonth,
                        drawDate = new Date(),
                        tempDate = new Date(),
                        today = this._daylightSavingAdjust(
                            new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
                        isRTL = this._get(inst, "isRTL"),
                        showButtonPanel = this._get(inst, "showButtonPanel"),
                        hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
                        navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
                        numMonths = this._getNumberOfMonths(inst),
                        showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
                        stepMonths = this._get(inst, "stepMonths"),
                        isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
                        currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
                            new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
                        minDate = this._getMinMaxDate(inst, "min"),
                        maxDate = this._getMinMaxDate(inst, "max"),
                        drawMonth = inst.drawMonth - showCurrentAtPos,
                        drawYear = inst.drawYear;

                    if (drawMonth < 0)
                    {
                        drawMonth += 12;
                        drawYear--;
                    }
                    if (maxDate)
                    {
                        maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
                            maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
                        maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
                        while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw)
                        {
                            drawMonth--;
                            if (drawMonth < 0)
                            {
                                drawMonth = 11;
                                drawYear--;
                            }
                        }
                    }
                    inst.drawMonth = drawMonth;
                    inst.drawYear = drawYear;

                    // Attach focus guards to the datepicker element so they can manage keeping focus inside the datepicker
                    startFocusGuard = "<div class='FastFocusGuard FastDatepickerFocusGuardStart' tabindex='0'></div>";
                    endFocusGuard = "<div class='FastFocusGuard FastDatepickerFocusGuardEnd' tabindex='0'></div>";
                    monthNames = this._get(inst, "monthNames");
                    monthNamesShort = this._get(inst, "monthNamesShort");

                    prevText = this._get(inst, "prevText") + ": " + monthNames[(drawMonth == 0 ? 11 : drawMonth - 1)] + " " + (drawMonth == 0 ? drawYear - 1 : drawYear);
                    prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
                        this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
                        this._getFormatConfig(inst)));

                    prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
                        "<button type='button' class='FastDatepickerChangeMonth TextButton ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' tabindex='0'" +
                        " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + (isRTL ? "e" : "w") + "'>" + prevText + "</span></button>" :
                        (hideIfNoPrevNext ? "" : "<button type='button' class='FastDatepickerChangeMonth TextButton ui-datepicker-prev ui-corner-all ui-state-disabled' title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + (isRTL ? "e" : "w") + "'>" + prevText + "</span></button>"));

                    nextText = this._get(inst, "nextText") + ": " + monthNames[(drawMonth == 11 ? 0 : drawMonth + 1)] + " " + (drawMonth == 11 ? drawYear + 1 : drawYear);
                    nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
                        this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
                        this._getFormatConfig(inst)));

                    next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
                        "<button type='button' class='FastDatepickerChangeMonth TextButton ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' tabindex='0'" +
                        " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + (isRTL ? "w" : "e") + "'>" + nextText + "</span></button>" :
                        (hideIfNoPrevNext ? "" : "<button type='button' class='FastDatepickerChangeMonth TextButton ui-datepicker-next ui-corner-all ui-state-disabled' title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + (isRTL ? "w" : "e") + "'>" + nextText + "</span></button>"));

                    currentText = this._get(inst, "currentText");
                    gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
                    currentText = (!navigationAsDateFormat ? currentText :
                        this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));

                    controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
                        this._get(inst, "closeText") + "</button>" : "");

                    buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
                        (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
                            ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";

                    if (!inst.inline)
                    {
                        buttonPanel = buttonPanel + endFocusGuard;
                    }

                    firstDay = parseInt(this._get(inst, "firstDay"), 10);
                    firstDay = (isNaN(firstDay) ? 0 : firstDay);

                    showWeek = this._get(inst, "showWeek");
                    dayNames = this._get(inst, "dayNames");
                    dayNamesMin = this._get(inst, "dayNamesMin");
                    beforeShowDay = this._get(inst, "beforeShowDay");
                    showOtherMonths = this._get(inst, "showOtherMonths");
                    selectOtherMonths = this._get(inst, "selectOtherMonths");
                    defaultDate = this._getDefaultDate(inst);
                    html = "";

                    for (row = 0; row < numMonths[0]; row++)
                    {
                        group = "";
                        // FAST: Force 6 rows in inline mode to prevent height changes
                        //this.maxRows = 4;
                        this.maxRows = inst.inline ? 6 : 4;
                        for (col = 0; col < numMonths[1]; col++)
                        {
                            selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
                            cornerClass = " ui-corner-all";
                            calender = "";
                            if (isMultiMonth)
                            {
                                calender += "<div class='ui-datepicker-group";
                                if (numMonths[1] > 1)
                                {
                                    switch (col)
                                    {
                                        case 0: calender += " ui-datepicker-group-first";
                                            cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
                                        case numMonths[1] - 1: calender += " ui-datepicker-group-last";
                                            cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
                                        default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
                                    }
                                }
                                calender += "'>";
                            }
                            calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
                                (inst.inline ? "" : startFocusGuard) + //Add focus gaurd at top of datepicker headers for dialog datepickers
                                this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
                                    row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 
                                (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
                                (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
                                "</div><table class='ui-datepicker-calendar' role='menu'><thead>" +
                                "<tr>";
                            thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
                            for (dow = 0; dow < 7; dow++)
                            { // days of the week
                                day = (dow + firstDay) % 7;
                                thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
                                    "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
                            }
                            calender += thead + "</tr></thead><tbody>";
                            daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
                            if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth)
                            {
                                inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
                            }
                            leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
                            curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
                            //numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
                            // FAST: Check maxRows if we're rendering an inline datepicker
                            numRows = ((isMultiMonth || inst.inline) ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
                            this.maxRows = numRows;
                            printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
                            for (dRow = 0; dRow < numRows; dRow++)
                            { // create date picker rows
                                calender += "<tr>";
                                tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
                                    this._get(inst, "calculateWeek")(printDate) + "</td>");
                                for (dow = 0; dow < 7; dow++)
                                { // create date picker days
                                    daySettings = (beforeShowDay ?
                                        beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
                                    otherMonth = (printDate.getMonth() !== drawMonth);
                                    currentMonth = (currentDate.getMonth() == drawMonth);
                                    unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
                                        (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
                                    drawDate = new Date(printDate.getFullYear(), printDate.getMonth(), printDate.getDate());

                                    // FAST: Added formatted date label. Review date format for aria-label; leave for now, might be ok?
                                    dateText = this.formatDate("DD MM dd yy", drawDate, inst).replace(/'/g, "&#39;");
                                    tbody += "<td class='FastDatepickerDayContainer" +
                                        ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
                                        (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
                                        ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
                                            (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?

                                            // or defaultDate is current printedDate and defaultDate is selectedDate
                                            " " + this._dayOverClass : "") + // highlight selected day
                                        (unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "") +  // highlight unselectable days
                                        (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
                                            (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
                                            (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
                                        ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
                                        (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
                                        (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
                                            "<button type='button' class='FastDatepickerDay ui-state-default " +
                                            (unselectable ? "" : "FRC") +                                        /* FAST: Added FRC, use buttons instead of links */
                                            (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
                                            (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
                                            (otherMonth ? " ui-priority-secondary'" : "'") + // distinguish dates from other months
                                            " aria-label='" + dateText + "'" + // FAST: Added aria-label to the formatted date                                            
                                            (printDate.getTime() === currentDate.getTime() ? " aria-current='date'" : "") + // FAST: set selected date to aria-current='date'   
                                            "tabindex='-1'" + // FAST: Added tab index
                                            (unselectable ? " aria-disabled='true' " : "") + // FAST: add disabled attribute to unselectable dates     
                                            "data-date='" + printDate.getDate() + "'" + // FAST: Added data-date attribute to store the date value
                                            " role='menuitem'>" + printDate.getDate() + // display selectable date      
                                            "</button>") + "</td>"; // end day cell
                                    printDate.setDate(printDate.getDate() + 1);
                                    printDate = this._daylightSavingAdjust(printDate);
                                }
                                calender += tbody + "</tr>";
                            }
                            drawMonth++;
                            if (drawMonth > 11)
                            {
                                drawMonth = 0;
                                drawYear++;
                            }
                            calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
                                ((numMonths[0] > 0 && col === numMonths[1] - 1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
                            group += calender;
                        }
                        html += group;
                    }
                    html += buttonPanel;
                    inst._keyEvent = false;
                    return html;
                }
            });

            $.widget("fast.linkset", {
                options: {
                    optionSelector: "a",
                    horizontal: false,
                    role: "menu",
                    itemrole: "menuitem"
                },
                targets: null,

                _create: function ()
                {
                    this.element.addClass("FastLinkSet");
                    this._refresh();
                },

                _refresh: function ()
                {
                    if (this.targets)
                    {
                        if (this.options.itemrole)
                        {
                            this.targets.removeAttr("role");
                        }

                        this._off(this.targets, "keydown");
                    }

                    this.targets = $(this.options.optionSelector, this.element);

                    if (this.options.itemrole)
                    {
                        this.targets.attr("role", this.options.itemrole);
                    }

                    if (this.options.role)
                    {
                        this.element.attr("role", this.options.role);
                    }

                    if (this.targets && this.targets.length)
                    {
                        this._on(true, this.targets, { "keydown": this._keydown });
                    }
                },

                _destroy: function ()
                {
                    if (this.targets)
                    {
                        if (this.options.itemrole)
                        {
                            this.targets.removeAttr("role");
                        }

                        this._off(this.targets, "keydown");
                        this.targets = null;
                    }
                    this.element.removeClass("FastLinkSet");
                },

                _keydown: function (event)
                {
                    if (!event.ctrlKey && !event.altKey && !event.shiftKey && !event.metaKey)
                    {
                        switch (event.which)
                        {
                            case _fwdc.keyCodes.UP:
                            case _fwdc.keyCodes.DOWN:
                                if (!this.options.horizontal)
                                {
                                    var currentIndex = this.targets.index(event.target);
                                    var nextIndex = event.which === _fwdc.keyCodes.UP ? currentIndex - 1 : currentIndex + 1;

                                    if (nextIndex > -1 && nextIndex < this.targets.length)
                                    {
                                        $(this.targets[nextIndex]).focus();
                                        _fwdc.stopEvent(event);
                                    }

                                }
                                break;
                            case _fwdc.keyCodes.LEFT:
                            case _fwdc.keyCodes.RIGHT:
                                if (this.options.horizontal)
                                {
                                    var currentIndex = this.targets.index(event.target);
                                    var nextIndex = event.which === _fwdc.keyCodes.LEFT ? currentIndex - 1 : currentIndex + 1;

                                    if (nextIndex > -1 && nextIndex < this.targets.length)
                                    {
                                        $(this.targets[nextIndex]).focus();
                                        _fwdc.stopEvent(event);
                                    }
                                }
                                break;
                        }
                    }
                },

                focus: function ()
                {
                    if (this.targets)
                    {
                        this.targets.firstVisible().focus();
                    }

                    return this;
                }
            });

            $.fn.reverse = [].reverse;

            $.extend($.expr[':'], {
                'containsi': function (elem, i, match, array)
                {
                    return containsi(elem, match[3]);
                },
                'containsr': function (elem, i, match, array)
                {
                    return containsr(elem, match[3]);
                }
            });

            $.extend({
                __scrollbarWidth: null,
                getScrollbarWidth: function ()
                {
                    var parent, child;

                    if (this.__scrollbarWidth === null)
                    {
                        parent = $('<div style="width:50px;height:50px;overflow:auto"><div></div></div>').appendTo('body');
                        child = parent.children();
                        this.__scrollbarWidth = child.innerWidth() - child.height(99).innerWidth();
                        parent.remove();
                    }

                    return this.__scrollbarWidth;
                }
            });

            if ("onprogress" in $.ajaxSettings.xhr())
            {
                var xhrBase = $.ajaxSettings.xhr;

                $.ajaxSettings.xhr = function ()
                {
                    var xhr = xhrBase.apply(this, arguments);

                    if (this.progress && xhr instanceof window.XMLHttpRequest)
                    {
                        xhr.addEventListener("progress", this.progress, false);
                    }

                    if (this.uploadprogress && xhr.upload)
                    {
                        xhr.upload.addEventListener("progress", this.uploadprogress, false);
                    }

                    return xhr;
                };
            }

        }(jQuery));
    }

    var FWDC = new FWDCApi(window, jQuery);

    var _onClientButtonClickedHandler;

    function FastControlApi()
    {
        var _fwdc = FWDC._fwdc;

        /**
         * Submits data to the control specified by controlScriptId.  This function is Asynchronous.
         * 
         * If calling code wants to handle when this succeeds, it must use the returned Promise.
         * 
         * Note that the call will cause the user interface to be refreshed, which will cause the script to be discarded based on the server response.
         * @param {string} controlScriptId - The script ID of the control, provided by GetControlScriptDataId()
         * @param {string} type - A type to pass along with the data to indicate what kind of data is being provided to the control.
         * @param {Object} data - A JSON.stringify compatible object to serialize and submit to the control.
         * @returns {Promise} Returns a Promise that will be resolved when the set operation completes.
         */
        this.SetControlScriptData = function (controlScriptId, type, data)
        {
            var busySource = _fwdc.busy.getBusySource();

            return new Promise(function (resolve, reject)
            {
                _fwdc.busy.done(function SetControlScriptDataBusy()
                {
                    _fwdc.afterCrossTransition(function SetControlScriptDataInternal()
                    {
                        _fwdc.setProperties(null, {
                            trigger: "SetControlScriptData",
                            control: controlScriptId.controlId,
                            type: "SetControlScriptData",
                            target: controlScriptId.controlUniqueId,
                            busy: true,
                            busySource: busySource,
                            properties: { type: type, data: JSON.stringify(data) },
                            callback: function (data, status, request, options)
                            {
                                resolve();
                            }
                            //errorCallback: function (request, options)
                            //{

                            //    reject();
                            //}
                        });
                    });
                });
            });
        };

        /**
         * Requests data from the control specified by controlScriptId.  This function is synchronous.
         * @param {any} controlScriptId - The script ID of the control, provided by GetControlScriptDataId()
         * @param {any} type - A type to pass indicating what data is being requested from the control.
         * @returns {any} - The data that was requested from the control.
         */
        this.GetControlScriptData = function (controlScriptId, type)
        {
            var result;
            _fwdc.setProperties(null, {
                trigger: "GetControlScriptData",
                control: controlScriptId.controlId,
                type: "GetControlScriptData",
                target: controlScriptId.controlUniqueId,
                busy: true,
                async: false,
                action: false,
                properties: { type: type },
                callback: function (data, status, request, options)
                {
                    result = data;
                }
            });

            return result;
        };

        /**
         * @callback ClientButtonHandler
         * @param {Event} event - The original event for the client button click.
         */

        /**
         * Sets a handler function for when a client button is clicked, allowing custom script to be bound to action buttons.
         * @param {ClientButtonHandler} handler
         */
        this.SetClientButtonHandler = function (handler)
        {
            _onClientButtonClickedHandler = handler;
        };

        /**
         * Shows the native application busy spinner, which also disables any native screen interactions.  Ensure that HideBusy is called to restore functionality after.
         */
        this.ShowBusy = function ()
        {
            _fwdc.busy.show("FastControlApi");
        };

        /**
         * Hides the native application busy spinner.  This should only be used if the FastControlApi was used to show it in the first place via ShowBusy.
         */
        this.HideBusy = function ()
        {
            _fwdc.busy.hide();
        };

        return this;
    }

    window.FastControlApi = new FastControlApi(window);

    return FWDC;
}(window, jQuery));

/*!
 * jQuery UI Touch Punch 1.1.4 as modified by RWAP Software
 * based on original touchpunch v0.2.3 which has not been updated since 2014
 *
 * Updates by RWAP Software to take account of various suggested changes on the original code issues
 *
 * Original: https://github.com/furf/jquery-ui-touch-punch
 * Copyright 2011–2014, Dave Furfero
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * Fork: https://github.com/RWAP/jquery-ui-touch-punch
 *
 * Depends:
 * jquery.ui.widget.js
 * jquery.ui.mouse.js
 */
(function (factory)
{
    if (typeof define === "function" && define.amd)
    {

        // AMD. Register as an anonymous module.
        define(["jquery", "jquery-ui"], factory);
    } else
    {

        // Browser globals
        factory(jQuery);
    }
}(function ($)
{
    // Detect touch support - Windows Surface devices and other touch devices
    $.mspointer = window.navigator.msPointerEnabled;
    $.touch = ('ontouchstart' in document
        || 'ontouchstart' in window
        || window.TouchEvent
        || (window.DocumentTouch && document instanceof DocumentTouch)
        || navigator.maxTouchPoints > 0
        || navigator.msMaxTouchPoints > 0
    );

    // Ignore browsers without touch or mouse support
    if ((!$.touch && !$.mspointer) || !$.ui.mouse)
    {
        return;
    }

    var mouseProto = $.ui.mouse.prototype,
        _mouseInit = mouseProto._mouseInit,
        _mouseDestroy = mouseProto._mouseDestroy,
        touchHandled, lastClickTime = 0;

    /**
    * Get the x,y position of a touch event
    * @param {Object} event A touch event
    */
    function getTouchCoords(event)
    {
        return {
            x: event.originalEvent.changedTouches[0].pageX,
            y: event.originalEvent.changedTouches[0].pageY
        };
    }

    /**
     * Simulate a mouse event based on a corresponding touch event
     * @param {Object} event A touch event
     * @param {String} simulatedType The corresponding mouse event
     */
    function simulateMouseEvent(event, simulatedType)
    {

        // Ignore multi-touch events
        if (event.originalEvent.touches.length > 1)
        {
            return;
        }

        //Ignore input or textarea elements so user can still enter text
        if ($(event.target).is("input") || $(event.target).is("textarea"))
        {
            return;
        }

        // Prevent "Ignored attempt to cancel a touchmove event with cancelable=false" errors
        if (event.cancelable)
        {
            event.preventDefault();
        }

        var touch = event.originalEvent.changedTouches[0],
            simulatedEvent = new MouseEvent(simulatedType, {
                bubbles: true,
                cancelable: true,
                view: window,
                screenX: touch.screenX,
                screenY: touch.screenY,
                clientX: touch.clientX,
                clientY: touch.clientY
            });

        // Dispatch the simulated event to the target element
        event.target.dispatchEvent(simulatedEvent);
    }

    /**
     * Handle the jQuery UI widget's touchstart events
     * @param {Object} event The widget element's touchstart event
     */
    mouseProto._touchStart = function (event)
    {
        var self = this;

        // Interaction time
        this._startedMove = event.timeStamp;

        // Track movement to determine if interaction was a click
        self._startPos = getTouchCoords(event);

        // Ignore the event if another widget is already being handled
        if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0]))
        {
            return;
        }

        // Set the flag to prevent other widgets from inheriting the touch event
        touchHandled = true;

        // Track movement to determine if interaction was a click
        self._touchMoved = false;

        // Simulate the mouseover event
        simulateMouseEvent(event, 'mouseover');

        // Simulate the mousemove event
        simulateMouseEvent(event, 'mousemove');

        // Simulate the mousedown event
        simulateMouseEvent(event, 'mousedown');
    };

    /**
     * Handle the jQuery UI widget's touchmove events
     * @param {Object} event The document's touchmove event
     */
    mouseProto._touchMove = function (event)
    {

        // Ignore event if not handled
        if (!touchHandled)
        {
            return;
        }

        // Interaction was moved
        this._touchMoved = true;

        // Simulate the mousemove event
        simulateMouseEvent(event, 'mousemove');
    };

    /**
     * Handle the jQuery UI widget's touchend events
     * @param {Object} event The document's touchend event
     */
    mouseProto._touchEnd = function (event)
    {

        // Ignore event if not handled
        if (!touchHandled)
        {
            return;
        }

        // Simulate the mouseup event
        simulateMouseEvent(event, 'mouseup');

        // Simulate the mouseout event
        simulateMouseEvent(event, 'mouseout');

        // If the touch interaction did not move, it should trigger a click
        // Check for this in two ways - length of time of simulation and distance moved
        // Allow for Apple Stylus to be used also
        var timeMoving = event.timeStamp - this._startedMove;
        if (!this._touchMoved || timeMoving < 500)
        {
            // Simulate the click event
            if (event.timeStamp - lastClickTime < 400)
                simulateMouseEvent(event, 'dblclick');
            else
                simulateMouseEvent(event, 'click');
            lastClickTime = event.timeStamp;
        } else
        {
            var endPos = getTouchCoords(event);
            if ((Math.abs(endPos.x - this._startPos.x) < 10) && (Math.abs(endPos.y - this._startPos.y) < 10))
            {

                // If the touch interaction did not move, it should trigger a click
                if (!this._touchMoved || event.originalEvent.changedTouches[0].touchType === 'stylus')
                {
                    // Simulate the click event
                    simulateMouseEvent(event, 'click');
                }
            }
        }

        // Unset the flag to determine the touch movement stopped
        this._touchMoved = false;

        // Unset the flag to allow other widgets to inherit the touch event
        touchHandled = false;
    };

    var _touchStartBound = mouseProto._touchStart.bind(mouseProto),
        _touchMoveBound = mouseProto._touchMove.bind(mouseProto),
        _touchEndBound = mouseProto._touchEnd.bind(mouseProto);

    /**
     * A duck punch of the $.ui.mouse _mouseInit method to support touch events.
     * This method extends the widget with bound touch event handlers that
     * translate touch events to mouse events and pass them to the widget's
     * original mouse event handling methods.
     */
    mouseProto._mouseInit = function ()
    {
        var self = this;

        // FAST Customization: Allow widgets to disable the touch overrides.
        if (!this.options.disableTouch)
        {
            // Microsoft Surface Support = remove original touch Action
            if ($.support.mspointer)
            {
                self.element[0].style.msTouchAction = 'none';
            }

            // Delegate the touch handlers to the widget's element
            self.element.on({
                touchstart: _touchStartBound,
                touchmove: _touchMoveBound,
                touchend: _touchEndBound
            });
        }

        // Call the original $.ui.mouse init method
        _mouseInit.call(self);
    };

    /**
     * Remove the touch event handlers
     */
    mouseProto._mouseDestroy = function ()
    {
        var self = this;

        // FAST Customization: Allow widgets to disable the touch overrides.
        if (this.options.disableTouch)
            return;

        // Delegate the touch handlers to the widget's element
        self.element.off({
            touchstart: _touchStartBound,
            touchmove: _touchMoveBound,
            touchend: _touchEndBound
        });

        // Call the original $.ui.mouse destroy method
        _mouseDestroy.call(self);
    };
}));

/*!
 * promise-polyfill v8.2.2 - Polyfill for Promise in IE11 and other older browsers.
 *
 * Repository: https://github.com/taylorhakes/promise-polyfill
 * License: MIT License: https://github.com/taylorhakes/promise-polyfill/blob/2aea6b8e2d5e6a7bc9930b2c5e11321c8d39adb2/LICENSE
 */
(function (global, factory)
{
    typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
        typeof define === 'function' && define.amd ? define(factory) :
            (factory());
}(this, (function ()
{
    'use strict';

    /**
     * @this {Promise}
     */
    function finallyConstructor(callback)
    {
        var constructor = this.constructor;
        return this.then(
            function (value)
            {
                // @ts-ignore
                return constructor.resolve(callback()).then(function ()
                {
                    return value;
                });
            },
            function (reason)
            {
                // @ts-ignore
                return constructor.resolve(callback()).then(function ()
                {
                    // @ts-ignore
                    return constructor.reject(reason);
                });
            }
        );
    }

    function allSettled(arr)
    {
        var P = this;
        return new P(function (resolve, reject)
        {
            if (!(arr && typeof arr.length !== 'undefined'))
            {
                return reject(
                    new TypeError(
                        typeof arr +
                        ' ' +
                        arr +
                        ' is not iterable(cannot read property Symbol(Symbol.iterator))'
                    )
                );
            }
            var args = Array.prototype.slice.call(arr);
            if (args.length === 0) return resolve([]);
            var remaining = args.length;

            function res(i, val)
            {
                if (val && (typeof val === 'object' || typeof val === 'function'))
                {
                    var then = val.then;
                    if (typeof then === 'function')
                    {
                        then.call(
                            val,
                            function (val)
                            {
                                res(i, val);
                            },
                            function (e)
                            {
                                args[i] = { status: 'rejected', reason: e };
                                if (--remaining === 0)
                                {
                                    resolve(args);
                                }
                            }
                        );
                        return;
                    }
                }
                args[i] = { status: 'fulfilled', value: val };
                if (--remaining === 0)
                {
                    resolve(args);
                }
            }

            for (var i = 0; i < args.length; i++)
            {
                res(i, args[i]);
            }
        });
    }

    // Store setTimeout reference so promise-polyfill will be unaffected by
    // other code modifying setTimeout (like sinon.useFakeTimers())
    var setTimeoutFunc = setTimeout;

    function isArray(x)
    {
        return Boolean(x && typeof x.length !== 'undefined');
    }

    function noop() { }

    // Polyfill for Function.prototype.bind
    function bind(fn, thisArg)
    {
        return function ()
        {
            fn.apply(thisArg, arguments);
        };
    }

    /**
     * @constructor
     * @param {Function} fn
     */
    function Promise(fn)
    {
        if (!(this instanceof Promise))
            throw new TypeError('Promises must be constructed via new');
        if (typeof fn !== 'function') throw new TypeError('not a function');
        /** @type {!number} */
        this._state = 0;
        /** @type {!boolean} */
        this._handled = false;
        /** @type {Promise|undefined} */
        this._value = undefined;
        /** @type {!Array<!Function>} */
        this._deferreds = [];

        doResolve(fn, this);
    }

    function handle(self, deferred)
    {
        while (self._state === 3)
        {
            self = self._value;
        }
        if (self._state === 0)
        {
            self._deferreds.push(deferred);
            return;
        }
        self._handled = true;
        Promise._immediateFn(function ()
        {
            var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
            if (cb === null)
            {
                (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
                return;
            }
            var ret;
            try
            {
                ret = cb(self._value);
            } catch (e)
            {
                reject(deferred.promise, e);
                return;
            }
            resolve(deferred.promise, ret);
        });
    }

    function resolve(self, newValue)
    {
        try
        {
            // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
            if (newValue === self)
                throw new TypeError('A promise cannot be resolved with itself.');
            if (
                newValue &&
                (typeof newValue === 'object' || typeof newValue === 'function')
            )
            {
                var then = newValue.then;
                if (newValue instanceof Promise)
                {
                    self._state = 3;
                    self._value = newValue;
                    finale(self);
                    return;
                } else if (typeof then === 'function')
                {
                    doResolve(bind(then, newValue), self);
                    return;
                }
            }
            self._state = 1;
            self._value = newValue;
            finale(self);
        } catch (e)
        {
            reject(self, e);
        }
    }

    function reject(self, newValue)
    {
        self._state = 2;
        self._value = newValue;
        finale(self);
    }

    function finale(self)
    {
        if (self._state === 2 && self._deferreds.length === 0)
        {
            Promise._immediateFn(function ()
            {
                if (!self._handled)
                {
                    Promise._unhandledRejectionFn(self._value);
                }
            });
        }

        for (var i = 0, len = self._deferreds.length; i < len; i++)
        {
            handle(self, self._deferreds[i]);
        }
        self._deferreds = null;
    }

    /**
     * @constructor
     */
    function Handler(onFulfilled, onRejected, promise)
    {
        this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
        this.onRejected = typeof onRejected === 'function' ? onRejected : null;
        this.promise = promise;
    }

    /**
     * Take a potentially misbehaving resolver function and make sure
     * onFulfilled and onRejected are only called once.
     *
     * Makes no guarantees about asynchrony.
     */
    function doResolve(fn, self)
    {
        var done = false;
        try
        {
            fn(
                function (value)
                {
                    if (done) return;
                    done = true;
                    resolve(self, value);
                },
                function (reason)
                {
                    if (done) return;
                    done = true;
                    reject(self, reason);
                }
            );
        } catch (ex)
        {
            if (done) return;
            done = true;
            reject(self, ex);
        }
    }

    Promise.prototype['catch'] = function (onRejected)
    {
        return this.then(null, onRejected);
    };

    Promise.prototype.then = function (onFulfilled, onRejected)
    {
        // @ts-ignore
        var prom = new this.constructor(noop);

        handle(this, new Handler(onFulfilled, onRejected, prom));
        return prom;
    };

    Promise.prototype['finally'] = finallyConstructor;

    Promise.all = function (arr)
    {
        return new Promise(function (resolve, reject)
        {
            if (!isArray(arr))
            {
                return reject(new TypeError('Promise.all accepts an array'));
            }

            var args = Array.prototype.slice.call(arr);
            if (args.length === 0) return resolve([]);
            var remaining = args.length;

            function res(i, val)
            {
                try
                {
                    if (val && (typeof val === 'object' || typeof val === 'function'))
                    {
                        var then = val.then;
                        if (typeof then === 'function')
                        {
                            then.call(
                                val,
                                function (val)
                                {
                                    res(i, val);
                                },
                                reject
                            );
                            return;
                        }
                    }
                    args[i] = val;
                    if (--remaining === 0)
                    {
                        resolve(args);
                    }
                } catch (ex)
                {
                    reject(ex);
                }
            }

            for (var i = 0; i < args.length; i++)
            {
                res(i, args[i]);
            }
        });
    };

    Promise.allSettled = allSettled;

    Promise.resolve = function (value)
    {
        if (value && typeof value === 'object' && value.constructor === Promise)
        {
            return value;
        }

        return new Promise(function (resolve)
        {
            resolve(value);
        });
    };

    Promise.reject = function (value)
    {
        return new Promise(function (resolve, reject)
        {
            reject(value);
        });
    };

    Promise.race = function (arr)
    {
        return new Promise(function (resolve, reject)
        {
            if (!isArray(arr))
            {
                return reject(new TypeError('Promise.race accepts an array'));
            }

            for (var i = 0, len = arr.length; i < len; i++)
            {
                Promise.resolve(arr[i]).then(resolve, reject);
            }
        });
    };

    // Use polyfill for setImmediate for performance gains
    Promise._immediateFn =
        // @ts-ignore
        (typeof setImmediate === 'function' &&
            function (fn)
            {
                // @ts-ignore
                setImmediate(fn);
            }) ||
        function (fn)
        {
            setTimeoutFunc(fn, 0);
        };

    Promise._unhandledRejectionFn = function _unhandledRejectionFn(err)
    {
        if (typeof console !== 'undefined' && console)
        {
            console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
        }
    };

    /** @suppress {undefinedVars} */
    var globalNS = (function ()
    {
        // the only reliable means to get the global object is
        // `Function('return this')()`
        // However, this causes CSP violations in Chrome apps.
        if (typeof self !== 'undefined')
        {
            return self;
        }
        if (typeof window !== 'undefined')
        {
            return window;
        }
        if (typeof global !== 'undefined')
        {
            return global;
        }
        throw new Error('unable to locate global object');
    })();

    // Expose the polyfill if Promise is undefined or set to a
    // non-function value. The latter can be due to a named HTMLElement
    // being exposed by browsers for legacy reasons.
    // https://github.com/taylorhakes/promise-polyfill/issues/114
    if (typeof globalNS['Promise'] !== 'function')
    {
        globalNS['Promise'] = Promise;
    } else if (!globalNS.Promise.prototype['finally'])
    {
        globalNS.Promise.prototype['finally'] = finallyConstructor;
    } else if (!globalNS.Promise.allSettled)
    {
        globalNS.Promise.allSettled = allSettled;
    }

})));
