﻿
// Declare a namespace.
Type.registerNamespace("WFControls");

// Define a simplified component.
WFControls.Combobox = function(element) {
    WFControls.Combobox.initializeBase(this, [element]);

    this.options = null;
    this.selectedIndex = -1;
    this.hoverIndex = -1;
    this.autovalidate = false;
    this.sValue = '';
    this.iSize = 20;
    this.bEnabled = true;
    
    this.divDropdown = null;
    this.tblListItems = null;

    this.containerid = null;
    this.container = null;
    
    this.buttonid = null;
    this.button = null;
    
    this.valuename = null;

    this.timeoutid = null;
}

// Create protytype.
WFControls.Combobox.prototype = 
{
    initialize : function() {
        WFControls.Combobox.callBaseMethod(this, 'initialize');
        
        // other initialization
        var element = this.get_element();
        if( !element ) return;
        
        var parent = element.parentNode;
        var doc = window.document;
    
        if ( this.containerid != null )
            this.container = $get( this.containerid );
                
        if ( this.buttonid != null )
            this.button = $get( this.buttonid );
            
        if ( this.button != null )
            this.button.className = 'cbxButton';

		this.hiddenValue = doc.createElement('input');
		this.hiddenValue.name = this.valuename;
		this.hiddenValue.setAttribute('type', 'hidden');
		parent.appendChild( this.hiddenValue );
        element.name = null;
        
        // initialize the value		
		this.selectedIndex = -1;
		this.set_value(this.sValue); 

        this._element_onfocus_handler = Function.createDelegate(this, this._element_onFocus);
        this._element_onkeydown_handler = Function.createDelegate(this, this._element_onKeyDown);
        this._element_onkeyup_handler = Function.createDelegate(this, this._element_onKeyUp);
        this._element_onchange_handler = Function.createDelegate(this, this._element_onChange);
        this._element_onclick_handler = Function.createDelegate(this, this.toggleShowListItems);

        $addHandler( element, 'focus', this._element_onfocus_handler );
        $addHandler( element, 'keydown', this._element_onkeydown_handler );
        $addHandler( element, 'keyup', this._element_onkeyup_handler );
        $addHandler( element, 'change', this._element_onchange_handler );
        if( this.autovalidate )
            $addHandler( element, 'click', this._element_onclick_handler );

        this.optionTD_onclick_handler = Function.createDelegate(this, this.optionTD_Click);
        this.optionTD_onmouseover_handler = Function.createDelegate(this, this.optionTD_MouseOver);
        this.optionTD_onmouseout_handler = Function.createDelegate(this, this.optionTD_MouseOut);

        if( this.container != null ) {        
            $addHandlers ( this.container, {
                    'mouseover' : this.container_onMouseOver, 
                    'mouseout': this.container_onMouseOut }, this );
        }
        
        if( this.button != null ) {
            this.button_onClick_handler = Function.createDelegate(this, this.toggleShowListItems);
            $addHandler ( this.button, 'click', this.button_onClick_handler );
        }
    },
    
    dispose : function() {
        this.releaseListItems();
        
        $clearHandlers( this.get_element());
        if( this.divDropDown != null ) $clearHandlers( this.divDropDown);
        if( this.button != null ) $clearHandlers( this.button);
        if( this.container != null ) $clearHandlers( this.container);
        
        WFControls.Combobox.callBaseMethod(this, 'dispose');
    },
	  
	  /* -- Property Methods -- */

    get_options : function() {
            return this.options;
        },
    
    get_option : function( index ) {
            if( this.options != null && this.options.length > index && index >= 0 )
                return this.options[index];
            return null;
        },
    
    add_option : function( option ) {
            var index;
               
            if( this.options == null ) {
                this.options = [ option ];
                index = 0;
            } else {
                index = this.options.length;
                this.options[index] = option;
            }
            this.refresh_options();
            return index;
        },
            
    get_options_count : function() {
            if( this.options != null )
                return this.options.length;
            return 0;
        },
        
    set_options : function( value ) {
            this.options = value;
            this.refresh_options();
        },
        
    clear_options : function() {
            this.options = [];
            this.refresh_options();
        },
        
    refresh_options : function() {
            if( this.divDropDown != null ) {
                if( this.isDropDownVisible() ) {
                    this.releaseListItems();
                    this.createListItems();
                    this.showListItems();
                } else {
                    this.releaseListItems();
                }
            }
        },
          	  
    get_buttonid : function() {
            return this.buttonid;
        },
    
    set_buttonid : function( value ) {
            this.buttonid = value;
        },
          	  
    get_button : function() {
            return this.button;
        },
    
    set_button : function( value ) {
            this.button = value;
        },
          	  
    get_valuename : function() {
            return this.valuename;
        },
    
    set_valuename : function( value ) {
            this.valuename = value;
        },
          	  
    get_containerid : function() {
            return this.containerid;
        },
    
    set_containerid : function( value ) {
            this.containerid = value;
        },
          	  
    get_container : function() {
            return this.container;
        },
    
    set_container : function( value ) {
            this.container = value;
        },
          	  
    get_autovalidate : function() {
			return this.autovalidate;
	  },
	  
    set_autovalidate : function( val ) {
			this.autovalidate = val;
			this.get_element().readOnly = this.autovalidate || !this.bEnabled;
	  },
	  
    get_Enabled : function() {
			return this.bEnabled;
	  },

    set_Enabled : function( val ) {
			this.bEnabled = val;
			this.get_element().readOnly = this.autovalidate || !this.bEnabled;
			this.get_element().disabled = !this.bEnabled;
	  },
	  
    get_selectedIndex : function() {
			return this.selectedIndex;
		},

    set_selectedIndex : function( val ) {
			if (val >= this.options.length) {
				throw new Error("Index Out of Bounds");
			} else {
				if (this.selectedIndex > -1)
					this.blurListItem(this.selectedIndex);
				this.selectedIndex=val;
				this.takeValueFromDropDown();
//				_selectedIndex.fireChange();
//				_value.fireChange();
			}
		},
		
    get_value : function() {
			if (this.hiddenValue != null) 
	    		return this.hiddenValue.value;
	    	else
	    	    return this.sValue;
    	},
		
    set_value : function(val) {
            if( val == null ) 
                val = ""; 
            else if( typeof( val ) != 'string' ) 
                val = val.toString();
            
			this.sValue = val;
			this.selectedIndex=-1;
			
			if (this.hiddenValue != null) {
				this.hiddenValue.value = val;
				var found = false;
				for(var i=0;i<this.options.length;i++) {
					if (this.options[i].Value.toUpperCase() == this.sValue.toUpperCase()) {
						this.selectedIndex=i;
						this.hiddenValue.value=this.options[i].Value;
						this.sValue = this.options[i].Text;
					    // this.options[i].Selected = true;
					} else {
					    // this.options[i].Selected = false;
					}
				}
				this.get_element().value = this.sValue;
			}
		},
		
    get_size : function() {
			return this.iSize;
		},
		
    set_size : function(val) {
			this.iSize = val;
		},

    /* -- Exposed Event Handlers  -- */

    add_change : function( handler ) {
            this.get_events().addHandler('change', handler );
        },
    
    remove_change : function( handler ) {
            this.get_events().removeHandler('change', handler );
        },

    add_fill : function( handler ) {
            this.get_events().addHandler('fill', handler );
        },
    
    remove_fill : function( handler ) {
            this.get_events().removeHandler('fill', handler );
        },

    fire_fill : function() {
            var h = this.get_events().getHandler('fill');
            if (h) h(this, Sys.EventArgs.Empty);
        },
    
    /* Event Handlers */

    divDropDown_onMouseOut : function(e) {
            this.selectListItem( this.selectedItem );
            return true;
        }, 
        
    divDropDown_onMouseWheel : function(e) {
		    this.checkListItems();
		
			e.cancelBubble = true;
			var iItemsLength = this.tblListItems.cells.length-1;
			var lastcell = this.optionTD_getCell(iItemsLength);
			
			var iItemTop = this.getPixelTop(lastcell,"DIV") + lastcell.offsetHeight + 1;
			if (((iItemTop-this.divDropDown.scrollTop)<=150 && e.wheelDelta <= 0)||(this.divDropDown.scrollTop <=1 && e.wheelDelta >=0))
				event.returnValue=false;
		},

    container_onMouseOver : function(e) {
            if( !this.bEnabled ) return false;
			if (!this.isDropDownVisible()) {
				if( this.button != null )
				    this.button.className = 'cbxButtonHover';
			}
		},

    container_onMouseOut : function(e) {
            if( !this.bEnabled ) return false;
			if (!this.isDropDownVisible()) {
				if( this.button != null )
				    this.button.className = 'cbxButton';
			}
		},

    schedule_hideDropDown : function(e) {
            window.setTimeout( this.divDropDown_onblur_handler, 500 );
        },
        
    divDropDown_onBlur : function(e) {
			var bIsDirty = false;
			this.blurListItem(this.selectedIndex);	
			
			// Hide DropDown on blur
			this.hideListItems();
		},

    schedule_change : function() {
		    this.timeoutid = window.setTimeout(this._element_onchange_handler, 1000);	//this.emitChangeEvent();
        },
    
    cancel_change : function() {
            if( this.timeoutid != null ) {
                window.clearTimeout( this.timeoutid );
                this.timeoutid = null;
            }
        },
    		
    _element_onFocus : function(e) {
            this.cancel_change();
			try {this.get_element().select();} catch (ex) {}
		},
		
    _element_onKeyDown : function(e) {
		    this.checkListItems();
					
			if (!this.isDropDownVisible())
				this.hoverIndex = this.selectedIndex;
			switch (e.keyCode) {
				case 40: // Down Arrow
					if (this.hoverIndex < this.options.length-1) {
						this.blurListItem(this.hoverIndex);
						this.hoverIndex += 1;
						if(this.isDropDownVisible()) {
    						var cell = this.optionTD_getCell(this.hoverIndex);
	    					var iItemTop = this.getPixelTop(cell,"DIV") + cell.offsetHeight + 1;
		    				if (iItemTop >= 150)
			    				this.divDropDown.scrollTop = this.divDropDown.scrollTop + cell.offsetHeight + 1;
			    	    }
						this.selectedIndex = this.hoverIndex;
						this.takeValueFromDropDown();
						this.schedule_change();
            			e.stopPropagation();
            			e.preventDefault();
					}
					break;
				case 38: // Up Arrow
					if (this.hoverIndex > 0) {
						this.blurListItem(this.hoverIndex);
						this.hoverIndex -= 1;
						if(this.isDropDownVisible()) {
						    var cell = this.optionTD_getCell(this.hoverIndex);
						    if (this.hoverIndex > -1)
							    this.divDropDown.scrollTop = this.getPixelTop(cell,"DIV")-1;
				        }
						this.selectedIndex = this.hoverIndex;
						this.takeValueFromDropDown();
						this.schedule_change();
            			e.stopPropagation();
			            e.preventDefault();
					}
					break;
				case 13:
					if (this.hoverIndex > -1 && this.isDropDownVisible()) {
						if (this.selectedIndex != this.hoverIndex) {
							this.selectedIndex = this.hoverIndex;
						}
						var item = this.optionTD_getCell(this.selectedIndex);
						this.get_element().value = item.innerText;
						this.get_element().select();
						if (this.hiddenValue.value != item.value)  {
							this.hiddenValue.value = item.value;
							this.emitChangeEvent();
						}
						this.hideListItems();
            			e.stopPropagation();
			            e.preventDefault();
						return;
					}
			}
			if (this.selectedIndex > -1 && e.keyCode != 13)
				this.selectListItem(this.selectedIndex);
		},

    _element_onKeyUp : function(e) {
			if (e.keyCode < 0x2f && e.keyCode != 32 && e.keyCode != 8 && e.keyCode != 46) {
				return;
			}
			var text = this.get_element().value;
			var utext = text.toUpperCase();
			var bMatch = false;
			this.blurListItem(this.selectedIndex);

			if( e.target.createTextRange ) {
			    if ( e.keyCode != 8 && e.keyCode != 46 ) {
				    for(var i=0;i<this.options.length;i++) {
					    var newtxt = this.options[i].Text;
					    if( newtxt != null ) {
					        var uopt = newtxt.toUpperCase();
					        if (uopt != utext && 0 == uopt.indexOf(utext) && utext.length > 0) {
						        bMatch = true;
						        var txtrange = e.target.createTextRange();
						        this.get_element().value = text + newtxt.substr(text.length);
						        txtrange.moveStart("character", text.length);
						        txtrange.select();
						        this.selectedIndex = i;
						        this.hoverIndex = i;
						        if(this.doesDropDownExist())
						            this.divDropDown.scrollTop = this.getPixelTop(this.optionTD_getCell(this.hoverIndex),"DIV")-1;
						        this.selectListItem(i);
						        break;
					        } else if (uopt == utext) {
						        bMatch=true;
						        this.selectedIndex = i;
						        this.hoverIndex = i;
						        if(this.doesDropDownExist())
						            this.divDropDown.scrollTop = this.getPixelTop(this.optionTD_getCell(this.hoverIndex),"DIV")-1;
						        this.selectListItem(i);
					        }
					    }
				    }
			    }
			    if (!bMatch) {
				    this.selectedIndex = -1;
				    this.hiddenValue.value = this.get_element().value;
			    }
			}
		},
		
	_element_onChange : function( e ) {
	        var value = this.get_element().value;
	        this.cancel_change();
    	    this.set_value(value);
	        this.emitChangeEvent(e);
	    },
	    
    emitChangeEvent : function(e) {
		    this.hideListItems();

            var h = this.get_events().getHandler('change');
            if (h) h(this, Sys.EventArgs.Empty);
		},
		
    isValid : function() {
			for(var i=0;i<this.options.length;i++) {
				if (this.options[i].Text.toUpperCase() == this.get_element().value.toUpperCase()) {
					return true;
				}
			}
			return false;
		},

    repaint : function() {
			this.selectedIndex=-1;
			this.createListItems();
			for (var i=0; i < this.options.length; i++) {
				if (this.get_element().value == this.options[i].Text) {
					this.selectedIndex=i;
					this.hiddenValue.value = this.options[i].Value;
				}
			}
		},
		
    checkListItems : function() {
			if( this.divDropDown == null )
				this.createDropDown();
			if( this.tblListItems == null )
				this.createListItems();
		},
		
	releaseListItems : function () {
            if( this.tblListItems != null ) {
                for( var i=0; i < this.tblListItems.rows.count; i++ )
                    $clearHandlers( this.tblListItems.rows[i].cell[0] );
                    
                this.tblListItems.parentNode.removeChild( this.tblListItems );
                this.tblListItems = null;
            }
	    },
	
	doesDropDownExist : function() {
	        return this.divDropDown != null;
	    },
	    
	isDropDownVisible : function() {
	        return this.doesDropDownExist() && this.divDropDown.style.display == 'block';
	    },
	    
	createDropDown : function() {
	        var parent = this.get_element();
	        
		    this.divDropDown = window.document.createElement('div');
		    this.divDropDown.setAttribute('UNSELECTABLE', 'on');
		    this.divDropDown.className = 'cbxDropDown';
		    while( parent.parentNode != null && parent.tagName != 'FORM' && parent.tagName != 'BODY' )
			    parent = parent.parentNode;
		    parent.insertBefore(this.divDropDown, null);

            this.divDropDown_onmousewheel_handler = Function.createDelegate(this, this.divDropDown_onMouseWheel);
            $addHandler ( this.divDropDown, 'mousewheel', this.divDropDown_onmousewheel_handler );
            this.divDropDown_onblur_handler = Function.createDelegate(this, this.divDropDown_onBlur);
            this.schedule_hideDropDown_handler = Function.createDelegate(this, this.schedule_hideDropDown);
            $addHandler( this.divDropDown, 'blur', this.schedule_hideDropDown_handler );
            this.divDropDown_onmouseout_handler = Function.createDelegate(this, this.divDropDown_onMouseOut);
            $addHandler( this.divDropDown, 'mouseout', this.divDropDown_onmouseout_handler );
            $addHandler( this.divDropDown, 'keydown', this._element_onkeydown_handler ); // use same handler as element
	    },
	    
    createListItems : function() {
            var element = this.get_element();
            if( !element ) return;

			this.divDropDown.style.display = 'block';
			this.tblListItems = window.document.createElement('table');
			this.tblListItems.setAttribute('cellspacing','0');
			this.tblListItems.setAttribute('cellpadding','0');
			this.tblListItems.style.width = '100%';
			this.tblListItems.setAttribute('UNSELECTABLE','on');
			if (this.options.length > 0) {
				for (var i=0; i < this.options.length; i++) {
				    var optitem = this.options[i];
					var tr = this.tblListItems.insertRow(i);
					var tc = tr.insertCell(0);
					tc.setAttribute('UNSELECTABLE', 'on');
					tc.className = "cbxItem";
					
					tc.value = optitem.value;
					var text = this.options[i].Text;
					tc.innerHTML = (text == '' || text == null)?'&nbsp;':text;
					
					tc.style.color = (this.options[i].Color != null?this.options[i].Color:"black");
					
					if( typeof(optitem.Enabled) === 'undefined' || optitem.Enabled ) {
					    $addHandler( tc, "click", this.optionTD_onclick_handler);
					    $addHandler( tc, "mouseover", this.optionTD_onmouseover_handler);
					    $addHandler( tc, "mouseout", this.optionTD_onmouseout_handler);
                    }
                    
					if( i == this.selectedIndex ) {
						//this.selectedIndex = i;
						this.selectListItem( i );
					}
				}
			} else {
			}
			
			this.divDropDown.appendChild(this.tblListItems);
			this.divDropDown.className = 'clsDropDownDiv';
			
			if (this.tblListItems.offsetHeight > 150) {
				this.divDropDown.style.height = 150;
			} else {
				this.divDropDown.style.height = '';
			}
			
			var container = (this.container?this.container:this.get_element());
			this.divDropDown.style.width = container.offsetWidth + 15;
			if (this.tblListItems.offsetWidth < container.offsetWidth) {
				this.tblListItems.style.width = container.offsetWidth + 15;
			}
			
			this.divDropDown.style.display = 'none';
			this.divDropDown.id = this.get_element().id + '_dropdown';
		},

    showListItems : function() {
            this.checkListItems();
			this.divDropDown.style.display = 'block';
			this.divDropDown.style.zIndex = 20003;
			
			var pos = Sys.UI.DomElement.getLocation( this.get_element() );
			Sys.UI.DomElement.setLocation( this.divDropDown, pos.x, pos.y+this.get_element().offsetHeight );
			if( this.button != null )
			    this.button.className = 'cbxButtonActive';
			this.get_element().select();
			this.divDropDown.scrollTop = this.getPixelTop(this.optionTD_getCell(this.hoverIndex),"DIV")-1;
			this.divDropDown.focus();
        },
        
    hideListItems : function () {
            if( this.isDropDownVisible() ) {
			    this.divDropDown.style.display = 'none';
			    if( this.button != null )
			        this.button.className = 'cbxButton';
            }
        },

    toggleShowListItems : function(e ) {
			if (!this.bEnabled)
				return;
		    
		    if( !this.isDropDownVisible() ) {
                this.fire_fill();
            }

			if (this.selectedIndex > -1) {
				this.selectListItem(this.selectedIndex);
				this.hoverIndex = this.selectedIndex;
			}
			if (this.isDropDownVisible()) {
				//hoverIndex = -1;
				this.hideListItems();
			    this.get_element().select();
			} else {
			    this.cancel_change();
				this.checkListItems();
                this.showListItems();					
			}
		},
	
    getPixelTop : function(elem, tagName) {
			if (elem == null)
			    return -1;
			    
			var top = 0;
			while (elem != null && elem.tagName != tagName) {
				top += elem.offsetTop-elem.scrollTop;
				elem = elem.offsetParent;
			}
			return top;
		},
		
    getPixelLeft : function(elem, tagName) {
			var left = 0;
			while (elem != null && elem.tagName != tagName) {
				left += elem.offsetLeft;
				elem = elem.offsetParent;
			}
			return left;
		},
		
    getFormElement : function() {
			var elem = element;
			while (elem.tagName != "FORM") {
				elem = elem.offsetParent;
			}
			return elem;
		},
		
    takeValueFromDropDown : function() {
			var bIsDirty = false;
			if (this.selectedIndex > -1) {
				bIsDirty = (this.hiddenValue.value != this.options[this.selectedIndex].Value);
				this.get_element().value = this.options[this.selectedIndex].Text;
				this.hiddenValue.value = this.options[this.selectedIndex].Value;
			}
			return bIsDirty;
		},
	
    selectListItem : function(index) {
		    this.checkListItems();

            if( index >= 0 ) {
			    var item = this.optionTD_getCell(index);
			    if( item != null ) {
			        item.style.backgroundColor = 'Highlight';
			        item.style.color = 'HighlightText';
			    }
			}
		},

    blurListItem : function(index) {
			if (index > -1) {
			    this.checkListItems();
					
				var item = this.optionTD_getCell(index);
				if( item != null ) {
				    item.style.backgroundColor = 'transparent';
				    item.style.color = (this.options[index].Color?this.options[index].Color:"black");
				}
			}
		},

    optionTD_getIndex : function(e) {
            return e.target.parentNode.rowIndex;
        },
    
    optionTD_getCell : function( index ) {
            if( index < 0 || this.tblListItems == null )
                return null;
                
            if( !this.tblListItems.cells || this.tblListItems.cells.length == 0 )
                return this.tblListItems.getElementsByTagName('td')[index];
            else
                return this.tblListItems.cells[index];
        },
    
    optionTD_Click : function(e) {
            var index = this.optionTD_getIndex(e);
            if( index >= 0 && index < this.options.length ) {
                var item = this.options[index];
                
			    this.hoverIndex = index;
			    this.selectedIndex = index;
			    this.get_element().value = item.Text;
			    this.get_element().select();
			    if (this.hiddenValue.value != item.Value) {
				    this.hiddenValue.value = item.Value;
				    this.emitChangeEvent();
			    }
			}
			e.stopPropagation();
			e.preventDefault();
		},
		
    optionTD_MouseOver : function(e) {
            var index = this.optionTD_getIndex(e);
			if (this.selectedIndex > -1)
				this.blurListItem(this.selectedIndex);
			this.selectListItem(index);
			this.hoverIndex = index;
			//e.stopPropagation();
			//e.preventDefault();
			return true;
		},
		
    optionTD_MouseOut : function(e) {
            var index = this.optionTD_getIndex(e);
			this.blurListItem(index);
			this.hoverIndex = -1;
			//e.stopPropagation();
			//e.preventDefault();
			return true;
		}
};
	
// descriptor for JSON serialization.
WFControls.Combobox.descriptor = {
    properties: [ 
        {name: 'options', type: Object}, 
        {name: 'autovalidate', type: Boolean}, 
        {name: 'size', type: Number},
        {name: 'containerid', type: String},
        {name: 'container', type: Object},
        {name: 'valuename', type: String},
        {name: 'value', type: String},
        {name: 'buttonid', type: String},
        {name: 'button', type: Object}
        ],
    events: [
        {name: 'change' }, {name: 'fill' }
        ]
}

// the base this class inherits from
WFControls.Combobox.inheritsFrom(Sys.UI.Behavior);

// Register the class as derived from UI.Behavior.
WFControls.Combobox.registerClass('WFControls.Combobox', Sys.UI.Behavior);

if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

