

var __aspxLoadFilteredItemsCallbackPrefix = "CBLF";
var __aspxCorrectFilterCallbackPrefix = "CBCF";
var __aspxDropDownNameSuffix = "_DDD";
var __aspxCalendarNameSuffix = "_C";
var __aspxListBoxNameSuffix = "_L";
ASPxClientDropDownEdit = _aspxCreateClass(ASPxClientButtonEditBase, {
    constructor: function(name) {
        this.constructor.prototype.constructor.call(this, name);
        this.DropDown = new ASPxClientEvent();
        this.CloseUp = new ASPxClientEvent();
        
        this.ddHeightCache = __aspxInvalidDimension;
        this.ddWidthCache = __aspxInvalidDimension;
        this.mainElementWidthCache = __aspxInvalidDimension;
        this.dropDownButtonIndex = -1;
        this.droppedDown = false;
        this.ddButtonPushed = false;
        this.lastSuccessText = "";

        aspxGetDropDownCollection().Add(this);
    },
    Initialize: function(){
        var pc = this.GetPopupControl();
        if(_aspxIsExists(pc))
            pc.allowCorrectYOffsetPosition = false;
        this.AssignClientAttributes();
        this.InitLastSuccessText();
        ASPxClientEdit.prototype.Initialize.call(this);
    },
    InitLastSuccessText: function(){
        var input = this.GetInputElement();        
        if (_aspxIsExistsElement(input))
            this.lastSuccessText = input.value;
    },
    IsRenderExists: function(){
        return _aspxIsExistsElement(this.GetMainElement());
    },
    AssignClientAttributes: function(){
        var element = this.GetDropDownButton();
        if(_aspxIsExistsElement(element))
            _aspxPreventElementDragAndSelect(element, true);
    },
    GetDropDownButton: function(){
        return this.GetButton(this.dropDownButtonIndex);
    },
    GetPopupControl: function(){
        return aspxGetControlCollection().Get(this.name + __aspxDropDownNameSuffix);
    },
    GetDropDownInnerControlName: function(suffix){
        var pc = this.GetPopupControl();
        if(_aspxIsExists(pc))
            return this.GetPopupControl().name + suffix;
        return "";
    },
    GetDropDownHeight: function(){
        return 0;
    },
    GetDropDownWidth: function(){
        return 0;
    },
    ShowDropDownArea: function(isRaiseEvent){
		aspxGetDropDownCollection().RegisterDroppedDownControl(this);
		
		this.lockListBoxClick = true;
		
        var pc = this.GetPopupControl();
        var element = this.GetMainElement();
        var pcwElement = pc.GetWindowElement(-1);
        
        _aspxSetElementDisplay(pcwElement, true);
        // Order is important. Width with scroll bar depends on Height
        var height = this.GetDropDownHeight();
        var width = this.GetDropDownWidth();
        if(this.ddHeightCache != height || this.ddWidthCache != width){
            pc.SetSize(width, height);
            this.ddHeightCache = height;
            this.ddWidthCache = width;
        }
        pc.popupVerticalOffset = - _aspxGetClientTop(element);
        pc.ShowAtElement(element);
        if(isRaiseEvent)
            this.RaiseDropDown();
        
        this.droppedDown = true;
    },
    HideDropDownArea: function(isRaiseEvent){
        this.DropDownButtonPop();
        var pc = this.GetPopupControl();
        if (_aspxIsExists(pc)){
            pc.Hide();
            if(isRaiseEvent)
                this.RaiseCloseUp();
            aspxGetDropDownCollection().UnregisterDroppedDownControl(this);
            this.droppedDown = false;
        }
    },
    ProcessInternalButtonClick: function(number) {
        return this.dropDownButtonIndex == number;
    },
    ToggleDropDown: function(){
        this.OnApplyChanges();
        if(this.droppedDown)
            this.HideDropDownArea(true);
        else
            this.ShowDropDownArea(true);        
    },
    SetTextInternal: function(text){
        if(!this.readOnly)
            ASPxClientButtonEditBase.prototype.SetValue.call(this, text);
    },
    // base events
    OnValueChanged: function() {
        this.lastSuccessText = this.GetInputElement().value;
        ASPxClientEdit.prototype.OnValueChanged.call(this);
    },
    
    OnApplyChanges: function(){
    },
    OnCancelChanges: function(){
        var isCancelProcessed = (this.GetInputElement().value != this.lastSuccessText);
        this.SetTextInternal(this.lastSuccessText);
        return isCancelProcessed;
    },
    OnClick: function(){
        this.SetFocus();
    },    
    IsCanToDropDown: function(){
        return true;
    },
    OnDropDown: function(evt) { 
        if(!this.IsCanToDropDown()) return true;
        
        this.SetFocus();
        if(!this.droppedDown)
            this.DropDownButtonPush();
        this.ToggleDropDown();
        return this.droppedDown ? _aspxCancelBubble(evt) : true;
    },
    DropDownButtonPush: function(){
        if(this.droppedDown || this.ddButtonPushed) return;
        this.ddButtonPushed = true;
        
        if(__aspxIE || __aspxOpera) 
            this.DropDownButtonPushPop(true);
        else
            this.DropDownButtonPushMozilla();
    },    
    DropDownButtonPop: function(){
        if(!this.droppedDown || !this.ddButtonPushed) return;
        this.ddButtonPushed = false;
        
        if(__aspxIE || __aspxOpera) 
            this.DropDownButtonPushPop(false);
        else
            this.DropDownButtonPopMozilla();
    },
    DropDownButtonPushPop: function(isPush){
        var buttonElement = this.GetDropDownButton();
        if(_aspxIsExists(buttonElement)){
            var controller = aspxGetStateController();
            var element = controller.GetPressedElement(buttonElement);
            if(_aspxIsExists(element)){
                if(isPush){
                    controller.SetCurrentHoverElement(null);
                    controller.DoSetPressedState(element);
                } else {
                    controller.DoClearPressedState(element);
                    controller.SetCurrentPressedElement(null);
                    controller.SetCurrentHoverElement(element);
                }
            }
        }
    },
    DropDownButtonPushMozilla: function(){
        this.DisableStyleControllerForDDButton();
        var controller = aspxGetStateController();
        controller.savedCurrentPressedElement = null;
    },
    DropDownButtonPopMozilla: function(){
        this.EnableStyleControllerForDDButton();
        var controller = aspxGetStateController();
        var buttonElement = this.GetDropDownButton();
        if(_aspxIsExists(buttonElement)){
            var element = controller.GetPressedElement(buttonElement);
            if(_aspxIsExists(element))
                controller.DoClearPressedState(element);
            controller.currentPressedElement = null;
            element = controller.GetHoverElement(buttonElement);
            if(_aspxIsExists(element))
                controller.SetCurrentHoverElement(element);
        }
    },
    EnableStyleControllerForDDButton: function(){
        var element = this.GetDropDownButton();
        if(_aspxIsExists(element)){
            var controller = aspxGetStateController();
            this.ReplaceElementControlStyleItem(controller.hoverItems, element, this.ddButtonHoverStyle);
            this.ReplaceElementControlStyleItem(controller.pressedItems, element, this.ddButtonPressedStyle);
            this.ReplaceElementControlStyleItem(controller.selectedItems, element, this.ddButtonSelectedStyle);
        }
    },
    DisableStyleControllerForDDButton: function(){
        var element = this.GetDropDownButton();
        if(_aspxIsExists(element)){
            var controller = aspxGetStateController();
            this.ddButtonHoverStyle = this.ReplaceElementControlStyleItem(controller.hoverItems, element, null);
            this.ddButtonPressedStyle = this.ReplaceElementControlStyleItem(controller.pressedItems, element, null);
            this.ddButtonSelectedStyle = this.ReplaceElementControlStyleItem(controller.selectedItems, element, null);
        }
    },
    ReplaceElementControlStyleItem: function(items, element, newStyleItem){
        var styleItem = items[element.id];
        items[element.id] = newStyleItem;
        return styleItem;
    },

    OnDocumentMouseDown: function() {
        this.HideDropDownArea(true);
    },
    OnDocumentMouseUp: function() {
        this.DropDownButtonPop();
    },
    OnDDButtonMouseMove: function(evt){
    },
    OnCloseUp: function(evt){
        this.HideDropDownArea(true);
    },
    OnOpenAnotherDropDown: function(){
        this.HideDropDownArea(true);
    },
    OnTextChanged: function() {
        this.ParseValue();
    },
    ChangeEnabledAttributes: function(enabled){
        ASPxClientButtonEditBase.prototype.ChangeEnabledAttributes.call(this, enabled);
        var btnElement = this.GetDropDownButton();
        if(_aspxIsExists(btnElement))
            this.ChangeButtonEnabledAttributes(btnElement, _aspxChangeAttributesMethod(enabled));
        var inputElement = this.GetInputElement();
        if(_aspxIsExists(inputElement))
            this.ChangeInputCellEnabledAttributes(inputElement.parentNode, _aspxChangeAttributesMethod(enabled));
    },
    ChangeEnabledStateItems: function(enabled){
        ASPxClientButtonEditBase.prototype.ChangeEnabledStateItems.call(this, enabled);
        var btnElement = this.GetDropDownButton();
        if(_aspxIsExists(btnElement))
            aspxGetStateController().SetElementEnabled(btnElement, enabled);
    },
	ChangeInputCellEnabledAttributes: function(element, method){
        method(element, "onclick");
        method(element, "onkeyup");
        method(element, "onmousedown");
        method(element, "onmouseup");
	},
    
    // Keyboard Support
    InitializeKeyHandlers: function() {
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_ENTER, "OnEnter");
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_ESC, "OnEscape");
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_PAGEUP, "OnPageUp");
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_PAGEDOWN, "OnPageDown");
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_END, "OnEndKeyDown");
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_HOME, "OnHomeKeyDown");
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_LEFT, "OnArrowLeft");
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_RIGHT, "OnArrowRight");
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_UP, "OnArrowUp");
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_DOWN, "OnArrowDown");
        this.AddKeyDownHandler(ASPxKeyConsts.KEY_TAB, "OnTab");
    },
    OnArrowUp: function(evt){
        if(evt.altKey) {
            this.ToggleDropDown();
            return true;
        }
        return false;
    },
    OnArrowDown: function(evt){
        if(evt.altKey) {
            this.ToggleDropDown();
            return true;
        }
        return false;
    },
    OnPageUp: function(evt){
        return false;
    },    
    OnPageDown: function(evt){
        return false;
    },
    OnEndKeyDown: function(evt){
        return false;
    },
    OnHomeKeyDown: function(evt){
        return false;
    },
    OnArrowLeft: function(evt){
        return false;
    },
    OnArrowRight: function(evt){
        return false;
    },
    OnEscape: function(evt){
        var isCancelProcessed = this.OnCancelChanges() || this.droppedDown;
        this.HideDropDownArea(true);
        return isCancelProcessed;
    },
    OnEnter: function(evt){
        return false;
    },
    OnTab: function(evt){
        return false;
    },
    // API
    RaiseCloseUp: function(){
        if(!this.CloseUp.IsEmpty()){
            var args = new ASPxClientEventArgs();
            this.CloseUp.FireEvent(this, args);
        }
    },
    RaiseDropDown: function(){
        if(!this.DropDown.IsEmpty()){
            var args = new ASPxClientEventArgs();
            this.DropDown.FireEvent(this, args);
        }
    },
    ShowDropDown: function(){
        this.ShowDropDownArea(false);
    },
    HideDropDown: function(){
        this.HideDropDownArea(false);
    }
});

