﻿Type.registerNamespace('Infragistics.Web.UI');

$IG.WebDropDown = function(element)
{
    /// <summary>
    /// the WebDropDown is an AJAX-enabled control ASP.NET consisting of an input box and a dropdown list of items
    /// its main functionalities include auto-complete/suggest, selection, value editing, binding to many
    /// data sources out of the box, templating, and a rich client-side and server-side API
    /// </summary>
    $IG.WebDropDown.initializeBase(this, [element]);
}

$IG.WebDropDown.prototype =
{

    _thisType: 'dropDown',
    
    /******OVERRIDES**********/
    initialize: function() {

        $IG.WebDropDown.callBaseMethod(this, 'initialize');

        //A.T. 08/07/2009 Fix for bug 19154
        // strip whitespace nodes, Firefox is really annoying because it considers these as real nodes
        var list = this._elements["List"];
        if (list && !$util.IsIE)
        {
            var initialCount = list.childNodes.length;
            var currentCount=0;
            
            while (list.childNodes[0] && currentCount <= initialCount) {
                if (list.childNodes[0].nodeType != 1)
                {
                    list.removeChild(list.childNodes[0]);
                }
                currentCount++;
            }
        }

        // we use the shared DropDown behavior for the dropdown control as well
        this.behavior = new $IG.DropDownBehavior(this._elements["Target"], this.get_dropDownIsChild());
        this.behavior.set_targetContainer(this._elements["DropDown"]);
        
       // this.resizeBehavior = new $IG.ResizeBehavior(this._elements["DropDown"]);
        
        this.behavior.set_position(this.get_dropDownOrientation());
        if (this.get_dropDownOrientation() != $IG.DropDownPopupPosition.Default) {
            this.behavior.set_enableAutomaticPositioning(false);
        }

        this.behavior.set_enableAnimations(this.get_enableAnimations());
        this.behavior.set_animationDurationMs(this.get_dropDownAnimationDuration());
        this.behavior.set_animationType(this.get_dropDownAnimationType());

        // set offsetX and offsetY if any
        if (this.get_offsetX() != 0)
        {
            this.behavior.set_offsetX(this.get_offsetX());
        }
        
        if (this.get_offsetY() != 0)
        {
            this.behavior.set_offsetY(this.get_offsetY());
        }
        // set dropdown container height
        // if (this.get_dropDownContainerHeight() && parseInt(this.get_dropDownContainerHeight()) > 0)
        // {
        //     var height =  parseInt(this.get_dropDownContainerHeight());
        //     $util.setAbsoluteHeight(this._elements["DropDown"], height);
        // }
        
        // this is used in case the EditorID property is set on the server-side control, and we want to use
        // out of the box Infragistics editors such as mask editors, percentage editors, etc
        // in that case we just set the reference of the editor to be our target and it is positioned correctly once the
        // dropdown behavior is initialized
        // we assume all editors we want to link to, are presented by HTML INPUT components
        if (this.get_editorID() !=null)
        {
            
            var editor = $get(this.get_editorID());
            if (editor!=null && editor.nodeName=="INPUT")
            {
               editor.className = this._elements["Input"].className;
                this._elements["Input"].parentNode.replaceChild(editor, this._elements["Input"]);
              //  this._elements["Input"].parentNode.appendChild(editor);
                this._elements["Input"] = editor; 
                
                var inputCustomDelegate = Function.createDelegate(this, this._onKeyupHandler);
                $addHandler(this._elements["Input"], 'keyup', inputCustomDelegate);
            }
            
            
        }
        
        // client cache can be configured and means that once we do a auto-suggest postback to fetch results, they are 
        // cached on the client, so if the user subsequently types the same string, we don't go to the server again
        this._clientCache = [];
        //this._activeItem = this.get_activeItemIndex() == -1 ? null : this.get_items()._getObjectByIndex(this.get_activeItemIndex());
        this._activeItem = this.get_activeItemIndex() == -1 ? null : this.get_items().getItem(this.get_activeItemIndex());

        // attach the delegate for selection
        var dropDownList = this._elements["List"];
        var selectDelegate = Function.createDelegate(this, this._select);
        $addHandler(dropDownList, 'mousedown', selectDelegate);

        var blurDelegate = Function.createDelegate(this, this._onBlurHandler);
        $addHandler(this._elements["Input"], 'blur', blurDelegate);

        var focusDelegate = Function.createDelegate(this, this._onFocusHandler);
        $addHandler(this._elements["Input"], 'focus', focusDelegate);
        
        var inputMouseOutDelegate = Function.createDelegate(this, this._onInputMouseOutHandler);
        $addHandler(this._elements["Input"], 'mouseout', inputMouseOutDelegate);
        
        var inputMouseOverDelegate = Function.createDelegate(this, this._onInputMouseOverHandler);
        $addHandler(this._elements["Input"], 'mouseover', inputMouseOverDelegate);

        var mouseOver = Function.createDelegate(this, this._mouseOverForBlur);
        $addHandler(this._elements["DropDown"], 'mouseover', mouseOver);
        
        var pasteHandler = Function.createDelegate(this, this._onPasteHandler);
        $addHandler(this._elements["Input"], 'paste', pasteHandler);
        
        var cutHandler = Function.createDelegate(this, this._onCutHandler);
        $addHandler(this._elements["Input"], 'cut', cutHandler);
        
        var changeHandler = Function.createDelegate(this, this._onChangeHandler);
        $addHandler(this._elements["Input"], 'change', changeHandler);
        
        // we have an option to show / hide the button next to the input box
        // if it is hidden we shouldn't attach any event handlers
        if (this.get_showDropDownButton())
        {
            $addHandler(this._elements["Button"], 'mouseover', mouseOver);
            $addHandler(this._elements["ButtonImage"], 'mouseover', mouseOver);
        }

        var mouseOut = Function.createDelegate(this, this._mouseOutForBlur);
        $addHandler(this._elements["DropDown"], 'mouseout', mouseOut);
        
        
        if (this.get_showDropDownButton())
        {
            $addHandler(this._elements["Button"], 'mouseout', mouseOut);
            $addHandler(this._elements["ButtonImage"], 'mouseout', mouseOut);
        }

        // we listen to browser scroll events for the LoadOnDemand feature - we check if the
        // current scrollTop value has reached a certain treshold (i.e. if the scrollbar is at the end of the container
        // and then invoke the load on demand postback
        if (this.get_enableLoadOnDemand()) {
            var loadOnDemandDelegate = Function.createDelegate(this, this._scrollingLoadOnDemand);
            $addHandler(this._elements["DropDownContents"], 'scroll', loadOnDemandDelegate);
        }// else
        //{
			/* // A.T. 6th of Feb. Fix for bug #27110 - You are not able to scroll when "Compatibility mode" or "IE 7 mode" are  enabled.
			 * // we have to remove this logic, because it creates various issues on some browsers 
             * // A.T. 16/06/2009: Fix for bug 18256
             * var genericScrollDelegate = Function.createDelegate(this, this._genericScrollHandler);
             * $addHandler(this._elements["DropDownContents"], 'scroll', genericScrollDelegate);
             */
             // catch blur on the list
             var listBlurDelegate = Function.createDelegate(this, this._listBlurHandler);
             $addHandler(this._elements["DropDownContents"], 'blur', listBlurDelegate);
        //}

        // pager event
        if (this.get_enablePaging()) {
            //var pagerDelegate = Function.createDelegate(this, this._onPagerMoreResults);
            //$addHandler(this._elements["PagerLink"], 'mousedown', pagerDelegate);

            if (this.get_pagerMode() == $IG.DropDownPagerMode.NextPrevious)
            {
                var pagerPrevDelegate = Function.createDelegate(this, this._onPagerPrevResults);
                $addHandler(this._elements["PagerPrevLink"], 'mousedown', pagerPrevDelegate);

                var pagerNextDelegate = Function.createDelegate(this, this._onPagerNextResults);
                $addHandler(this._elements["PagerNextLink"], 'mousedown', pagerNextDelegate);
                
            } else if(this.get_pagerMode() == $IG.DropDownPagerMode.Numeric || this.get_pagerMode() == $IG.DropDownPagerMode.NumericFirstLast)
            {
                var numberDelegate = Function.createDelegate(this, this._onPagerNumberResults);
               // for (var i=0; i<this.get_pageCount(); i++)
               // {
               //     $addHandler(this._elements["PagerNumberLink"], 'mousedown', numberDelegate);
               // }
               // attach the handler on the pager itself
               $addHandler(this._elements["Pager"], 'mousedown', numberDelegate);
               
               // check if we have quick pages
               if (this._elements["PagerQPPrevLink"])
               {
                    var pagerPrevDelegate = Function.createDelegate(this, this._onPagerPrevResults);
                    $addHandler(this._elements["PagerQPPrevLink"], 'mousedown', pagerPrevDelegate);
               }
               
               if (this._elements["PagerQPNextLink"])
               {
                    var pagerNextDelegate = Function.createDelegate(this, this._onPagerNextResults);
                    $addHandler(this._elements["PagerQPNextLink"], 'mousedown', pagerNextDelegate);
               }
               
            } else if (this.get_pagerMode() == $IG.DropDownPagerMode.NextPreviousFirstLast)
            {
                var pagerPrevDelegate = Function.createDelegate(this, this._onPagerPrevResults);
                $addHandler(this._elements["PagerPrevLink"], 'mousedown', pagerPrevDelegate);

                var pagerNextDelegate = Function.createDelegate(this, this._onPagerNextResults);
                $addHandler(this._elements["PagerNextLink"], 'mousedown', pagerNextDelegate);
                
                var pagerFirstDelegate = Function.createDelegate(this, this._onPagerFirstResults);
                $addHandler(this._elements["PagerFirstLink"], 'mousedown', pagerFirstDelegate);

                var pagerLastDelegate = Function.createDelegate(this, this._onPagerLastResults);
                $addHandler(this._elements["PagerLastLink"], 'mousedown', pagerLastDelegate);
            }
        }
        
        // we need to detach the span element displaying the loading message and display it on top of the 
        // list, so that it doesn't take any space for the items, and we don't have unwanted visual effects
        // i mean the list popping up and down to accomodate the loading message element
        if (this.get_loadingItemsMessageText()!=null)
        {
            this.__detachLoadingItemsMessage();
        }

        // attach the delegate for keyboard navigation
        var navDelegate = Function.createDelegate(this, this._navigateItems);
        $addHandler(dropDownList, 'keydown', navDelegate);

        var mouseOverDelegate = Function.createDelegate(this, this._onMouseoverListHandler);
        $addHandler(dropDownList, 'mouseover', mouseOverDelegate);
        
        var mouseOutDelegate = Function.createDelegate(this, this._onMouseoutListHandler);
        $addHandler(dropDownList, 'mouseout', mouseOutDelegate);
        
        // behavior.init();
        // var valueDisplay = this._elements["Input"];
        // $addHandler(valueDisplay, "keydown", Function.createDelegate(this, this._onInputKeyDownHandler) );

        this.behavior._setAnimationEndListener(this);

        // initialize the dropdown behavior
        this.behavior.init();
        
        if (this.get_valueListMaxHeight() > 0)
        {
            this.behavior.set_containerMaxHeight(this.get_valueListMaxHeight(), this._elements["List"], this._elements["DropDownContents"]);
        }
        
        if (this.get_enableDropDownContainerAutoWidth())
        {
            var height = this.get_valueListMaxHeight() > 0 ? this.get_valueListMaxHeight() : this.get_dropDownContainerHeight();
            this.behavior.set_containerAutoWidth(this._elements["List"], this._elements["DropDown"], height);
        }

        // restore value
        //A.T. 18/11/2009 Fix for bug #24952
        if (this.get_currentValue() != null && this.get_currentValue != undefined)
        { 
            this._elements["Input"].value = this.get_currentValue();
        }
        
        this.set_hoverItemIndex(-1);
        //this._elements["Input"].focus();

        // manage max drop down height property
      //  this._adjustMaxHeight();
      
      
        // A.T. 17/08/2009 Support for Ajax Indicator
        if (this._pi !=null)
        {
            this._pi.setRelativeContainer(this._elements["DropDown"]);
        }

        // fire the initialize client-side event
        this._raiseClientEvent('Initialize', 'DropDown', null, null);
        
        this.__blurFlag = true;
        
        this.__clearTextNodesFromUL();
        
        if (this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client)
        {
            this.__clientFilteringItemCount = this.get_items().getLength();
            
            for (i=0;i<this.get_items().getLength();i++)
            {
                // dummy, serves just to create every item, since lazy loading & client side filtering require some special attention
                this.get_items().getItem(i);
            }
        }
                    
        this.__keydowncount=0;
        
         // pre-load button images 
        if (this.get_buttonNormalImageUrl() !=null && this.get_buttonNormalImageUrl()!="")
        {
            var buttonNormalImage= new Image();
            buttonNormalImage.src = this.get_buttonNormalImageUrl();
        }

        if (this.get_buttonHoverImageUrl() !=null && this.get_buttonHoverImageUrl()!="")
        {
            var buttonHoverImage = new Image();
            buttonHoverImage.src = this.get_buttonHoverImageUrl();
        }

        if (this.get_buttonPressedImageUrl() !=null && this.get_buttonPressedImageUrl()!="")
        {
            var buttonPressedImage = new Image();
            buttonPressedImage.src = this.get_buttonPressedImageUrl();
        }
        
        // restore back button state if any
        var backState = this._getBackState(0);
        
        if (backState!=null)
        {
			this.__restoreBackButtonValues(backState);
		}
		
    },
    
    ///
    /// restores the CurrentValue and the SelectedItemIndex, also marks the corresponding item as selected
    /// 
    __restoreBackButtonValues: function(backState)
    {
		var states = backState.split('|');
		
		// states[0] - current value
		if (states[0])
		{
			this.set_currentValue(states[0],true);
		}
		// states[1] - selected item index
		if (states[1])
		{
			this.set_selectedItemIndex(states[1]);
			var item = this.get_items().getItem(states[1]);
			if (item)
			{
				item.select();
			}
		}
    },
    
    __clearTextNodesFromUL: function()
    {
       // clear text nodes: Firefox and other browsers consider text as a node, so the UL.childNodes.length is wrong !
        var initialLength = this._elements["List"].childNodes.length;
        for (i=0;i<initialLength;i++)
        {
            if (this._elements["List"].childNodes[i] && this._elements["List"].childNodes[i].tagName!='LI')
            {
                this._elements["List"].removeChild(this._elements["List"].childNodes[i]);
            }
        } 
    },

    // add global control event handlers 
    _addHandlers: function() {
    
        $IG.WebDropDown.callBaseMethod(this, '_addHandlers');
        this._registerHandlers([ "keydown", "keyup", "mouseup", "mousedown", "keypress", "mouseover", "mouseout"]);
    },

    dispose: function() {
    
        // very important - make sure we don't have any memory leaks 
        $clearHandlers(this.get_element());
        $IG.WebDropDown.callBaseMethod(this, 'dispose');
    },

    // if the ValueListMaxHeight property is set on the server-side control, we need to calculate whether to set explicit height style or not
    _adjustMaxHeight: function() {
    
        // do some hacks in order to circumvent flickering issues 
      //  this._elements["DropDownContents"].style.position = 'absolute';
      //  this._elements["DropDownContents"].style.left = -10000;
      //  this._elements["DropDownContents"].style.top = -10000;
      //  this._elements["DropDownContents"].style.display='';
      //  this._elements["DropDownContents"].style.visibility = 'visible';
        
      //  this._elements["List"].style.display='';
      //  this._elements["List"].style.visibility = 'visible';
        
        if (this.get_valueListMaxHeight() > 0) {
            if (this._elements["List"].offsetHeight > this.get_valueListMaxHeight()) {
                this._elements["DropDownContents"].style.height = this.get_valueListMaxHeight() + 'px';

            } else {

                this._elements["DropDownContents"].style.height = '';
            }
        }
        
      //  this._elements["DropDownContents"].style.position = '';
      //  this._elements["DropDownContents"].style.left = 0;
      //  this._elements["DropDownContents"].style.top =  0;
      //  this._elements["DropDownContents"].style.display='none';
      //  this._elements["DropDownContents"].style.visibility = 'hidden';
        
    },

    // this function allows a developer to programatically populate the dropdown with items, based on certain filtering criteria
    loadItems: function(text) {
        this._setLoadItemsText(text);
        var cbo = this._callbackManager.createCallbackObject();
        cbo.serverContext.type = "itemsRequested";
        this.__manualLoadItems=true;
        this.set_valueBeforeFilter(this.get_currentValue());
        // cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(item._csm.get_transactionList())
        cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(this._clientStateManager.get_transactionList());
        
        if (this._pi) 
        {
            this._pi.set_enabled(false);
        }
        this._callbackManager.execute(cbo, true);
        if (this._pi) 
        {
            this._pi.set_enabled(true);
        }

    },

    // reset cache
    invalidateCache: function() {

        this._clientCache = [];
    },
    
    get_enabled: function() {
        
        return this._get_value($IG.DropDownProps.Enabled);
    },
    
    // A.T. 30/06/2009: Fix for bug # 18703 - adding functions to enable / disable control from client-side
    set_enabled: function(controlEnabled) {
    
        this._set_value($IG.DropDownProps.Enabled, controlEnabled);
        
        if (this._elements["Input"].disabled && !controlEnabled)
        {
            return; // do nothing if control is already disabled and we still want to disable it 
        } else if (!this._elements["Input"].disabled && !controlEnabled)
        {
            this._elements["Input"].disabled = true;
            this._elements["Input"].className = this.get_inputDisabledCssClass();
            this._element.className = this.get_controlDisabledCssClass();
            
        } else if (this._elements["Input"].disabled && controlEnabled)
        {
            this._elements["Input"].disabled = false;
            this._elements["Input"].className = this.get_inputCssClass();
            this._element.className = this.get_controlCssClass();
        }
    },

    // opens the dropdown container and fires the associated events 
    openDropDown: function() {

        if (this.get_displayMode() != $IG.DropDownDisplayMode.ReadOnly) {
        
            if (this.behavior._dropDownAnimation && this.behavior._dropDownAnimation.get_isAnimating() && this.__isButtonClick)
            {
                this.__isButtonClick=false;
                this.behavior._dropDownAnimation.stop();
                this.behavior._dropDownAnimation.onEnd();
                this.closeDropDown();
                return;
            }
            
            var args = this._raiseClientEvent('DropDownOpening', 'DropDownContainer', null, null);
            var cancel = args ? args.get_cancel() : false;
            if (!cancel) {
            
                this.__willDoInternalFocus=true;
                this.behavior.set_visible(true);
                //this._adjustMaxHeight();
                
                if (!this.get_enableAnimations())
                {
                    this._raiseClientEvent('DropDownOpened', 'DropDownContainer', null, null);
                    
                } else 
                {
                    // will be handled in _onAnimationEnd
                    this.__isOpening = true;
                }
            }

        }
    },

    // closes the dropdown container and fires the associated events
    closeDropDown: function() {
    
                
        if (this.behavior._dropDownAnimation && this.behavior._dropDownAnimation.get_isAnimating())
        {
            this.behavior._dropDownAnimation.stop();
            this.behavior._dropDownAnimation.onEnd();
            this.openDropDown();
            return;
        }

        var args = this._raiseClientEvent('DropDownClosing', 'DropDownContainer', null, null);
        var cancel = args ? args.get_cancel() : false;
        if (!cancel) {

            this.behavior.set_visible(false);

            if (!this.get_enableAnimations())
            {
                this._raiseClientEvent('DropDownClosed', 'DropDownContainer', null, null);
                
            } else {
                // will be handled in _onAnimationEnd
                this.__isClosing = true;
            }
        }
    },

    // overriden, called at initialization
    _createItem: function(element, adr) {
        this._itemCollection._addObject($IG.DropDownItem, element, adr);
    },
    
    // returns a reference to the current active item, if any
    get_activeItem: function()
    {
        if (this._activeItem)
        {
            return this._activeItem;
        } 
        else if (this.get_activeItemIndex()!=-1)
        {
            return this.get_items().getItem(this.get_activeItemIndex());
        }
    },
    
    set_activeItem: function(item, cancelEvents)
    {
        var args = null;
        
        if (!cancelEvents) 
        {
            args = this._raiseClientEvent('ActivationChanging', 'DropDownActivation', null, null, item, this._activeItem);
        }

        var cancel = args ? args.get_cancel() : false;
        
        var oldActiveItem=null;
        
        if (!cancel || cancelEvents) {
                            
            if (this._activeItem)
            {
                this._activeItem.inactivate();
                oldActiveItem = this._activeItem;
                
            } else if (this.get_activeItemIndex() != -1)
            {
                // look up active item
               // var currentActiveItem = this.get_items()._getObjectByIndex(this.get_activeItemIndex());
               var currentActiveItem = this.get_items().getItem(this.get_activeItemIndex());
                if (currentActiveItem!=null)
                {
                    currentActiveItem.inactivate();
                    oldActiveItem = currentActiveItem;
                }
            }
            
            item.activate();
            this.set_activeItemIndex(item.get_index());
            this._activeItem = item;
       
            if (!cancelEvents) 
            {
                this._raiseClientEvent('ActivationChanged', 'DropDownActivation', null, null, item, oldActiveItem);
            }
       }
    },

    // this is the text -  filtering criteria , with which the load items postback was initiated (see loadItems)
    _setLoadItemsText: function(text) {
        this._set_value($IG.DropDownProps.LoadItemsText, text);
    },

    // overriden, called by Aikido automatically at initialization
    _setupCollections: function() {
        this._itemCollection = this._collectionsManager.register_collection(0, $IG.DropDownItemCollection);
        this._collectionsManager.registerUIBehaviors(this._itemCollection);
    },

    //_createItem:function(element, adr)
    //{
    //    this._itemCollection._addObject($IG.DropDownItem, element, adr);
    // },


    /*
    createItem:function()
    {
    // what about the templates ? 
    var li = document.createElement("li");
    this._itemCollection._addObject($IG.DropDownItem, element, this.get_items()._items.length);
    },
    */

    get_items: function() {
        /// <summary>
        /// The collection of DropDownItem in the WebDropDown.
        /// </summary>
        return this._itemCollection;
    },

    /// get item based on selectedItemIndex - this should be used only with single item selection
    get_selectedItem: function() {
        if (this.get_selectedItemIndex() < 0)
            return null;
        else
            //return this.get_items()._items[this.get_selectedItemIndex()];
            return this.get_items().getItem(this.get_selectedItemIndex());
    },
    
    __createSelectedItems: function()
    {
        if (this.get_enableMultipleSelection()) {
            var results = [];
            var count = 0;

            for (i = 0; i < this.get_items().getLength(); i++) {
                //if (this.get_items()._items[i].get_selected()) {
                //    results[count] = this.get_items()._items[i];
                if (this.get_items().getItem(i).get_selected()) {
                    results[count] = this.get_items().getItem(i);
                    count++;
                }
            }

            this.__selectedItemsArray = results;

        } else {
            this.__selectedItemsArray = [this.get_selectedItem()];
        }    
    },

    /// get an array of selected items, if multiple selection is enabled
    /// this is done by iterating through all items and checking if the "selected" property is enabled
    get_selectedItems: function() {
    
        
        if (this.get_enableMultipleSelection()) {
            var results = [];
            var count = 0;

            for (i = 0; i < this.get_items().getLength(); i++) {
               // if (this.get_items()._items[i].get_selected()) {
               //     results[count] = this.get_items()._items[i];
               if (this.get_items().getItem(i).get_selected()) {
                    results[count] = this.get_items().getItem(i);
                    count++;
                }
            }
            return results;

        } else {
            return this.get_selectedItem() == null ? [] : [this.get_selectedItem()];
        }
        
        //return this.__selectedItemsArray;
    },

    set_valueBeforeFilter: function(val) {
        this.__valueBeforeFilter = val;
    },

    get_valueBeforeFilter: function() {
        return this.__valueBeforeFilter;
    },

    get_closeDropDownOnSelect: function() {
        ///<summary>
        /// if the dropdown is opened, and we select an item, the dropdown container will be automatically closed
        /// if this property is enabled
        ///</summary>
        return this._get_value($IG.DropDownProps.CloseDropDownOnSelect);
    },

    set_closeDropDownOnSelect: function(closeDropDownOnSelect) {

        return this._set_value($IG.DropDownProps.CloseDropDownOnSelect, closeDropDownOnSelect);
    },

    /// <summary>
    /// the animation duration in milliseconds of the dropdown container 
    /// </summary>
    get_dropDownAnimationDuration: function() {
        return this._get_value($IG.DropDownProps.DropDownAnimationDuration);
    },

    /// <summary>
    /// orientation of the dropdown container relative to its target (input box)
    /// </summary>
    get_dropDownOrientation: function() {
        return this._get_value($IG.DropDownProps.DropDownOrientation);
    },
    
    get_dropDownIsChild: function() {
        return this._get_value($IG.DropDownProps.DropDownIsChild);
    },
    
    
    /// <summary>
    /// enables caching filtering results on the client, for that purpose a hashtable is used where the key is the search string
    /// </summary>
    get_enableCachingOnClient: function() {
    
        return this._get_value($IG.DropDownProps.EnableCachingOnClient);
    },
    
    /// <summary>
    /// enables caching filtering results on the client, for that purpose a hashtable is used where the key is the search string
    /// </summary>
    get_enableCustomValues: function() {
    
        return this._get_value($IG.DropDownProps.EnableCustomValues);
    },
    
    /// <summary>
    /// enables caching filtering results on the client, for that purpose a hashtable is used where the key is the search string
    /// </summary>
    get_enableMarkingMatchedText: function() {
    
        return this._get_value($IG.DropDownProps.EnableMarkingMatchedText);
    },
    
    /// <summary>
    /// auto select on match (when filtering or typing) 
    /// </summary>
    get_autoSelectOnMatch: function() {
    
        return this._get_value($IG.DropDownProps.AutoSelectOnMatch);
    },
    
    get_enableDropDownContainerAutoWidth: function() {
    
        return this._get_value($IG.DropDownProps.EnableDropDownAutoWidth);
    },
    
    /// <summary>
    /// editorID is the client side ID of the editor control, if we have associated any Infragistics built-in editors and want to 
    /// use them in place of the vanilla input box
    /// </summary>
    get_editorID: function() {
    
        return this._get_value($IG.DropDownProps.EditorID);
    },

    /// <summary>
    /// if this property is enabled, when we type text in the dropdown input box, once a match is made, it will be automatically completed 
    /// and the remaining text will be highlighted
    /// </summary>
    get_enableAutoCompleteFirstMatch: function() {
        return this._get_value($IG.DropDownProps.EnableAutoCompleteFirstMatch);
    },

    set_enableAutoCompleteFirstMatch: function(autoComplete) {
        return this._set_value($IG.DropDownProps.EnableAutoCompleteFirstMatch, autoComplete);
    },

    /// <summary>
    /// if the control loses focus, and the dropdown container is opened, it will be automatically closed
    /// </summary>
    get_enableClosingDropDownOnBlur: function() {
        return this._get_value($IG.DropDownProps.EnableClosingDropDownOnBlur);
    },

    set_enableClosingDropDownOnBlur: function(close) {
        return this._set_value($IG.DropDownProps.EnableClosingDropDownOnBlur, close);
    },
    
    /// <summary>
    /// look at the $IG.AnimationEquationType enum, for the list of available enums 
    /// </summary>
    get_dropDownAnimationType: function() {
        return this._get_value($IG.DropDownProps.DropDownAnimationType);
    },
    
    /// <summary>
    /// shows a loading message while the AJAX postback to request more items is executing 
    /// </summary>
    get_loadingItemsMessageText: function() {
        return this._get_value($IG.DropDownProps.LoadingItemsMessageText);
    },

    /// <summary>
    /// display mode can be DropDown (full-blown), DropDownList(dropdown with selection), ReadOnlyList (dropdown readonly) and ReadOnly (only input box)
    /// </summary>
    get_displayMode: function() {
        return this._get_value($IG.DropDownProps.DisplayMode);
    },

    /// <summary>
    /// if not set this will be zero 
    /// </summary>
    get_valueListMaxHeight: function() {
        return this._get_value($IG.DropDownProps.ValueListMaxHeight);
    },

    set_valueListMaxHeight: function(value) {
        return this._set_value($IG.DropDownProps.ValueListMaxHeight, value);
    },

    /// <summary>
    /// horizontal offset in pixels of the dropdown container relative to the target (allows for manual adjustment of the source and target)
    /// </summary>
    get_offsetX: function() {
        return this._get_value($IG.DropDownProps.OffsetX);
    },

    get_offsetY: function() {
        return this._get_value($IG.DropDownProps.OffsetY);
    },

    set_offsetX: function(value) {
        return this._set_value($IG.DropDownProps.OffsetX, value);
    },

    set_offsetY: function(value) {
        return this._set_value($IG.DropDownProps.OffsetY, value);
    },

    get_enablePaging: function() {
        return this._get_value($IG.DropDownProps.EnablePaging);
    },

    get_pageSize: function() {
        return this._get_value($IG.DropDownProps.PageSize);
    },

    get_selectedItemIndex: function() {
        return this._get_value($IG.DropDownProps.SelectedItemIndex);
    },

    set_selectedItemIndex: function(index) {
		
		//A.T. 14 Jan 2010 Fix for bug #26293 - back button support for WebDropDown
        this._setBackState(0, this.get_currentValue() + ',' + index);
        
        return this._set_value($IG.DropDownProps.SelectedItemIndex, index);
    },

    /// <summary>
    /// used when multiple selection is enabled
    /// </summary>
    get_selectedItemIndices: function() {
        return this._get_value($IG.DropDownProps.SelectedItemIndices);
    },

    set_selectedItemIndices: function(indices) {
        return this._set_value($IG.DropDownProps.SelectedItemIndices, indices);
    },

    /// <summary>
    /// this represents a single character that will automatically delimit in the input box the list of multiple-selected items
    /// </summary>
    get_multiSelectValueDelimiter: function() {
        return this._get_value($IG.DropDownProps.MultiSelectValueDelimiter);
    },

    /// <summary>
    /// items marked "Custom" will not be allowed for selection, if this property is turned on
    /// </summary>
    get_enableCustomValueSelection: function() {
        return this._get_value($IG.DropDownProps.EnableCustomValueSelection);
    },

    /// <summary>
    /// sets / enables multiple selection in general. Further, multiple selection can be either implemented with checkboxes
    /// or with 
    /// </summary>
    get_enableMultipleSelection: function() {
        return this._get_value($IG.DropDownProps.EnableMultipleSelection);
    },

    /// <summary>
    /// enables / disables persisting of custom values. If some value that doesn't exist in the list is typed, and we remove the
    /// focus from the control, a new item is created, and marked IsCustom=true, and persisted to the server
    /// persisting of custom values SHOULD NOT be enabled along with loadOnDemand or Paging ! 
    /// or with 
    /// </summary>
    get_persistCustomValues: function() {
        return this._get_value($IG.DropDownProps.PersistCustomValues);
    },
    
    /// <summary>
    /// milliseconds that will pass while the user is typing, until a postback will be made
    /// this means we don't do a postback on every keystroke in the input box, in order to fetch filtering results 
    /// </summary>
    get_autoFilterTimeoutMs: function () {
        
        return this._get_value($IG.DropDownProps.AutoFilterTimeoutMs); 
    },
   
    /// <summary>
    /// enables automatic filtering if items on the server. Also see EnableClientFilteringOnly
    /// </summary>
    get_enableAutoFiltering: function() {
        return this._get_value($IG.DropDownProps.EnableAutoFiltering);
    },

    /// <summary>
    /// We support a predefined set of automatic server-side filtering queries, such as StartsWith, EndsWith, Contains, etc.
    /// </summary>
    get_autoFilterQueryType: function() {
        return this._get_value($IG.DropDownProps.AutoFilterQueryType);
    },

    /// <summary>
    /// maximum number of resulting items that will be sent to the client, after automatic filtering is performed
    /// </summary>
    get_autoFilterResultSize: function() {
        return this._get_value($IG.DropDownProps.AutoFilterResultSize);
    },

    /// <summary>
    /// we support sorting of the resulting items (ascending and descending)
    /// </summary>
    get_autoFilterSortOrder: function() {
        return this._get_value($IG.DropDownProps.AutoFilterSortOrder);
    },
    
    /// <summary>
    /// type of multiple selection - Keyboard or Checkbox (if checkbox, checkboxes are automatically rendered in front of every item)
    /// </summary>
    get_multipleSelectionType: function() {
        return this._get_value($IG.DropDownProps.MultipleSelectionType);
    },
    
    /// <summary>
    /// PagerMode
    /// </summary>
    get_pagerMode: function() {
        return this._get_value($IG.DropDownProps.PagerMode);
    },
    
    get_lastPageIndex:function() {
        return this._get_value($IG.DropDownProps.LastPageIndex);
    },
    
    get_shouldFireMultipleSelect:function() {
        return this._get_value($IG.DropDownProps.ShouldFireMultipleSelect);
    },
    
    get_enableAnimations:function() {
        return this._get_value($IG.DropDownProps.EnableAnimations);
    },
    
    get_enableDropDownOpenOnClick:function() {
        return this._get_value($IG.DropDownProps.EnableDropDownOpenOnClick);
    },
    
    get_activeItemIndex:function() {
        
        return this._get_value($IG.DropDownProps.ActiveItemIndex);
    },
    
    set_activeItemIndex:function(value) {
    
        this._set_value($IG.DropDownProps.ActiveItemIndex, value);
    },
    
    set_shouldFireMultipleSelect:function(val) {
        return this._set_value($IG.DropDownProps.ShouldFireMultipleSelect, val);
    },

    /// <summary>
    /// load on demand is a kind of "virtual scrolling" where , once the user scrolls down to the bottom of the dropdown container
    /// new items are fetched from the server, if any
    /// </summary>
    get_enableLoadOnDemand: function() {
        return this._get_value($IG.DropDownProps.EnableLoadOnDemand);
    },

    /// <summary>
    /// as one types, filtering is only performed on the item collection which is on the client, and no postback is done
    /// </summary>
   // get_enableClientFilteringOnly: function() {
   //     return this._get_value($IG.DropDownProps.EnableClientFilteringOnly);
   // },

    get_dropDownContainerWidth: function() {
        return this._get_value($IG.DropDownProps.DropDownContainerWidth);
    },

    get_dropDownContainerHeight: function() {
        return this._get_value($IG.DropDownProps.DropDownContainerHeight);
    },

    get_enableCaseSensitivity: function() {
        return this._get_value($IG.DropDownProps.EnableCaseSensitivity);
    },

    get_showDropDownButton: function() {
        return this._get_value($IG.DropDownProps.ShowDropDownButton);
    },

    get_dropDownValueDisplayType: function() {
        return this._get_value($IG.DropDownProps.DropDownValueDisplayType);
    },

    get_inputFocusCssClass: function() {
        return this._get_clientOnlyValue("dropDownInputFocusClass");
    },

    get_inputHoverCssClass: function() {
        return this._get_clientOnlyValue("dropDownInputHoverClass");
    },

    get_inputCssClass: function() {
        return this._get_clientOnlyValue("dropDownInputClass");
    },
    
    get_inputDisabledCssClass: function() {
        return this._get_clientOnlyValue("dropDownInputDisabledClass");
    },
    
    get_controlDisabledCssClass: function() {
        return this._get_clientOnlyValue("controlDisabledClass");
    },
    
    get_controlCssClass: function() {
        return this._get_clientOnlyValue("controlClass");
    },

    get_dropDownFocusCssClass: function() {
        return this._get_clientOnlyValue("dropDownFocusClass");
    },

    get_dropDownHoverCssClass: function() {
        return this._get_clientOnlyValue("dropDownHoverClass");
    },

    get_controlAreaHoverCssClass: function() {
        return this._get_clientOnlyValue("controlAreaHoverClass");
    },

   // get_buttonFocusCssClass: function() {
   //     return this._get_clientOnlyValue("dropDownButtonFocusClass");
   // },

    get_buttonCssClass: function() {
        return this._get_clientOnlyValue("dropDownButtonClass");
    },

    get_controlAreaFocusCssClass: function() {
        return this._get_clientOnlyValue("controlAreaFocusClass");
    },


    get_controlAreaCssClass: function() {
        return this._get_clientOnlyValue("controlAreaClass");
    },
    
    get_pageCount: function() {
        return this._get_clientOnlyValue("pageCount");
    },
    
    get_buttonNormalImageUrl: function() {
        return this._get_clientOnlyValue("dropDownButtonNormalImageUrl");
    },

    get_buttonHoverImageUrl: function() {
        return this._get_clientOnlyValue("dropDownButtonHoverImageUrl");
    },

    get_buttonPressedImageUrl: function() {
        return this._get_clientOnlyValue("dropDownButtonPressedImageUrl");
    },

    /// <summary>
    /// 'currentValue' is the value in the input box of the dropdown control. It could be assumed to mean the "Display Value" 
    /// </summary>
    get_currentValue: function() {
        return this._get_value($IG.DropDownProps.CurrentValue);
    },

    /// <summary>
    /// programatically set the display value
    /// </summary>
    set_currentValue: function(val, copyToInputValue) {
        
        if (val != this.get_currentValue() || !this.__getViewStateEnabled())
        {
           if (copyToInputValue)
           {
                this._elements["Input"].value = val;
           }
            this._set_value($IG.DropDownProps.CurrentValue, val);
            
            //A.T. 14 Jan 2010 Fix for bug #26293 - back button support for WebDropDown
            this._setBackState(0, val + '|' + this.get_selectedItemIndex());
        }
    },


    set_previousValue: function(val) {
        this._previousValue = val;
    },

    get_previousValue: function() {
        return this._previousValue;
    },

    get_hoverItemIndex: function() {
        return this.__hoverItemIndex;
    },

    set_hoverItemIndex: function(index) {
        this.__hoverItemIndex = index;
    },

    _selectItem: function(item, val) {
        this.__selectItem(item, val, true);
    },

    __selectItem: function(item, val, fireEvent) {
        //  if(!this.__initializing)
        //  {
        //      $util.removeCompoundClass(item._element, this.get_selectedClass());
        //      $util.removeCompoundClass(item._element, item.get_selectedCssClass());
        //  }
        if (val) {
            //   $util.addCompoundClass(item._element, this.get_selectedClass());
            //   $util.addCompoundClass(item._element, item.get_selectedCssClass());
            if (fireEvent && !this.__initializing)
                this._raiseClientEvent('ItemSelected', 'DropDownControl', null, null, item);
        }

    },

    /// <summary>
    /// in case there is event, such as key up / down or mouse down / up , we don't automatically assume that the 
    /// target event element will be an item (i.e. <LI> tag), but we search up (bubble) in order to find the actual item 
    /// represented by the LI tag.
    /// </summary>
    __getNearestItem: function(elem) {
        if (elem == null) {
            return null;
        }

        var item = null;
        var adr = null;

        $util._initAttr(elem);
        
        if (elem.getAttribute) {

            adr = elem.getAttribute("adr");
			
			// A.T. 6th Feb. 2010 Fix for bug #26987 - Microsoft JScript runtime error: 'this._items[...].0' is null or not an object (WebDataTree interop.)
            if (adr != null && elem.getAttribute && !elem.getAttribute('_expImage')) {
                item = this.get_items().getItem(adr);

                if (item != null)
                    return item;
            }
        }

        if (!this._elements["DropDown"])
            return;
            
        if (elem.parentNode == null || elem.parentNode.id == this._elements["DropDown"].id)
            return null;
        else
            return this.__getNearestItem(elem.parentNode);

    },

    _select: function(event) {
        this.__isDropDownEvent = true;
        
        var navigate = true;

        // selection is not allowed when we are in read only list mode
        if (this.get_displayMode() == $IG.DropDownDisplayMode.ReadOnlyList)
            return;

        var item = this.__getNearestItem(event.target);
       
        if (item != null && !item.get_disabled()) {

            //A.T. 1 Sept. 2009 - Fix for bug 21172: When selection is set to the same previous selection, postback is made, but the SelectionChanged event is not fired on the server-side
            if (!this.get_enableMultipleSelection() && item.get_index() != this.get_selectedItemIndex()) {
            
                // handle single item selection first 
                 var oldIndex = this.get_selectedItemIndex();
                // var oldItem = oldIndex == -1 ? null : this.get_items()._getObjectByIndex(oldIndex);
                var oldItem = oldIndex == -1 ? null : this.get_items().getItem(oldIndex);
                 
                if ((!item.get_custom() ) || (item.get_custom() && this.get_enableCustomValueSelection())) {

                    this.set_activeItem(item);
                    
                    var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', event, null, [item], [oldItem]);
                    var cancel = args ? args.get_cancel() : false;
                    if (!cancel) {
                    
                        if (this.get_enableMultipleSelection())
                        {
                            this.__unselectAllItems();
                        } else 
                        {
                            if (this.get_selectedItem()!=null)
                                this.get_selectedItem().unselect();
                        }
                        
                        item.select();
                       // this.set_selectedItemIndex(this.get_items().get_indexOf(item));
                       this.set_selectedItemIndex(item.get_index());
                        this.__lastSelectionWasContinuous=false;

                       // args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', event, null, this._elements["Input"].value, this.get_currentValue());
                       args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', event, null, item.get_text(), this.get_currentValue());

                        var cancel = args ? args.get_cancel() : false;
                        if (!cancel) {
                            var previousValue = this.get_currentValue();
                            this.set_currentValue(item.get_text(), true);
                            this._raiseClientEvent('ValueChanged', 'DropDownEdit', event, null, this.get_currentValue(), previousValue);
                        }
                        //} else {
                        //    item.select();
                        // }

                        var args = this._raiseClientEvent('SelectionChanged', 'DropDownSelection', event, null, [item], [oldItem]);

                    }

                } else {
                    
                    /*
                    // reset selection
                    var oldIndex = this.get_selectedItemIndex();
                    //var oldItem = oldIndex == -1 ? null : this.get_items()._getObjectByIndex(oldIndex);
                    var oldItem = oldIndex == -1 ? null : this.get_items().getItem(oldIndex);
                    var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', event, null, [null], [oldItem]);
                    var cancel = args ? args.get_cancel() : false;
                    if (!cancel) {
                        item.unselect();
                        this.set_selectedItemIndex(-1);
                        var args = this._raiseClientEvent('SelectionChanged', 'DropDownSelection', event, null, [null], [oldItem]);
                        
                        this.__lastSelectionWasContinuous=false;

                    }
                    */
                }
            }
            // change value display
            // this._elements["Input"].value = item.get_text();
            if (this.get_enableMultipleSelection()) {
            
                if (this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Checkbox)
                {
                    var checked = item._element.childNodes[0].checked;
                    var isEventOnCheckbox = false;
                    var eventSource = event.target;
                    if (eventSource.getAttribute && eventSource.getAttribute("type") == "checkbox") {
                        isEventOnCheckbox = true;
                    }

                    if (!isEventOnCheckbox)
                    {
                        // A.T. 27/11/2009 Fix for bug #23711
                        //return;
                        checked = item.get_selected();
                        item._element.childNodes[0].checked = !checked;
                    }

                    if (!item.get_disabled() && (!item.get_custom() ) || (item.get_custom() && this.get_enableCustomValueSelection()))
                    {
                    
                        // fire the SelectionChanging event 
                        // 1. get current array of selected items
                        var oldSelectedItems = this.get_selectedItems();
                        
                        // construct newSelectedItems
                        if (checked)
                        {
                            // remove item 
                            var newSelectedItems = new Array();
                            for (var i=0; i < oldSelectedItems.length; i++)
                            {
                                if (oldSelectedItems[i].get_index() != item.get_index())
                                {
                                    newSelectedItems.push(oldSelectedItems[i]);
                                }   
                            }
                            
                        } else 
                        {
                            // add item
                            var newSelectedItems = Array.clone(oldSelectedItems);
                            newSelectedItems.push(item);
                        }
                        
                        // fire selection changing event
                        var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', event, null, newSelectedItems, oldSelectedItems);
                        var cancel = args ? args.get_cancel() : false;
            
                        if (!cancel)
                        {
                            if (checked) {
                            
                                item.unselect(true);
                                
                            } else {
                                item.select(true);
                            }
                            
                            // fire selection changed event
                            this.set_shouldFireMultipleSelect(true);
                                 // set active item just in case Async Postback flags are used, because if we set it afterwards
                                // it will not get set if we set it in client code AFTER the event is fired 
                                this.set_activeItem(item);
                                
                            this._raiseClientEvent('SelectionChanged', 'DropDownSelection', event, null, newSelectedItems, oldSelectedItems);
                            
                            this.__lastSelectionWasContinuous=false;
                        }
                        
                    }
                    
                } else {
                    
                    // keyboard multiple selection
                    var eventSource = event.target;
                    
                   if (event.ctrlKey)
                   {
                        //navigate = false;
                        
                        if (!item.get_disabled() && (!item.get_custom() ) || (item.get_custom() && this.get_enableCustomValueSelection()))
                        {
                        
                            // fire the SelectionChanging event 
                            // 1. get current array of selected items
                            var oldSelectedItems = this.get_selectedItems();
                                                    
                            // construct newSelectedItems
                            if (item.get_selected())
                            {
                                // remove item 
                                var newSelectedItems = new Array();
                                for (var i=0; i < oldSelectedItems.length; i++)
                                {
                                    if (oldSelectedItems[i].get_index() != item.get_index())
                                    {
                                        newSelectedItems.push(oldSelectedItems[i]);
                                    }   
                                }
                                
                            } else 
                            {
                                // add item
                                var newSelectedItems = Array.clone(oldSelectedItems);
                                newSelectedItems.push(item);
                            }
                        
                            // fire selection changing event
                            var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', event, null, newSelectedItems, oldSelectedItems);
                            var cancel = args ? args.get_cancel() : false;
                
                            if (!cancel)
                            {
                                
                                if (!item.get_selected())
                                {
                                    item.select(true);
                                } else
                                {
                                    item.unselect(true);
                                }
                                                        
                                // fire selection changed event
                                this.set_shouldFireMultipleSelect(true);
                                     // set active item just in case Async Postback flags are used, because if we set it afterwards
                                // it will not get set if we set it in client code AFTER the event is fired 
                                this.set_activeItem(item);
                                this._raiseClientEvent('SelectionChanged', 'DropDownSelection', event, null, newSelectedItems, oldSelectedItems);
                                
                                this.__lastSelectionWasContinuous=false;
                            }
                        }
                        
                   } else if (event.shiftKey)
                   {
                       // navigate = false;
                        
                       // var currentItemIndex = this.get_items().get_indexOf(item);
                       // var prevItemIndex = this.get_items().get_indexOf(this.get_activeItem());
                       
                       var currentItemIndex = item.get_index();
                       
                       if (!this.get_activeItem())
                        return;
                        
                       var prevItemIndex = this.get_activeItem().get_index();
                        
                        if (prevItemIndex < 0) 
                        {
                            return;
                        }
                        // construct selected items arrays
                         var oldSelectedItems = this.get_selectedItems();
                         var newSelectedItems = null;
                         
                         var itemsForUnselect = new Array();
                         
                         if (this.__lastSelectionWasContinuous)
                         {
                            newSelectedItems = Array.clone(oldSelectedItems);
                         } else 
                         {
                            newSelectedItems = new Array();
                         }
                        
                        if (currentItemIndex > prevItemIndex)
                        {
                            
                            //newSelectedItems.push( this.get_items().getItem(prevItemIndex));
                            if (!item.get_disabled() && this.__lastSelectionWasContinuous)
                            {
                                if (!Array.contains(newSelectedItems,item))
                                 newSelectedItems.push(item);
                            }
                            
                            for (i=prevItemIndex; i<= currentItemIndex; i++)
                            {
                               
                                if (!this.__lastSelectionWasContinuous)
                                {
                                     if (!Array.contains(newSelectedItems, this.get_items().getItem(i)))
                                    newSelectedItems.push(this.get_items().getItem(i));
                                } 
                                
                                if (this.get_items().getItem(i).get_activated() && !this.get_items().getItem(prevItemIndex+1).get_selected() && this.get_items().getItem(i).get_index()!= item.get_index())
                                {
                                   if (!Array.contains(newSelectedItems, this.get_items().getItem(i)))
                                    newSelectedItems.push(this.get_items().getItem(i));
                                }
                                
                                if (!this.get_items().getItem(i).get_disabled() && !this.get_items().getItem(i).get_selected() && this.get_items().getItem(i).get_index()!= item.get_index())
                                {
                                    if (!Array.contains(newSelectedItems, this.get_items().getItem(i)))
                                    newSelectedItems.push(this.get_items().getItem(i));
                                    
                                } //else 
                                //{
                                //    this.get_items().getItem(i).unselect();
                                //}
                                else if (this.__lastSelectionWasContinuous && this.get_items().getItem(i).get_index()!= item.get_index() && this.get_items().getItem(i).get_selected() && (!this.get_items().getItem(i).get_activated() || (this.get_items().getItem(i).get_activated() && this.get_items().getItem(prevItemIndex+1).get_selected())))
                                {
                                    itemsForUnselect.push(this.get_items().getItem(i));
                                    if (Array.contains(newSelectedItems, this.get_items().getItem(i)))
                                    {
                                        Array.remove(newSelectedItems, this.get_items().getItem(i));
                                    }
                                }
                            }
                            
                            // fire 'ing' event
                            // fire selection changing event
                            var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', event, null, newSelectedItems, oldSelectedItems);
                            var cancel = args ? args.get_cancel() : false;
                
                            if (!cancel)
                            {
                                // unselect all first
                                if (!this.__lastSelectionWasContinuous) 
                                    this.__unselectAllItems();
                                
                                for (i= 0; i < newSelectedItems.length; i++)
                                {
                                    var tmpItem = newSelectedItems[i];
                                    if (!tmpItem.get_disabled() && (!tmpItem.get_custom() ) || (tmpItem.get_custom() && this.get_enableCustomValueSelection()))
                                    {
                                        tmpItem.select(true);
                                    }
                                }
                                
                                for (i=0; i < itemsForUnselect.length;i++)
                                {
                                    itemsForUnselect[i].unselect(true);
                                }
                                
                                 // fire selection changed event
                                 this.set_shouldFireMultipleSelect(true);
                                      // set active item just in case Async Postback flags are used, because if we set it afterwards
                                // it will not get set if we set it in client code AFTER the event is fired 
                                this.set_activeItem(item);
                                this._raiseClientEvent('SelectionChanged', 'DropDownSelection', event, null, newSelectedItems, oldSelectedItems);
                                
                                this.__lastSelectionWasContinuous=true;
                            
                            }
                            
                        } else if (currentItemIndex < prevItemIndex)
                        {
                          //  newSelectedItems.push( this.get_items().getItem(prevItemIndex));
                          
                            if (!item.get_disabled() && this.__lastSelectionWasContinuous)
                            {
                                if (!Array.contains(newSelectedItems, item))
                                newSelectedItems.push(item);
                            }
                            
                            for (i=currentItemIndex; i<= prevItemIndex; i++)
                            {
                                if (!this.__lastSelectionWasContinuous)
                                {
                                    if (!Array.contains(newSelectedItems, this.get_items().getItem(i)))
                                        newSelectedItems.push(this.get_items().getItem(i));
                                }
                                
                               if (this.get_items().getItem(i).get_activated() && !this.get_items().getItem(prevItemIndex-1).get_selected() && this.get_items().getItem(i).get_index()!= item.get_index())
                                {
                                    if (!Array.contains(newSelectedItems, this.get_items().getItem(i)))
                                        newSelectedItems.push(this.get_items().getItem(i));
                                }
                                
                                if (!this.get_items().getItem(i).get_disabled() && !this.get_items().getItem(i).get_selected() && this.get_items().getItem(i).get_index()!= item.get_index())
                                {
                                    if (!Array.contains(newSelectedItems, this.get_items().getItem(i)))
                                        newSelectedItems.push(this.get_items().getItem(i));
                                    
                                } 
                                /*
                                else if (this.get_items().getItem(i).get_selected())
                                { 
                                    if (this.__lastSelectionWasContinuous)
                                    {
                                        this.get_items().getItem(i).unselect();
                                    } else 
                                    {
                                        newSelectedItems.push(this.get_items().getItem(i));
                                    }
                                }
                                */
                                // the item that will become active (CurrentItemIndex), must always be also selected
                                else if (this.__lastSelectionWasContinuous && this.get_items().getItem(i).get_index() != item.get_index() && this.get_items().getItem(i).get_selected() && (!this.get_items().getItem(i).get_activated() || (this.get_items().getItem(i).get_activated() && this.get_items().getItem(prevItemIndex-1).get_selected())))
                                {
                                    itemsForUnselect.push(this.get_items().getItem(i));
                                     if (Array.contains(newSelectedItems, this.get_items().getItem(i)))
                                    {
                                        Array.remove(newSelectedItems, this.get_items().getItem(i));
                                    }
                                }
                            }
                            
                            // fire 'ing' event
                            // fire selection changing event
                            var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', event, null, newSelectedItems, oldSelectedItems);
                            var cancel = args ? args.get_cancel() : false;
                
                            if (!cancel)
                            {
                                // unselect all items first, if last selection was not of type multiple continuous
                                if (!this.__lastSelectionWasContinuous)
                                {
                                    this.__unselectAllItems();
                                }    
                                
                                for (i= 0; i < newSelectedItems.length; i++)
                                {
                                    var tmpItem = newSelectedItems[i];
                                    if (!tmpItem.get_disabled() && (!tmpItem.get_custom() ) || (tmpItem.get_custom() && this.get_enableCustomValueSelection()))
                                    {
                                        tmpItem.select(true);
                                    } 
                                }
                                
                                for (i=0; i < itemsForUnselect.length;i++)
                                {
                                    itemsForUnselect[i].unselect(true);
                                }
                                
                                // fire selection changed event
                                this.set_shouldFireMultipleSelect(true);
                                // set active item just in case Async Postback flags are used, because if we set it afterwards
                                // it will not get set if we set it in client code AFTER the event is fired 
                                this.set_activeItem(item);
                                this._raiseClientEvent('SelectionChanged', 'DropDownSelection', event, null, newSelectedItems, oldSelectedItems);
                                
                                this.__lastSelectionWasContinuous=true;
                            }
                        }
                        
                   } else 
                   {
                        //A.T. 1 Sept. 2009 - Fix for bug 21172: When selection is set to the same previous selection, postback is made, but the SelectionChanged event is not fired on the server-side
                        if (item.get_index() != this.get_selectedItemIndex() && !item.get_disabled() && (!item.get_custom() ) || (item.get_custom() && this.get_enableCustomValueSelection()))
                        {
                            // fire selection events !!! 
                            var oldSelectedIndex = this.get_selectedItemIndex();
                           // var oldItem = oldSelectedIndex == -1 ? null : this.get_items()._getObjectByIndex(oldSelectedIndex);
                           var oldItem = oldSelectedIndex == -1 ? null : this.get_items().getItem(oldSelectedIndex);
                            var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', event, null, [item], [oldItem]);
                            var cancel = args ? args.get_cancel() : false;
                            if (!cancel)
                            {
                                this.__unselectAllItems();
                                item.select(true);
                              //  this.set_selectedItemIndex(item.get_index());
                              this.set_selectedItemIndex(item.get_index());
                                // set active item just in case Async Postback flags are used, because if we set it afterwards
                                // it will not get set if we set it in client code AFTER the event is fired 
                                this.set_activeItem(item);
                                this.set_shouldFireMultipleSelect(true);
                                this.__lastSelectionWasContinuous=false;
                                this._raiseClientEvent('SelectionChanged', 'DropDownSelection', event, null, [item], [oldItem]);
                                
                            }
                        }
                   }
                }
                
                this.set_activeItem(item);
                //var currentVal = this.get_currentValue();
                //var delim = this.get_multiSelectValueDelimiter();
                //this.set_currentValue(currentVal+delim+item.get_text());
                
                this.__constructMultiSelectValue(event);
            }

            // close drop down

            if (this.get_closeDropDownOnSelect()) {

                var args = this._raiseClientEvent('DropDownClosing', 'DropDownContainer', event, null);
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    this.behavior.set_visible(false);
                   // this._adjustMaxHeight();
                    this._raiseClientEvent('DropDownClosed', 'DropDownContainer', event, null);
                }
            }

            if (!this._elements["Input"].disabled) {
                setTimeout(Function.createDelegate(this, this.__focusInput) , 20);

            } else {
            
                // A.T. Fix for bug #22775
                try 
                {
                    this._element.focus();
                    
                } catch (e)
                {
                    // maybe control is disabled, maybe it's not visible, maybe this._element was disposed
                    // for some reason - there is no stable way to detect when to call focus() and when not to 
                }
            }

        }
        
   //     event.cancelBubble = true;
   //     return false;
   
         // just don't do anything on mouse clicks ! 
        /*
        if (!event.shiftKey || !event.ctrlKey)
        {
            window.navigate(item.get_navigateUrl());
        }
        */

    },
    
    /// <summary>
    /// same as selectItem(), but uses the passed item index instead:
    /// usage: selectItemByIndex(2)
    /// /summary>
    selectItemByIndex: function(itemIndex,activate,updateCurrentValue)
    {
        this.selectItem(this.get_items().getItem(itemIndex), activate,updateCurrentValue);
    },
    
    /// <summary>
    /// Selects an item and optionally activates it and updates the current value and input text
    /// usage: selectItem(myItem,activate,updateCurrentValue);
    /// if the second parameter is true, the item will be also activated
    /// if the third parameter is true, the current value and the input text will also be updated
    /// this works for both Single (EnableMultipleSelection=false) and Multiple selections
    /// the default values for the second and third parameters are both 'true' 
    /// </summary>
    selectItem: function(item, activate, updateCurrentValue) 
    {
        var localActivate=true;
        var localUpdateCurrentValue=true;
        
        if (activate != undefined && !activate) localActivate=false;
        if (updateCurrentValue != undefined && !updateCurrentValue) localUpdateCurrentValue=false;
        
        if (item == null)
            return;
            
        // get actual collection item
        var newItem = this.get_items().getItem(item.get_index());
        
        if (newItem==null)
            return;
            
        var oldIndex = this.get_selectedItemIndex();
        var oldItem = oldIndex == -1 ? null : this.get_items().getItem(oldIndex);
        
        if (oldItem!=null)
        {
            if (!this.get_enableMultipleSelection())
            {
                // deselect old item
                oldItem.unselect();
                this.set_selectedItemIndex(-1);
                // inactivate it
                if (oldItem.get_activated() && localActivate)
                {
                    oldItem.inactivate();
                    this.set_activeItemIndex(-1);
                }
            } else
            {
                var currentActiveItem = this.get_activeItem();
                if (currentActiveItem!=null && localActivate)
                {
                    currentActiveItem.inactivate();
                    this.set_activeItemIndex(-1);
                }
            }

        }
        
        // select , activate new item, and update current value
        newItem.select();
        this.set_selectedItemIndex(newItem.get_index());
        if (localActivate)
        {
            newItem.activate();
            this.set_activeItemIndex(newItem.get_index());
        }
        
        // finally , update current value
        if (localUpdateCurrentValue)
        {
            if (!this.get_enableMultipleSelection())
            {
                this.set_currentValue(newItem.get_text(),true);
            }
            else
            {
                var newVal = this.__constructMultiSelectValueInternal();
                this.set_currentValue(newVal,true);
            }
        }
        
    },
    
    __focusInput: function() {
        
        if (this._elements && this._elements["Input"])
        {
            // A.T. Fix for bug #22775
            try 
            {
                this._elements["Input"].focus();
                
            } catch (e)
            {
                // maybe control is disabled, maybe it's not visible, maybe this._element was disposed
                // for some reason - there is no stable way to detect when to call focus() and when not to 
            }
            this.__moveInputCursorToEnd();
            this.__isInternalFocus=true;
        }
    },

    __unselectAllItems: function() {

      //  var items = this.get_items()._items;
       //var items = this.get_selectedItems();
       var length = this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client ? this.__clientFilteringItemCount : this.get_items().getLength();
       
        for (i = 0; i < length; i++) {
           // if (!items[i].get_disabled()) {
               // items[i].unselect();
               this.get_items().getItem(i).unselect();
           // }
        }
    },
    
    __unselectAllItemsWithoutActiveItem: function() {
    
        //  var items = this.get_items()._items;
       //var items = this.get_selectedItems();
       var length = this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client ? this.__clientFilteringItemCount : this.get_items().getLength();
       
        for (i = 0; i < length; i++) {
           // if (!items[i].get_activated() && items[i].get_selected()) {
           //     items[i].unselect();
           // }
            if (!this.get_items().getItem(i).get_activated() && this.get_items().getItem(i).get_selected()) {
                this.get_items().getItem(i).unselect();
            }
        }
    },

    _navigateItems: function(event) {
        // item navigation
    },


    _onPagerMoreResults: function(event) {
        if (!this._noMoreResults) {
        
            if (this.get_loadingItemsMessageText()!=null)
            {
                this.__showLoadingItemsMessage();
            }
            var cbo = this._callbackManager.createCallbackObject();
            cbo.serverContext.type = "pagerMoreResults";
            //cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(item._csm.get_transactionList())
            this._callbackManager.execute(cbo, true);
        }

    },

    _onPagerPrevResults: function(event) {

        if (this.get_loadingItemsMessageText()!=null)
        {
            this.__showLoadingItemsMessage();
        }
        var cbo = this._callbackManager.createCallbackObject();
        cbo.serverContext.type = "prevPage";
        //cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(item._csm.get_transactionList())
        this._callbackManager.execute(cbo, true);

    },

    _onPagerNextResults: function(event) {

        if (this.get_loadingItemsMessageText()!=null)
        {
            this.__showLoadingItemsMessage();
        }
        var cbo = this._callbackManager.createCallbackObject();
        cbo.serverContext.type = "nextPage";
        //cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(item._csm.get_transactionList())
        this._callbackManager.execute(cbo, true);

    },
    
        _onPagerFirstResults: function(event) {

        if (this.get_loadingItemsMessageText()!=null)
        {
            this.__showLoadingItemsMessage();
        }
        var cbo = this._callbackManager.createCallbackObject();
        cbo.serverContext.type = "firstPage";
        //cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(item._csm.get_transactionList())
        this._callbackManager.execute(cbo, true);

    },
    
        _onPagerLastResults: function(event) {

        if (this.get_loadingItemsMessageText()!=null)
        {
            this.__showLoadingItemsMessage();
        }
        var cbo = this._callbackManager.createCallbackObject();
        cbo.serverContext.type = "lastPage";
        //cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(item._csm.get_transactionList())
        this._callbackManager.execute(cbo, true);

    },
    
    _onPagerNumberResults: function(event) {
    
        if (this.get_loadingItemsMessageText()!=null)
        {
            this.__showLoadingItemsMessage();
        }
        
         var cbo = this._callbackManager.createCallbackObject();
         cbo.serverContext.type = "gotoPage";
         cbo.serverContext.value = escape(event.target.innerHTML);
         //cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(item._csm.get_transactionList())
         this._callbackManager.execute(cbo, true);
    },

    _scrollingLoadOnDemand: function(event) {
        var container = this._elements["DropDownContents"];

        //alert (container.scrollHeight + " ; " + container.clientHeight + " ; " + container.scrollTop);

        if (container.scrollHeight == container.clientHeight + container.scrollTop) {
            // trigger load on demand
            // store scroll top
            this._dropDownScrollTop = container.scrollTop;
            this._onPagerMoreResults(event);
        }
    },
    
    _genericScrollHandler: function(event) {

		// A.T. Fix for bug #22775
		try
		{
			if (!this.__isMouseDown)
			{
				this._elements["Input"].focus();
			}
			
		} catch (e)
		{
			// maybe control is disabled, maybe it's not visible, maybe this._element was disposed
			// for some reason - there is no stable way to detect when to call focus() and when not to 
		}
    },
    
    _listBlurHandler: function(event) 
    {
		if (this.get_enableClosingDropDownOnBlur())
		{
			setTimeout(Function.createDelegate(this, this.__closeOnListBlur), 100);
			this.__listBlurEvent = event;
		}
    },
    
    __closeOnListBlur: function()
    {
		// check if focus is in the input, and if not, close the dropdown
		if (this.__listBlurFlag)
		{
			if (this.behavior.get_visible())
			{
				this.closeDropDown();
			}
			
			if (this.get_showDropDownButton())
            {
                this._elements["ButtonImage"].className = this.get_buttonCssClass();
            }
            this._elements["TargetTable"].className = this.get_controlAreaCssClass();

			this._raiseClientEvent('Blur', 'DropDownControl', this.__listBlurEvent, null);
			
			// persisting logic
			// TODO: this should be in a common place
			// custom value persistence: if the current value in the input doesn't match any of the items text EXACTLY
            var shouldPersist=true;
            if (this.get_persistCustomValues())
            {
                for (i=0; i < this.get_items().getLength(); i++)
                {  
                   // if (this.get_currentValue() == this.get_items()._items[i].get_text())
                   if (this.get_currentValue() == this.get_items().getItem(i).get_text())
                    {
                        shouldPersist=false;
                        break;     
                    }
                }
                
                if (shouldPersist)
                {
                    // create a new item object
                    var newItem = this.get_items().createItem();
                    newItem.set_text(this.get_currentValue());
                    // mark the item as custom so that we can check the EnableCustomSelection later on 
                    newItem.set_custom(true);
                    // persist the item
                    this.get_items().add(newItem);
                }
            }
		}
    },

    _mouseOverForBlur: function(evnt) {
        this.__mouseOver = true;
    },

    _mouseOutForBlur: function(evnt) {
        this.__mouseOver = false;
    },
    
    _onInputMouseOutHandler: function(evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
    
         // if (this._elements["Input"].id == evnt.id) {
            // fire InputMouseDown event 
            this._raiseClientEvent('InputMouseOut', 'DropDownControl', evnt, null);
            
            // remove hover style
            $util.removeCompoundClass(this._elements["Input"], this.get_inputHoverCssClass());
        //}
        
    },
    
    _onInputMouseOverHandler: function(evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
         // if (this._elements["Input"].id == evnt.id) {
            // fire InputMouseDown event 
            this._raiseClientEvent('InputMouseOver', 'DropDownControl', evnt, null);
            
            // add hover style
            $util.addCompoundClass(this._elements["Input"], this.get_inputHoverCssClass());
            
        //}
        
    },

    _onFocusHandler: function(evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
    
        if (evnt.target.id == this._elements["Input"].id) {
            // change style to focused
            $util.addCompoundClass(this._elements["Input"], this.get_inputFocusCssClass());
            // this._elements["ButtonImage"].className =  this.get_buttonFocusCssClass();
            this._elements["TargetTable"].className = this.get_controlAreaFocusCssClass();
            // raise focus event on the control itself
           
           if (this.__blurFlag)
            this._raiseClientEvent('Focus', 'DropDownControl', evnt, null);
            
            this.__blurFlag = false;
            
            this.__listBlurFlag = false;
        }
             
             /*               
            if (this.get_enableDropDownOpenOnClick())
            {
                this.openDropDown();
                this._elements["Input"].select();
            }
            */
      //  this.__isInternalFocus=false;
        
    },

    // this handler is needed in order to set focus on the dropdown input element, as soon as the animation ends
    _onAnimationEnd: function() {
    
        // fire dropdown closing / opening events 
        if (this.__isClosing)
        {
            this._raiseClientEvent('DropDownClosed', 'DropDownContainer', null, null);
            this.__isClosing=false;
            
        } else if (this.__isOpening)
        {
            this._raiseClientEvent('DropDownOpened', 'DropDownContainer', null, null);
            this.__isOpening=false;
        }
        
        try {

            
            if (this.__isDropDownEvent) {
                // A.T. Fix for bug #22775
                try 
                {
                    this._elements["Input"].focus();
                    
                } catch (e)
                {
                    // maybe control is disabled, maybe it's not visible, maybe this._element was disposed
                    // for some reason - there is no stable way to detect when to call focus() and when not to 
                }
                //this.__moveInputCursorToEnd();
                this.__isInternalFocus=true;
                this.__isDropDownEvent = false;

            }
            
        } catch (err) {
            // die ... 
        }

    },

    _onBlurHandler: function(evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
        
        if(evnt.target.id == this._elements["Input"].id)
        {
			this.__listBlurFlag = true;
        }
    
        if (evnt.target.id == this._elements["Input"].id && !this.__mouseOver) {
        
            this.__blurFlag = true;
            
            $util.removeCompoundClass(this._elements["Input"], this.get_inputFocusCssClass());
            //$util.removeCompoundClass(this._elements["ButtonImage"], this.get_buttonFocusCssClass());
            //$util.removeCompoundClass(this._elements["TargetTable"], this.get_controlAreaFocusCssClass());

            if (this.get_showDropDownButton())
            {
                this._elements["ButtonImage"].className = this.get_buttonCssClass();
            }
            this._elements["TargetTable"].className = this.get_controlAreaCssClass();

            // focus is somewhere else, therefore close this dropdown and fire blur even

            if (this.get_enableClosingDropDownOnBlur()) {
               // this.behavior.set_visible(false);
               if (this.behavior.get_visible())
               {
                    this.closeDropDown();
               }
            }
            //this._adjustMaxHeight();
            // blur event for the control itself
            this._raiseClientEvent('Blur', 'DropDownControl', evnt, null);
            
            // custom value persistence: if the current value in the input doesn't match any of the items text EXACTLY
            var shouldPersist=true;
            if (this.get_persistCustomValues())
            {
                for (i=0; i < this.get_items().getLength(); i++)
                {  
                   // if (this.get_currentValue() == this.get_items()._items[i].get_text())
                   if (this.get_currentValue() == this.get_items().getItem(i).get_text())
                    {
                        shouldPersist=false;
                        break;     
                    }
                }
                
                if (shouldPersist)
                {
                    // create a new item object
                    var newItem = this.get_items().createItem();
                    newItem.set_text(this.get_currentValue());
                    // mark the item as custom so that we can check the EnableCustomSelection later on 
                    newItem.set_custom(true);
                    // persist the item
                    this.get_items().add(newItem);
                }
            }

        } else {

            // find nearest item and raise blur event on it
            var item = this.__getNearestItem(evnt.target);

         //   if (item) {
         //       this._raiseClientEvent('BlurItem', 'DropDownItem', evnt.target, null, item);
         //   }
        }

    },

    _onSelectstartHandler: function(elem, adr, evnt) {
        //   $util.cancelEvent(evnt);
    },

    _onMouseoverListHandler: function(evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
    
        clearTimeout(this._unhoverTimeoutID);
        
        var item = this.__getNearestItem(evnt.target);
            
        if (item != null && !item.get_disabled()) 
        {
           // if (this.__getHoveredItem()) {
           //     this.__getHoveredItem().unhover();

           // }
            item.hover();
        }

        if (this.__getHoveredItem() !=null && item!=null && item.get_index() == this.__getHoveredItem().get_index())
        {
            return;
        }
        
        if (item!=null)
        {
            if (this.__getHoveredItem())
            {
                this._raiseClientEvent('ItemMouseOut', 'DropDownControl', evnt, null, this.__getHoveredItem()); 
            }
            this._raiseClientEvent('ItemMouseOver', 'DropDownControl', evnt, null, item);
        } 
        
        if (item != null && !item.get_disabled()) 
        {           
            this.__setHoveredItem(item);
        }
    },

    __setHoveredItem: function(item) {
        this.__hoveredItem = item;
    },

    __getHoveredItem: function() {
        return this.__hoveredItem;
    },

   // __unhoverItems: function() {
   //     for (i = 0; i < this.get_items()._items.length; i++) {
   //         if (!this.get_items()._items[i].get_disabled()) {
   //             this.get_items()._items[i].unhover();
   //         }
   //     }
   // },

    // we support automatic postback when the dropdown is initially opened, if and only if there are no items
    // this enables us to support lazy loading scenarios, where we don't want any initial footprint, unless the user types or opens the dropdown
    __loadInitial: function(elem, adr, evnt) {
        if (this.get_items()._items.length == 0) {
        
            /*
            if (this.get_displayMode() != $IG.DropDownDisplayMode.ReadOnly) {
                var args = this._raiseClientEvent('DropDownOpening', 'DropDownContainer', evnt, null);
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    this.behavior.set_visible(true);
                    this._adjustMaxHeight();
                    this._raiseClientEvent('DropDownOpened', 'DropDownContainer', evnt, null);
                }

            }
            */
            
            // go to the server, no items avaiiable
           // this.__autoFilterOnServer(elem, adr, evnt);
           this.loadItems();
        }
    },
    
    _onMousedownHandler: function(elem,adr,evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
    
        var item = this.__getNearestItem(elem);
        
        if (item!=null)
        {
            this._raiseClientEvent('ItemMouseDown', 'DropDownControl', evnt, null, item);
        }
        
        // handle mouse down on the value display (Input is the marker / mkr of the input value display component)
        if (this._elements["Input"].id == elem.id) {
        
            // fire InputMouseDown event 
            this._raiseClientEvent('InputMouseDown', 'DropDownControl', evnt, null);
        }
    
		// change button image
		//A.T. 26 Feb. Fix for bug #27945 - Exception thrown on hovering the drop-down input field when Button.Visible = False
		if (this.get_showDropDownButton())
		{
			if ((this._elements["Button"].id == elem.id || this._elements["ButtonImage"].id == elem.id) && 
			this.get_buttonPressedImageUrl()!=null && this.get_buttonPressedImageUrl()!= "") 
			{
				this._elements["ButtonImage"].src = this.get_buttonPressedImageUrl();
			}
        }   
    },

    _onMouseupHandler: function(elem, adr, evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
        
        this.__isDropDownEvent = true;

        if (this.get_showDropDownButton() && (this._elements["Button"].id == elem.id || this._elements["ButtonImage"].id == elem.id)) {

            // change button image
            if (this.get_buttonNormalImageUrl()!=null && this.get_buttonNormalImageUrl()!= "") 
            {
                if (this.get_buttonHoverImageUrl()!=null && this.get_buttonHoverImageUrl()!="")
                {
                    this._elements["ButtonImage"].src = this.get_buttonHoverImageUrl();
                }
                else 
                {
                 this._elements["ButtonImage"].src = this.get_buttonNormalImageUrl();
                }
            }
        
            this.__isButtonClick=true;
        //    this._elements["Input"].focus();
            
            //this.__loadInitial(elem, adr, evnt);
            
            // trigger dropdown open / close
            // this.set_selectedItemIndex(0); // set the first item as the selected one
            if (this.behavior.get_visible()) {
            
                /*
                var args = this._raiseClientEvent('DropDownClosing', 'DropDownContainer', evnt, null);
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    this.behavior.set_visible(false);
                    this._adjustMaxHeight();
                    this._raiseClientEvent('DropDownClosed', 'DropDownContainer', evnt, null);
                }
                */
                this.closeDropDown();

            } else {

                if (this.get_displayMode() != $IG.DropDownDisplayMode.ReadOnly) {
                    
                    /*
                    var args = this._raiseClientEvent('DropDownOpening', 'DropDownContainer', evnt, null);
                    var cancel = args ? args.get_cancel() : false;
                    if (!cancel) {
                        this.behavior.set_visible(true);
                        this._adjustMaxHeight();
                        this._raiseClientEvent('DropDownOpened', 'DropDownContainer', evnt, null);
                    }
                    */

                    this.openDropDown();

                }
            }
            // A.T. Fix for bug #22775
            try 
            {
                this._elements["Input"].focus();
                
            } catch (e)
            {
                // maybe control is disabled, maybe it's not visible, maybe this._element was disposed
                // for some reason - there is no stable way to detect when to call focus() and when not to 
            }
            this.__moveInputCursorToEnd();
            this.__isInternalFocus = true;

        } else {

        }
        
        /*
        if (this.get_enableDropDownOpenOnClick() && this._elements["Input"].hasFocus )
        {
            this.openDropDown();
            this._elements["Input"].select();
        }
        */
    },
    
    _onPasteHandler: function(elem,adr,evnt) 
    {
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
        
        // detect whether value has changed, and if so , fire filtering
        if (evnt==null)
            evnt=elem;
            
        this._currentEvent = evnt;
        
        setTimeout(Function.createDelegate(this, this.filter), 20);
        this.__isPasteOperation = true;
    },
    
    _onCutHandler: function(evnt)
    {
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
        
        this._currentEvent = evnt;
        setTimeout(Function.createDelegate(this, this.filter), 20);
        this.__isPasteOperation = true;
    },
    
    filter: function()
    {
         args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', null, null, this._elements["Input"].value, this.get_currentValue());
         var cancel = args ? args.get_cancel() : false;
         
         if (!cancel && this.get_displayMode() == $IG.DropDownDisplayMode.DropDown) {
                
                // handle value display
            this.set_currentValue(this._elements["Input"].value, false);
            this._raiseClientEvent('ValueChanged', 'DropDownEdit', null, null, this.get_currentValue(), this.get_previousValue());


            if (this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client)
            {
                var args = this._raiseClientEvent('AutoFilterStarting', 'DropDownEdit', null, null, this.get_currentValue(), this.get_previousValue());
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    this.__autoFilter();
                    this._raiseClientEvent('AutoFilterStarted', 'DropDownEdit', null, null, this.get_currentValue(), this.get_previousValue());
                    
                }
                
                if (this.get_enableAutoCompleteFirstMatch())
                {
                    this.__autoCompleteFirstMatch(this._elements["Input"]);
                }
                
            } else if (this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Server)
            {
                clearTimeout(this._timeoutID);
                this.__autoFilterOnServer();
                
            }
            else {
                // find and select first match
                this.__findAndSelectItem();
            }
        }   else {
                    // rollback old value
                    this._elements["Input"].value = this.get_currentValue();
            }
    },
    
    /// onchange event for the input box component
    /// this may be triggered whenever the user pastes text or sth
    _onChangeHandler: function(elem, adr, evnt) {
     
        /*
        if (elem.id == this._elements["Input"].id) {
		
			if (this.get_currentValue() == this._elements["Input"].value)
        return;
				
	        var args;
	        
        if (this._elements["Input"].id == elem.id)             
        args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', evnt, null, this._elements["Input"].value, this.get_currentValue());
	        
        var cancel = args ? args.get_cancel() : false;
        if (!cancel) 
        {
        var previousValue = this.get_currentValue();
        this.set_currentValue(this._elements["Input"].value);
        this._raiseClientEvent('ValueChanged', 'DropDownEdit', evnt, null, this.get_currentValue(), previousValue);
	          
        if (this.get_enableClientFilteringOnly()) 
        {
        // perform auto complete
        if (this.get_enableAutoCompleteFirstMatch())
        {
        this.__autoCompleteFirstMatch(elem,adr, evnt);
        }
	                    
        if (this.get_enableAutoFiltering())
        {
        //if (!(evnt.keyCode== 40 || evnt.keyCode==38)) // up and down arrow keys are intercepted by another event
        //{
        var args = this._raiseClientEvent('AutoFilterStarting', 'DropDownEdit', evnt, null, this.get_currentValue(), this.get_previousValue());
        var cancel = args ? args.get_cancel() : false;
        if (!cancel)
        {
        this.__autoFilter(elem,adr, evnt);  
        this._raiseClientEvent('AutoFilterStarted', 'DropDownEdit', evnt, null, this.get_currentValue(), this.get_previousValue());
        }
        //}
        }
	
	            } else {
	                
        // go to the server to fetch the items
        // if (this.get_previousValue() != this.get_currentValue())
        // {
        this._currentEvent = evnt;
        clearTimeout(this._timeoutID);
        this._timeoutID =  setTimeout(Function.createDelegate(this, this.__autoFilterOnServer), 300); 
        // } 
        }
        }
        }
        */

        //this.filter();
        //this.__isPasteOperation=true;
       
    },
    
    _onMouseoutHandler:function(elem,adr,evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
        
        // remove hover class for control
        $util.removeCompoundClass(this._elements["TargetTable"], this.get_controlAreaHoverCssClass());
    
		// change button image
		//A.T. 26 Feb. Fix for bug #27945 - Exception thrown on hovering the drop-down input field when Button.Visible = False
		if (this.get_showDropDownButton())
		{
			if (this.get_buttonNormalImageUrl()!=null && this.get_buttonNormalImageUrl()!= "" && this._elements["ButtonImage"].src != this.get_buttonNormalImageUrl()) 
			{
				this._elements["ButtonImage"].src = this.get_buttonNormalImageUrl();
			}
        }
    },
    
    _onMouseoverHandler:function(elem,adr,evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
    
        $util.addCompoundClass(this._elements["TargetTable"], this.get_controlAreaHoverCssClass());
        
        // change button image
        //A.T. 26 Feb. Fix for bug #27945 - Exception thrown on hovering the drop-down input field when Button.Visible = False
        if (this.get_showDropDownButton())
        {
			if (this.get_buttonHoverImageUrl()!=null && this.get_buttonHoverImageUrl()!= "" && this._elements["ButtonImage"].src != this.get_buttonHoverImageUrl()) 
			{
				this._elements["ButtonImage"].src = this.get_buttonHoverImageUrl();
			}
        }
    },
    
    _onMouseoutListHandler: function(elem,adr,evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
    
        if (evnt==null) evnt = elem;
        
        var item = this.__getNearestItem(evnt.target);

      //  if (item==null) item = this.__getHoveredItem();
        
        if (item!=null)
        {
            // unhover item , if any
            if (this.__getHoveredItem()) {
                this.__getHoveredItem().unhover();

            }
        }
        this._currentUnhoverEvent = evnt;
        this._unhoverTimeoutID = setTimeout(Function.createDelegate(this, this.__realUnhover), 20);
    }, 
    
    __realUnhover: function()
    {
        this.__setHoveredItem(null);
        var item = this.__getNearestItem(this._currentUnhoverEvent.target);
        this._raiseClientEvent('ItemMouseOut', 'DropDownControl', this._currentUnhoverEvent, null, item);

    },
    
    _onKeypressHandler: function(elem,adr,evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
        
        // check if there is a match, and if EnableCustomValues is false, and there is no match, set cancel to true
        if (!this.get_enableCustomValues())
        {
            if (this.__isDeleting)
            {
                this.__isDeleting=false;
                return;
            }
            
            var character = String.fromCharCode(evnt.charCode);

            // A.T. 23/11/2009 Fix for bug #24843 Not able to type matched value on the selected text when EnableCustomValues set to "false".
            var compareToValue = "";
                        
            if (!this.get_enableAutoCompleteFirstMatch()) {
                compareToValue = this._elements["Input"].value + character;
            } else {
                compareToValue = this.__get_valueBeforeAutoCompleteFirstMatch() + character;
            }

            
            // check selection
            var selectionText = "";
            if ($util.IsIE)
            {
                selectionText = document.selection.createRange().htmlText;
            } else
            {
                var start = this._elements["Input"].selectionStart;
                var end = this._elements["Input"].selectionEnd;
                selectionText = this._elements["Input"].value.substring(start, end);
            }
            
            if (selectionText == this._elements["Input"].value)
            {
               // value will be deleted, so compare only with the character
                compareToValue=character;
            }
            
            this._cancelKeyUp = this.__checkIfValueIsCustom(compareToValue);
            
            if(this._cancelKeyUp)
            {
                evnt.preventDefault();
                $util.cancelEvent(evnt);
            }
        }
    },

    _onKeydownHandler: function(elem, adr, evnt) {
    
        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }

        // raise the keydown client event
       // this._raiseClientEvent('KeyDown', 'DropDownControl', evnt, null);
       this.__isButtonClick=false;
       this.__inKeyUp=false;

        // A.T. 10/07/2009 Fix for bug 19246 (adding support for DEL key)
       if (evnt.keyCode==8 || evnt.keyCode == 127) // backspace and DEL 
       {
        this.__isDeleting=true;
       } else {
       
        this.__isDeleting=false;
       }
       
       // disallow F1 to F12 ;
       // A.T. 20/07/2009 Bug 19586: keyCode "99" is Numlock 3 and should not be disallowed 
       if ((evnt.keyCode >= 112 && evnt.keyCode <= 123) || evnt.keyCode==20 || evnt.keyCode==19 || (evnt.keyCode==45 && !evnt.shiftKey) 
       || evnt.keyCode==93 || evnt.keyCode==92 || evnt.keyCode==145
       )
       {
            evnt.preventDefault();
            $util.cancelEvent(evnt);
            return;
       }

        if (evnt.keyCode == 40 || evnt.keyCode == 38 || evnt.keyCode == 13 || evnt.keyCode == 32 || 
        
        evnt.keyCode==33 || evnt.keyCode==34 || evnt.keyCode==35 || evnt.keyCode==36) {

            this.__handleKbNavigation(evnt);

        }

        if (this._elements["Input"].id == elem.id) {
        
            // fire InputKeyDown event 
            this._raiseClientEvent('InputKeyDown', 'DropDownControl', evnt, null);
            
            // store previous value
            this.set_previousValue(this._elements["Input"].value);
            
            // RETURN KEY
            if (evnt.keyCode == 13) {
                // cancel the form submission on Enter key
                evnt.preventDefault();
                $util.cancelEvent(evnt);
            }
        }

        if (evnt.keyCode == 27) // ESC key 
        {
            if (this.behavior.get_visible()) {
                var args = this._raiseClientEvent('DropDownClosing', 'DropDownContainer', evnt, null);
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    this.behavior.set_visible(false);
                   // this._adjustMaxHeight();
                    this._raiseClientEvent('DropDownClosed', 'DropDownContainer', evnt, null);
                }
            }
        }
    },

    _onKeyupHandler: function(elem, adr, evnt) {

        if (this.get_enabled() == false)
        {
            // do not intercept events if control is marked as disabled
            return;
        }
        
        if (this.__isPasteOperation)
        {
            this.__isPasteOperation=false;
            return;
            
        }
        
        if (this._cancelKeyUp)
        {
            this._cancelKeyUp=false;
            return;
            
        }
        
        // paste keyboard commands are handled by the onPasteHandler
        if ((evnt.keyCode==45 && evnt.shiftKey) || (evnt.ctrlKey && evnt.keyCode== 86))
        {
            return;
        }
        
        if (evnt==null) 
        {
            evnt = elem;
            elem = evnt.target;
        }
        
        if (evnt.event)
            evnt = evnt.event;
        
        if (this._elements["Input"].id == elem.id) 
        {
            // fire InputKeyUp event 
            this._raiseClientEvent('InputKeyUp', 'DropDownControl', evnt, null);
        }
        
        if (evnt.keyCode == 27 || evnt.keyCode == 9) // ESC key is handled in onKeydownHandler; Do nothing for TAB key
            return;
        
        // Fx keys
    // disallow F1 to F12 ; 
       if ((evnt.keyCode >= 112 && evnt.keyCode <= 123) || evnt.keyCode==20 || evnt.keyCode==19 || evnt.keyCode==45
       || evnt.keyCode==93 || evnt.keyCode==92 || evnt.keyCode==145
       )
       {
            return;
       }
       // A.T. 20/07/2009 Bug 19586: keyCode "99" is Numlock 3 and should not be disallowed 
        if (evnt.keyCode == 16 || evnt.keyCode == 17 || evnt.keyCode == 18
        || evnt.keyCode == 33 || evnt.keyCode == 34 || evnt.keyCode==35 || evnt.keyCode==36
        || evnt.keyCode == 91 || evnt.keyCode == 144 )
        {
            return;
        }

        // handle key up on the list -> up arrow and down arrow !

        // toggle dropdown (open or close)
        if (evnt.altKey && (evnt.keyCode == 40 || evnt.keyCode == 38)) {
            if (evnt.keyCode == 38) {

                /*
                var args = this._raiseClientEvent('DropDownClosing', 'DropDownContainer', evnt, null);
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    this.behavior.set_visible(false);
                    this._raiseClientEvent('DropDownClosed', 'DropDownContainer', evnt, null);
                }*/

                this.closeDropDown();
                return;

            } else if (evnt.keyCode == 40) {

                 
                if (this.get_displayMode() != $IG.DropDownDisplayMode.ReadOnly) {
                    /*
                    var args = this._raiseClientEvent('DropDownOpening', 'DropDownContainer', evnt, null);
                    var cancel = args ? args.get_cancel() : false;
                    if (!cancel) {
                        this.behavior.set_visible(true);
                        this._adjustMaxHeight();
                        this._raiseClientEvent('DropDownOpened', 'DropDownContainer', evnt, null);
                    }
                    */
                    this.openDropDown();
                    return;
                }
            }
        }

        // keycode 45 == INSERT key
        if (evnt.ctrlKey || evnt.altKey || (evnt.shiftKey && evnt.keyCode == 45))
            return;

        // if (evnt.keyCode== 40 || evnt.keyCode==38 || evnt.keyCode==13) 
        // {
        //     this.__handleKbNavigation(evnt);

        // } else 
        
        
        if (evnt.keyCode == 37 || evnt.keyCode == 39)
        {
            // we will do filtering if there was selected text in the input, and by moving
            // the left and right arrow keys, the selection is gone
            if (this.get_currentValue() == this.__get_valueBeforeAutoCompleteFirstMatch())
            {
                return;
            }
        }

        if (evnt.keyCode != 40 && evnt.keyCode != 38 && evnt.keyCode != 13) {
            var args;

            if (this._elements["Input"].id == elem.id || this._element == elem.id) {

                // check if custom selection is enabled
             //   if (this.get_enableCustomValueSelection() && this.get_enableClientFilteringOnly() && evnt.keyCode != 27 &&
             
              /* <<------------------------------
             if (this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client && evnt.keyCode != 27 &&
		        	evnt.keyCode != 13 && evnt.keyCode != 40 && evnt.keyCode != 38) // also handle backspace ?
                {
                    var hasMatch = false;
                    var currentText = this._elements["Input"].value;

                    // check if the currentText exists
                    var items = this.get_items()._items;
                    for (i = 0; i < items.length; i++) {
                        if (items[i].get_text().toLowerCase().startsWith(currentText)) {
                            hasMatch = true;
                            break;
                        }
                    }

                    if (!hasMatch) // no match, don't change the value and don't perform auto filtering, don't raise events
                    {
                        this._elements["Input"].value = this.get_currentValue();
                        return;
                    }

               // } else if (this.get_enableCustomValueSelection() && !this.get_enableClientFilteringOnly() && evnt.keyCode != 27 &&
               
               }
               */  /* <<------------------------------*/
               
               
               /* else if (!this.get_enableClientFilteringOnly() && evnt.keyCode != 27 &&
		        	evnt.keyCode != 13 && evnt.keyCode != 40 && evnt.keyCode != 38 && this.get_enableAutoFiltering()) {
                    this._currentEvent = evnt;
                    clearTimeout(this._timeoutID);
                    this._timeoutID = setTimeout(Function.createDelegate(this, this.__autoFilterOnServerCustom), this.get_autoFilterTimeoutMs());
                    return;
                }
                */
                
                args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', evnt, null, this._elements["Input"].value, this.get_currentValue());

            }

            var cancel = args ? args.get_cancel() : false;
            
            if (!cancel && this.get_displayMode() == $IG.DropDownDisplayMode.DropDown) {
                
                // handle value display
                if (this._elements["Input"].id == elem.id) {

                    // no change
                   // if (this._elements["Input"].value.toLowerCase() == this.get_currentValue().toLowerCase())
                   // {
                   //     return;
                   // }
                    if (this.__inKeyUp)
                    {
                        return;
                    } else 
                    {
                        this.__inKeyUp=true;
                    }
                    
                    this.set_currentValue(this._elements["Input"].value, false);

                    this._raiseClientEvent('ValueChanged', 'DropDownEdit', evnt, null, this.get_currentValue(), this.get_previousValue());

                    if (this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client) {

                    this._currentEvent = evnt;
                      //  if (this.get_enableAutoFiltering()) {
                            if (!(evnt.keyCode == 40 || evnt.keyCode == 38)) // up and down arrow keys are intercepted by another event
                            {
                                var args = this._raiseClientEvent('AutoFilterStarting', 'DropDownEdit', evnt, null, this.get_currentValue(), this.get_previousValue());
                                var cancel = args ? args.get_cancel() : false;
                                if (!cancel) {
                                   // this.__autoFilter(elem, adr, evnt);
                                    clearTimeout(this._timeoutID);
                                    // this.__start1 = new Date().getTime();
                                    this._timeoutID = setTimeout(Function.createDelegate(this, this.__autoFilter), 50);
                                    this._raiseClientEvent('AutoFilterStarted', 'DropDownEdit', evnt, null, this.get_currentValue(), this.get_previousValue());
                                }
                            }
                      //  }
                      // perform auto complete
                        if (this.get_enableAutoCompleteFirstMatch()) {
                            //this.__autoCompleteFirstMatch(elem, adr, evnt);
                             clearTimeout(this._autoCompleteTimeoutID);
                            // this.__start1 = new Date().getTime();
                            this._autoCompleteTimeoutID = setTimeout(Function.createDelegate(this, this.__autoCompleteFirstMatch), 50);
                        }


                    } else if (this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Server) {

                        // go to the server to fetch the items
                        // if (this.get_previousValue() != this.get_currentValue())
                        // {
                        this._currentEvent = evnt;
                        clearTimeout(this._timeoutID);
                       // this.__start1 = new Date().getTime();
                        this._timeoutID = setTimeout(Function.createDelegate(this, this.__autoFilterOnServer), this.get_autoFilterTimeoutMs());
                        // } 
                        
                    } else {
                    
                        this.__findAndSelectItem(elem,adr,evnt);
                    }
                }

            } else {
                    // rollback old value
                    this._elements["Input"].value = this.get_currentValue();
            }
        }
    },
    
    __get_valueBeforeAutoCompleteFirstMatch: function()
    {
        return (this.__valueBeforeAutoCompleteFirstMatch == null) ? this.get_currentValue() : this.__valueBeforeAutoCompleteFirstMatch;
    },
    
    __set_valueBeforeAutoCompleteFirstMatch: function(val)
    {
        this.__valueBeforeAutoCompleteFirstMatch = val;
    },
    
    __findAndSelectItem: function(elem,adr,evnt)
    {
        if (evnt!=null && evnt.keyCode != 27 && evnt.keyCode != 13 && evnt.keyCode != 40 && evnt.keyCode != 38) // also handle backspace ?
        {
            var hasMatch = false;
            var currentText = this._elements["Input"].value;
            
            var matchedItem=null;

            // check if the currentText exists
           // var items = this.get_items()._items;
           
            if (this.get_enableCaseSensitivity())
            {
                for (i = 0; i < this.get_items().getLength(); i++) {
                   // if (items[i].get_text() == currentText || items[i].get_text().startsWith(currentText)) {
                   if (this.get_items().getItem(i).get_text() == currentText || this.get_items().getItem(i).get_text().startsWith(currentText)) {
                        matchedItem = this.get_items().getItem(i);
                        hasMatch = true;
                        break;
                    }
                }
            } else 
            {
                for (i = 0; i < this.get_items().getLength(); i++) {
                   // if (items[i].get_text() == currentText.toLowerCase() || items[i].get_text().toLowerCase().startsWith(currentText.toLowerCase())) {
                   if (this.get_items().getItem(i).get_text() == currentText.toLowerCase() || this.get_items().getItem(i).get_text().toLowerCase().startsWith(currentText.toLowerCase())) {
                        matchedItem = this.get_items().getItem(i);
                        hasMatch = true;
                        break;
                    }
                }
            }

            if (hasMatch && matchedItem!=null && !matchedItem.get_disabled()) // select item and scroll to it 
            {
                if (this.get_autoSelectOnMatch())
                {
                     var oldIndex = this.get_selectedItemIndex();
                    // var oldItem = oldIndex == -1 ? null : this.get_items()._getObjectByIndex(oldIndex);
                    var oldItem = oldIndex == -1 ? null : this.get_items().getItem(oldIndex);
                    
                    //A.T. 1 Sept. 2009 - Fix for bug 21172: When selection is set to the same previous selection, postback is made, but the SelectionChanged event is not fired on the server-side
                    if (matchedItem.get_index()!= this.get_selectedItemIndex())
                    {
                         var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', evnt, null, [matchedItem], [oldItem]);
                         var cancel = args ? args.get_cancel() : false;
                         if (!cancel) {
                            this.__unselectAllItems();
                            matchedItem.select();
                            //this.set_selectedItemIndex(matchedItem.get_index());
                            this.set_selectedItemIndex(matchedItem.get_index());
                            
                            if (!this.behavior.get_visible() && !this.behavior.get_isAnimating())
                            {
                                this.openDropDown();
                            }
                            this.__scrollToItem(matchedItem);
                            // activate ? 
                            this.set_activeItem(matchedItem);
                            
                            this._raiseClientEvent('SelectionChanged', 'DropDownSelection', evnt, null, [matchedItem], [oldItem]);
                            
                        } 
                    }
                }
                else
                {
                    if (!this.behavior.get_visible() && !this.behavior.get_isAnimating())
                    {
                        this.openDropDown();
                    }
                    this.__scrollToItem(matchedItem);
                }
                
            } else {
                this.__unselectAllItems();
                // A.T. 30/11/2009 Fix for bug #25247 - When typing a custom value with EnableAutoFiltering = Off/Client, the index of the selected item is not reset to -1
                this.__resetSelection(oldItem,evnt);
            }
        }
        
        if (this.get_enableAutoCompleteFirstMatch()) {
            if (elem==null)
                elem = this._elements["Input"];
            this.__autoCompleteFirstMatch(elem, adr, evnt);
        }     
    },
    
    __resetSelection: function(currentSelectedItem,event)
    {
        // check index and if the old one is != -1, change it and fire events 
        if (this.get_selectedItemIndex() != -1)
        {
            // fire events and change index 
			//A.T. 6th of Feb 2010 - Fix for bug #27004 - Javascript error is thrown when we  try to access the old selected items.
            var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', event, null, [], [currentSelectedItem]);
            var cancel = args ? args.get_cancel() : false;
            if (!cancel) 
            {
                this.set_selectedItemIndex(-1);
				//A.T. 6th of Feb 2010 - Fix for bug #27004 - Javascript error is thrown when we  try to access the old selected items.
                this._raiseClientEvent('SelectionChanged', 'DropDownSelection', event, null, [], [currentSelectedItem]);
            }
        }
    },
   
    __scrollToItem: function(item) {
        
       // var firstItem = this.get_items()._items[0];
      // var offset = Sys.UI.DomElement.getBounds(item._element).height* item.get_index();
        var offset = Math.abs($util.getPosition(item._element).y - $util.getPosition(this._elements["DropDownContents"]).y);
        this._elements["DropDownContents"].scrollTop = offset;
        
    },
    
    __checkIfValueIsCustom: function(val) 
    {
       // var items = this.get_items()._items;
        for (i=0;i<this.get_items().getLength();i++)
        {
           // if (items[i].get_text().toLowerCase().startsWith(val.toLowerCase()))
           if (this.get_items().getItem(i).get_text().toLowerCase().startsWith(val.toLowerCase()))
                return false;
        }
        return true;
    },

    __getNextVisibleItem: function(selectedIndex) {
    
        var length = this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client ? this.__clientFilteringItemCount : this.get_items().getLength();
       
        if (selectedIndex >= 0 && selectedIndex < length) {
            var index = selectedIndex + 1;

            while (index < length) {
              //  var nextItem = this.get_items()._getObjectByIndex(index);
               var nextItem = this.get_items().getItem(index);
                if (nextItem._get_visible() && !nextItem.get_disabled())
                    return nextItem;

                index++;
            }
        }

        return null;
    },

    __getPreviousVisibleItem: function(selectedIndex) {
    
        var length = this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client ? this.__clientFilteringItemCount : this.get_items().getLength();
       
        if (selectedIndex >= 0 && selectedIndex < length) {
            var index = selectedIndex - 1;
            while (index >= 0) {
                //var prevItem = this.get_items()._getObjectByIndex(index);
                var prevItem = this.get_items().getItem(index);
                if (prevItem._get_visible() && !prevItem.get_disabled())
                    return prevItem;

                index--;
            }
        }

        return null;
    },
    
    // e - event, newItem - item that will be selected, oldItem - currently selected item 
    __singleSelect: function(e, newItem, oldItem) 
    {
        if ((newItem!=null && oldItem!=null && newItem.get_index() != oldItem.get_index()) || (newItem==null || oldItem==null))
        {
            var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', e, null, [newItem], [oldItem]);
            var cancel = args ? args.get_cancel() : false;
            if (!cancel) {
               
               if (this.get_enableMultipleSelection())
               { 
                    this.__unselectAllItems();
               } else 
               {
                    if (this.get_selectedItem()!=null)
                    {
                        this.get_selectedItem().unselect();
                    }
               }
               newItem.select();

                //this.set_selectedItemIndex(newItem.get_index());
                this.set_selectedItemIndex(newItem.get_index());

                if (this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Checkbox) {
                    newItem._element.childNodes[0].checked = true;
                    
                   if (oldItem)
                        oldItem._element.childNodes[0].checked = false;
                }
            
                this._raiseClientEvent('SelectionChanged', 'DropDownSelection', e, null, [newItem], [oldItem]);        
            }
        }
    },
    
    __multipleNoncontinuousSelect:function(e,newItem, allowUnselectActiveItem)
    {
    
        var oldSelectedItems = this.get_selectedItems();
        var newSelectedItems;
                          
        // construct newSelectedItems
        if (newItem.get_selected())
        {
            // remove item 
            newSelectedItems = new Array();
            for (var i=0; i < oldSelectedItems.length; i++)
            {
                if (oldSelectedItems[i].get_index() != newItem.get_index())
                {
                    newSelectedItems.push(oldSelectedItems[i]);
                }   
            }
            
        } else 
        {
            // add item
            newSelectedItems = Array.clone(oldSelectedItems);
            newSelectedItems.push(newItem);
        }
        
        var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', e, null, newSelectedItems, oldSelectedItems);
        var cancel = args ? args.get_cancel() : false;
        if (!cancel) {
           
           if (newItem.get_selected() && (!newItem.get_activated() || allowUnselectActiveItem))
           { 
                newItem.unselect();
           }
           else if (!newItem.get_selected())
           {
                newItem.select();
                //this.set_selectedItemIndex(newItem.get_index());
                this.set_selectedItemIndex(newItem.get_index());
           }

            if (this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Checkbox) {
                newItem._element.childNodes[0].checked = true;
              //  if (currentItem)
                    newItem._element.childNodes[0].checked = false;
            }
        
            this._raiseClientEvent('SelectionChanged', 'DropDownSelection', e, null, newSelectedItems, oldSelectedItems);        
        }
    },
    
    __multipleContinuousSelect:function()
    {
    
    },

    // implements all of the keyboard navigation functionality
    __handleKbNavigation: function(e) {
        this.__isDropDownEvent = true;

        if (this.get_displayMode() == $IG.DropDownDisplayMode.ReadOnlyList)
            return;


        //var selectedIndex = this.get_selectedItemIndex();
        
        var activeItemIndex = 0;
        if (this.get_activeItem() !=null)
        {
            //activeItemIndex = this.get_items().get_indexOf(this.get_activeItem());
            activeItemIndex = this.get_activeItem().get_index();
        }

        //if (selectedIndex == null)
        //    selectedIndex=0;

        //var currentItem = this.get_items()._getObjectByIndex(activeItemIndex);
        var currentItem = this.get_items().getItem(activeItemIndex);
        
       // if (currentItem==null)
       //     return;
       
             // END KEY
      var length = this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client ? this.__clientFilteringItemCount : this.get_items().getLength();
       
      if (e.keyCode==35)
      {
      
        if (length==0)
            return;
            
       // var lastItem = this.get_items()._items[this.get_items()._items.length-1];
       var lastItem = this.get_items().getItem(length-1);
        if (lastItem!=null)
        {
            this.__scrollToItem(lastItem);
            this.set_activeItem(lastItem);
            if (!this.get_enableMultipleSelection() || (this.get_multipleSelectionType() != $IG.DropDownMultipleSelectionType.Checkbox && this.get_enableMultipleSelection()))
                this.__singleSelect(e,lastItem,currentItem);
        }
        return;
      }
      
      // HOME KEY
      if (e.keyCode == 36)
      {
        if (length<=0)
            return;
          
       // var firstItem = this.get_items()._items[0];
       var firstItem = this.get_items().getItem(0);
        if (firstItem!=null)
        {
            this.__scrollToItem(firstItem);
            this.set_activeItem(firstItem);
             if (!this.get_enableMultipleSelection() || (this.get_multipleSelectionType() != $IG.DropDownMultipleSelectionType.Checkbox && this.get_enableMultipleSelection()))
                this.__singleSelect(e,firstItem,currentItem);
        }
        return;
        
      }
      
      /*
      
      NOT IMPLEMENTED 
      
      // PAGE DOWN
      if (e.keyCode == 34)
      {
        
      }
      
      // PAGE UP
      if (e.keyCode == 33)
      {
      
      }
      */

        if (currentItem && currentItem._get_visible()) {

            //if (!currentItem.get_selected()) {
            //    currentItem.select();
            //    return;
            //}
            
            if (!currentItem.get_activated() && !e.altKey && !e.ctrlKey && !e.shiftKey && !currentItem.get_disabled())
            {
                this.set_activeItem(currentItem);
                 if (!this.get_enableMultipleSelection() || (this.get_multipleSelectionType() != $IG.DropDownMultipleSelectionType.Checkbox && this.get_enableMultipleSelection()))
                    this.__singleSelect(e, currentItem,null);
                return;
            }
            
        } else {

            // get the nearest item that is visible
            currentItem = this.__getNextVisibleItem(activeItemIndex);

            if (!currentItem)
                currentItem = this.__getPreviousVisibleItem(activeItemIndex);

          //  if (currentItem && !currentItem.get_selected()) {
          //      currentItem.select();
          //      return;
          //  }
            if (currentItem && !currentItem.get_activated() && !e.altKey && !e.ctrlKey && !e.shiftKey && !currentItem.get_disabled())
            {
                this.set_activeItem(currentItem);
                 if (!this.get_enableMultipleSelection() || (this.get_multipleSelectionType() != $IG.DropDownMultipleSelectionType.Checkbox && this.get_enableMultipleSelection()))
                    this.__singleSelect(e, currentItem,null);
                return;
            }

        }
        
       // if (currentItem==null)
       //     return;

        //if (currentItem && currentItem.get_disabled())
        //    return;

        var container = this._elements["DropDownContents"];
        var container_pos = $util.getPosition(container);
        
        // ENTER and SPACE key handling
      //  if ((e.keyCode == 13 || (e.keyCode == 32 && !this._elements["Input"].focused)) && currentItem!=null) 
      
      if (e.keyCode==32 && e.ctrlKey && currentItem!=null)
      {
          this.__multipleNoncontinuousSelect(e, currentItem, true);
          // rollback the old value, so that we avoid having an interval character in the input box 
          this.__constructMultiSelectValue(e);
          this.__moveInputCursorToEnd();
          this.__lastSelectionWasContinuous=false;
      }
      
      if (e.keyCode == 13  && currentItem!=null) 
        {
        
            //if (currentItem != null) {
            //    this._elements["Input"].value = currentItem.get_text();
            //}
            
            // A.T. 22/09/2009 Fix for bug #22142 Keyboard directional should be used as navigation when multiple selection through checkboxes is enabled
            if (currentItem.get_selected() || (this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Checkbox && this.get_enableMultipleSelection()) || !this.get_enableMultipleSelection())
            {
                
                if (!currentItem.get_selected())
                {
                    this.__singleSelect(e,currentItem,null);
                 
                    args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, currentItem.get_text(), this.get_currentValue());

                    var cancel = args ? args.get_cancel() : false;
                    if (!cancel) {
                        var previousValue = this.get_currentValue();
                        this.set_currentValue(currentItem.get_text(),true);
                        this._raiseClientEvent('ValueChanged', 'DropDownEdit', e, null, this.get_currentValue(), previousValue);
                    }
                }

                if (this.get_closeDropDownOnSelect()) {
                  //  var args = this._raiseClientEvent('DropDownClosing', 'DropDownContainer', e, null);
                  //  var cancel = args ? args.get_cancel() : false;
                  //  if (!cancel) {
                  //      this.behavior.set_visible(false);
                  //      this._raiseClientEvent('DropDownClosed', 'DropDownContainer', e, null);
                  //  }
                  
                  this.closeDropDown();
                  
                }
                
                // navigate URL 
                var url = currentItem.get_navigateUrl();
                var targetFrame = currentItem.get_target();
                
                // TFS Bug # 15806: if the url is empty, set the target frame to self, so that
                // we don't get a blank new window. Instead the dropdown will be just closed 
                if (url==null || url=="") targetFrame="_self";
                
                if(targetFrame == "_self" 
					    || targetFrame == "_parent"
					    || targetFrame == "_media"
					    || targetFrame == "_top"
					    || targetFrame == "_blank"
					    || targetFrame == "_search")
					    window.open(url, targetFrame);
				    else
					    window.open(url);
    					
		    }
            /*
            if (!e.ctrlKey && !e.shiftKey && !currentItem.get_disabled())
            {
                
                // select item
                var oldIndex = this.get_selectedItemIndex();
                
                // unselect old item
                var oldItem = this.get_items()._getObjectByIndex(oldIndex);
                //if (oldItem!=null && oldItem.get_selected())
                //{
                //    oldItem.unselect();
                //}
                
                // changed the above to this 
                this.__unselectAllItems();

                var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', e, null, [currentItem], [oldItem]);
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    if (currentItem.get_selected()) {
                        currentItem.unselect();
                    } else 
                    {
                        currentItem.select();
                    }
                    this.set_selectedItemIndex(currentItem.get_index());

                    if (this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Checkbox) {
                        currentItem._element.childNodes[0].checked = true;
                        if (currentItem)
                            currentItem._element.childNodes[0].checked = false;
                    }
                    // this._elements["Input"].value = prevItem.get_text(); 

                    // update value displ. & raise value changed event  ? 
                   // args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, this._elements["Input"].value, this.get_currentValue());
                   args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, currentItem.get_text(), this.get_currentValue());

                    var cancel = args ? args.get_cancel() : false;
                    if (!cancel) {
                        var previousValue = this.get_currentValue();
                        this.set_currentValue(currentItem.get_text(), true);
                        this._raiseClientEvent('ValueChanged', 'DropDownEdit', e, null, this.get_currentValue(), previousValue);
                    }

                    this._raiseClientEvent('SelectionChanged', 'DropDownSelection', e, null, [currentItem], [oldItem]);
                }
            
            } else if (e.shiftKey && this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Keyboard)  // continuous selection with the keyboard only
            {
                          // navigate = false;
                
                var currentItemIndex = this.get_items().get_indexOf(currentItem);
                
                // find closest selected item
                var prevItemIndex = this.__findClosestSelected(currentItemIndex);
                
                if (currentItemIndex > prevItemIndex)
                {
                    // construct selected items arrays
                     var oldSelectedItems = this.get_selectedItems();
                     var newSelectedItems = new Array();
                     
                    for (i=prevItemIndex; i<= currentItemIndex; i++)
                    {
                        if (!this.get_items().getItem(i).get_disabled())
                        {
                            newSelectedItems.push(this.get_items().getItem(i));
                        }
                    }
                    
                    // fire 'ing' event
                    // fire selection changing event
                    var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', e, null, newSelectedItems, oldSelectedItems);
                    var cancel = args ? args.get_cancel() : false;
        
                    if (!cancel)
                    {
                        // unselect all first 
                        this.__unselectAllItems();
                        
                        for (i= prevItemIndex; i <= currentItemIndex; i++)
                        {
                            var item = this.get_items().getItem(i);
                            if (!item.get_disabled() && (!item.get_custom() ) || (item.get_custom() && this.get_enableCustomValueSelection()))
                            {
                                item.select();
                            }
                        }
                        
                         // fire selection changed event
                         this.set_shouldFireMultipleSelect(true);
                        this._raiseClientEvent('SelectionChanged', 'DropDownSelection', e, null, newSelectedItems, oldSelectedItems);
                    
                    }
                    
                } 
                else if (currentItemIndex < prevItemIndex)
                {
                    // construct selected items arrays and fire events 
                    
                    // construct selected items arrays
                     var oldSelectedItems = this.get_selectedItems();
                     var newSelectedItems = new Array();
                     
                    for (i=currentItemIndex; i<= prevItemIndex; i++)
                    {
                        if (!this.get_items().getItem(i).get_disabled())
                        {
                            newSelectedItems.push(this.get_items().getItem(i));
                        }
                    }
                    
                    // fire 'ing' event
                    // fire selection changing event
                    var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', e, null, newSelectedItems, oldSelectedItems);
                    var cancel = args ? args.get_cancel() : false;
        
                    if (!cancel)
                    {
                        // unselect all items first
                        this.__unselectAllItems();    
                        
                        for (i= currentItemIndex; i <= prevItemIndex; i++)
                        {
                            var item = this.get_items().getItem(i);
                            if (!item.get_disabled() && (!item.get_custom() ) || (item.get_custom() && this.get_enableCustomValueSelection()))
                            {
                                item.select();
                            }
                        }
                        
                        // fire selection changed event
                        this.set_shouldFireMultipleSelect(true);
                        this._raiseClientEvent('SelectionChanged', 'DropDownSelection', e, null, newSelectedItems, oldSelectedItems);
                        
                    }
                }
                
            } else if (e.ctrlKey && !currentItem.get_disabled() &&  this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Keyboard) // non-continuous selection with the keyboard only 
            {
                //navigate = false;
                    
                    if ((!currentItem.get_custom() ) || (currentItem.get_custom() && this.get_enableCustomValueSelection()))
                    {
                    
                        // fire the SelectionChanging event 
                        // 1. get current array of selected items
                        var oldSelectedItems = this.get_selectedItems();
                                                
                        // construct newSelectedItems
                        if (currentItem.get_selected())
                        {
                            // remove item 
                            var newSelectedItems = new Array();
                            for (var i=0; i < oldSelectedItems.length; i++)
                            {
                                if (oldSelectedItems[i].get_index() != currentItem.get_index())
                                {
                                    newSelectedItems.push(oldSelectedItems[i]);
                                }   
                            }
                            
                        } else 
                        {
                            // add item
                            var newSelectedItems = Array.clone(oldSelectedItems);
                            newSelectedItems.push(currentItem);
                        }
                    
                        // fire selection changing event
                        var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', e, null, newSelectedItems, oldSelectedItems);
                        var cancel = args ? args.get_cancel() : false;
            
                        if (!cancel)
                        {
                            
                            if (!currentItem.get_selected())
                            {
                                currentItem.select();
                            } else
                            {
                                currentItem.unselect();
                            }
                                                    
                            // fire selection changed event
                            this.set_shouldFireMultipleSelect(true);
                            this._raiseClientEvent('SelectionChanged', 'DropDownSelection', e, null, newSelectedItems, oldSelectedItems);
                            
                            this.__lastSelectionWasContinuous=false;
                        }
                    }
                        
            }
            
            if ((e.ctrlKey || e.shiftKey) && this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Keyboard)
            {
               
                this.set_activeItem(currentItem);
                //var currentVal = this.get_currentValue();
                //var delim = this.get_multiSelectValueDelimiter();
                //this.set_currentValue(currentVal+delim+item.get_text());

                var currentVal = '';
                var delim = this.get_multiSelectValueDelimiter();

                // go through all items and check which are selected
                var isFirst = true;

                for (var i = 0; i < this.get_items()._items.length; i++) {
                    if (this.get_items()._items[i].get_selected()) {
                        if (!isFirst) {
                            currentVal += delim + this.get_items()._items[i].get_text();
                        }
                        else {
                            // first item, don't put delim in front
                            currentVal += this.get_items()._items[i].get_text();
                            isFirst = false;
                        }
                    }
                }

               // args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, this._elements["Input"].value, this.get_currentValue());
               args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, currentVal, this.get_currentValue());

                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    var previousValue = this.get_currentValue();
                    this.set_currentValue(currentVal, true);
                    this._raiseClientEvent('ValueChanged', 'DropDownEdit', e, null, this.get_currentValue(), previousValue);
                }

            }
            */
        }

        // down arrow and up arrows only change the activation, when we hit space or enter, selection happens for the active item !
        if (e.keyCode == 40 && !e.altKey) // down arrow
        {

            //var nextItem = this.get_items()._getObjectByIndex(++activeItemIndex);
            var nextItem = this.get_items().getItem(++activeItemIndex);

            if (nextItem && (!nextItem._get_visible() || nextItem.get_disabled()))
                
                nextItem = this.__getNextVisibleItem(activeItemIndex);
            
            if (nextItem) {

             //   this.set_activeItem(nextItem);
                
                if (!e.ctrlKey && !e.shiftKey)
                {
                    this.set_activeItem(nextItem);
                    // select item
                    var oldIndex = this.get_selectedItemIndex();
                    
                    // unselect old item
                   // var oldItem = this.get_items()._getObjectByIndex(oldIndex);
                   var oldItem = this.get_items().getItem(oldIndex);
                   
                   // A.T. 22/09/2009 Fix for bug #22142 Keyboard directional should be used as navigation when multiple selection through checkboxes is enabled
                   if (!this.get_enableMultipleSelection() || (this.get_multipleSelectionType() != $IG.DropDownMultipleSelectionType.Checkbox && this.get_enableMultipleSelection()))
                   {
                        this.__singleSelect(e,nextItem,oldItem);
                    
                        if (nextItem!=null && oldItem!=null && nextItem.get_index() != oldItem.get_index() || (nextItem==null || oldItem==null))
                        {
                              // update value displ. && raise value changed event
                              //  args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, this._elements["Input"].value, this.get_currentValue());
                              args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, nextItem.get_text(), this.get_currentValue());

                            var cancel = args ? args.get_cancel() : false;
                            if (!cancel) {
                                var previousValue = this.get_currentValue();
                                this.set_currentValue(nextItem.get_text(), true);
                                this._raiseClientEvent('ValueChanged', 'DropDownEdit', e, null, this.get_currentValue(), previousValue);
                            }
                        }
                    }
                    
                } else if (e.keyCode==40 && e.shiftKey && this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Keyboard)
                {

                    if (!this.__lastSelectionWasContinuous)
                    {
                        this.__unselectAllItemsWithoutActiveItem();
                    }
                    
                    this.set_activeItem(nextItem);
                    if (nextItem.get_selected()) 
                    {
                        currentItem.unselect();
                    }
                    
                    this.__multipleNoncontinuousSelect(e, nextItem);
                    
                    this.__lastSelectionWasContinuous=true;
                    
                } else if (e.keyCode==40 && e.ctrlKey && this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Keyboard)
                {
                    this.set_activeItem(nextItem);
                    this.__lastSelectionWasContinuous=false;
                   // this.__multipleNoncontinuousSelect(e,nextItem);
                }

            } else {

                /*
                // only change the class  to hover
                if (nextItem) {
                
                this.set_hoverItemIndex(nextItem.get_index());
                nextItem.hover();
                    
                if (currentItem)
                currentItem.unhover();
                }
                */
            }

            // this._elements["Input"].value = nextItem.get_text();

            if (nextItem) {

                var pos = $util.getPosition(nextItem._element);
             
                if (pos.y + Sys.UI.DomElement.getBounds(nextItem._element).height > container_pos.y + container.offsetHeight) {
                //    container.scrollTop = container.scrollTop + Sys.UI.DomElement.getBounds(nextItem._element).height;
                //   container.scrollTop =container.scrollTop +  pos.y - container_pos.y;
                 container.scrollTop = (pos.y + Sys.UI.DomElement.getBounds(nextItem._element).height) - (container_pos.y + container.offsetHeight);

                }

            }
            //  selectedIndex++;  

        } else if (e.keyCode == 38 && !e.altKey) // up arrow
        {

            // selectedIndex--;
            //var prevItem = this.get_items()._getObjectByIndex(--activeItemIndex);
            var prevItem = this.get_items().getItem(--activeItemIndex);

            if (prevItem && (!prevItem._get_visible() || prevItem.get_disabled()))
                prevItem = this.__getPreviousVisibleItem(activeItemIndex);

            if (prevItem) {
            
                //prevItem.activate();
                //this.set_activeItem(prevItem);
                    
                if (!e.ctrlKey && !e.shiftKey)
                {
                    this.set_activeItem(prevItem);
                    // select item
                    var oldIndex = this.get_selectedItemIndex();
                    
                    // unselect old item
                    //var oldItem = this.get_items()._getObjectByIndex(oldIndex);
                    var oldItem = this.get_items().getItem(oldIndex);
                    //if (oldItem!=null && oldItem.get_selected())
                    //{
                    //    oldItem.unselect();
                    //}
                    
                    // A.T. 22/09/2009 Fix for bug #22142 Keyboard directional should be used as navigation when multiple selection through checkboxes is enabled
                    if (!this.get_enableMultipleSelection() || (this.get_multipleSelectionType() != $IG.DropDownMultipleSelectionType.Checkbox && this.get_enableMultipleSelection()))
                    {
                        this.__singleSelect(e,prevItem,oldItem);
                    
                        if (nextItem!=null && prevItem!=null && nextItem.get_index() != prevItem.get_index() || (nextItem==null || prevItem==null))
                        {
                              // update value displ. && raise value changed event
                              //  args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, this._elements["Input"].value, this.get_currentValue());
                            args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, prevItem.get_text(), this.get_currentValue());

                            var cancel = args ? args.get_cancel() : false;
                            if (!cancel) {
                                var previousValue = this.get_currentValue();
                                this.set_currentValue(prevItem.get_text(),true);
                                this._raiseClientEvent('ValueChanged', 'DropDownEdit', e, null, this.get_currentValue(), previousValue);
                            }
                        }
                    }
                    
                } else if (e.keyCode==38 && e.shiftKey && this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Keyboard)
                {
                    if (!this.__lastSelectionWasContinuous)
                    {
                        this.__unselectAllItemsWithoutActiveItem();
                    }
                    this.set_activeItem(prevItem);
                    if (prevItem.get_selected()) 
                    {
                        currentItem.unselect();
                    }
                    
                    this.__multipleNoncontinuousSelect(e, prevItem);
                    
                    this.__lastSelectionWasContinuous=true;
                    
                    
                } else if (e.keyCode==38 && e.ctrlKey && this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Keyboard)
                {
                    this.set_activeItem(prevItem);
                    this.__lastSelectionWasContinuous=false;
                   // this.__multipleNoncontinuousSelect(e,nextItem);
                }

            } else {

                /*
                if (prevItem) {
                    
                this.set_hoverItemIndex(prevItem.get_index());
                prevItem.hover();
                    
                if (currentItem)
                currentItem.unhover();
                }
                */
            }

            if (prevItem) {

                var pos = $util.getPosition(prevItem._element);

                if (pos.y < container_pos.y + container.scrollTop) {
                    if (container.scrollTop - Sys.UI.DomElement.getBounds(prevItem._element).height >= 0) {
                        container.scrollTop = container.scrollTop - Sys.UI.DomElement.getBounds(prevItem._element).height;
                     //  container.scrollTop =  container_pos.y - pos.y;
                    // container.scrollTop = pos.y  
                    }
                    else {
                    
                        container.scrollTop = 0;
                    }
                }

            }

            //    selectedIndex--;
        } 
        
        if (((e.keyCode==40 && (e.shiftKey)) || (e.keyCode==38 && (e.shiftKey))) && this.get_enableMultipleSelection() && this.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Keyboard )
        {
            this.__constructMultiSelectValue(e);
        }
        
    },
    
    __constructMultiSelectValue: function(e)
    {
        var currentVal = this.__constructMultiSelectValueInternal();
        
        //A.T. 1 Sept. 2009 - Fix for bug 21172: When selection is set to the same previous selection, postback is made, but the SelectionChanged event is not fired on the server-side
        if (currentVal!=this.get_currentValue())
        {
           // args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, this._elements["Input"].value, this.get_currentValue());
           var args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', e, null, currentVal, this.get_currentValue());

            var cancel = args ? args.get_cancel() : false;
            if (!cancel) {
                var previousValue = this.get_currentValue();
                this.set_currentValue(currentVal, true);
                this._raiseClientEvent('ValueChanged', 'DropDownEdit', e, null, this.get_currentValue(), previousValue);
            }
        }
    },
    
    // same as the above, but doesn't fire events and doesn't need an event as an argument
     __constructMultiSelectValueInternal: function()
    {
        var currentVal = '';
        var delim = this.get_multiSelectValueDelimiter();

        // go through all items and check which are selected
        var isFirst = true;
        
        var length = this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client ? this.__clientFilteringItemCount : this.get_items().getLength();

        for (var i = 0; i < length; i++) {
           if (this.get_items().getItem(i).get_selected()) {
                if (!isFirst) {
                   currentVal += delim + this.get_items().getItem(i).get_text();
                }
                else {
                   currentVal += this.get_items().getItem(i).get_text();
                    isFirst = false;
                }
            }
        }
        return currentVal;
    },
    
    __findClosestSelected: function(index) 
    {
        
        var nextIndex=index;
        var prevIndex=index;
        
        var length = this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client ? this.__clientFilteringItemCount : this.get_items().getLength();
        
        for (i=index; i < length; i++)
        {
           // if (this.get_items()._getObjectByIndex(i).get_selected())
           if (this.get_items().getItem(i).get_selected())
                break;
            
            nextIndex++;
        }
        
        for (i=index; i >=0 ; i--)
        {
           // if (this.get_items()._getObjectByIndex(i).get_selected())
           if (this.get_items().getItem(i).get_selected())
                break;
            
            prevIndex--;
        }
        
        
        if (prevIndex <0 && nextIndex >=0) return nextIndex;
        if (nextIndex <0 && prevIndex >=0) return prevIndex;
        if (prevIndex <0 && nextIndex <0) return index;
        return  (nextIndex < prevIndex) ? nextIndex : prevIndex;
        
    },

    // handles async AJAX response
    _responseComplete: function(callbackObject, responseObject) {

        // hide loading items message if needed
        if (this.get_loadingItemsMessageText()!=null)
        {
            this.__hideLoadingItemsMessage();
        }
        
        // handle results from the Items requested event
        var manualLoadItems = this.__manualLoadItems;
        var currentControl = this;
        var props = eval(responseObject.context[0]);
        var html = responseObject.context[1];
        var pagerHtml = responseObject.context[2];
        var type = callbackObject.serverContext.type;
        
        var eventName = callbackObject.serverContext.eventName;

        // replace Li items
        var list = this._elements["List"];

        var val = this.get_currentValue();

        if (this.get_enableCustomValueSelection()) {
            val = this._elements["Input"].value;
        }
        
        if ((type == "itemsRequested" || type == "itemsRequestedCustom") && this.get_valueBeforeFilter() != val) {
            if (this.get_enableCustomValueSelection())
                this.__autoFilterOnServerCustom();
            // initiate a new request
            else {
                 //   if (this.get_enableAutoCompleteFirstMatch() && this.__get_valueBeforeAutoCompleteFirstMatch() != this.get_valueBeforeFilter())
                   // {
                     //   this.set_currentValue(this.__get_valueBeforeAutoCompleteFirstMatch());
                      //  this.__autoFilterOnServer();
                    //} else if (!this.get_enableAutoCompleteFirstMatch())
                   // {
                    //    this.__autoFilterOnServer();
                   // }
                clearTimeout(this._timeoutID);
                this._timeoutID = setTimeout(Function.createDelegate(this, this.__autoFilterOnServer), this.get_autoFilterTimeoutMs());
            }

            return;
        }

        if (type == "itemsRequested" || type == "itemsRequestedCustom" || type == "remove" || type==null ||
        type == "nextPage" || type == "prevPage" || type=="gotoPage" ||  type=="firstPage" || type=="lastPage" || 
        type == "insert" || eventName == "SelectionChanged" || eventName == "ValueChanged") {
        
            if (type == "itemsRequestedCustom" && !html.toLowerCase().startsWith("<li")) // no items available
            {
                // no results
                this._elements["Input"].value = this.get_currentValue();
                return;

            }
            
            //LEAKS FIX
            for (i=0;i<this.get_items()._items.length;i++)
            {
                //this.get_items()._items[i].dispose();
                var item = this.get_items()._items[i];
                if (item!=null)
                {
                    this.get_items()._items[i].dispose();
                }
            }
            this.get_items().dispose();
            
            list.innerHTML = html; 

        } else if (type == "add") {
            //var span = document.createElement("span");
            list.innerHTML += html;
            //list.appendChild(span);
        } else if (type == "pagerMoreResults") {
            if (!html.toLowerCase().startsWith("<li")) {
                this._noMoreResults = true;
            }
            else {
                list.innerHTML += html;
            }
        }

        if (this.get_enablePaging()) {
            var pager = this._elements["PagerArea"];
            pager.innerHTML = pagerHtml;
        }
        //else if (type == "insert")
        //{
        //
        //}
        
        this.__clearTextNodesFromUL();
        // we need to re-attach the dropdown to the parent , before the initialization/walkThrough is done

        this._elements = []; // clear markers
        //this._events._list = []; // it's very important to clear the events !
        $clearHandlers(this._element);
        this.__clearOtherEvents();

        //this.set_props(props);
        // everything that's done in set_props, except setting again the client event handlers
        this._dataStore = props;
        this._props = props[0];
        this._clientStateManager = new $IG.ObjectClientStateManager(this._props);
        this._objectsManager = new $IG.ObjectsManager(this, props[1]);
        this._collectionsManager = new $IG.CollectionsManager(this, props[2]);
        
        //var items = responseObject.context[2];
        //var itemsCount = items.length;

        this.behavior._attach();
        
        $IG.WebDropDown.callBaseMethod(this, 'initialize');
        
        // we need to re-attach the paging event, since we have replaced the whole inner HTML
        // and have swiped out the handler

        /*
        if (this.get_enablePaging())
        {

            var pagerDelegate = Function.createDelegate(this, this._onPagerMoreResults);
        $addHandler(this._elements["PagerLink"], 'mousedown', pagerDelegate);
        }
        */

        if (this.get_enablePaging()) {
            //var pagerDelegate = Function.createDelegate(this, this._onPagerMoreResults);
            //$addHandler(this._elements["PagerLink"], 'mousedown', pagerDelegate);

            if (this.get_pagerMode() == $IG.DropDownPagerMode.NextPrevious)
            {
                var pagerPrevDelegate = Function.createDelegate(this, this._onPagerPrevResults);
                $addHandler(this._elements["PagerPrevLink"], 'mousedown', pagerPrevDelegate);

                var pagerNextDelegate = Function.createDelegate(this, this._onPagerNextResults);
                $addHandler(this._elements["PagerNextLink"], 'mousedown', pagerNextDelegate);
                
            } else if (this.get_pagerMode() == $IG.DropDownPagerMode.Numeric || this.get_pagerMode() == $IG.DropDownPagerMode.NumericFirstLast)
            {
                var numberDelegate = Function.createDelegate(this, this._onPagerNumberResults);
                $addHandler(this._elements["Pager"], 'mousedown', numberDelegate);
                
                 // check if we have quick pages
               if (this._elements["PagerQPPrevLink"])
               {
                    var pagerPrevDelegate = Function.createDelegate(this, this._onPagerPrevResults);
                    $addHandler(this._elements["PagerQPPrevLink"], 'mousedown', pagerPrevDelegate);
               }
               
               if (this._elements["PagerQPNextLink"])
               {
                    var pagerNextDelegate = Function.createDelegate(this, this._onPagerNextResults);
                    $addHandler(this._elements["PagerQPNextLink"], 'mousedown', pagerNextDelegate);
               }
                
            } else if (this.get_pagerMode() == $IG.DropDownPagerMode.NextPreviousFirstLast)
            {
                var pagerPrevDelegate = Function.createDelegate(this, this._onPagerPrevResults);
                $addHandler(this._elements["PagerPrevLink"], 'mousedown', pagerPrevDelegate);

                var pagerNextDelegate = Function.createDelegate(this, this._onPagerNextResults);
                $addHandler(this._elements["PagerNextLink"], 'mousedown', pagerNextDelegate);
                
                var pagerFirstDelegate = Function.createDelegate(this, this._onPagerFirstResults);
                $addHandler(this._elements["PagerFirstLink"], 'mousedown', pagerFirstDelegate);

                var pagerLastDelegate = Function.createDelegate(this, this._onPagerLastResults);
                $addHandler(this._elements["PagerLastLink"], 'mousedown', pagerLastDelegate);
            }
        }

        this.behavior._detach();

        // reattach handlers
        // var selectDelegate = Function.createDelegate(this, this._select);  
        // $addHandler(list, 'mousedown', selectDelegate);

        // attach the delegate for keyboard navigation
        // var navDelegate = Function.createDelegate(this, this._navigateItems);
        // $addHandler(list, 'keydown', navDelegate);

        // this._registerHandlers(["selectstart", "keydown", "keyup", "mousedown"]);
        
        if (type == "itemsRequestedCustom") {
            // update value
            args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', this._currentEvent, null, this._elements["Input"].value, this.get_currentValue());
            var cancel = args ? args.get_cancel() : false;
            if (!cancel) {
                var previousValue = this.get_currentValue();
                this.set_currentValue(this._elements["Input"].value, false);
                this._raiseClientEvent('ValueChanged', 'DropDownEdit', this._currentEvent, null, this.get_currentValue(), previousValue);
            }
        }

        // select the first item when there are results ; update the current value and fire value changing/ed events 
       // if (type=="itemsRequested"  && !manualLoadItems && this.get_items().getLength() > 0 && this._elements["Input"].value != this.get_currentValue() )
        if (type!="itemsRequested"  && !manualLoadItems && this._elements["Input"].value != this.get_currentValue() )
        {
           // fire value changing
            args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', this._currentEvent, null, this._elements["Input"].value, this.get_currentValue());
            var cancel = args ? args.get_cancel() : false;
            if (!cancel) {
                //var previousValue = this.get_currentValue();
               // this.set_currentValue(this._elements["Input"].value, false);
               var previousValue = this._elements["Input"].value;
                this._elements["Input"].value = this.get_currentValue();
                this._raiseClientEvent('ValueChanged', 'DropDownEdit', this._currentEvent, null, this.get_currentValue(), previousValue);
            }  
         }
         
         if (this.get_items().getLength() > 0 && type=="itemsRequested" && !manualLoadItems && this.get_autoSelectOnMatch())
         {
           // fire selection events
           var oldIndex = this.get_selectedItemIndex();
          // var oldItem = oldIndex == -1 ? null : this.get_items()._getObjectByIndex(oldIndex);
          var oldItem = oldIndex == -1 ? null : this.get_items().getItem(oldIndex);
            // var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', this._currentEvent, null, [this.get_items()._getObjectByIndex(0)], [oldItem]);
            var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', this._currentEvent, null, [this.get_items().getItem(0)], [oldItem]);
            var cancel = args ? args.get_cancel() : false;
            if (!cancel) {
            
                var previousIndex = this.get_selectedItemIndex();
                //this.get_items()._getObjectByIndex(0).select();
                this.get_items().getItem(0).select();
                this.set_selectedItemIndex(0);
                
                //var args = this._raiseClientEvent('SelectionChanged', 'DropDownSelection', this._currentEvent, null, [this.get_items()._getObjectByIndex(0)], [oldItem]);
                var args = this._raiseClientEvent('SelectionChanged', 'DropDownSelection', this._currentEvent, null, [this.get_items().getItem(0)], [oldItem]);

                // also activate first item
              //  this.set_activeItem(this.get_items()._getObjectByIndex(0));
               this.set_activeItem(this.get_items().getItem(0));
            } 
         }          

        if (this._currentEvent && this.get_enableAutoCompleteFirstMatch()) {
            this.__autoCompleteFirstMatch(this._elements["Input"], 0, this._currentEvent);
        }
        
        // STORE IN CACHE, if enabled
        if (type == "itemsRequested" && this.get_enableCachingOnClient())
        {
            if (this.get_enableAutoCompleteFirstMatch())
            {
                this._clientCache[this.get_valueBeforeFilter().toLowerCase()] = [html,props];
            } else {
            
                this._clientCache[val.toLowerCase()] = [html, props];
            }
        }

        // this.set_selectedItemIndex(-1);

        // items requested is raised whenever the items arrive from the server
        // on the other hand, the AutoFilteringStarted is raised, without caring whether items have arrived or not

        if (type == "itemsRequested")
            this._raiseClientEvent('ItemsRequested', 'DropDownControl', this._currentEvent, null);
            
        // fire client events for items
        if (type=="add" || type == "insert")
        {
            var items;
            if (this.get_enablePaging())
            {
                items = responseObject.context[3];
                
            } else
            {
                items = responseObject.context[2];
            }
            
            //this._raiseClientEvent('ItemAdded', 'DropDownControl', null, null, item);
            if (items != null && items.length > 0)
			{
				for (var i = 0; i < items.length; i++)
				{
					//var item = this.get_items()._getObjectByAdr(items[i]);
					var item = this.get_items().getItem(items[i]);
					if (type == "add")
						this._raiseClientEvent('ItemAdded', 'DropDownControl', null, null, item);
					else if (type == "insert")
						this._raiseClientEvent('ItemInserted', 'DropDownControl', null, null, item);
				}
			}
        } 
        else if (type == "remove")
		{
			    var item = callbackObject.clientContext.item;
			    this._raiseClientEvent('ItemRemoved', 'DropDownControl', null, null, item);
		}
	
	    
        if (this.get_displayMode() != $IG.DropDownDisplayMode.ReadOnly) {
            if (this._currentEvent) {
                var args = this._raiseClientEvent('DropDownOpening', 'DropDownContainer', this._currentEvent, null);
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    this.behavior.set_visible(true);
                    //this._adjustMaxHeight();
                    this._raiseClientEvent('DropDownOpened', 'DropDownContainer', this._currentEvent, null);
                }
            } else {

                if (this.get_items().getLength() > 0 && (type == "nextPage" || type == "prevPage" || type=="gotoPage" ||  type=="firstPage" || type=="lastPage"))
                {
                   // this.set_currentValue(this.get_items()._items[0].get_text(), true);
                   this.set_currentValue(this.get_items().getItem(0).get_text(), true);
                }

                var args = this._raiseClientEvent('DropDownOpening', 'DropDownContainer', null, null);
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    this.behavior.set_visible(true);
                    //this._adjustMaxHeight();
                    this._raiseClientEvent('DropDownOpened', 'DropDownContainer', null, null);
                }

                // A.T. Fix for bug #22775
                try 
                {
                    this._elements["Input"].focus();
                    
                } catch (e)
                {
                    // maybe control is disabled, maybe it's not visible, maybe this._element was disposed
                    // for some reason - there is no stable way to detect when to call focus() and when not to 
                }
                this.__moveInputCursorToEnd();
                this.__isInternalFocus=true;
            }
        }

        // unhover any hanging items
        //this.__unhoverItems();

       // this._activeItem = this.get_activeItemIndex() == -1 ? null : this.get_items()._getObjectByIndex(this.get_activeItemIndex());
        this._activeItem = this.get_activeItemIndex() == -1 ? null : this.get_items().getItem(this.get_activeItemIndex());

        // restore drop down scroll top state
        if (this._dropDownScrollTop != null && this._dropDownScrollTop > 0) {
            this._elements["DropDownContents"].scrollTop = this._dropDownScrollTop;
        }

        // adjust max container height, if this property is set 
       // this._adjustMaxHeight();
            
        if (this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client)
        {
            for (i=0;i<this.get_items().getLength();i++)
            {
                // dummy, serves just to create every item, since lazy loading & client side filtering require some special attention
                this.get_items().getItem(i);
            }
            this.__clientFilteringItemCount = this.get_items().getLength();
        }
    },

    __autoFilterOnServer: function(elem, adr, evnt) {

        // check if the current value is the same as the value at the time at which the auto filtering
        // timeout was registered
        // if the values are not the same, don't proceed !

        // if (this.get_previousValue() == this.get_currentValue()) {
        
        // show loading items message if needed
        if (this.get_loadingItemsMessageText()!=null)
        {
            this.__showLoadingItemsMessage();
        }

        // will do ajax - items requested
        this._raiseClientEvent('ItemsRequesting', 'DropDownEdit', evnt, null, this.get_currentValue(), this.get_previousValue());

        var args = this._raiseClientEvent('AutoFilterStarting', 'DropDownEdit', evnt, null, this.get_currentValue(), this.get_previousValue());
        var cancel = args ? args.get_cancel() : false;
        if (!cancel) {

            if (this.get_currentValue()!=null && this._clientCache[this.get_currentValue().toLowerCase()] != null && this.get_enableCachingOnClient()) 
            {

                //LEAKS FIX
                for (i=0;i<this.get_items()._items.length;i++)
                {
                    //this.get_items()._items[i].dispose();
                    var item = this.get_items()._items[i];
                    if (item!=null)
                    {
                        this.get_items()._items[i].dispose();
                    }
                }
                this.get_items().dispose();
                
                var html = this._clientCache[this.get_currentValue().toLowerCase()][0];
                
                var list = this._elements["List"];
                // remove the items 
                //while (list.childNodes[0]) {
                //    list.removeChild(list.childNodes[0]);
                //}

                list.innerHTML = html;
                this.__clearTextNodesFromUL();
                var props = this._clientCache[this.get_currentValue().toLowerCase()][1];
                
                this._elements = []; // clear markers
                $clearHandlers(this._element);
                this.__clearOtherEvents();
                
                this._dataStore = props;
                this._props = props[0];
                this._clientStateManager = new $IG.ObjectClientStateManager(this._props);
                this._objectsManager = new $IG.ObjectsManager(this, props[1]);
                this._collectionsManager = new $IG.CollectionsManager(this, props[2]);
                
                 this.behavior._attach();
                 $IG.WebDropDown.callBaseMethod(this, 'initialize');
                 this.behavior._detach();
        
                //this.get_items()._items = items[0];
                this.openDropDown();
                // A.T. Fix for bug #22775
                try 
                {
                    this._elements["Input"].focus();
                    
                } catch (e)
                {
                    // maybe control is disabled, maybe it's not visible, maybe this._element was disposed
                    // for some reason - there is no stable way to detect when to call focus() and when not to 
                }
                this.__moveInputCursorToEnd();
                this.__isInternalFocus=true;
                if (this._currentEvent) {
                     this.__autoCompleteFirstMatch(this._elements["Input"], 0, this._currentEvent);
                }
                
                // unhover any hanging items
                //this.__unhoverItems();

                   // fire selection events
                   if (this.get_autoSelectOnMatch())
                   {
                       var oldIndex = this.get_selectedItemIndex();
                      // var oldItem = oldIndex == -1 ? null : this.get_items()._getObjectByIndex(oldIndex);
                      var oldItem = oldIndex == -1 ? null : this.get_items().getItem(oldIndex);
                        // var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', this._currentEvent, null, [this.get_items()._getObjectByIndex(0)], [oldItem]);
                        var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', this._currentEvent, null, [this.get_items().getItem(0)], [oldItem]);
                        var cancel = args ? args.get_cancel() : false;
                        if (!cancel) {
                        
                            var previousIndex = this.get_selectedItemIndex();
                            //this.get_items()._getObjectByIndex(0).select();
                            this.get_items().getItem(0).select();
                            this.set_selectedItemIndex(0);
                            
                            //var args = this._raiseClientEvent('SelectionChanged', 'DropDownSelection', this._currentEvent, null, [this.get_items()._getObjectByIndex(0)], [oldItem]);
                            var args = this._raiseClientEvent('SelectionChanged', 'DropDownSelection', this._currentEvent, null, [this.get_items().getItem(0)], [oldItem]);

                            // also activate first item
                          //  this.set_activeItem(this.get_items()._getObjectByIndex(0));
                           this.set_activeItem(this.get_items().getItem(0));
                        }           
                    
                        this._activeItem = this.get_activeItemIndex() == -1 ? null : this.get_items().getItem(this.get_activeItemIndex());
                    }
                    
                if (this._dropDownScrollTop != null && this._dropDownScrollTop > 0) {
                    this._elements["DropDownContents"].scrollTop = this._dropDownScrollTop;
                }
            }
            else 
            {
                if (this._pi && !this.behavior.get_visible()) 
                {
                    this._pi.set_enabled(false);
                }
                var cbo = this._callbackManager.createCallbackObject();
                cbo.serverContext.type = "itemsRequested";
                cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(this._clientStateManager.get_transactionList());
                this.set_valueBeforeFilter(this.get_currentValue());
                this._callbackManager.execute(cbo, true);
                
                if (this._pi) 
                {
                    this._pi.set_enabled(true);
                }

            }
            // raise autoFilter started event
            this._raiseClientEvent('AutoFilterStarted', 'DropDownEdit', evnt, null, this.get_currentValue(), this.get_previousValue());

        }

        // } 
    },

    __autoFilterOnServerCustom: function(elem, adr, evnt) {
        this._raiseClientEvent('ItemsRequesting', 'DropDownEdit', evnt, null, this._elements["Input"].value, this.get_currentValue());

        var args = this._raiseClientEvent('AutoFilterStarting', 'DropDownEdit', evnt, null, this._elements["Input"].value, this.get_currentValue());
        var cancel = args ? args.get_cancel() : false;
        if (!cancel) {
            this._setLoadItemsText(this._elements["Input"].value);
            var cbo = this._callbackManager.createCallbackObject();
            cbo.serverContext.type = "itemsRequestedCustom";
            cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(this._clientStateManager.get_transactionList());

            this.set_valueBeforeFilter(this._elements["Input"].value);

            if (this._pi && !this.behavior.get_visible()) 
            {
                this._pi.set_enabled(false);
            }
            this._callbackManager.execute(cbo, true);

            if (this._pi && !this.behavior.get_visible())
            {
                this._pi.set_enabled(true);
            }
            // raise autoFilter started event
            this._raiseClientEvent('AutoFilterStarted', 'DropDownEdit', evnt, null, this._elements["Input"].value, this.get_currentValue());

        }
    },

    __autoFilter: function(elem, adr, evnt) {
        // get input value
        // var text = this.get_autoFilterInputValue();
        var text = this.get_currentValue();
        
       //if (this.get_enableAutoCompleteFirstMatch())
       //{ 
       //     text = this.__get_valueBeforeAutoCompleteFirstMatch();
       //}

        //var items = this.get_items()._items;

        // if (this.get_enableClientFilteringOnly()) 
        // {

        // detach items 

        var list = this._elements["List"];
               
        // remove the items 
        while (list.childNodes[0]) {
            list.removeChild(list.childNodes[0]);
        }

        var tempResults = new Array();

        for (i = 0; i < this.__clientFilteringItemCount; i++) {
           // items[i]._set_visible(false);
           // var item_text = items[i].get_text();
           
           this.get_items().getItem(i)._set_visible(false);
           var item_text = this.get_items().getItem(i).get_text();

            if (this.get_autoFilterQueryType() == $IG.DropDownAutoFilterQueryTypes.StartsWith) {
            
            // check case sensitivity !!! 
                if (!this.get_enableCaseSensitivity())
                {
                    if (item_text.toLowerCase().startsWith(text.toLowerCase()) || text == "") {
                        // list.appendChild(items[i]._element);
                        
                        //tempResults.push(items[i]);
                        tempResults.push(this.get_items().getItem(i));
                    }
                } else 
                {
                    if (item_text.startsWith(text) || text == "") {
                        // list.appendChild(items[i]._element);
                        
                        //tempResults.push(items[i]);
                        tempResults.push(this.get_items().getItem(i));
                    }
                }
                
            } else if (this.get_autoFilterQueryType() == $IG.DropDownAutoFilterQueryTypes.EndsWith) {
            
            // check case sensitivity !!!
                if (!this.get_enableCaseSensitivity())
                {
                    if (item_text.toLowerCase().endsWith(text.toLowerCase()) || text == "") {
                        // list.appendChild(items[i]._element);
                        
                       // tempResults.push(items[i]);
                       tempResults.push(this.get_items().getItem(i));
                    }
                } else
                {
                    if (item_text.endsWith(text) || text == "") {
                        // list.appendChild(items[i]._element);
                        
                        //tempResults.push(items[i]);
                        tempResults.push(this.get_items().getItem(i));
                    }
                }

            } else {
                // contains
                if (item_text.toLowerCase().indexOf(text.toLowerCase()) != -1 || text == "") {
                    // list.appendChild(items[i]._element);
                    
                   // tempResults.push(items[i]);
                   tempResults.push(this.get_items().getItem(i));
                }
            }
        }

        // sort array if descending
        if (this.get_autoFilterSortOrder() == $IG.DropDownAutoFilterSortOrder.Descending)
        {
            tempResults.sort(function sortItems(item1, item2) { return (item1.get_text() > item2.get_text()) ? -1 : 1 ;}); 
        }
        
        // if (tempResults.length==0 && this.get_persistCustomValues())
        // {
        //    var customItem =  this.get_items().createItem();
        //    customItem.set_text(this.get_currentValue());
        //    this.get_items().add(customItem);

        // } else {
        
        if (this.get_autoFilterResultSize() > 0) {

            for (i = 0; i < this.get_autoFilterResultSize() && i < tempResults.length; i++) {
                list.appendChild(tempResults[i]._element);
                if (this.get_enableMarkingMatchedText())
                {
                    this.__markMatchedText(tempResults[i]._element, tempResults[i].get_text());
                }
                tempResults[i]._set_visible(true);
            }

        } else {

            for (i = 0; i < tempResults.length; i++) {
                list.appendChild(tempResults[i]._element);
                if (this.get_enableMarkingMatchedText())
                {
                    this.__markMatchedText(tempResults[i]._element,tempResults[i].get_text());
                }
                tempResults[i]._set_visible(true);
            }
        }
        //}
        
        //A.T. 1 Sept. 2009 - Fix for bug 21172: When selection is set to the same previous selection, postback is made, but the SelectionChanged event is not fired on the server-side
        if (list.childNodes.length > 0 && this.get_autoSelectOnMatch() && tempResults[0].get_index() != this.get_selectedItemIndex()) {

           // fire selection events
           //A.T. 6th of Feb 2010 - Fix for bug #27004 - Javascript error is thrown when we  try to access the old selected items.
			var oldItem = this.get_selectedItemIndex() == -1 ? null : this.get_items().getItem(this.get_selectedItemIndex());
            var args = this._raiseClientEvent('SelectionChanging', 'DropDownSelection', evnt, null, [tempResults[0]], [oldItem]);
            var cancel = args ? args.get_cancel() : false;
            if (!cancel) {
                var previousIndex = this.get_selectedItemIndex();
                this.__unselectAllItems();
                tempResults[0].select();
                //this.set_selectedItemIndex(tempResults[0].get_index());
                this.set_selectedItemIndex(tempResults[0].get_index());
                //A.T. 6th of Feb 2010 - Fix for bug #27004 - Javascript error is thrown when we  try to access the old selected items.
                var previousItem = previousIndex == -1 ? null : this.get_items().getItem(previousIndex);
                var args = this._raiseClientEvent('SelectionChanged', 'DropDownSelection', evnt, null, [this.get_items().getItem(this.get_selectedItemIndex())], [previousItem]);
                // also activate
                this.set_activeItem(tempResults[0]);
            }
         } else
         {
            // A.T. 30/11/2009 Fix for bug #25247 - When typing a custom value with EnableAutoFiltering = Off/Client, the index of the selected item is not reset to -1
            var selectedItem = this.get_selectedItem();
            
            if (this.get_enableMultipleSelection())
            {
                this.__unselectAllItems();
            } else
            {
                if (this.get_selectedItem()!=null)
                {
                    this.get_selectedItem().unselect();
                }
            }
            
            this.__resetSelection(selectedItem, evnt);
         }           

       // this.behavior.set_targetContainerHeight(Sys.UI.DomElement.getBounds(this._elements["DropDown"]).height);

        if (list.childNodes.length > 0) {
        
            /*
            if (this.get_displayMode() != $IG.DropDownDisplayMode.ReadOnly) {
                var args = this._raiseClientEvent('DropDownOpening', 'DropDownContainer', evnt, null);
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    this.behavior.set_visible(true);
                    this._adjustMaxHeight();
                    this._raiseClientEvent('DropDownOpened', 'DropDownContainer', evnt, null);
                }
            }
            */
            this.openDropDown();
        }

        //}
    },
    
    __markMatchedText:function (elem, elemText)
    {
        if (elem.childNodes[0]!=null && elem.childNodes[0].nodeName!="A")
            return;
        
        var val = this.get_currentValue();
        if (elemText.toLowerCase().startsWith(val.toLowerCase()))
        {
             elem.childNodes[0].innerHTML = "<em>" + elemText.substring(0, val.length) + "</em>" + elemText.substring(val.length);
        }
           
    },

    __autoCompleteFirstMatch: function(elem, adr, evnt) {
    
        //if (!elem)
            elem = this._elements["Input"];
            
        if (!evnt)
            evnt = this._currentEvent;
        // store current value, before auto complete
        //if (this.get_enableAutoFiltering() != $IG.DropDownAutoFiltering.Server) 
        //{
        //    this.__set_valueBeforeAutoCompleteFirstMatch(this.get_currentValue());
        //} else 
        //{
            this.__set_valueBeforeAutoCompleteFirstMatch(elem.value);
        //}
        
        // get items
        //var items = this.get_items()._items;

        var source = elem;
        var value;
        if (this.get_enableCaseSensitivity())
        {
            value = source.value;
        } else 
        {
            value = source.value.toLowerCase();
        }
        
        if (this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Server && (this.get_enableCachingOnClient() == false || (this.get_enableCachingOnClient() ==true && this._clientCache[value.toLowerCase()]==null)) )
        {
            
            if (this.get_currentValue()==null)
                return;
                
            // work on the currentValue
            if (this.get_enableCaseSensitivity())
            {
                if (this.get_currentValue().startsWith(value) && value.length < this.get_currentValue().length) {
                    
                     var args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', evnt, null, this.get_currentValue(), this._elements["Input"].value);
                     var cancel = args ? args.get_cancel() : false;
                     if (!cancel) {
                                
                        this._elements["Input"].value = this.get_currentValue();
                        
                        if (source.createTextRange && !$util.IsOpera) {
                            range = source.createTextRange();
                            // range.findText(item_text.substr(value.length));
                            //A.T. 18 Dec 2009 Fix for bug #25749 - AutoCompleteFirstMatch places focus in wrong letter of textbox after more than one match is found
                           range.findText(this.get_currentValue().substr(value.length),1,1);
                            range.select();

                        } else {
                            source.setSelectionRange(value.length, this.get_currentValue().length);
                        }
                        this._raiseClientEvent('ValueChanged', 'DropDownEdit', evnt, null, this.get_currentValue(), this.get_previousValue());    
                    }
                }
                
             } else 
                {
                    if (this.get_currentValue().toLowerCase().startsWith(value) && value.length < this.get_currentValue().length) {
                       // source.value = item_text;
                        var args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', evnt, null, this.get_currentValue(), this._elements["Input"].value);
                        var cancel = args ? args.get_cancel() : false;
                        if (!cancel) {
                             
                           this._elements["Input"].value = this.get_currentValue();
                           
                            if (source.createTextRange && !$util.IsOpera) {
                                range = source.createTextRange();
                                //A.T. 18 Dec 2009 Fix for bug #25749 - AutoCompleteFirstMatch places focus in wrong letter of textbox after more than one match is found
                                range.findText(this.get_currentValue().substr(value.length),1,1);
                                range.select();

                            } else {
                                source.setSelectionRange(value.length, this.get_currentValue().length);
                            }
                            
                            this._raiseClientEvent('ValueChanged', 'DropDownEdit', evnt, null, this.get_currentValue(), this.get_previousValue());    
                        }
                    }
                }
            
        } else {

            // if (value.length==0)
            //     return;

            //   if (evnt.keyCode== 40 || evnt.keyCode==38) // up and down arrow are intercepted by another event
            //   {
            //       this.__handleKbNavigation(evnt);
            //   }

            if (evnt.keyCode == 40 || evnt.keyCode == 38)
                return;

            if (evnt.keyCode == 16)
                return;


            // RETURN key   
            /* 
            if (evnt.keyCode == 13) {

                var args = this._raiseClientEvent('DropDownClosing', 'DropDownContainer', event, null);
                var cancel = args ? args.get_cancel() : false;
                if (!cancel) {
                    this.behavior.set_visible(false);
                    this._raiseClientEvent('DropDownClosed', 'DropDownContainer', event, null);
                }
                //  return false;
            }
            */

            //  if (e.keyCode == 8) // backspace {
            //value=value.substr(0, value.length-1);
            //    return;

            // A.T. 10/07/2009 Fix for bug # 19246 (adding support for DEL key)
            if (evnt.keyCode != 8 && evnt.keyCode !=127) {
            
                var length = this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client ? this.__clientFilteringItemCount : this.get_items().getLength();
      
                for (i = 0; i < length; i++) {
                   // var item_text = items[i].get_text();
                   var item_text = this.get_items().getItem(i).get_text();

                    if (this.get_enableCaseSensitivity())
                    {
                        // A.T. 15/06/2009 Fix for bug 18201
                        if (item_text == value) // exact match, do nothing
                        {
                            break;
                        }
                        
                        if (item_text.startsWith(value) && value.length < item_text.length) {
                            //source.value = item_text;
                            var args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', evnt, null, item_text, this.get_currentValue());

                            var cancel = args ? args.get_cancel() : false;
                            if (!cancel) {
                                
                                if (this.get_enableCachingOnClient()  && this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Server)
                                {
                                    var previousValue = value;
                                    this._elements["Input"].value = this.get_currentValue();
                                } else
                                
                                {
                                    var previousValue = this.get_currentValue();
                                    this.set_currentValue(item_text, true);
                                }
                                this._raiseClientEvent('ValueChanged', 'DropDownEdit', evnt, null, this.get_currentValue(), previousValue);
                            }
                            
                            if (source.createTextRange && !$util.IsOpera) {
                                range = source.createTextRange();
                                //A.T. 18 Dec 2009 Fix for bug #25749 - AutoCompleteFirstMatch places focus in wrong letter of textbox after more than one match is found
                                range.findText(item_text.substr(value.length),1,1);
                                range.select();

                            } else {
                                source.setSelectionRange(value.length, item_text.length);
                            }
                            break;
                        }
                    } else 
                    {
                        // A.T. 15/06/2009 Fix for bug 18201
                        if (item_text && value && item_text.toLowerCase() == value.toLowerCase()) // exact match, do nothing
                        {
                            break;
                        }
                        
                        if (item_text.toLowerCase().startsWith(value.toLowerCase()) && value.length < item_text.length) {
                           // source.value = item_text;
                           var args = this._raiseClientEvent('ValueChanging', 'DropDownEdit', evnt, null, item_text, this.get_currentValue());
                            var cancel = args ? args.get_cancel() : false;
                            if (!cancel) {
                            
                                if (this.get_enableCachingOnClient() && this.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Server)
                                {
                                    var previousValue = value;
                                    this._elements["Input"].value = this.get_currentValue();
                                } else
                                
                                {
                                    var previousValue = this.get_currentValue();
                                    this.set_currentValue(item_text, true);
                                }
                                this._raiseClientEvent('ValueChanged', 'DropDownEdit', evnt, null, this.get_currentValue(), previousValue);
                            }
                            
                            if (source.createTextRange && !$util.IsOpera) {
                                range = source.createTextRange();
                                //A.T. 18 Dec 2009 Fix for bug #25749 - AutoCompleteFirstMatch places focus in wrong letter of textbox after more than one match is found
                                range.findText(item_text.toLowerCase().substr(value.length),1,1);
                                range.select();

                            } else {
                                source.setSelectionRange(value.length, item_text.length);
                            }
                            break;
                        }
                    }
                }

            }
        
        }
    },
    
    __moveInputCursorToEnd: function()
    {
    
        var input = this._elements["Input"];
        
        if (input.createTextRange && !$util.IsOpera) {
            range = input.createTextRange();
            range.move("character", input.value.length);
            range.select();
            
        } else {
            input.setSelectionRange(input.value.length, input.value.length);
        }
    },
    
    __showLoadingItemsMessage: function()
    {
        // lookup loading items message element
        var msgBox = this._elements["LoadingMessage"];
        var dropDownList = this._elements["List"];
        var left = dropDownList.offsetLeft;
        var top = dropDownList.offsetTop;
        msgBox.style.display="";
        msgBox.style.width = dropDownList.offsetWidth;
        msgBox.style.visibility="visible";
        msgBox.style.left=left;
        msgBox.style.top=top;
        
    },
    
    __hideLoadingItemsMessage: function()
    {
        
        var msgBox = this._elements["LoadingMessage"];
        msgBox.style.display="none";
        msgBox.style.visibility="hidden";
    },
    
    __detachLoadingItemsMessage: function()
    {
    
       // var msgBox = this._elements["LoadingMessage"];
        
    }

}

