function AutoSuggestMenu() {
    var REFRESH_TYPE_COMPLETE = "Complete";
    var REFRESH_TYPE_NEXT_PAGE = "Next Page";
    var REFRESH_TYPE_PREVIOUS_PAGE = "Previous Page";
    var self = this;
    self.id = null;
    self.textBoxID = null;
    self.hiddenSelectedValueID = null;
    self.minSuggestChars = 1;
    self.maxSuggestChars = 5;
    self.keyPressDelay = 300;
    self.usePaging = true;
    self.pageSize = 10;
    self.maxHeight = null;
    self.cssClass = "asmMenu";
    self.menuItemCssClass = "asmMenuItem";
    self.selMenuItemCssClass = "asmSelMenuItem";
    self.navigationLinkCssClass = "asmNavigationLink";
    self.useIFrame = true;
    self.updateTextBoxOnUpDown = true;
    self.resourceDir = null;
    self.menuItems = new Array();
    self.onGetMenuItems = null;
    self.onTextBoxUpdate = null;
    var _dom = null;
    var _oldTextBoxValue = "";
    var _selMenuItemIndex = null;
    var _cancelSubmit = false;
    var _iFrame = null;
    var _keyPressTimer = null;
    var _onBlurTimer = null;
    var _cancelOnBlur = false;
    var _hasVerticalScrollbar = false;
    var _pageIndex = 0;
    var _totalResults = 0;
    var _refreshType;
    function getTextBoxCtrl() {
        return document.getElementById(self.textBoxID);
    }
    function getMenuItemsCount() {
        return self.menuItems.length;
    }
    function ensureMenuItemVisible(menuItemIndex) {
        TRACE("AutoSuggestMenu.ensureMenuItemVisible menuItemIndex=" + menuItemIndex + ", _hasVerticalScrollbar=" + _hasVerticalScrollbar);
        if (!_hasVerticalScrollbar) {
            return ;
        }
        var menuStartY = _dom.scrollTop;
        var menuEndY = _dom.scrollTop + _dom.offsetHeight;
        var menuItem = self.menuItems[menuItemIndex];
        var menuItemDiv = menuItem.getDOM();
        var menuItemStartY = menuItemDiv.offsetTop;
        var menuItemEndY = menuItemDiv.offsetTop + menuItemDiv.offsetHeight;
        TRACE("AutoSuggestMenu.ensureMenuItemVisible menuStartY=" + menuStartY + ", menuEndY=" + menuEndY);
        TRACE("AutoSuggestMenu.ensureMenuItemVisible menuItemStartY=" + menuItemStartY + ", menuItemEndY=" + menuItemEndY);
        if (menuItemStartY < menuStartY) {
            _dom.scrollTop = menuItemStartY;
        }
        if (menuItemEndY > menuEndY) {
            _dom.scrollTop = _dom.scrollTop + (menuItemEndY - menuEndY);
        }
    }
    function moveUp() {
        TRACE("AutoSuggestMenu.moveUp _selMenuItemIndex=" + _selMenuItemIndex);
        if (_selMenuItemIndex == null) {
            itemIndex = getMenuItemsCount() - 1;
        }
        else {
            itemIndex = _selMenuItemIndex - 1;
        }
        if (itemIndex >= 0) {
            selectMenuItem(itemIndex, self.updateTextBoxOnUpDown);
            ensureMenuItemVisible(itemIndex);
        }
    }
    function moveDown() {
        TRACE("AutoSuggestMenu.moveDown _selMenuItemIndex=" + _selMenuItemIndex);
        var itemIndex;
        if (_selMenuItemIndex == null) {
            itemIndex = 0;
        }
        else {
            itemIndex = _selMenuItemIndex + 1;
        }
        if (itemIndex < getMenuItemsCount()) {
            selectMenuItem(itemIndex, self.updateTextBoxOnUpDown);
            ensureMenuItemVisible(itemIndex);
        }
    }
    function highlightMenuItem(itemIndex) {
        if (_selMenuItemIndex != null) {
            if (_selMenuItemIndex == itemIndex) {
                return ;
            }
            var menuItem = self.menuItems[_selMenuItemIndex];
            menuItem.unhighlight();
        }
        var menuItem = self.menuItems[itemIndex];
        menuItem.highlight();
    }
    function selectMenuItem(itemIndex, updateTextBox) {
        TRACE("AutoSuggestMenu.selectMenuItem itemIndex=" + itemIndex);
        highlightMenuItem(itemIndex);
        _selMenuItemIndex = itemIndex;
        if ((updateTextBox == null) || (updateTextBox == true)) {
            updateTextBoxValue();
        }
    }
    function updateTextBoxValue() {
        var menuItem = self.getSelectedMenuItem();
        self.setSelectedValue(menuItem.value);
        var preventUpdate = false;
        if (self.onTextBoxUpdate) {
            var evt = new TextBoxUpdateEvent();
            evt.source = self;
            evt.selMenuItem = menuItem;
            eval(self.onTextBoxUpdate + "(evt);");
            preventUpdate = evt.getPreventDefault();
        }
        if (!preventUpdate) {
            var textBox = getTextBoxCtrl();
            textBox.value = menuItem.label;
        }
    }
    function getTextBoxValue() {
        var textBox = getTextBoxCtrl();
        return (textBox.value);
    }
    function focusOnTextBox() {
        window.clearTimeout(_onBlurTimer);
        _onBlurTimer = null;
        var textBox = getTextBoxCtrl();
        if (XUtils.isIE()) {
            var value = textBox.value;
            var textRange = textBox.createTextRange();
            textRange.moveStart("character", value.length);
            textRange.select();
        }
        textBox.focus();
    }
    function isPreviousPageLinkEnabled() {
        var enabled = (_pageIndex != 0);
        return enabled;
    }
    function isNextPageLinkEnabled() {
        var numMenuItems = (_pageIndex * self.pageSize) + self.menuItems.length;
        TRACE("AutoSuggestMenu.isNextPageLinkEnabled numMenuItems=" + numMenuItems + ", _totalResults=" + _totalResults);
        if (numMenuItems < _totalResults) {
            return true;
        }
        else {
            return false;
        }
    }
    function renderNavigationControlsMenuItem() {
        var showPrev = isPreviousPageLinkEnabled();
        var showNext = isNextPageLinkEnabled();
        TRACE("AutoSuggestMenu.renderNavigationControlsMenuItem showPrev=" + showPrev + ", showNext=" + showNext);
        if (!showPrev &&!showNext) {
            return ;
        }
        var div = XUtils.createElement("div");
        var table = XUtils.createElement("table");
        table.width = "50px";
        var tbody = XUtils.createElement("tbody");
        var tr = XUtils.createElement("tr");
        var td = XUtils.createElement("td");
        td.width = "20px";
        td.align = "left";
        if (showPrev) {
            var link = XUtils.createElement("a");
            link.className = self.navigationLinkCssClass;
            link.href = "";
            link.innerHTML = "&lt;&lt;";
            link.onclick = self.onPreviousPage;
            td.appendChild(link);
        }
        tr.appendChild(td);
        td = XUtils.createElement("td");
        td.width = "10px";
        tr.appendChild(td);
        td = XUtils.createElement("td");
        td.width = "20px";
        td.align = "right";
        if (showNext) {
            var link = XUtils.createElement("a");
            link.className = self.navigationLinkCssClass;
            link.href = "";
            link.innerHTML = "&gt;&gt;";
            link.onclick = self.onNextPage;
            td.appendChild(link);
        }
        tr.appendChild(td);
        tbody.appendChild(tr);
        table.appendChild(tbody);
        div.appendChild(table);
        _dom.appendChild(div);
    }
    function createIFrame() {
        TRACE("AutoSuggestMenu.createIFrame");
        var iFrame = XUtils.createElement("IFRAME");
        var blankPage = self.resourcesDir + "/Blank.html";
        TRACE("AutoSuggestMenu.createIFrame blankPage=" + blankPage);
        iFrame.setAttribute("src", blankPage);
        iFrame.style.position = "absolute";
        iFrame.style.visibility = "hidden";
        iFrame.style.left = 0;
        iFrame.style.top = 0;
        iFrame.style.width = "0px";
        iFrame.style.height = "0px";
        return iFrame;
    }
    function renderMenuItems() {
        TRACE("AutoSuggestMenu.renderMenuItems");
        while (_dom.childNodes[0]) {
            _dom.removeChild(_dom.childNodes[0]);
        }
        var menuItem;
        var menuItemDiv;
        var func;
        for (count = 0; count < self.menuItems.length; count++) {
            menuItem = self.menuItems[count];
            if (!menuItem.cssClass) {
                menuItem.cssClass = self.menuItemCssClass;
            }
            if (!menuItem.selCssClass) {
                menuItem.selCssClass = self.selMenuItemCssClass;
            }
            menuItem.index = count;
            menuItem.menu = self;
            menuItemDiv = menuItem.render();
            _dom.appendChild(menuItemDiv);
        }
        if (self.usePaging) {
            renderNavigationControlsMenuItem();
        }
        _hasVerticalScrollbar = false;
        if (self.maxHeight) {
            var maxHeight = parseInt(self.maxHeight);
            _dom.style.height = null;
            TRACE("AutoSuggestMenu.renderMenuItems _dom.offsetHeight=" + _dom.offsetHeight + ", maxHeight=" + maxHeight);
            if (_dom.offsetHeight > maxHeight) {
                _dom.style.height = maxHeight + "px";
                _dom.scrollTop = 0;
                _hasVerticalScrollbar = true;
            }
            TRACE("AutoSuggestMenu.renderMenuItems _dom.style.height=" + _dom.style.height);
        }
    }
    function refreshMenuItems(refreshType) {
        if (!refreshType) {
            _refreshType = REFRESH_TYPE_COMPLETE;
        }
        else {
            _refreshType = refreshType;
        }
        TRACE("AutoSuggestMenu.refreshMenuItems _refreshType=" + _refreshType);
        if (self.isVisible()) {
            self.hide();
        }
        if (self.onGetMenuItems == null) {
            throw"Handler of AutoSuggestMenu.onGetMenuItems was not specified.";
        }
        var value = getTextBoxValue();
        value = value.replace(/\"/, '\\"');
        switch (_refreshType) {
            case REFRESH_TYPE_COMPLETE:
                _pageIndex = 0;
                break;
            case REFRESH_TYPE_NEXT_PAGE:
                _pageIndex++;
                break;
            case REFRESH_TYPE_PREVIOUS_PAGE:
                _pageIndex--;
                break;
        }
        var func = self.onGetMenuItems + '("' + value + '", ' + self.usePaging + ", " + _pageIndex + ", " + self.pageSize + ", self.refreshMenuItemsCallback)";
        TRACE("AutoSuggestMenu.refreshMenuItems func=" + func);
        eval(func);
    }
    self.refreshMenuItemsCallback = function (jsonData) {
        TRACE("AutoSuggestMenu.refreshMenuItemsCallback");
        var json = eval("(" + jsonData + ")");
        var jsonMenuItem;
        var menuItem;
        self.menuItems = new Array();
        for (count = 0; count < json.menuItems.length; count++) {
            jsonMenuItem = json.menuItems[count];
            menuItem = new AutoSuggestMenuItem();
            menuItem.label = jsonMenuItem.label;
            menuItem.value = jsonMenuItem.value;
            if (jsonMenuItem.isSelectable != null) {
                menuItem.isSelectable = jsonMenuItem.isSelectable;
            }
            if (jsonMenuItem.cssClass != null) {
                menuItem.cssClass = jsonMenuItem.cssClass;
            }
            addMenuItem(menuItem);
        }
        TRACE("AutoSuggestMenu.refreshMenuItemsCallback getMenuItemsCount()=" + getMenuItemsCount());
        if (getMenuItemsCount() > 0) {
            if ((_refreshType == REFRESH_TYPE_COMPLETE) && self.usePaging) {
                _totalResults = json.totalResults;
            }
            renderMenuItems();
            self.show();
        }
    };
    function addMenuItem(menuItem) {
        self.menuItems[self.menuItems.length] = menuItem;
    }
    self.setSelectedValue = function (value) {
        TRACE("AutoSuggestMenu.setSelectedValue value=" + value);
        var hdnSelectedValue = document.getElementById(self.hiddenSelectedValueID);
        hdnSelectedValue.value = value;
    };
    self.getSelectedValue = function () {
        TRACE("AutoSuggestMenu.getSelectedValue");
        var hdnSelectedValue = document.getElementById(self.hiddenSelectedValueID);
        return hdnSelectedValue.value;
    };
    self.getSelectedMenuItem = function () {
        TRACE("AutoSuggestMenu.getHighlightedMenuItem _selMenuItemIndex=" + _selMenuItemIndex);
        if (_selMenuItemIndex != null) {
            return self.menuItems[_selMenuItemIndex];
        }
        else {
            return null;
        }
    };
    self.isVisible = function () {
        if (!_dom) {
            return false;
        }
        if (_dom.style.visibility == "hidden") {
            return false;
        }
        else {
            return true;
        }
    };
    function updateIFrame() {
        _iFrame.style.left = _dom.style.left;
        _iFrame.style.top = _dom.style.top;
        _iFrame.style.width = _dom.offsetWidth + "px";
        _iFrame.style.height = _dom.offsetHeight + "px";
    }
    self.show = function () {
        //Fix for issue 2139 & 2215
        try{
        if(focusedCtlId!=self.textBoxID) {self.hide();return false;}
        }catch(e){}
        TRACE("AutoSuggestMenu.show _dom=" + _dom);
        if (_dom == null) {
            self.render();
        }
        var textBox = getTextBoxCtrl();
        _dom.style.left = XUtils.getAbsoluteLeft(textBox) + "px";
        _dom.style.top = XUtils.getAbsoluteTop(textBox) + textBox.offsetHeight + "px";
        if (_iFrame) {
            updateIFrame();
            _iFrame.style.visibility = "visible";
        }
        _dom.style.visibility = "visible";
    };
    self.hide = function () {
        TRACE("AutoSuggestMenu.hide");
        if (!self.isVisible()) {
            TRACE("AutoSuggestMenu.Hide already hidden");
            return ;
        }
        _selMenuItemIndex = null;
        _dom.style.visibility = "hidden";
        if (_iFrame) {
            _iFrame.style.visibility = "hidden";
        }
    };
    self.render = function () {
        TRACE("AutoSuggestMenu.render");
        if (self.id == null) {
            throw"id is required.";
        }
        if (self.textBoxID == null) {
            throw"textBoxID is required.";
        }
        if (self.hiddenSelectedValueID == null) {
            throw"hiddenSelectedValueID is required.";
        }
        var textBox = getTextBoxCtrl();
        var menuDiv;
        menuDiv = XUtils.createElement("div");
        menuDiv.id = self.id;
        menuDiv.className = self.cssClass;
        menuDiv.sourceObject = self;
        XUtils.addEventListener(menuDiv, "scroll", self.onMenuScroll);
        TRACE("AutoSuggestMenu.render absoluteLeft=" + XUtils.getAbsoluteLeft(textBox) + ", absoluteTop=" + XUtils.getAbsoluteTop(textBox));
        menuDiv.style.left = XUtils.getAbsoluteLeft(textBox) + "px";
        menuDiv.style.top = XUtils.getAbsoluteTop(textBox) + textBox.offsetHeight + "px";
        menuDiv.style.visibility = "hidden";
        XUtils.addEventListener(textBox, "keydown", self.onTextBoxKeyDown);
        XUtils.addEventListener(textBox, "keypress", self.onTextBoxKeyPress);
        XUtils.addEventListener(textBox, "keyup", self.onTextBoxKeyUp);
        XUtils.addEventListener(textBox, "blur", self.onTextBoxBlur);
        textBox.setAttribute("autocomplete", "off");
        TRACE("AutoSuggestMenu.render Moving to menuDiv.style.left=" + menuDiv.style.left + ", " + menuDiv.style.top);
        _dom = menuDiv;
        if (XUtils.isIE() && self.useIFrame) {
            _iFrame = createIFrame();
            if (_dom.style.zIndex == null) {
                _dom.style.zIndex = 0;
            }
            _iFrame.style.zIndex = _dom.style.zIndex;
            document.body.appendChild(_iFrame);
            _dom.style.zIndex = _dom.style.zIndex + 1;
        }
        TRACE("AutoSuggestMenu.render  _dom.style.zIndex=" + _dom.style.zIndex);
        document.body.appendChild(_dom);
    };
    self.onMenuItemClick = function (itemIndex) {
        TRACE("AutoSuggestMenu.onMenuItemClick  itemIndex=" + itemIndex);
        selectMenuItem(itemIndex);
        self.hide();
        focusOnTextBox();
    };
    self.onMenuItemMouseOver = function (itemIndex) {
        selectMenuItem(itemIndex, false);
    };
    self.onTextBoxKeyDown = function (evt) {
        TRACE("AutoSuggestMenu.OnTextBoxKeyDown  " + XUtils.getEventKey(evt) + ", " + self.textBoxID);
        _oldTextBoxValue = getTextBoxValue();
        TRACE("AutoSuggestMenu.OnTextBoxKeyDown  old text box value='" + _oldTextBoxValue + "'");
        var key = XUtils.getEventKey(evt);
        TRACE("AutoSuggestMenu.OnTextBoxKeyDown  Key is " + key);
        if (key == 38) {
            moveUp();
        }
        else {
            if (key == 40) {
                moveDown();
            }
            else {
                if (key == 13) {
                    TRACE("AutoSuggestMenu.OnTextBoxKeyDown : isVisible - " + self.isVisible());
                    if (self.isVisible()) {
                        if (!self.updateTextBoxOnUpDown) {
                            updateTextBoxValue();
                        }
                        self.hide();
                        _cancelSubmit = true;
                    }
                    else {
                        _cancelSubmit = false;
                    }
                }
            }
        }
        return true;
    };
    self.onTextBoxKeyPress = function (evt) {
        TRACE("AutoSuggestMenu.onTextBoxKeyPress : " + XUtils.getEventKey(evt));
        if ((XUtils.getEventKey(evt) == 13) && (_cancelSubmit)) {
            if (!evt) {
                evt = window.event;
            }
            evt.cancelBubble = true;
            evt.returnValue = false;
            if (evt.stopPropagation) {
                evt.preventDefault();
                evt.stopPropagation();
            }
        }
        return true;
    };
    self.onTextBoxKeyUp = function (evt) {
        var key = XUtils.getEventKey(evt);
        TRACE("AutoSuggestMenu.onTextBoxKeyUp " + key);
        var newValue = getTextBoxValue();
        if ((key != 38) && (key != 40) && (key != 13)) {
            if ((newValue.length > 0) && (newValue.length >= self.minSuggestChars) && (newValue.length <= self.maxSuggestChars)) {
                var divMenu = _dom;
                if (_keyPressTimer != null) {
                    window.clearTimeout(_keyPressTimer);
                }
                TRACE("AutoSuggestMenu.OnTextBoxKeyUp newValue=" + newValue + ", self.keyPressDelay=" + self.keyPressDelay);
                _keyPressTimer = window.setTimeout(self.onTextBoxKeyUpTimer, self.keyPressDelay);
            }
            else {
                if (self.isVisible()) {
                    self.hide();
                }
            }
            TRACE("AutoSuggestMenu.onTextBoxKeyUp self.oldTextBoxValue=" + _oldTextBoxValue + ", newValue=" + newValue);
            if (_oldTextBoxValue != newValue) {
                self.setSelectedValue("");
            }
        }
    };
    self.onTextBoxKeyUpTimer = function () {
        TRACE("AutoSuggestMenu.onTextBoxKeyUpTimer");
        refreshMenuItems();
    };
    self.onTextBoxBlur = function () {
        TRACE("AutoSuggestMenu.onTextBoxBlur");
        if (_cancelOnBlur) {
            focusOnTextBox();
        }
        else {
            _onBlurTimer = window.setTimeout(self.hide, 500);
        }
        _cancelOnBlur = false;
    };
    self.onNextPage = function () {
        TRACE("AutoSuggestMenu.onNextPage");
        focusOnTextBox();
        refreshMenuItems(REFRESH_TYPE_NEXT_PAGE);
        return false;
    };
    self.onPreviousPage = function () {
        TRACE("AutoSuggestMenu.onNextPage");
        focusOnTextBox();
        refreshMenuItems(REFRESH_TYPE_PREVIOUS_PAGE);
        return false;
    };
    self.onMenuScroll = function () {
        TRACE("AutoSuggestMenu.onMenuScrol");
        focusOnTextBox();
        _cancelOnBlur = true;
    }
}
AutoSuggestMenu.getMenu = function (B) {
    var C = $(B);
    if (C == null) {
        throw"AutoSuggestMenu (ID: '" + B + "') doesn't exist";
    }
    var A = C.sourceObject;
    return A;
};
if (typeof (Sys) !== "undefined") {
    Sys.Application.notifyScriptLoaded();
};