ASPxClientDropDownCollection = _aspxCreateClass(ASPxClientControlCollection, {
    constructor: function(){
		this.constructor.prototype.constructor.call(this);
		
		this.droppedControlName = "";
		this.focusedControlName = "";
    },
    SetFocusedDropDownName: function(name){
        this.focusedControlName = name;
    },
    ResetDroppedDownControl: function(){
        this.droppedControlName = "";
    },
    ResetFocusedControl: function(){
        this.focusedControlName = "";
    },
    GetFocusedDropDown: function(){
        var control = this.GetDropDownControlInternal(this.focusedControlName);
        if(control == null) this.ResetFocusedControl();
        return control;
    },
    GetDroppedDropDown: function(){
        var control = this.GetDropDownControlInternal(this.droppedControlName);
        if(control == null) this.ResetDroppedDownControl();
        return control;
    },
    GetDropDownControlInternal: function(name){
        var control = this.Get(name);
        var isControlExists = _aspxIsExists(control) && control.IsRenderExists();
        if(!isControlExists)
            control = null;
        return control;
    },
    OnDDButtonMouseMove: function(evt){
        var dropDownControl = this.GetDroppedDropDown();
        if(dropDownControl != null)
            dropDownControl.OnDDButtonMouseMove(evt);
    },
    OnDocumentMouseDown: function(evt){
        this.CloseDropDownByDocumentEvent(evt, false);
        this.ClearFocusedDropDownByDocumentEvent(evt);
    },
    OnResize: function(evt){
        this.CloseDropDownByDocumentEvent(evt, true);
        this.AdjustControls();
    },
    
    CloseDropDownByDocumentEvent: function(evt, isResize){
        var dropDownControl = this.GetDroppedDropDown();
        if(dropDownControl != null && (this.IsEventNotFromControlSelf(evt, dropDownControl) || isResize))
            dropDownControl.OnDocumentMouseDown();
    },
    ClearFocusedDropDownByDocumentEvent: function(evt){
        var focusedDropDown = this.GetFocusedDropDown();
        if(focusedDropDown != null && this.IsEventNotFromControlSelf(evt, focusedDropDown))
            this.SetFocusedDropDownName("");        
    },
    AdjustControls: function(){
        for(var name in this.elements) {
            this.elements[name].AdjustControl(false);
        }
    },
    IsEventNotFromControlSelf: function(evt, control){
        // Prevent DocumentOnClick event fired by the DropDown control and DropDownElement(Mozilla only) click
        var srcElement = _aspxGetEventSource(evt);
        var mainElement = control.GetMainElement();
        var popupControl = control.GetPopupControl();
        if(srcElement == null || !_aspxIsExists(mainElement) || !_aspxIsExists(popupControl)) return true;
        
        return (_aspxGetParentById(srcElement, mainElement.id) == null &&
            _aspxGetParentById(srcElement, popupControl.GetWindowElementId(-1)) == null);
    },
    OnDocumentMouseUp: function(evt){
        var dropDownControl = this.GetDroppedDropDown();
        if(dropDownControl != null)
            dropDownControl.OnDocumentMouseUp();
    },
    RegisterDroppedDownControl: function(dropDownControl){
        var previousDropDownControl = this.GetDroppedDropDown();
        if(previousDropDownControl != null)
            previousDropDownControl.OnOpenAnotherDropDown();
        this.droppedControlName = dropDownControl.name;
    },
    UnregisterDroppedDownControl: function(dropDownControl){
        if(this.droppedControlName == dropDownControl.name)
            this.ResetDroppedDownControl();
    }
});
ASPxClientDateEdit = _aspxCreateClass(ASPxClientDropDownEdit, {
    constructor: function(name) {
        this.constructor.prototype.constructor.call(this, name);
        this.dateFormatter = new ASPxDateFormatter();        
        this.calendarMainElementOnClick = null;        
        
        //set from server        
        this.date = null;        
        this.dateOnError = "u";
        this.allowNull = true;
        this.calendarOwnerName = null;
        this.DateChanged = new ASPxClientEvent();
    },
    Initialize: function() {
        var calendar = this.GetCalendar();
        if(_aspxIsExists(calendar)) {
			this.calendarMainElementOnClick = _aspxCreateEventHandlerFunction("aspxEdDECMainElementClick", this.name);            
            if (__aspxNS)
                calendar.GetMainElement().style.borderCollapse = "separate";
        }
        ASPxClientDropDownEdit.prototype.Initialize.call(this);
    },
    InlineInitialize: function(){
        this.InitSpecialKeyboardHandling();
        ASPxClientEditBase.prototype.InlineInitialize.call(this);
    },
        
    ShowDropDownArea: function(isRaiseEvent){
        var cal = this.GetCalendar();
        if(_aspxIsExists(cal))            
            cal.SetValue(this.date);
        cal.forceMouseDown = true;
        __aspxActiveCalendar = cal;
        
		cal.SelectionChanging.ClearHandlers();
		cal.SelectionChanging.AddHandler(ASPxClientDateEdit.CreateDelegate(this, this.OnCalendarSelectionChanging));
		
		cal.MainElementClick.ClearHandlers();
		cal.MainElementClick.AddHandler(this.calendarMainElementOnClick);
        
        ASPxClientDropDownEdit.prototype.ShowDropDownArea.call(this, isRaiseEvent);        
    },    	  
    GetPopupControl: function() { // overriden
		var calendarOwner = this.GetCalendarOwner();
		if(calendarOwner != null)
			return calendarOwner.GetPopupControl();
		return ASPxClientDropDownEdit.prototype.GetPopupControl.call(this);
    },    
    GetCalendar: function() {    
        var name = this.GetDropDownInnerControlName(__aspxCalendarNameSuffix);
        return aspxGetControlCollection().Get(name);
    },
    GetCalendarOwner: function() {
		if(!this.calendarOwnerName)
			return null;
		return aspxGetControlCollection().Get(this.calendarOwnerName);
    },
    GetFormattedDate: function() {
        if(!this.date)
            return "";
        return this.dateFormatter.Format(this.date);
    },
    RaiseValueChangedEvent: function() {
        var processOnServer = ASPxClientEdit.prototype.RaiseValueChangedEvent.call(this);
        processOnServer = this.RaiseDateChanged(processOnServer);
        return processOnServer;
    },
    OnApplyChanges: function(){
        this.OnTextChanged();
    },
    OnCalendarSelectionChanging: function(sender, e) {
        if(!this.GetCalendar().isDateChangingByKeyboard) {
            this.HideDropDownArea(true);
            var date = null;
            if (_aspxIsExists(e.selection))
                date = e.selection.GetFirstDate();
            else
                date = this.GetCalendar().GetValue();
                
            if(date != null && this.date != null) {
                date.setHours(this.date.getHours());
                date.setMinutes(this.date.getMinutes());
                date.setSeconds(this.date.getSeconds());
                date.setMilliseconds(this.date.getMilliseconds());
            }         
            this.ChangeDate(date);
            this.SelectInputElement();
        }
    },
    OnCalendarMainElementClick: function() {
        this.SetFocus();
    },
    OnArrowUp: function(evt){
        var isProcessed = ASPxClientDropDownEdit.prototype.OnArrowUp.call(this, evt);
        if (!isProcessed && this.droppedDown)
            this.GetCalendar().OnArrowUp(evt);
        return true;
    },
    OnArrowDown: function(evt){
        var isProcessed = ASPxClientDropDownEdit.prototype.OnArrowDown.call(this, evt);
        if (!isProcessed && this.droppedDown)
            this.GetCalendar().OnArrowDown(evt);
        return true;
    },
    OnArrowLeft: function(evt){
        if (this.droppedDown) {
            this.GetCalendar().OnArrowLeft(evt);
            return true;
        }
        return false;
    },
    OnArrowRight: function(evt){
        if (this.droppedDown) {    
            this.GetCalendar().OnArrowRight(evt);
            return true;
        }
        return false;
    },
    
    OnPageUp: function(evt){
        if (this.droppedDown) {    
            this.GetCalendar().OnPageUp(evt);
            return true;
        }
        return false;        
    },
    OnPageDown: function(evt){
        if (this.droppedDown) {
            this.GetCalendar().OnPageDown(evt);
            return true;
        }
        return false;        
    },
    OnEndKeyDown: function(evt) {
        if (this.droppedDown) {
            this.GetCalendar().OnEndKeyDown(evt);
            return true;
        }
        return false;
    },
    OnHomeKeyDown: function(evt) {
        if (this.droppedDown) {
            this.GetCalendar().OnHomeKeyDown(evt);
            return true;
        }
        return false;    
    },
    
    OnEnter: function() {
        this.enterProcessed = false; // hack for defaultbutton
        if (this.droppedDown) {
			var calendar = this.GetCalendar();
            if (calendar.IsFastNavigationActive()) {
                calendar.GetFastNavigation().OnEnter();
            } else {
				var args = new ASPxClientCalendarSelectionEventArgs(false, null);				
                this.OnCalendarSelectionChanging(this, args);
            }
            this.enterProcessed = true;
        }
        else
            this.OnApplyChanges();
        return this.enterProcessed;
    },
    OnEscape: function() {
        if (this.droppedDown){
            if (this.GetCalendar().IsFastNavigationActive())
                this.GetCalendar().OnEscape();
            else
                ASPxClientDropDownEdit.prototype.OnEscape.call(this);
        }
        return true;
    },
    OnTab: function(evt){
        if(!this.droppedDown) return;
        
		var calendar = this.GetCalendar();
        if (calendar.IsFastNavigationActive()) 
            calendar.GetFastNavigation().Hide();
            
		var args = new ASPxClientCalendarSelectionEventArgs(false, null);				
        this.OnCalendarSelectionChanging(this, args);
    },
        
    ParseValue: function() {
        var value = ASPxClientButtonEditBase.prototype.GetValue.call(this);
        if(value == null || value == "") {
            this.allowNull ? this.ChangeDate(null) : this.UpdateDateEditInputs();
        } else {
            var date = this.ParseDate(value);
            if(!date || !this.GetCalendar().IsDateInRange(date)) {
                switch(this.dateOnError) {
                    case "n":
						this.allowNull ? this.ChangeDate(null) : this.UpdateDateEditInputs();
						break;
                    case "t":
                        this.ChangeDate(new Date());
                        break;
                    default:
						this.UpdateDateEditInputs();                        
                        break;
                }
            } else
                this.ChangeDate(date);
        }
    },
    ParseDate: function(str) {
        return this.dateFormatter.Parse(str);
    },
    
    GetValue: function() {
        return this.date;
    },    
    GetValueString: function() {
		if(this.date == null)
			return null;
		var result = ASPxClientCalendar.GetInvariantDateString(this.date);
		// time
		var time = { 
			h: this.date.getHours(),
			m: this.date.getMinutes(),
			s: this.date.getSeconds()
		};
		for(var key in time) {		
			var str = time[key].toString();
			if(str.length < 2)
				str = "0" + str;				
			time[key] = str;			
		}		
		result += " " + time.h + ":" + time.m + ":" + time.s;
		var msec = this.date.getMilliseconds();
		if(msec > 0)
			result += "." + msec.toString();		
		return result;
    },
    SetValue: function(date) {        
        this.date = date;
        this.UpdateDateEditInputs();        
    },
    UpdateDateEditInputs: function() {        
		ASPxClientButtonEditBase.prototype.SetValue.call(this, this.GetFormattedDate());
		var input = this.GetTimestampInput();
		if(input != null)		
			input.value = this.date == null ? "N" : this.date.valueOf() - 60000 * this.date.getTimezoneOffset();
    },
    GetTimestampInput: function() {
		return _aspxGetElementById(this.name + "_TS");
    },    
    ChangeDate: function(date) {
        var oldDate = this.date;
        this.SetValue(date);
        if(!this.AreDatesEqualExact(oldDate, date)) {
            this.RaisePersonalStandardValidation();
            this.OnValueChanged();
        }        
    },
    AreDatesEqualExact: function(date1, date2) {
        if(date1 == null && date2 == null)
            return true;
        if(date1 == null || date2 == null)
            return false;
        return date1.getTime() == date2.getTime();
    },
    GetText: function() {
		return this.GetFormattedDate();
    },
    SetText: function(value) {
		ASPxClientTextEdit.prototype.SetValue.call(this, value);
		this.ParseValue();
    },    
    // API
    RaiseDateChanged: function(processOnServer) {
        if(!this.DateChanged.IsEmpty()) {
            var args = new ASPxClientProcessingModeEventArgs(processOnServer);
            this.DateChanged.FireEvent(this, args);
            processOnServer = args.processOnServer;
        }
        return processOnServer;
    },
    SetDate: function(date) {
        this.SetValue(date);
    },
    GetDate: function() {
        return this.date;
    }
});