$IG.WebDropDown.registerClass('Infragistics.Web.UI.WebDropDown', $IG.ControlMain);

$IG.DropDownValueDisplayType  = function()
{

}

$IG.DropDownValueDisplayType.prototype = 
{  
   Simple:0,   
   WebTextEditor:1
   
};

$IG.DropDownValueDisplayType.registerEnum("Infragistics.Web.UI.DropDownValueDisplayType");

$IG.DropDownAutoFilterSortOrder  = function()
{

}

$IG.DropDownAutoFilterSortOrder.prototype = 
{  
   None:0,
   Ascending:1,   
   Descending:2
   
};


$IG.DropDownAutoFilterSortOrder.registerEnum("Infragistics.Web.UI.DropDownAutoFilterSortOrder");

$IG.DropDownMultipleSelectionType  = function()
{

}

$IG.DropDownMultipleSelectionType.prototype = 
{  
   Checkbox:0,   
   Keyboard:1
   
};

$IG.DropDownMultipleSelectionType.registerEnum("Infragistics.Web.UI.DropDownMultipleSelectionType");


$IG.DropDownPagerMode  = function()
{

}

$IG.DropDownPagerMode.prototype = 
{  
   Numeric:0,   
   NextPrevious:1,
   NextPreviousFirstLast:2,
   NumericFirstLast:3
   
};