ASPxClientDateEdit.CreateDelegate = function(object, method) {
	function handler(sender, e) {
		method.call(object, sender, e);
	}
	return handler;		
}

__aspxCCValueInputSuffix = "VI";
ASPxClientComboBoxBase = _aspxCreateClass(ASPxClientDropDownEdit, {
    constructor: function(name) {
        this.constructor.prototype.constructor.call(this, name);
        
        this.lbEventLockCount = 0;
        // Cashe
        this.listBox = null;
        this.lastSuccessValue = "";
        this.islastSuccessValueInit = false;        
        this.SelectedIndexChanged = new ASPxClientEvent();
    },
    Initialize: function(){
        this.InitializeListBoxOwnerName();
        ASPxClientDropDownEdit.prototype.Initialize.call(this);
    },
    InitializeListBoxOwnerName: function(){
        var lb = this.GetListBoxControl();
        if(_aspxIsExists(lb))
            lb.ownerName = this.name;
    },
    GetDropDownInnerControlName: function(suffix){
        return "";
    },
    GetListBoxControl: function(){
        if(!_aspxIsExistsElement(this.listBox)){
            var name = this.GetDropDownInnerControlName(__aspxListBoxNameSuffix);
            this.listBox = aspxGetControlCollection().Get(name);
        }
        return this.listBox;
    },
    GetCallbackArguments: function(){
        return this.GetListBoxCallbackArguments();
    },
    GetListBoxCallbackArguments: function(){
        var lb = this.GetListBoxControl();
        return lb.GetCallbackArguments();
    },
    SendCallback: function(){
        this.CreateCallback(this.GetCallbackArguments());
    },
    SetText: function (text){
        var lb = this.GetListBoxControl();
        var index = this.FindItemIndexByText(lb, text);
        this.SelectIndex(index, false);
        this.SetTextInternal(text);
        this.lastSuccessText = text;
        this.lastSuccessValue = index >= 0 ? lb.GetValue() : text;
        this.islastSuccessValueInit = true;
    },
    GetValue: function(){
        return this.islastSuccessValueInit ? this.lastSuccessValue : this.GetValueInternal();
    },
    GetValueInternal: function(){
        var text = ASPxClientDropDownEdit.prototype.GetValue.call(this);
        var lb = this.GetListBoxControl();
        if (_aspxIsExists(lb)){
            var index = this.FindItemIndexByText(lb, text);
            lb.SelectIndexSilent(index, false); // Prevent to direct input value changing
            if(index != -1)
                return lb.GetValue();
        }
        return text;
    },
    SetValue: function(value){
        var lb = this.GetListBoxControl();
        lb.SetValue(value);
        // TODO Extract method with OnSelectChanged (params: value)
        var item = lb.GetSelectedItem();
        var text = _aspxIsExists(item) ? item.text : value;
        this.SetTextInternal(text);
        this.lastSuccessText = text;
        this.lastSuccessValue = item != null ? item.value : text;
        this.islastSuccessValueInit = true;
        
        this.UpdateValueInput();
        //
    },
    
    FindItemIndexByText: function(lb, text){
        if (!_aspxIsExists(lb)) return;
        for(var i = 0; i < lb.GetItemCount(); i ++){
            if(lb.GetItem(i).text == text)
                return i;
        }
        return -1;
    },
    CollectionChanged: function(){
    },
    SelectIndex: function(index, initialize){
        var lb = this.GetListBoxControl();
        var isSelectionChanged = lb.SelectIndexSilent(index, initialize);
        var item = lb.GetSelectedItem();
        var text = item != null ? item.text : "";
        
        if(isSelectionChanged){
            this.SetTextInternal(text);
            this.lastSuccessText = text;
            this.lastSuccessValue = item != null ? item.value : text;
            this.islastSuccessValueInit = true;
        }
        this.UpdateValueInput();
        
        return isSelectionChanged;
    },
    OnSelectChanged: function(){
        if(this.lbEventLockCount > 0) return;
        
        var lb = this.GetListBoxControl();
        // TODO Extract method with SetValue (params: value = "")
        var item = lb.GetSelectedItem();
        var text = item != null ? item.text : "";
        this.lastSuccessText = text;
        this.lastSuccessValue = item != null ? item.value : text;
        this.islastSuccessValueInit = true;
        this.SetTextInternal(text);
        //
        this.OnChange(); 
        
        if(!this.isToolbarItem)
            this.SelectInputElement();
    },
    OnCallback: function(result) {
    },
    OnChange: function(){
        this.UpdateValueInput();
        this.RaisePersonalStandardValidation();
        this.OnValueChanged();
    },
    UpdateValueInput: function() {
    },
    
    RaiseValueChangedEvent: function() {
        var processOnServer = ASPxClientTextEdit.prototype.RaiseValueChangedEvent.call(this);
        processOnServer = this.RaiseSelectedIndexChanged(processOnServer);
        return processOnServer;
    },
    RaiseSelectedIndexChanged: function(processOnServer) {
        if(!this.SelectedIndexChanged.IsEmpty()){
            var args = new ASPxClientProcessingModeEventArgs(processOnServer);
            this.SelectedIndexChanged.FireEvent(this, args);
            processOnServer = args.processOnServer;
        }
        return processOnServer;
    },
    AddItem: function(text, value, imageUrl){
        var index = this.GetListBoxControl().AddItem(text, value, imageUrl);
        this.CollectionChanged();
        return index;
    },
    InsertItem: function(index, text, value, imageUrl){
        this.GetListBoxControl().InsertItem(index, text, value, imageUrl);
        this.CollectionChanged();
    },
    RemoveItem: function(index){
        this.GetListBoxControl().RemoveItem(index);
        this.CollectionChanged();
    },
    ClearItems: function(){
        this.GetListBoxControl().ClearItems();
        this.ClearItemsInternal();
    },
    BeginUpdate: function(){
         this.GetListBoxControl().BeginUpdate();
    },
    EndUpdate: function(){
        this.GetListBoxControl().EndUpdate();
        this.CollectionChanged();
    },
    MakeItemVisible: function(index){
    },
    GetItem: function(index){
        return this.GetListBoxControl().GetItem(index);
    },
    GetItemCount: function(){
        return this.GetListBoxControl().GetItemCount(); 
    },
    GetSelectedIndex: function(){
        return this.GetListBoxControl().GetSelectedIndexInternal();
    },
    SetSelectedIndex: function(index){
        this.SelectIndex(index, false);
    },
    GetSelectedItem: function(){
        var lb = this.GetListBoxControl();
        var index = lb.GetSelectedIndexInternal();
        return lb.GetItem(index);
    },
    SetSelectedItem: function(item){
        var index = (item != null) ? item.index : -1;
        this.SelectIndex(index, false);
    },
    GetText: function(){
        return this.lastSuccessText;
    },
    PerformCallback: function(arg) {
    },
    ClearItemsInternal: function(){
        this.SetValue(null);
        this.CollectionChanged();
    }
});