$IG.DropDownPagerMode.registerEnum("Infragistics.Web.UI.DropDownPagerMode");

$IG.DropDownAutoFilterQueryTypes = function() {

}

$IG.DropDownAutoFilterQueryTypes.prototype =
{
    StartsWith:0,
    EndsWith:1,
    Contains:2,
    DoesNotContain:3,
    Equals:4,
    DoesNotEqual:5
    
};

$IG.DropDownAutoFilterQueryTypes.registerEnum("Infragistics.Web.UI.DropDownAutoFilterQueryTypes");

$IG.DropDownDisplayMode  = function()
{

}

$IG.DropDownDisplayMode.prototype = 
{  
    DropDownList:0,
    DropDown:1,
    ReadOnly:2,
    ReadOnlyList:3
   
};

$IG.DropDownDisplayMode.registerEnum("Infragistics.Web.UI.DropDownDisplayMode");

$IG.DropDownAutoFiltering  = function()
{

}

$IG.DropDownAutoFiltering.prototype = 
{  
    Server:0,
    Client:1,
    Off:2
   
};

$IG.DropDownAutoFiltering.registerEnum("Infragistics.Web.UI.DropDownAutoFiltering");


$IG.DropDownProps = new function() {
    this.DisplayMode = [$IG.ControlMainProps.Count + 0, $IG.DropDownDisplayMode.DropDown];
    this.ValueListMaxHeight = [$IG.ControlMainProps.Count + 1, 0];
    this.OffsetX = [$IG.ControlMainProps.Count + 2, 0];
    this.OffsetY = [$IG.ControlMainProps.Count + 3, 0];
    this.EnablePaging = [$IG.ControlMainProps.Count + 4, false];
    this.PageSize = [$IG.ControlMainProps.Count + 5, 0];
    this.SelectedItemIndex = [$IG.ControlMainProps.Count + 6, -1];
    this.SelectedItemIndices = [$IG.ControlMainProps.Count + 7, []];
    this.MultiSelectValueDelimiter = [$IG.ControlMainProps.Count + 8, ","];
    this.EnableCustomValueSelection = [$IG.ControlMainProps.Count + 9, false];
    this.EnableMultipleSelection = [$IG.ControlMainProps.Count + 10, false];
    this.CloseDropDownOnSelect = [$IG.ControlMainProps.Count + 11, true];
    this.PersistCustomValues = [$IG.ControlMainProps.Count + 12, false];
    this.EnableAutoFiltering = [$IG.ControlMainProps.Count + 13, $IG.DropDownAutoFiltering.Off];
    this.AutoFilterQueryType = [$IG.ControlMainProps.Count + 14, $IG.DropDownAutoFilterQueryTypes.StartsWith];
    this.AutoFilterResultSize = [$IG.ControlMainProps.Count + 15, 0];
    this.AutoFilterSortOrder = [$IG.ControlMainProps.Count + 16, $IG.DropDownAutoFilterSortOrder.None];
    this.EnableAutoCompleteFirstMatch = [$IG.ControlMainProps.Count + 17, true];
    this.EnableLoadOnDemand = [$IG.ControlMainProps.Count + 18, false];
    this.DropDownContainerWidth = [$IG.ControlMainProps.Count + 19, 0];
    this.DropDownContainerHeight = [$IG.ControlMainProps.Count + 20, 0];
    this.EnableCaseSensitivity = [$IG.ControlMainProps.Count + 21, false];
    this.CurrentValue = [$IG.ControlMainProps.Count + 22, null];
    this.ShowDropDownButton = [$IG.ControlMainProps.Count + 23, true];
    this.DropDownValueDisplayType = [$IG.ControlMainProps.Count + 24, $IG.DropDownValueDisplayType.Simple];
    //this.EnableClientFilteringOnly = [$IG.ControlMainProps.Count + 25, false];
    this.DropDownAnimationDuration = [$IG.ControlMainProps.Count + 25, 500];
    this.DropDownOrientation = [$IG.ControlMainProps.Count + 26, 6];
    this.LoadItemsText = [$IG.ControlMainProps.Count + 27, null];
    this.EnableClosingDropDownOnBlur = [$IG.ControlMainProps.Count + 28, true];
    this.AutoFilterTimeoutMs = [$IG.ControlMainProps.Count + 29, 200];
    this.EnableCachingOnClient = [$IG.ControlMainProps.Count + 30, false];
    this.MultipleSelectionType = [$IG.ControlMainProps.Count + 31, $IG.DropDownMultipleSelectionType.Checkbox];
    this.EditorID = [$IG.ControlMainProps.Count + 32, null];
    this.DropDownAnimationType = [$IG.ControlMainProps.Count + 33, 0];
    this.LoadingItemsMessageText =[$IG.ControlMainProps.Count + 34,null];
    this.PagerMode =[$IG.ControlMainProps.Count + 35,$IG.DropDownPagerMode.Numeric];
    this.LastPageIndex =[$IG.ControlMainProps.Count + 36,-1];
    this.ShouldFireMultipleSelect =[$IG.ControlMainProps.Count + 37,false];
    this.EnableAnimations =[$IG.ControlMainProps.Count + 38,true];
    this.EnableDropDownOpenOnClick =[$IG.ControlMainProps.Count + 39,true];
    this.ActiveItemIndex = [$IG.ControlMainProps.Count + 40, -1];
    this.DropDownIsChild = [$IG.ControlMainProps.Count + 41, true];
    this.EnableCustomValues = [$IG.ControlMainProps.Count + 42, true];
    this.EnableMarkingMatchedText = [$IG.ControlMainProps.Count + 43, false];
    this.EnableDropDownAutoWidth = [$IG.ControlMainProps.Count + 44, false];
    this.AutoSelectOnMatch = [$IG.ControlMainProps.Count +45, true];
    this.Enabled = [$IG.ControlMainProps.Count +46, true];
    this.Count = $IG.ControlMainProps.Count + 47;

}