ASPxClientComboBox = _aspxCreateClass(ASPxClientComboBoxBase, {
    constructor: function(name) {
        this.constructor.prototype.constructor.call(this, name);
        
        this.filterTimerId = -1;
        // Callback
        this.allowMultipleCallbacks = false;
        this.isApplyAndCloseAfterCallback = false;
        this.isCallbackMode = false;
        this.isPerformCallback = false;
        this.changeSelectAfterCallback = 0;
        // Filtering
        this.isFilterEnabled = false;
        this.isEnterLocked = false;
        this.isLastFilteredKeyWasTab = false; // B30455. FilteringHighlightComplitedText invoke setFocus().
        this.filter = "";
        this.filterTimer = 100;
        this.isPostponedFiltration = false;
        
        this.isToolbarItem = false;
        this.isDropDownListStyle = true;
        this.dropDownHeight = "";
        this.dropDownWidth = "";
    },
    Initialize: function(){
        var lb = this.GetListBoxControl();
        this.InitializeListBoxOwnerName();

        var mainElement = this.GetMainElement();
        if(_aspxIsExists(mainElement))
            _aspxAttachEventToElement(mainElement, __aspxNS ? "DOMMouseScroll" : "mousewheel", aspxCBMouseWheel);    
        var input = this.GetInputElement();
        var ddbutton = this.GetDropDownButton();
        if(_aspxIsExists(ddbutton))
            _aspxAttachEventToElement(ddbutton, "mousemove", aspxCBDDButtonMMove);
        if(this.isFilterEnabled)
            _aspxAttachEventToElement(input, "keyup", aspxCBKeyUp);
        if(this.isDropDownListStyle && __aspxIE){
            _aspxPreventElementDragAndSelect(mainElement, true);
            _aspxPreventElementDragAndSelect(input, true);
            if(_aspxIsExists(ddbutton))
                _aspxPreventElementDragAndSelect(ddbutton, true);
        }
        if(this.isToolbarItem){
            mainElement.unselectable="on";
            input.unselectable="on";
            if(_aspxIsExists(input.offsetParent))
                input.offsetParent.unselectable="on";
            if(_aspxIsExists(ddbutton))
                ddbutton.unselectable="on";
            if(_aspxIsExists(lb)){
                var table = lb.GetListTable();
                for(var i = 0; i < table.rows.length; i ++){
                    for(var j = 0; j < table.rows[i].cells.length; j ++)
                        _aspxSetElementAsUnselectable(table.rows[i].cells[j], true);
                }
            }
        }
        
        this.RemoveRaisePSValidationFromListBox();
        this.RedirectStandardValidators();
        this.UpdateValueInput();
        this.InitDropDownSize();
        this.InitListBoxScrollStyle();
        
        ASPxClientComboBoxBase.prototype.Initialize.call(this);
    },
    InlineInitialize: function(){
        this.InitSpecialKeyboardHandling();
        ASPxClientEditBase.prototype.InlineInitialize.call(this);
    },
        
    GetDropDownInnerControlName: function(suffix){
        return ASPxClientDropDownEdit.prototype.GetDropDownInnerControlName.call(this, suffix);
    },
    AdjustControlCore: function() {
        ASPxClientEdit.prototype.AdjustControlCore.call(this);
        this.ddHeightCache = __aspxInvalidDimension;
        this.ddWidthCache = __aspxInvalidDimension;
    },
    
    RemoveRaisePSValidationFromListBox: function() {
        var listBox = this.GetListBoxControl();
        if (_aspxIsExists(listBox))
            listBox.RaisePersonalStandardValidation = function() { };
    },
    RedirectStandardValidators: function() {
        var valueInput = this.GetValueInput();
        if(_aspxIsExistsElement(valueInput) && _aspxIsExists(valueInput.Validators)) {
            for(var i = 0; i < valueInput.Validators.length; i++)
                valueInput.Validators[i].controltovalidate = valueInput.id;
        }
    },
    GetValueInputToValidate: function(){
        return this.GetValueInput();
    },
    GetValueInput: function(){
        return document.getElementById(this.name + "_" + __aspxCCValueInputSuffix);
    },
    GetListBoxScrollDivElement: function(){
        return this.GetListBoxControl().GetScrollDivElement();
    },
    GetIsControlWidthWasChanged: function(){
        return this.mainElementWidthCache == __aspxInvalidDimension || this.mainElementWidthCache != this.GetMainElement().clientWidth;
    },
    GetDropDownHeight: function(){
        return (this.ddHeightCache != __aspxInvalidDimension) ? this.ddHeightCache : this.InitListBoxHeight();
    },
    GetDropDownWidth: function(){
        return (this.ddWidthCache != __aspxInvalidDimension && !this.GetIsControlWidthWasChanged()) ? this.ddWidthCache : this.InitListBoxWidth();
    },
    UpdateValueInput: function() {
        var inputElement = this.GetValueInput();
        if(_aspxIsExists(inputElement)){
            var value = this.GetValue();
            inputElement.value = value != null ? value : "";
        }
    },
    
    CollectionChanged: function(){
        if(this.GetListBoxControl().APILockCount == 0)
            this.InitDropDownSize();
    },
    InitDropDownSize: function(){
        var pc = this.GetPopupControl();
        if(_aspxIsExists(pc) && this.IsDisplayed()) {
            var pcwElement = pc.GetWindowElement(-1);
            if(_aspxIsExistsElement(pcwElement)){
                var isPcwDisplayad = _aspxGetElementDisplay(pcwElement);
                if(!isPcwDisplayad)
                    pc.SetWindowDisplay(-1, true);
                this.ddHeightCache = this.InitListBoxHeight();
                this.ddWidthCache = this.InitListBoxWidth();
                pc.SetSize(this.ddWidthCache, this.ddHeightCache);
                if(!isPcwDisplayad)
                    pc.SetWindowDisplay(-1, false);
            }
        }
    },
    InitMainElementCache: function(){
        this.mainElementWidthCache = this.GetMainElement().clientWidth;
    },
    InitListBoxHeight: function(){
        var lbScrollDiv = this.GetListBoxScrollDivElement();
        var height = this.dropDownHeight;
        var lb = this.GetListBoxControl();
        lb.GetMainElement().style.height = "0px";
        var lbHeight = 0;
        if(height == ""){
            var listHeight = lb.GetListTableHeight();
            var count = lb.GetItemCount();
            if(count > 7)
                height = ((listHeight / count) * 7) + "px";
            else
                height = count == 0 ? "0px" : listHeight + "px";
            lbScrollDiv.style.height = height;
            lbHeight = lbScrollDiv.offsetHeight;
        } else {
            var lbMainElement = lb.GetMainElement();
            lbMainElement.style.height = "0px";
            lbScrollDiv.style.height = "0px";
            lbMainElement.style.height = height;
            var trueLbOffsetHeight = lbMainElement.offsetHeight;
            var trueLbClientHeight = lbMainElement.clientHeight;
            lbScrollDiv.style.height = lbMainElement.clientHeight + "px";
            lbHeightCorrection = lbMainElement.offsetHeight - trueLbOffsetHeight;
            lbScrollDiv.style.height = (trueLbClientHeight - lbHeightCorrection) + "px";
            lbHeight = lbMainElement.offsetHeight;
        }
        lb.InitializePageSize();
        return lbHeight;
    },
    InitListBoxWidth: function(){
        this.InitMainElementCache();
        
        var mainElement = this.GetMainElement();
        var lb = this.GetListBoxControl();
        var lbMainElement = lb.GetMainElement();
        var lbScrollDiv = this.GetListBoxScrollDivElement();
        var lbTable = lb.GetListTable();
        lbMainElement.style.width = "";
        lbScrollDiv.style.width = "100%";
        
        if(this.dropDownWidth != ""){
            lbMainElement.style.width = this.dropDownWidth;
            lbScrollDiv.style.width = lbMainElement.clientWidth + "px";
            var difference = lbTable.offsetWidth - lbScrollDiv.clientWidth;
            if(!__aspxIE && difference > 0){
                lbMainElement.style.width = (lbMainElement.offsetWidth + difference) + "px";
                lbScrollDiv.style.width = (lbMainElement.clientWidth)  + "px";
            }
        }
        else {
            var pc = this.GetPopupControl();
            var width = lbTable.offsetWidth;
            var scrollWidth = lb.GetVerticalScrollBarWidth();
            var isBrowserPutScrollOnContent = !__aspxIE || __aspxIE55;
            var isBrowserAbleAnimScroll = !__aspxMozilla || __aspxFirefox || !pc.enableAnimation;
            if(isBrowserPutScrollOnContent && isBrowserAbleAnimScroll)
                width += scrollWidth;
            lbScrollDiv.style.width = width + "px";
            if(__aspxFirefox && lbMainElement.offsetWidth < lbScrollDiv.offsetWidth)
                lbMainElement.style.width = "0%"; // FIX B19014
            var widthDifference = mainElement.offsetWidth - lbMainElement.offsetWidth;
            if(widthDifference > 0){
                lbScrollDiv.style.width = (width + widthDifference) + "px";
                var twoBorderSize = (lbMainElement.offsetWidth - lbMainElement.clientWidth);
                lbMainElement.style.width = (width + widthDifference + twoBorderSize) + "px"; // prevent lbMainElement size hover ScrollBar
            }
        }
        return lbScrollDiv.offsetWidth;
    },
    InitListBoxScrollStyle: function(){
        this.PreventScrollSpoilDDShowing();
    },
    SelectIndexSilent: function(lb, index){
        this.lbEventLockCount ++;
        lb.SelectIndexSilent(index);
        this.lbEventLockCount --;
    },
    SelectInputText: function(){
        var input = this.GetInputElement();
        _aspxSetInputSelection(input, 0, input.value.length);
    },
    ShowDropDownArea: function(isRaiseEvent){
        var lb = this.GetListBoxControl();
        if(!_aspxIsExists(lb) || lb.GetItemCount() == 0) 
            return;
        var pc = this.GetPopupControl();

        ASPxClientDropDownEdit.prototype.ShowDropDownArea.call(this, isRaiseEvent);
        
        var text = ASPxClientDropDownEdit.prototype.GetValue.call(this);
        var lbItem = lb.GetSelectedItem();
        var lbText = lbItem != null ? lbItem.text : "";
        if(text != lbText && text != null && lbText != ""){
            var newSelectedIndex = this.FindItemIndexByText(lb, text);
            lb.SelectIndexSilent(newSelectedIndex, false);
        }
        lb.EnsureSelectedItemVisible();
        lb.CallbackSpaceInit();
    },
    HideDropDownArea: function(isRaiseEvent){
        this.FilteringStop();
        ASPxClientDropDownEdit.prototype.HideDropDownArea.call(this, isRaiseEvent);

        this.PreventScrollSpoilDDShowing();
    },
    IsScrollSpoilDDShowing: function (){
        var pc = this.GetPopupControl();
        return ((__aspxMozilla || __aspxFirefox)  && pc.enableAnimation); // Prevent mozilla wrong animation
    },
    EnableLBDivOverflow: function(){
        var divElement = this.GetListBoxScrollDivElement();
        divElement.style.overflow = "auto";
    },
    DisableLBDivOverflow: function(){
        var divElement = this.GetListBoxScrollDivElement();
        divElement.style.overflow = "hidden";
    },
    PreventScrollSpoilDDShowing: function(){
        if(this.IsScrollSpoilDDShowing())
            this.DisableLBDivOverflow();
    },
    ChangeReadOnlyAttribute: function(element, enabled){
        if(!this.isDropDownListStyle || this.isFilterEnabled)
            ASPxClientTextEdit.prototype.ChangeReadOnlyAttribute.call(this, element, enabled);
    },
    // Filtering
    IsInputValueChangingEventKeyCode: function(evt){
        var keyCode = _aspxGetKeyCode(evt);
        var isSystemKey = ASPxKeyConsts.KEY_WINDOWS <= keyCode && keyCode <= ASPxKeyConsts.KEY_CONTEXT_MENU;
        var isFKey = ASPxKeyConsts.KEY_F1 <= keyCode && keyCode <= 127; // 127 - F16 for MAC
        return ASPxKeyConsts.KEY_DELETE <= keyCode && !isSystemKey && !isFKey || keyCode == ASPxKeyConsts.KEY_BACK || keyCode == ASPxKeyConsts.KEY_SPACE;
    },
    OnFilteringKeyUp: function(evt){
        if(!this.isFilterEnabled || this.InCallback()) return;
        
        if(this.IsInputValueChangingEventKeyCode(evt)){
            this.FilterStopTimer();
            var input = this.GetInputElement();
            var newFilter = input.value.toLowerCase();
            if(evt.keyCode == ASPxKeyConsts.KEY_BACK && _aspxHasInputSelection(input) && newFilter == this.filter)
                this.FilteringBackspace();
            else 
                this.FilterStartTimer();
        }
    },
    IsFilterTimerActive: function(){
        return (this.filterTimerId != -1);
    },
    FilterStartTimer: function(){
        this.isEnterLocked = true;
        this.filterTimerId = _aspxSetTimeout("aspxCBFilterByTimer('" + this.name + "')", this.filterTimer);
    },
    FilterStopTimer: function(){
        this.filterTimerId = _aspxClearTimer(this.filterTimerId);
    },
    EnshureShowDropDownArea: function(){
        if(!this.droppedDown)
            this.ShowDropDownArea(true);
    },
    Filtering: function(){
        this.FilterStopTimer();
        this.isPostponedFiltration = false;
    
        var input = this.GetInputElement();
        var newFilter = input.value.toLowerCase();
        if(this.filter != newFilter){
            this.filter = newFilter;
            this.EnshureShowDropDownArea();
            
            if(this.isCallbackMode)
                this.FilteringOnServer();
            else
                this.FilteringOnClient(input); 
        } else 
            this.isEnterLocked = false;
    },
    FilteringBackspace: function(){
        if(this.isFilterEnabled){
            var input = this.GetInputElement();
            input.value = input.value.slice(0, -1);
            this.FilterStartTimer();
        } 
    },
    GetCallbackArguments: function(){
        var args = ASPxClientComboBoxBase.prototype.GetCallbackArguments.call(this);
        if(this.isCallbackMode)
            args += this.GetCallbackArgumentsInternal();
        return args;
    },
    GetCallbackArgumentsInternal: function(){
        var args = "";
        if(this.filter != "")
            args = this.GetCallbackArgumentFilter(this.filter);
        return args;
    },
    GetCallbackArgumentFilter: function(value){
        var callbackPrefix = this.isDropDownListStyle ? __aspxCorrectFilterCallbackPrefix : __aspxLoadFilteredItemsCallbackPrefix;
        return this.FormatCallbackArg(callbackPrefix, value);
    },
    FilteringOnServer: function(){
        if(!this.InCallback()){
            var listBox = this.GetListBoxControl();
            
            listBox.ClearItems(); // TODO Extract method in 8.x with ListBoxAPI
            listBox.serverIndexOfFirstItem = 0;
            listBox.SetScrollSpacerVisibility(true, false);
            listBox.SetScrollSpacerVisibility(false, false);
            
            this.SendCallback();
        }
    },
    FilteringOnClient: function(input){
        var filter = this.filter.toLowerCase();
        var lb = this.GetListBoxControl();
        var listTable = lb.GetListTable();
        var count = lb.GetItemCount();
        var text = "";
        var isSatisfy = false;
        var isFirstSatisfyItemFinded = false;
        
        if(this.isDropDownListStyle){
            var coincide = new Array(count);
            var maxCoincide = 0;
            for(var i = count - 1; i >= 0; i--) {
                coincide[i] = this.GetCoincideCharCount(lb.GetItem(i).text.toLowerCase(), filter);
                if(coincide[i] > maxCoincide)
                    maxCoincide = coincide[i];
            }
            filter = filter.substr(0, maxCoincide);
            this.GetInputElement().value = filter;
        }
        for(var i = 0; i < count; i ++){
            text = lb.GetItem(i).text; //TODO create able to get server-cached text
            isSatisfy = this.isDropDownListStyle ? (coincide[i] == maxCoincide) : 
                (text.toLowerCase().indexOf(filter) == 0);
            _aspxSetElementDisplay(listTable.rows[i], isSatisfy);
            if(!isFirstSatisfyItemFinded && isSatisfy){
                var isTextClearing = !this.isDropDownListStyle && this.filter == "" && this.filter != text;
                if(!isTextClearing)
                    this.FilteringHighlightComplitedText(text);
                this.SelectIndexSilent(lb, isTextClearing ? -1 : i);
                isFirstSatisfyItemFinded = true;
            }
        }
        if(this.isDropDownListStyle)
            this.filter = filter;
        if(!isFirstSatisfyItemFinded)
            this.HideDropDownArea(true);
        this.isEnterLocked = false;
    },
    GetCoincideCharCount: function(text, filter) {
        while(filter != "" && text.indexOf(filter) != 0) {
            filter = filter.slice(0, -1);
        }
        return filter.length;
    },
    FilteringHighlightComplitedText: function(filterItemText){
        var lb = this.GetListBoxControl();
        var input = this.GetInputElement();
        var text = input.value;
        var valueLenght = text.length;
        var itemTextLenght = filterItemText.length;
        
        input.value = filterItemText;
        if(valueLenght < itemTextLenght)
            _aspxSetInputSelection(input, valueLenght, itemTextLenght);
    },
    FilteringStop: function(){
        if(this.isFilterEnabled){
            this.isEnterLocked = false;
            if(!this.isCallbackMode)
                this.FilteringStopClient();
        }
    },
    FilteringStopClient: function(){
        var lb = this.GetListBoxControl();
        var listTable = lb.GetListTable();
        var count = lb.GetItemCount();
        for(var i = 0; i < count; i ++)
            _aspxSetElementDisplay(listTable.rows[i], true);
    },
    // LoadingPanel
    ShowLoadingPanel: function() {    
        var lb = this.GetListBoxControl();
        var loadingParentElement = lb.GetScrollDivElement().parentNode;
        if(!_aspxIsExists(this.loadingDivElement))
            this.CreateLoadingDiv(loadingParentElement);
        if(!_aspxIsExists(this.loadingPanelElement))
            this.CreateLoadingPanelWithAbsolutePosition(loadingParentElement, loadingParentElement);
    },
    HideLoadingPanelOnCallback: function(){
        return false;
    },
    // CallbackMode
    FormatCallbackArg: function(prefix, arg) {
        return (_aspxIsExists(arg) ? prefix + "|" + arg.length + ';' + arg + ';' : "");
    },
    OnCallback: function(result) {
        if(this.IsFilteringCallback() && this.IsCallbackResultContradictsCurrentFilter()) {
            this.preventEndCallbackRising = true;
            _aspxSetTimeout("aspxCBFilterByTimer('" + this.name + "')", 0);
        } else {
            this.OnCallbackBeforeListBox();
            this.GetListBoxControl().OnCallback(result);
            this.OnCallbackInternal(result);
            this.OnCallbackFinally(true);
        }
    },
    IsFilteringCallback: function(){
        return this.filter != "";
    },
    IsCallbackResultContradictsCurrentFilter: function(){
        var input = this.GetInputElement();
        return this.filter != input.value.toLowerCase();
    },
    DoEndCallback: function(){
        if(this.preventEndCallbackRising)
            this.preventEndCallbackRising = false;
        else
            ASPxClientDropDownEdit.prototype.DoEndCallback.call(this);
    },
    OnCallbackError: function(result, data){
        this.GetListBoxControl().OnCallbackError(result);
        this.OnCallbackFinally(false);
    },
    OnCallbackFinally: function(isSuccessful){
        this.CollectionChanged();
        this.HideLoadingDiv();
        this.HideLoadingPanel();
        this.isPerformCallback = false;
        this.changeSelectAfterCallback = 0;
        if(isSuccessful){
            if(this.isApplyAndCloseAfterCallback){
                this.OnApplyChangesAndCloseWithEvents();
                this.isApplyAndCloseAfterCallback = false;
            }
        }
    },
    OnCallbackBeforeListBox: function(){
        var lb = this.GetListBoxControl();
        this.changeSelectAfterCallback = lb.changeSelectAfterCallback;
    },
    OnCallbackCorrectSelectedIndex: function(){
        var lb = this.GetListBoxControl();
        if(this.changeSelectAfterCallback != 0)
            this.SetTextInternal(lb.GetSelectedItem().text);
    },
    OnCallbackInternal: function(result){
        this.OnCallbackCorrectSelectedIndex();
        this.OnFilterCallback(result);
    },
    OnFilterCallback: function(result){
        var lb = this.GetListBoxControl();
        if(lb.GetItemCount() == 0)
            this.HideDropDownArea(true);
        else 
            this.OnFilterCallbackWithResult(lb);        
        this.isEnterLocked = false;
    },
    OnFilterCallbackWithResult: function(lb){
        this.OnFilterCallbackHighlightAndSelect(lb);
        var isNeedToKeepDropDownVisible = !this.isPerformCallback && !this.isLastFilteredKeyWasTab;
        if(isNeedToKeepDropDownVisible)
            this.EnshureShowDropDownArea();
    },
    OnFilterCallbackHighlightAndSelect: function(lb){
        var firstItemText = lb.GetItem(0).text;
        var isTextClearing = !this.isDropDownListStyle && this.filter == "" && this.filter != firstItemText;
        if(!isTextClearing){
            var isFilterRollBack = this.CheckForFilterRollback(lb, firstItemText);
            var isNonFilterChangingCallback = (lb.GetSelectedItem() == null);
            if(isFilterRollBack || isNonFilterChangingCallback){
                if(this.isLastFilteredKeyWasTab){
                    this.isLastFilteredKeyWasTab = false;
                    this.SelectIndex(0);
                    this.OnChange(); // B94483
                } else  {
                    this.FilteringHighlightComplitedText(firstItemText);
                    if(this.isPerformCallback )
                    this.SelectIndex(0); // this.isPerformCallback - Q96137, B30516 
                else
                    this.SelectIndexSilent(lb, 0);
            }
        }
        }
    },
    CheckForFilterRollback: function(lb, firstItemText){
        var isHasCorrection = false;
        var filter = this.filter.toLowerCase();
        firstItemText = firstItemText.toLowerCase();
        
        while(firstItemText.substring(0, filter.length).toLowerCase() != filter){
            filter = filter.slice(0, -1);
            isHasCorrection = true;
        }
        if(isHasCorrection){
            this.filter = this.filter.substring(0, filter.length);
            this.GetInputElement().value = this.filter;
        } 
        return isHasCorrection;
    },
    SendCallback: function(){
        this.ShowLoadingPanel();
        ASPxClientComboBoxBase.prototype.SendCallback.call(this);
    },
    
    // Key Board support
    SelectNeighbour: function (step){
        if(this.isToolBarItem && !this.droppedDown) return;
        
        var lb = this.GetListBoxControl();
        var step = this.GetStepForClientFiltrationEnabled(lb, step);
        this.SelectNeighbourInternal(lb, step);
    },
    SelectNeighbourInternal: function(lb, step){
        if(this.droppedDown)
            this.lbEventLockCount ++;
        
        lb.SelectNeighbour(step);
        
        if(this.droppedDown){
            this.SetTextInternal(lb.GetSelectedItem().text);
            this.lbEventLockCount --;
        } 
    },
    GetStepForClientFiltrationEnabled: function(lb, step){
        var isClientFiltrationEnabled = this.isFilterEnabled && !this.isCallbackMode;
        if(isClientFiltrationEnabled){
            var stepDirection = step > 0 ? 1 : -1;
            var startIndex = this.GetSelectedIndex();
            var count = lb.GetItemCount();
            var listTable = lb.GetListTable();
            var needVisibleItemCount = Math.abs(step);
            var outermostVisibleIndex = startIndex;
            
            for(var index = startIndex + stepDirection; needVisibleItemCount > 0; index += stepDirection){
                if(index < 0 || count <= index) break;
                
                if(_aspxGetElementDisplay(listTable.rows[index])){
                    outermostVisibleIndex = index;
                    needVisibleItemCount --;
                }
            }
            step = outermostVisibleIndex - this.GetSelectedIndex();
        }
        return step;
    },
    
    OnSpecialKeyDown: function(evt){
        if(this.isFilterEnabled && this.IsInputValueChangingEventKeyCode(evt)) {
            this.FilterStopTimer();
            this.isPostponedFiltration = true; 
        }

        return ASPxClientEdit.prototype.OnSpecialKeyDown.call(this, evt);
    },
    OnArrowUp: function(evt){
        var isProcessed = ASPxClientDropDownEdit.prototype.OnArrowUp.call(this, evt);
        if (!isProcessed)
            this.SelectNeighbour(-1);
        return true;
    },
    OnArrowDown: function(evt){
        var isProcessed = ASPxClientDropDownEdit.prototype.OnArrowDown.call(this, evt);
        if (!isProcessed)
            this.SelectNeighbour(1);
        return true;
    },
    OnPageUp: function(){
        return this.OnPageButtonDown(false);
    },
    OnPageDown: function(){
        return this.OnPageButtonDown(true);
    },
    OnPageButtonDown: function(isDown){
        var lb = this.GetListBoxControl();
        if(_aspxIsExists(lb)){
            var direction = isDown ? 1 : -1;
            this.SelectNeighbour(lb.scrollPageSize * direction);
        }
        return true;
    },
    OnHomeKeyDown: function(evt){
        return this.OnHomeEndKeyDown(evt, true);
    },
    OnEndKeyDown: function(evt){
        return this.OnHomeEndKeyDown(evt, false);
    },
    OnHomeEndKeyDown: function(evt, isHome){
        var input = this.GetValueInput();
        if(input.readOnly || evt.ctrlKey){
            var lb = this.GetListBoxControl();
            var count = lb.GetItemCount();
            this.SelectNeighbour(isHome ? -count : count);
            return true;
        }
        return false;
    },
    OnEnter: function(){
        this.enterProcessed = this.droppedDown; // hack for defaultbutton
        if(!this.isEnterLocked) //Prevent to extra fast push enter while filtering continue
            this.OnApplyChangesAndCloseWithEvents();
        return this.enterProcessed;
    },
    OnTab: function(evt){
        if(this.IsFilterTimerActive() || this.isPostponedFiltration){
            this.isLastFilteredKeyWasTab = true;
            // B91550 Tab sends KeyDown without KeyUp
            this.Filtering(); 
        }
        
        if(this.InCallback())
            this.isApplyAndCloseAfterCallback = true;
        else
            this.OnApplyChangesAndCloseWithEvents();
    },

    OnApplyChanges: function(){
        if(this.isDropDownListStyle && !this.isFilterEnabled) return;
        this.OnApplyChangesInternal();
    },
    OnApplyChangesAndCloseWithEvents: function(){
        this.OnApplyChangesInternal();
        this.HideDropDownArea(true);
    },
    OnApplyChangesInternal: function(){
        this.filter = "";
        var text = this.GetInputElement().value;
        var isChanged = this.lastSuccessText != text;
        if(isChanged){
            var lb = this.GetListBoxControl();
            if(this.isDropDownListStyle && this.FindItemIndexByText(lb, text) < 0){
                var lbItem = lb.GetSelectedItem();
                text = lbItem != null ? lbItem.text : this.lastSuccessText;
            }
        } 
        this.SetText(text);
        if(isChanged)
            this.OnChange();
    },
    OnButtonClick: function(number){
        if(number != this.dropDownButtonIndex){
            this.HideDropDownArea(true);
        }
        ASPxClientButtonEditBase.prototype.OnButtonClick.call(this, number);
    },
    OnCancelChanges: function(){
        var isCancelProcessed = ASPxClientDropDownEdit.prototype.OnCancelChanges.call(this);
        this.filter = "";
        var lb = this.GetListBoxControl();
        var index = this.FindItemIndexByText(lb, this.lastSuccessText);
        this.SelectIndexSilent(lb, index);
        return isCancelProcessed;
    },
    OnCloseUp: function(evt){
        var evt = _aspxGetEvent(evt);
        var scrollDiv = this.GetListBoxControl().GetScrollDivElement();
        var scrollDivID = _aspxIsExists(scrollDiv) ? scrollDiv.id : "";
        if(__aspxFirefox && evt.type == "mouseup" && 
            (_aspxGetEventSource(evt).tagName == "DIV" && scrollDivID == _aspxGetEventSource(evt).id)) // Prevent FF closing DropDownArea by DropDownArea ScrollBar MouseUp
            return;
        ASPxClientDropDownEdit.prototype.OnCloseUp.call(this, evt);
    },
    OnDDButtonMouseMove: function(evt){
        return (this.droppedDown ? _aspxCancelBubble(evt) : true);
    },
    OnDocumentMouseDown: function(){
        this.OnApplyChangesInternal();
        ASPxClientDropDownEdit.prototype.OnDocumentMouseDown.call(this);
    },
    IsCanToDropDown: function(){
        return (this.GetListBoxControl().GetItemCount() > 0);
    },
    OnPopupControlShown: function(){
        if(this.IsScrollSpoilDDShowing())
            _aspxSetTimeout("aspxCBMozillaOverflowOn(\"" + this.name + "\")", 100);
        if(this.lockListBoxClick)
            delete this.lockListBoxClick;
    },
    OnItemClick: function(){
        if(!this.lockListBoxClick) {
            this.OnSelectChanged();
            this.OnClick();
        }
    },
    OnListBoxClick: function(evt){
        if(!this.lockListBoxClick && !this.InCallback() && _aspxGetIsLeftButtonPressed(evt)){
            this.OnApplyChangesInternal();
            this.OnCloseUp(evt);
        }
    },
    OnMouseWheel: function(evt){
        if(!this.droppedDown){
            var wheelDelta = _aspxGetWheelDelta(evt);
            if(wheelDelta > 0)
			    this.SelectNeighbour(-1);
		    else  if(wheelDelta < 0)
			    this.SelectNeighbour(1);
			return _aspxPreventEvent(evt);
		}
    },
    OnFocus: function(){
        this.OnSetFocus(true);
        ASPxClientDropDownEdit.prototype.OnFocus.call(this);
    },
    OnLostFocus: function(){
        this.OnSetFocus(false);
        ASPxClientDropDownEdit.prototype.OnLostFocus.call(this);
    },
    OnSetFocus: function(isFocused){
        if(isFocused && this.isFilterEnabled && !this.isToolbarItem)
            this.SelectInputText();
        aspxGetDropDownCollection().SetFocusedDropDownName(isFocused ? this.name : "");
    },
    OnOpenAnotherDropDown: function(){
        this.OnApplyChangesAndCloseWithEvents();
    },
    OnClick: function(){
        if(!this.isToolbarItem)
            ASPxClientDropDownEdit.prototype.OnClick.call(this);
    },    

    ParseValue: function() {
        var newText = ASPxClientButtonEditBase.prototype.GetValue.call(this);
        var oldText = this.GetText();
        if(oldText != newText){
            this.SetText(newText);
            this.OnChange();
        }
    },

    MakeItemVisible: function(index){
        var lb = this.GetListBoxControl();
        lb.MakeItemVisible(index);
    },
    PerformCallback: function(arg) {
        this.isPerformCallback = true;
        this.filter = "";
        this.ClearItemsInternal();
        this.GetListBoxControl().PerformCallback(arg);
    },

    ClearItemsInternal: function(){
        ASPxClientComboBoxBase.prototype.ClearItemsInternal.call(this);
        var lbScrollDiv = this.GetListBoxScrollDivElement();
        if(_aspxIsExists(lbScrollDiv))
            lbScrollDiv.scrollTop = "0px";
    }
});

ASPxClientNativeComboBox = _aspxCreateClass(ASPxClientComboBoxBase, {
    constructor: function(name) {
        this.constructor.prototype.constructor.call(this, name);
        
        this.initSelectedIndex = -1;
        this.raiseValueChangedOnEnter = false;
    },
    Initialize: function(){
        var lb = this.GetListBoxControl();
        if(lb != null) lb.SetMainElement(this.GetMainElement());
        
        ASPxClientComboBoxBase.prototype.Initialize.call(this);
    },
    InitLastSuccessText: function(){
        this.SelectIndex(this.initSelectedIndex, true);
    },
    FindInputElement: function(){
        return this.GetMainElement();
    },    
    GetDropDownInnerControlName: function(suffix){
        return this.name + suffix;
    },
    PerformCallback: function(arg) {
        this.GetListBoxControl().PerformCallback(arg);
    },
    SetText: function (text){
        var lb = this.GetListBoxControl();
        var index = this.FindItemIndexByText(lb, text);
        this.SelectIndex(index, false);
        this.lastSuccessText = (index > -1) ? text : "";
        this.lastSuccessValue = (index > -1) ? lb.GetValue() : null;
        this.islastSuccessValueInit = true;
    },
    GetValue: function(){
        var selectedItem = this.GetSelectedItem();
        return (selectedItem != null) ? selectedItem.value : null;
    },
    SetValue: function(value){
        var lb = this.GetListBoxControl();
        lb.SetValue(value);
        // TODO Extract method with OnSelectChanged (params: value)
        var item = lb.GetSelectedItem();
        var text = _aspxIsExists(item) ? item.text : value;
        this.lastSuccessText = (item != null) ? text : "";
        this.lastSuccessValue = (item != null) ? item.value : null;
        this.islastSuccessValueInit = true;
    },
    OnCallback: function(result) {
        this.GetListBoxControl().OnCallback(result);
        if(this.GetItemCount() > 0)
            this.SetSelectedIndex(0);
    },
    OnTextChanged: function() {
        this.OnChange();
    },
    SetTextInternal: function(text){
    },
    ChangeEnabledAttributes: function(enabled){
        this.GetMainElement().disabled = !enabled;
    }
});