$IG.DropDownItemProps = new function()
{
    this.Text        =[$IG.ListItemProps.Count + 0, ""];
    this.Value          =[$IG.ListItemProps.Count + 1, ""];
    this.Selected    =[$IG.ListItemProps.Count + 2, false];
   this.Disabled = [$IG.ListItemProps.Count + 3, false];
    this.Activated = [$IG.ListItemProps.Count + 4, false];
    this.IsCustom = [$IG.ListItemProps.Count + 5, false];
    this.Count            = $IG.ListItemProps.Count + 6;
};
/*
$IG.DropDownProps = new function()
{
    this.Orientation   = [$IG.ControlMainProps.Count + 0, 0];
    this.FirstItem     = [$IG.ControlMainProps.Count + 1, 0];
    this.ScrollPosition= [$IG.ControlMainProps.Count + 2, 0];
    this.DragScroll    = [$IG.ControlMainProps.Count + 3, true]; 
    this.WrapAround    = [$IG.ControlMainProps.Count + 4, true]; 
    this.Count         =  $IG.ControlMainProps.Count + 5;
};
*/


$IG.DropDownItem = function(adr, element, props, control, csm)
{    
    /// <summary>
    /// Represents an item in the WebImageViewer control. 
    /// </summary>
    this._control = control;
         
	$IG.DropDownItem.initializeBase(this, [adr, element, props, control,csm]);
	//this._element.className = this.get_cssClass();
	//this._cssClass = element.className;
	this.__visible = true;
	
	// attach item over / out handlers
	
}

$IG.DropDownItem.prototype =
{
	
	activate:function()
	{
	    ///<summary>
        ///Sets the DropDownItem as selected.
        ///</summary>
	    //this._owner.set_selectedItem(this);
	    if (this._element && this._element.className && this.get_activeCssClass() )
	    $util.addCompoundClass(this._element, this.get_activeCssClass());
	    
	    this._set_value($IG.DropDownItemProps.Activated, true);
	   // this._element.className = this.get_selectedCssClass();
	   // this.set_selected(true);
	    //this._element.focus();
	},
	
	inactivate:function()
	{
	    if (this._element && this._element.className && this.get_activeCssClass() )
	    $util.removeCompoundClass(this._element, this.get_activeCssClass());
	    this._set_value($IG.DropDownItemProps.Activated, false);
	},
	
	select:function(triggeredByUser)
	{
	    ///<summary>
        ///Sets the DropDownItem as selected.
        ///</summary>
	    //this._owner.set_selectedItem(this);
	    if (this._element && this._element.className && this.get_selectedCssClass() )
	    $util.addCompoundClass(this._element, this.get_selectedCssClass());
	   // this._element.className = this.get_selectedCssClass();
	    this.set_selected(true);
	    //this._element.focus();
	    
	    // A.T. 22/06/2009 Fix for bug 18651
	    if (this._control && this._control.get_enableMultipleSelection() && this._control.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Checkbox && !triggeredByUser)
	    {
	        if (this._element !=null && this._element.childNodes[0] !=null)
	            this._element.childNodes[0].checked = true;
	    }
	},
	
	unselect: function(triggeredByUser)
	{
	    if (this._element && this._element.className && this.get_selectedCssClass() )
	   $util.removeCompoundClass(this._element, this.get_selectedCssClass());
	   // this._element.className = this.get_cssClass();
	    this.set_selected(false);
	    
	    // A.T. 22/06/2009 Fix for bug 18651
	    if (this._control && this._control.get_enableMultipleSelection() && this._control.get_multipleSelectionType() == $IG.DropDownMultipleSelectionType.Checkbox && !triggeredByUser)
	    {
	        if (this._element !=null && this._element.childNodes[0] !=null)
	            this._element.childNodes[0].checked = false;
	    }
	},
	
	hover: function()
	{
	    if (this._element && this._element.className && this.get_hoverCssClass() )
        $util.addCompoundClass(this._element, this.get_hoverCssClass());
	   // this._element.className = this.get_hoverCssClass();
	},
	
	unhover: function()
	{
	    if (this._element && this._element.className && this.get_hoverCssClass() )
	    $util.removeCompoundClass(this._element, this.get_hoverCssClass());
	    //this._element.className = this.get_cssClass();
	},
	
	_ensureFlags:function()
    {
        $IG.DropDownItem.callBaseMethod(this, "_ensureFlag");
        this._ensureFlag($IG.ClientUIFlags.Selectable, $IG.DefaultableBoolean.True);
        this._ensureFlag($IG.ClientUIFlags.Visible, $IG.DefaultableBoolean.True);
    },
    
    get_text:function() 
	{
	    ///<summary>
        ///Returns/sets the text of the DropDownItem.
        ///</summary>
	    return this._get_value($IG.DropDownItemProps.Text);
	},
	
	set_text:function(text)
	{	   
	    this._set_value($IG.DropDownItemProps.Text, text);
        // how do we set the inner item value !!!!
        
        // do we allow setting / modifying the text ???
        
        // what about templates ? 
	},
	
    get_value:function() 
	{
	    ///<summary>
        ///Returns/sets the text of the DropDownItem.
        ///</summary>
	    return this._get_value($IG.DropDownItemProps.Value);
	},
	
	set_value:function(val)
	{	   
	    this._set_value($IG.DropDownItemProps.Value, val);
        // how do we set the inner item value !!!!
        
        // do we allow setting / modifying the text ???
        
        // what about templates ? 
	},

	get_index:function()
	{
	    ///<summary>
        ///Returns the index of the item in the WebImageViewer's ImageItemCollection.
        ///</summary>
	    return parseInt(this._get_address());
	},
	
    get_selected:function() 
	{
	    ///<summary>
        ///Returns/sets the text of the DropDownItem.
        ///</summary>
	    return this._get_value($IG.DropDownItemProps.Selected);
	},
	
	get_activated:function() 
	{
	    ///<summary>
        /// 
        ///</summary>
	    return this._get_value($IG.DropDownItemProps.Activated);
	},
	
	get_custom:function() 
	{
	    ///<summary>
        /// 
        ///</summary>
	    return this._get_value($IG.DropDownItemProps.IsCustom);
	},
	
	set_custom:function(custom)
	{
	    this._set_value($IG.DropDownItemProps.IsCustom, custom);
	},
	
	get_disabled:function()
	{
	    return this._get_value($IG.DropDownItemProps.Disabled);
	},
	
	set_disabled:function(val)
	{
	    this._set_value($IG.DropDownItemProps.Disabled, val);
	   // this._element.className = this.get_disabledCssClass();
	   
	   // A.T. fix for bug 17088
	   if (val)
	   {
	        $util.addCompoundClass(this._element, this.get_disabledCssClass());
	   } else
	   {
	        $util.removeCompoundClass(this._element, this.get_disabledCssClass());     
	   }
	},
	
	_get_visible: function()
	{
	    return this.__visible;
	},
	
	_set_visible: function(visible)
	{
	    this.__visible=visible;
	},
	
	set_selected:function(selected)
	{	   
	    this._set_value($IG.DropDownItemProps.Selected, selected);
        // how do we set the inner item value !!!!
        
        // do we allow setting / modifying the text ???
        
        // what about templates ? 
	},
		
	isSelected:function()
	{
	    ///<summary>
        /// Determines if the item is selected.
        ///</summary>
        ///<returns>True if the image is in selected. </returns>
	    return this._getFlags().getSelected();  
	},
	
	get_cssClass:function() 
	{ 
	    ///<summary>
        ///Returns/sets the CSS class that will be applied to the ImageItem when it is selected.
        ///</summary>
	   // return this._get_value($IG.DropDownItemProps.SelectedCssClass);
	   if (this._get_clientOnlyValue("cssClass")!= "")
	        return this._get_clientOnlyValue("cssClass");
	    else
	        return this._control._get_clientOnlyValue("dropDownItemClass");
	},
	
	get_activeCssClass: function()
	{
		   if (this._get_clientOnlyValue("activeCssClass")!= "")
	        return this._get_clientOnlyValue("cssClass");
	    else
	        return this._control._get_clientOnlyValue("dropDownItemActiveClass");
	},
	
    get_selectedCssClass:function() 
	{ 
	    ///<summary>
        ///Returns/sets the CSS class that will be applied to the ImageItem when it is selected.
        ///</summary>
	   // return this._get_value($IG.DropDownItemProps.SelectedCssClass);
   	   if (this._get_clientOnlyValue("selectedCssClass")!= "")
            return this._get_clientOnlyValue("selectedCssClass");
	    else
	        return this._control._get_clientOnlyValue("dropDownItemSelected");
	},
	
	get_disabledCssClass:function() 
	{ 
	    ///<summary>
        ///Returns/sets the CSS class that will be applied to the ImageItem when it is selected.
        ///</summary>
	   // return this._get_value($IG.DropDownItemProps.SelectedCssClass);
   	   if (this._get_clientOnlyValue("disabledCssClass")!= "")
            return this._get_clientOnlyValue("disabledCssClass");
	    else
	        return this._control._get_clientOnlyValue("dropDownItemDisabled");
	},
	
	get_hoverCssClass:function() 
	{ 
	    ///<summary>
        ///Returns/sets the CSS class that will be applied to the DropDownItem when it is selected.
        ///</summary>
	   // return this._get_value($IG.DropDownItemProps.SelectedCssClass);
	   if (this._get_clientOnlyValue("hoverCssClass")!= "")
	        return this._get_clientOnlyValue("hoverCssClass");
	    else
	     return this._control._get_clientOnlyValue("dropDownItemHover");
	}
	
}