// DropDown
var __aspxDropDownCollection = null;
function aspxGetDropDownCollection(){
    if(__aspxDropDownCollection == null)
        __aspxDropDownCollection  = new ASPxClientDropDownCollection();
    return __aspxDropDownCollection;
}

_aspxAttachEventToDocument("mousedown", aspxDropDownDocumentMouseDown);
function aspxDropDownDocumentMouseDown(evt){
    return aspxGetDropDownCollection().OnDocumentMouseDown(evt);
}
_aspxAttachEventToDocument("mouseup", aspxDropDownDocumentMouseUp);
function aspxDropDownDocumentMouseUp(evt){
    return aspxGetDropDownCollection().OnDocumentMouseUp(evt);
}
_aspxAttachEventToElement(window, "resize", aspxCBWindowResize);
function aspxCBWindowResize(evt){
    aspxGetDropDownCollection().OnResize(evt);	
}

function aspxDDDropDown(name, evt){
    if(_aspxGetIsLeftButtonPressed(evt)){
        var dd = aspxGetControlCollection().Get(name);
        if(_aspxIsExists(dd))
            return dd.OnDropDown(evt);
    }
}
function aspxDDCloseUp(name, evt){
    var dd = aspxGetControlCollection().Get(name);
    dd.OnCloseUp(evt);
}