$IG.DropDownItem.registerClass('Infragistics.Web.UI.DropDownItem', $IG.ListItem);


$IG.DropDownItemCollection = function(control, clientStateManager, index, manager)
{
    /// <summary>
    /// A collection of DropDownItems.
    /// </summary>
    $IG.DropDownItemCollection.initializeBase(this, [control, clientStateManager, index, manager]);
}

$IG.DropDownItemCollection.prototype = 
{
    add:function(item)
    {        
        ///<summary>
        ///Adds the specified DropDownItem via an AJAX callback.
        ///</summary>
        ///<param name="item">The DropDownItem that should be added</param>
        if(item == null)
            return;
        var cbo = this._control._callbackManager.createCallbackObject();
        cbo.serverContext.type = "add";
        cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(item._csm.get_transactionList());
        if (this._pi) 
        {
            this._pi.set_enabled(false);
        }
        this._control._callbackManager.execute(cbo, true);
        
        if (this._pi) 
        {
            this._pi.set_enabled(true);
        }
    },
    
    remove:function(item)
    {
        ///<summary>
        ///Removes the specified DropDownItem from the collection.
        ///</summary>
        ///<param name="dropDownItem">The DropDownItem that should be removed.</param>
        if(item != null)
	    {
	        var cbo = this._control._callbackManager.createCallbackObject();
            cbo.serverContext.type = "remove";
            cbo.clientContext.item = item;
            cbo.serverContext.index = item.get_index();

            if (this._pi) 
            {
                this._pi.set_enabled(false);
            }
            this._control._callbackManager.execute(cbo, true);

            if (this._pi) 
            {
                this._pi.set_enabled(true);
            }
        }
    },
    
       
    insert:function(index, item)
    {
        ///<summary>
        ///Creates an DropDownItem with the specified parameters an inserts the Item at the specified index. via an AJAX callback.
        ///</summary>
        ///<param name="index">The index in which to insert the DropDownItem.</param>
        ///<param name="item">The DropDownItem that should be added</param>
        if(item == null)
            return;
        var cbo = this._control._callbackManager.createCallbackObject();
        if(index >= 0 && index < this.get_length())
            cbo.serverContext.type = "insert";
        else
            cbo.serverContext.type = "add";        
        cbo.serverContext.index = index;
        cbo.serverContext.props = Sys.Serialization.JavaScriptSerializer.serialize(item._csm.get_transactionList())
        if (this._pi) 
        {
            this._pi.set_enabled(false);
        }
        this._control._callbackManager.execute(cbo, true);
        if (this._pi) 
        {
            this._pi.set_enabled(true);
        }
    }, 
    
    createItem:function()
    {
        ///<summary>
        ///Creates an empty item that can be used in the add, addRange, and insert methods.
        ///</summary>
        var props = new Array();
        var clientProps = new Array();
        var length = $IG.DropDownProps.Count;
        for(var i = 0; i < length; i++)
            clientProps.push(null);
        props.push(clientProps);
        var elem = document.createElement("li");
        var csm = new $IG.ObjectClientStateManager(props);
        var item = new $IG.DropDownItem("-1", elem, props, this._control, csm);
        return item;
    },
    
    getItem:function(index)
    {
        ///<summary>
        ///Returns the DropDownItem at the specified index. 
        ///</summary>
        var item=null;
        
        // IMPLEMENTS LAZY LOADING OF ITEMS
        //if(index >= 0 && index < this.get_length())
        if (!this._control)
            return;
            
        var length = (this._control.get_enableAutoFiltering() == $IG.DropDownAutoFiltering.Client) ? this._control.__clientFilteringItemCount : this._control._elements["List"].childNodes.length;
        
        if(index >= 0 && index < length)
        {
           // item = this._items[index];
           // if (item==null && this._itemCollection !=null)
           // {
           if(this._getObjectByAdr(index) == null)
           {
                return this._addObject($IG.DropDownItem, this._control._elements["List"].childNodes[index], index);
           } else
           {
                return this._getObjectByAdr(index);
           }
        }
        return item;
    },
    
    // USED IN LAZY LOADING
    getLength: function()
    {
        return this._control._elements["List"].childNodes.length;
    }
    
    
}