function aspxEdDECMainElementClick(name) {
    var dateEdit = aspxGetControlCollection().Get(name);
    if(dateEdit)
        dateEdit.OnCalendarMainElementClick();
}

// DropDownEdit
function aspxDDMainElementClick(name, evt){
    var dd = aspxGetControlCollection().Get(name);
    if(dd != null) dd.OnClick();
}
// ComboBox
function aspxCBPCShown(name, evt){
    var cb = aspxGetControlCollection().Get(name);
    if(cb != null) cb.OnPopupControlShown();
}
function aspxCBIClick(name, evt){
    var cb = aspxGetControlCollection().Get(name);
    if(cb != null) cb.OnItemClick();
}
function aspxCBLBClick(name, evt){
    var cb = aspxGetControlCollection().Get(name);
    if(cb != null) cb.OnListBoxClick(evt);
}
function aspxCBMozillaOverflowOn(name){
    var cb = aspxGetControlCollection().Get(name);
    cb.EnableLBDivOverflow();
}
function aspxCBDDButtonMMove(evt){
    return aspxGetDropDownCollection().OnDDButtonMouseMove(evt);
}
function aspxCBMouseWheel(evt){
    var cb = aspxGetDropDownCollection().GetFocusedDropDown();
    if (cb != null) 
        return cb.OnMouseWheel(evt);
}

function aspxCBKeyUp(evt){
    var cb = aspxGetDropDownCollection().GetFocusedDropDown();
    if (cb != null) 
        cb.OnFilteringKeyUp(evt);
}
function aspxCBFilterByTimer(name){
    var cb = aspxGetControlCollection().Get(name);
    if(cb != null) cb.Filtering();
}