$IG.DropDownItemCollection.registerClass('Infragistics.Web.UI.DropDownItemCollection', $IG.ObjectCollection);

/// Register event arguments
$IG.DropDownControlEventArgs = function()
{

	$IG.DropDownControlEventArgs.initializeBase(this);
}

$IG.DropDownControlEventArgs.prototype =
{
    get_value: function()
    {
        return this._props[2];
    }
}
$IG.DropDownControlEventArgs.registerClass('Infragistics.Web.UI.DropDownControlEventArgs', $IG.CancelEventArgs);

/// Register selection event arguments
$IG.DropDownSelectionEventArgs = function()
{

	$IG.DropDownSelectionEventArgs.initializeBase(this);
}

$IG.DropDownSelectionEventArgs.prototype =
{
	getNewSelection: function()
	{
	    /// <summary>
        /// 
        /// </summary>
	    return this._props[2];
	},
	
	getOldSelection: function()
	{
		/// <summary>
        /// 
        /// </summary>
        return this._props[3];
	}
}
$IG.DropDownSelectionEventArgs.registerClass('Infragistics.Web.UI.DropDownSelectionEventArgs', $IG.DropDownControlEventArgs);

/// Register value changing event arguments
$IG.DropDownEditEventArgs = function()
{

	$IG.DropDownEditEventArgs.initializeBase(this);
}

$IG.DropDownEditEventArgs.prototype =
{
	getNewValue: function()
	{
	    /// <summary>
        /// 
        /// </summary>
	    return this._props[2];
	},
	
	getOldValue: function()
	{
		/// <summary>
        /// 
        /// </summary>
        return this._props[3];
	}
}
$IG.DropDownEditEventArgs.registerClass('Infragistics.Web.UI.DropDownEditEventArgs', $IG.DropDownControlEventArgs);


/// Register selection event arguments
$IG.DropDownActivationEventArgs = function()
{

	$IG.DropDownActivationEventArgs.initializeBase(this);
}

$IG.DropDownActivationEventArgs.prototype =
{
	getNewActiveItem: function()
	{
	    /// <summary>
        /// 
        /// </summary>
	    return this._props[2];
	},
	
	getOldActiveItem: function()
	{
		/// <summary>
        /// 
        /// </summary>
        return this._props[3];
	}
}
$IG.DropDownActivationEventArgs.registerClass('Infragistics.Web.UI.DropDownActivationEventArgs', $IG.DropDownControlEventArgs);



/// Register selection event arguments
$IG.DropDownContainerEventArgs = function()
{

	$IG.DropDownContainerEventArgs.initializeBase(this);
}

$IG.DropDownContainerEventArgs.prototype =
{
	//getVisible: function()
	//{
	    /// <summary>
        /// returns the state of the dropdown container - 0 = closed, = 1 opened
        /// </summary>
	  //  return this._props[2];
	//}
}
$IG.DropDownContainerEventArgs.registerClass('Infragistics.Web.UI.DropDownContainerEventArgs', $IG.DropDownControlEventArgs);


/// Register selection event arguments
$IG.DropDownItemEventArgs = function()
{

	$IG.DropDownItemEventArgs.initializeBase(this);
}

$IG.DropDownItemEventArgs.prototype =
{
	getItem: function()
	{
	    /// <summary>
        /// returns current item on which the event has been raised
        /// </summary>
	    return this._props[1];
	}
}
$IG.DropDownItemEventArgs.registerClass('Infragistics.Web.UI.DropDownItemEventArgs', $IG.DropDownControlEventArgs);

