/*
jquery.combobox
version 0.1.2.7

Copyright © 2007,2008 Minel Pather|Ahura Mazda|jquery.sanchezsalvador.com
Dual licensed under MIT and GPL licences:
	* www.opensource.org/licenses/mit-license.php
	* www.gnu.org/licenses/gpl.html
*/
jQuery.fn.combobox =
	function(styles, options)
	{
		var _context = this;
		// create a combobox class instance instead of jQuery.fn.combobox which is a namespace.
		this.combobox = new Function();
		
		var styleSettings =
		{		
			comboboxContainerClass: null,
			comboboxValueContentContainerClass: null,
			comboboxValueContentClass: null,
			comboboxDropDownButtonClass: null,
			comboboxDropDownClass: null,
			comboboxDropDownItemClass: null,
			comboboxDropDownItemHoverClass: null,
			comboboxDropDownGroupItemHeaderClass: null,
			comboboxDropDownGroupItemContainerClass: null
		};
		
		var optionSettings =
		{
			animationType: "slide",
			animationSpeed: "fast", 
			width: 120
		};
		
		if (styles)
		{
			jQuery.extend(styleSettings, styles);
		}
		
		if (options)
		{
			jQuery.extend(optionSettings, options);
		}
		
		this.combobox.onChange = null;
		
		return this.each(
			function()
			{
				this.internalCombobox = new ComboboxClass(this);
				
				// Call the instance to initialise itself
				this.internalCombobox.initialise();
				
				function ComboboxClass(elementDOM)
				{
					var _originalElementJQuery = jQuery(elementDOM);
					var _containerJQuery = null;
					var _containerDefaultStyle = "background-color:#fff;border-left: solid 2px #777;border-top: solid 2px #777;border-right: solid 1px #ccc;border-bottom: solid 1px #ccc;";
					var _containerEnforcedStyle = "padding:0;";
					var _dropDownListJQuery = null;
					var _dropDownListEnforcedStyle = "list-style-type:none;min-height:15px;padding-top:0;margin:0;overflow:auto";
					var _dropDownListDefaultStyle = "cursor:default;padding:2px;background:#fff;border-right:solid 1px #000;border-bottom:solid 1px #000;border-left:solid 1px #aaa;border-top:solid 1px #aaa;";
					var _dropDownListItemEnforcedStyle = "display:block;";
					var _dropDownListItemDefaultStyle = "cursor:default;padding-left:2px;font-weight:normal;font-style:normal;";
					var _dropDownListGroupItemContainerEnforcedStyle = "list-style-type:none;";
					var _dropDownListGroupItemContainerDefaultStyle = "padding-left:10px;margin-left:0;";
					var _dropDownListGroupItemHeaderEnforcedStyle = "";
					var _dropDownListGroupItemHeaderDefaultStyle = "font-style:italic;font-weight:bold;";
					var _dropdownListMaximumHeight = 300; // default max height: 300px
					var _valueContentContainerJQuery = null;
					var _valueContentContainerEnforcedStyle = "position:relative;overflow:hidden;";
					var _valueContentJQuery = null;
					var _valueContentEnforcedStyle = "float:left;position:absolute;cursor:default;overflow:hidden;";
					var _valueContentDefaultStyle = "padding-left:3px;";
					var _dropDownButtonJQuery = null;
					var _dropDownButtonDefaultStyle = "overflow:hidden;width:16px;height:18px;color:#000;background:#D6D3CE;font-family:arial;font-size:8px;cursor:default;text-align:center;vertical-align:middle;";
					var _dropDownButtonEnforcedStyle = "background-repeat:no-repeat;float:right;";
					var _dropDownButtonDefaultUnselectedStyle = "padding-left:0px;padding-top:1px;width:12px;height:13px;border-right:solid 2px #404040;border-bottom:solid 2px #404040;border-left:solid 2px #f0f0f0;border-top:solid 2px #f0f0f0";
					var _dropDownButtonDefaultSelectedStyle = "padding-left:1px;padding-top:3px;width:12px;height:13px;border:solid 1px #808080";
					var _dropDownButtonDefaultCharacter = "&#9660;"; //down-arrow character
					var _lastItemSelectedJQuery = null;
					var _lastItemHoveredJQuery = null;
					var _lastValue = null;
					var _downdownListPositionIsInverted = false;
					var _maximumItemLength = 0;
					var _dropDownListOffset = null;
					var _dropDownListHeight = 0;
					var _dropDownButtonImageDimension = null;
					var _valueContentContainerImageDimension = null;
					var _valueContentMaximumHeight = null;
					
					String.format =
						function()
						{
							var currentString = null;
							if (arguments.length != 0)
							{
								currentString = arguments[0];
								for (var argumentIndex = 1; argumentIndex < arguments.length; argumentIndex++)
								{
									var modifiedString = new RegExp('\\{' + (argumentIndex - 1) + '\\}','gm');
									currentString = currentString.replace(modifiedString, arguments[argumentIndex]);
								}
							}
							
							return currentString;
						};
						
					function getPixelValue(object)
					{
						var pixelValue = null;
						
						if (object)
						{
							if (object.substr(-2, 2) == "px")
							{
								pixelValue = object.substr(0, (object.length - 2));
							}
						}
						
						return pixelValue;
					}

					function setInnerWidth(elementJQuery, width)
					{
						var differenceWidth = (elementJQuery.outerWidth() - elementJQuery.width());
						
						elementJQuery.width(width - differenceWidth);
					}
				
					function setInnerHeight(elementJQuery, height)
					{
						var differenceheight = (elementJQuery.outerHeight() - elementJQuery.height());
						
						elementJQuery.height(height - differenceheight);
					}
					
					function applyMultipleStyles(elementJQuery, multipleCSSStyles)
					{
						var stylePairArray = multipleCSSStyles.split(";");
						if (stylePairArray.length > 0)
						{
							for (var stylePairArrayIndex = 0; stylePairArrayIndex < stylePairArray.length; stylePairArrayIndex++)
							{
								var stylePair = stylePairArray[stylePairArrayIndex];
								var splitStylePair = stylePair.split(":");
								
								elementJQuery.css(splitStylePair[0], splitStylePair[1]);
							}
						}
					}
					
					function getImageDimension(imageURL)
					{
						var dimension = new Object();
						dimension.width = 0;
						dimension.height = 0;
						
						sizingImageJQuery = jQuery("<img style='border:none;margin:0;padding:0;'></img>");
						sizingImageJQuery.attr("src", imageURL);
						
						_containerJQuery.append(sizingImageJQuery);
						
						dimension.width = sizingImageJQuery.width();
						dimension.height = sizingImageJQuery.height();
						
						sizingImageJQuery.remove();

						return dimension;
					}

					function calculateIndividualImageDimension(jqueryElement)
					{
						var dimension = null;
						var backgroundImageURL = jqueryElement.css("background-image");
						backgroundImageURL = backgroundImageURL.replace("url(", "", "gi");
						backgroundImageURL = backgroundImageURL.replace('"', '', "gi");
						backgroundImageURL = backgroundImageURL.replace('\"', '', "gi");
						backgroundImageURL = backgroundImageURL.replace(")", "", "gi");
						
						if (backgroundImageURL != "none")
						{
							dimension = getImageDimension(backgroundImageURL);
						}
						
						return dimension;
					}
					
					function calculateImageDimensions()
					{
						_dropDownButtonImageDimension = calculateIndividualImageDimension(_dropDownButtonJQuery);
						_valueContentContainerImageDimension = calculateIndividualImageDimension(_valueContentContainerJQuery);
					}
					
					function setValueContentContainerState(state)
					{
						if (styleSettings.comboboxValueContentContainerClass)
						{
							// Only process buttomn states if a background-image has been set
							if (_valueContentContainerImageDimension != null)
							{
								var height = _valueContentContainerJQuery.height();
								var offset = (state * height);
								
								// Check if the image is higher than the set height.
								// This signifies that the image file contain different images below each other for different
								// states.
								if (_valueContentContainerImageDimension.height > offset)
								{
									var background_positionCSS = String.format("0px -{0}px", offset);
									_valueContentContainerJQuery.css("background-position", background_positionCSS);
								}
							}
						}
					}
					
					function setDropDownButtonState(state)
					{
						if (styleSettings.comboboxDropDownButtonClass)
						{
							// Only process buttomn states if a background-image has been set
							if (_dropDownButtonImageDimension != null)
							{
								var width = _dropDownButtonJQuery.width();
								var offset = (state * width);
								
								// Check if the image is wider than the set width.
								// This signifies that the image file contain different images next to each other for different
								// states.
								if (_dropDownButtonImageDimension.width > offset)
								{
									var background_positionCSS = String.format("-{0}px 0px", offset);
									_dropDownButtonJQuery.css("background-position", background_positionCSS);
								}
							}
						}
						else
						{
							var style = _dropDownButtonDefaultUnselectedStyle;
							
							if (state == 1)
							{
								style = _dropDownButtonDefaultSelectedStyle;
							}
							
							applyMultipleStyles(_dropDownButtonJQuery, style);
						}			
					}

					function setControlVisualState(state)
					{
						setValueContentContainerState(state);
						
						setDropDownButtonState(state);
					}
					

					function buildValueContent()
					{

						var valueContentContainerHTML = "";
						if (styleSettings.comboboxValueContentContainerClass)
						{
							valueContentContainerHTML = String.format("<div class='{0}' style='{1}'></div>", styleSettings.comboboxValueContentContainerClass, _valueContentContainerEnforcedStyle);
						}
						else
						{
							valueContentContainerHTML = String.format("<div style='{0}'></div>", _valueContentContainerEnforcedStyle);
						}
						
						var valueContentHTML = "";
						if (styleSettings.comboboxValueContentClass)
						{
							valueContentHTML = String.format("<div class='{0}' style='{1}'></div>", styleSettings.comboboxValueContentClass, _valueContentEnforcedStyle);
						}
						else
						{
							valueContentHTML = String.format("<div style='{0}'></div>", _valueContentEnforcedStyle + _valueContentDefaultStyle);
						}
						
						var dropdownButtonHTML = "";
						if (styleSettings.comboboxDropDownButtonClass)
						{
							dropdownButtonHTML = String.format("<div class='{1}' style='{0}'></div>",_dropDownButtonEnforcedStyle, styleSettings.comboboxDropDownButtonClass);
						}
						else
						{
							dropdownButtonHTML = String.format("<div style='{0}'>{1}</div>", (_dropDownButtonEnforcedStyle + _dropDownButtonDefaultStyle), _dropDownButtonDefaultCharacter);
						}
						
						_valueContentJQuery = jQuery(valueContentHTML);
						_dropDownButtonJQuery = jQuery(dropdownButtonHTML);
						_valueContentContainerJQuery = jQuery(valueContentContainerHTML);
						
						_valueContentContainerJQuery.appendTo(_containerJQuery);
						_valueContentJQuery.appendTo(_valueContentContainerJQuery);
						_dropDownButtonJQuery.appendTo(_valueContentContainerJQuery);
						
						calculateImageDimensions();
						
						_valueContentMaximumHeight = getPixelValue(_valueContentJQuery.css("max-height"));
					
						// Set control to normal state
						setControlVisualState(0);
					}
					
					function buildDropDownItem(childJQuery)
					{
						var dataItemHTML = "";
						var dataItemClass = null;
						var dataItemText = "";
						var dataItemTitle = "";
						var dataItemValue = null;
						var dataItemStyle = "";
						var dataItemType = "option";
						var childElement = childJQuery[0];
						
						if (childElement.title)
						{
							if (childElement.title != "")
							{
								dataItemTitle = childElement.title;
							}
						}
						
						if (childJQuery.is('option'))
						{
							if (childElement.dataText)
							{
								dataItemText = childElement.dataText;
							}
							else
							{
								dataItemText = childJQuery.text();
							}
							dataItemValue = childJQuery.val();
							
							if (styleSettings.comboboxDropDownItemClass)
							{
								dataItemClass = styleSettings.comboboxDropDownItemClass;
								dataItemStyle = _dropDownListItemEnforcedStyle;
							}
							else
							{
								dataItemStyle = (_dropDownListItemEnforcedStyle + _dropDownListItemDefaultStyle);
							}
							
							if (dataItemClass)
							{						
								dataItemHTML = String.format("<li style='{0}' class='{1}'>{2}</li>", dataItemStyle, dataItemClass, dataItemText);
							}
							else
							{
								dataItemHTML = String.format("<li style='{0}'>{1}</li>", dataItemStyle, dataItemText);
							}
							
						}
						else
						{
							if (childJQuery[0].dataText)
							{
								dataItemText = childJQuery[0].dataText;
							}
							else
							{
								dataItemText = childJQuery.attr('label');
							}
							dataItemValue = childJQuery.attr('class');
							dataItemType = "optgroup";
							
							if (styleSettings.comboboxDropDownGroupItemHeaderClass)
							{
								dataItemClass = styleSettings.comboboxDropDownGroupItemHeaderClass;
								dataItemStyle = _dropDownListGroupItemHeaderEnforcedStyle;
							}
							else
							{
								dataItemStyle = (_dropDownListGroupItemHeaderEnforcedStyle + _dropDownListGroupItemHeaderDefaultStyle);
							}
							
							if (dataItemClass)
							{						
								dataItemHTML = String.format("<li><span style='{0}' class='{1}'>{2}</span></li>", dataItemStyle, dataItemClass, dataItemText);
							}
							else
							{
								dataItemHTML = String.format("<li><span style='{0}'>{1}</span></li>", dataItemStyle, dataItemText);
							}
						}
						
						var dataItemJQuery = jQuery(dataItemHTML);
						
						// The element's style is set to inline for the calculation of the true width
						// The element is then reset to its enforced style (display:block) later
						dataItemJQuery.css("display", "inline");
						// Store the value with the DOMElement which is persisted with the Browser
						dataItemJQuery[0].dataText = dataItemText;
						dataItemJQuery[0].dataValue = dataItemValue;
						dataItemJQuery[0].dataType = dataItemType;
						if (dataItemTitle == "")
						{
							dataItemTitle = dataItemText
						}
						dataItemJQuery[0].title = dataItemTitle;
						
						return dataItemJQuery;
					}

					function recursivelyBuildList(parentJQuery, childrenOptionsJQuery)
					{
						childrenOptionsJQuery.each(
							function()
							{
								var childJQuery = jQuery(this);
								var builtDropDownItemJQuery = buildDropDownItem(childJQuery);
								parentJQuery.append(builtDropDownItemJQuery);
								
								var offsetLeft = builtDropDownItemJQuery.offset().left;
								
								offsetLeft -= _dropDownListOffset.left;
								
								if (offsetLeft < 0)
								{
									offsetLeft = 0;
								}
								
								var width = (offsetLeft + builtDropDownItemJQuery.outerWidth());
								if (width > _maximumItemLength)
								{
									_maximumItemLength = width;
								}
								
								// Set the enforced style of display:block after the width has been calculated.
								applyMultipleStyles(builtDropDownItemJQuery, _dropDownListItemEnforcedStyle);
								
								if (childJQuery.is('optgroup'))
								{
									var dataGroupItemHTML = "";
									if (styleSettings.comboboxDropDownGroupItemContainerClass)
									{
										dataGroupItemHTML = String.format("<ul style='{0}' class='{1}'></ul>", _dropDownListGroupItemContainerEnforcedStyle, styleSettings.comboboxDropDownGroupItemContainerClass);
									}
									else
									{
										dataGroupItemHTML = String.format("<ul style='{0}'></ul>", (_dropDownListGroupItemContainerEnforcedStyle + _dropDownListGroupItemContainerDefaultStyle));
									}
									
									var dataGroupItemJQuery = jQuery(dataGroupItemHTML);
									builtDropDownItemJQuery.append(dataGroupItemJQuery);
									
									// If not an option, then the child of a Select must be an optgroup element
									recursivelyBuildList(dataGroupItemJQuery, childJQuery.children());
								}
							});
					}

					function buildDropDownList()
					{
						var originalElementChildrenJQuery = _originalElementJQuery.children();
						_lastItemSelectedJQuery = null;
						_lastValue = null;

						// If the Drop Down List container already exists, recreate only the items,
						// else create the container and the items as well.
						if (_dropDownListJQuery)
						{
							// Clear out any existing children elements
							_dropDownListJQuery.empty();
						}
						else
						{
							var dropDownHTML = "";
							if (styleSettings.comboboxDropDownClass)
							{
								dropDownHTML = String.format("<ul class='{0}' style='{1}'></ul>", styleSettings.comboboxDropDownClass, _dropDownListEnforcedStyle);
							}
							else
							{
								dropDownHTML = String.format("<ul style='{0}'></ul>", (_dropDownListEnforcedStyle + _dropDownListDefaultStyle));
							}
							
							_dropDownListJQuery = jQuery(dropDownHTML);
							// Create the equivalent of the drop down list where the all the values are shown
							_dropDownListJQuery.appendTo(_containerJQuery);
							
							// Enable the Drop Down List to be able to receive focus and key events
							_dropDownListJQuery.attr("tabIndex", 0);
						}
						
						// Create the internal list of values if they exist
						if (originalElementChildrenJQuery.length > 0)
						{
							_maximumItemLength = 0;
							_dropDownListOffset = _dropDownListJQuery.offset();
								
							recursivelyBuildList(_dropDownListJQuery, originalElementChildrenJQuery);
						}

						var maximumHeight = getPixelValue(_dropDownListJQuery.css("max-height"));
										
						// Only use the maximum height if it has been set correctly
						if (maximumHeight)
						{
							_dropdownListMaximumHeight = maximumHeight;
						}
						
						var dropdownListHeight = _dropDownListJQuery.height();
						if (dropdownListHeight > _dropdownListMaximumHeight)
						{
							_dropDownListJQuery.height(_dropdownListMaximumHeight);
						}
						
						_dropDownListHeight = _dropDownListJQuery.height();
					}

					function updateDropDownListWidth()
					{
						//Drop down list element
						var dropdownListWidth = _containerJQuery.outerWidth();
						if (dropdownListWidth < _maximumItemLength)
						{
							dropdownListWidth = _maximumItemLength;
						}
						
						_dropDownListJQuery.width(dropdownListWidth);
					}
					
					function positionDisplayValue()
					{
						_valueContentJQuery.height("auto");
						var displayValueHeight = _valueContentJQuery.outerHeight();
						var displayContainerHeight = _valueContentContainerJQuery.height();

						if (_valueContentMaximumHeight)
						{
							if (_valueContentMaximumHeight < displayValueHeight)
							{
								displayValueHeight = _valueContentMaximumHeight;
								_valueContentJQuery.height(displayValueHeight);
							}
						}
						
						var difference = ((displayContainerHeight - displayValueHeight) / 2);
						
						if (difference < 0)
						{
							difference = 0;
						}
						
						_valueContentJQuery.css("top", difference);
					}
					

					function applyLayout()
					{
						_containerJQuery.width(optionSettings.width);
						
						// Removes any units and retrieves only the value of width
						var controlWidth = _containerJQuery.width();
						setInnerWidth(_valueContentContainerJQuery, controlWidth);
						
						var displayValueWidth = (_valueContentContainerJQuery.width() - _dropDownButtonJQuery.outerWidth());
						setInnerWidth(_valueContentJQuery, displayValueWidth);
						var dropDownButtonHeight = _dropDownButtonJQuery.outerHeight();
						setInnerHeight(_valueContentContainerJQuery, dropDownButtonHeight);
						
						_dropDownListJQuery.css("position", "absolute");
						_dropDownListJQuery.css("z-index", "20000");
						
						updateDropDownListWidth();
						
						// Position the drop down list correctly, taking the main display control border into consideration
						var currentLeftPosition = _dropDownListJQuery.offset().left;
						var leftPosition = (currentLeftPosition - (_containerJQuery.outerWidth() - _containerJQuery.width()));
						_dropDownListJQuery.css("left", leftPosition + 1);
						
						_dropDownListJQuery.hide();
					}

					function setContentDisplay()
					{
						var valueHasChanged = false;
						var originalElement = _originalElementJQuery[0];
						var dataItemJQuery;
						
						if (originalElement.length > 0)
						{
							//var selectedText = originalElement[originalElement.selectedIndex].text;
							var selectedDropDownListItemJQuery = jQuery("li[dataValue='" + _originalElementJQuery.val() + "']", _dropDownListJQuery);
							
							if(selectedDropDownListItemJQuery[0]) {
								_valueContentJQuery.html(selectedDropDownListItemJQuery[0].dataText);
								_valueContentJQuery.attr("title", selectedDropDownListItemJQuery[0].title);
							}
							
							// Reposition the display value based on height of the element after the text has changed
							positionDisplayValue();
							
							if (_lastValue != null && _originalElementJQuery.val() != null)
							{
								if (_lastValue != _originalElementJQuery.val())
								{
									valueHasChanged = true;
								}
							}
							
							_lastValue = _originalElementJQuery.val();
							
							if (valueHasChanged)
							{
								// Fire the OnChange event for the original select element
								if (originalElement.onchange)
								{
									originalElement.onchange();
								}
							}
							
							if (_lastItemSelectedJQuery)
							{
								toggleItemHighlight(_lastItemSelectedJQuery, false);
							}
							
							_lastItemSelectedJQuery = selectedDropDownListItemJQuery;
							
							toggleItemHighlight(_lastItemSelectedJQuery, true);
						}
					}
					
					function toggleItemHighlight(elementJQuery, isHighlighted)
					{
						if (elementJQuery)
						{
							if (styleSettings.comboboxDropDownItemHoverClass)
							{
								if (isHighlighted)
								{
									elementJQuery.addClass(styleSettings.comboboxDropDownItemHoverClass);
								}
								else
								{
									elementJQuery.removeClass(styleSettings.comboboxDropDownItemHoverClass);
								}
							}
							else
							{
								if (isHighlighted)
								{
									elementJQuery.css("background", "#000");
									elementJQuery.css("color", "#fff");
								}
								else
								{
									elementJQuery.css("background", "");
									elementJQuery.css("color", "");
								}
							}
						}
					}

					function buildContainer()
					{
						var containerHTML = "";
						if (styleSettings.comboboxContainerClass)
						{
							containerHTML = String.format("<div class='{0}' style='{1}'></div>", styleSettings.comboboxContainerClass, _containerEnforcedStyle);
						}
						else
						{
							containerHTML = String.format("<div style='{0}' style='{1}'></div>", _containerDefaultStyle, _containerEnforcedStyle);
						}
						_containerJQuery = jQuery(containerHTML);
						_originalElementJQuery.before(_containerJQuery);
						_containerJQuery.append(_originalElementJQuery);
						_originalElementJQuery.hide();
						
						// Allow the custom jquery.combobox be able to receive focus and key events
						_containerJQuery.attr("tabIndex", 0);
					}

					this.initialise =
						function ()
						{
							buildContainer();
							
							buildValueContent();
							
							buildDropDownList();
							
							applyLayout();
							
							bindEvents();
							
							setContentDisplay();
						};

					function slideUp(newTop)
					{
						_dropDownListJQuery.animate(
							{
								height: "toggle",
								top: newTop
							},
							optionSettings.animationSpeed);
					}

					function slideDown(newTop)
					{
						_dropDownListJQuery.animate(
							{
								height: "toggle",
								opacity: "toggle",
								top: newTop
							},
							optionSettings.animationSpeed);
					}
					
					function slideToggle(callback)
					{
						_dropDownListJQuery.animate(
							{
								height: "toggle",
								opacity: "toggle"
							},
							optionSettings.animationSpeed,
							callback);
					}
					
					function getDropDownListTop()
					{
						var comboboxTop = _containerJQuery.position().top;
						var dropdownListHeight = _dropDownListJQuery.outerHeight();
						var comboboxBottom = (comboboxTop + _containerJQuery.outerHeight());
						var windowScrollTop = jQuery(window).scrollTop();
						var windowHeight = jQuery(window).height();	
						var availableSpaceBelow = (windowHeight - (comboboxBottom - windowScrollTop));
						var dropdownListTop;

						dropdownListTop = comboboxBottom;
						_downdownListPositionIsInverted = false;

						if (availableSpaceBelow < dropdownListHeight)
						{
							if ((comboboxTop - windowScrollTop)> dropdownListHeight)
							{
								// There is space above
								dropdownListTop = (comboboxTop - dropdownListHeight);
								_downdownListPositionIsInverted = true;
							}
						}
						
						return dropdownListTop;
					}
				
					function toggleDropDownList(isShown)
					{
						if (isShown)
						{
							if (_dropDownListJQuery.is(":hidden"))
							{
								toggleItemHighlight(_lastItemHoveredJQuery, false);
								
								toggleItemHighlight(_lastItemSelectedJQuery, true);
				
								setControlVisualState(1);
								
								var dropdownListTop = getDropDownListTop();
								_dropDownListJQuery.css("top", dropdownListTop);
								_dropDownListJQuery.css("left", _containerJQuery.offset().left);
								
								switch (optionSettings.animationType)
								{
									case "slide":
										if (_downdownListPositionIsInverted)
										{
											var comboboxTop = _containerJQuery.position().top;
											var containerHeight = _containerJQuery.outerHeight();

											_dropDownListJQuery.css("top", (comboboxTop - containerHeight));

											slideUp(dropdownListTop);
										}
										else
										{
											slideToggle();
										}
										break;
										
									case "fade":
										_dropDownListJQuery.fadeIn(optionSettings.animationSpeed);
										break;
										
									default:
										_dropDownListJQuery.show(1);
								}
							}
						}
						else
						{
							if (_dropDownListJQuery.is(":visible"))
							{
								setControlVisualState(0);
								
								switch (optionSettings.animationType)
								{
									case "slide":
										if (_downdownListPositionIsInverted)
										{
											comboboxTop = _containerJQuery.position().top;
											dropdownListHeight = _dropDownListJQuery.height();

											slideDown(comboboxTop - _containerJQuery.outerHeight());
										}
										else
										{
											slideToggle();
										}
										break;
										
									case "fade":
										_dropDownListJQuery.fadeOut(optionSettings.animationSpeed);
										break;
										
									default:
										_dropDownListJQuery.hide();
								}
							}
						}
					}

					function setOriginalSelectItem(selectedIndex, selectedValue)
					{
						var originalElementDOM = _originalElementJQuery[0];
						
						if (selectedValue == null)
						{
							originalElementDOM.selectedIndex = selectedIndex;
						}
						else
						{
							originalElementDOM.value = selectedValue;
							//some wiered ie bug	
							if(originalElementDOM.selectedIndex < 0)
								originalElementDOM.selectedIndex = 0;
						}
						
						setContentDisplay();
					}

					function selectValue(subSelector)
					{
						var originalElement = _originalElementJQuery[0];
						var currentIndex = originalElement.selectedIndex;
						var newIndex = -1;
						// {select}.length returns the array size of the options. Does not count optgroup elements
						var optionCountZeroBased = originalElement.length - 1;
						
						switch (subSelector)
						{
							case ":next":
								newIndex = currentIndex + 1;
								if (newIndex > optionCountZeroBased)
								{
									newIndex = optionCountZeroBased;
								}
								break;
							
							case ":previous":
								newIndex = currentIndex - 1;
								if (newIndex < 0)
								{
									newIndex = 0;
								}

								break;
								
							case ":first":
								newIndex = 0;
								
								break;
								
							case ":last":
								newIndex = optionCountZeroBased;
								
								break;
						}

						setOriginalSelectItem(newIndex, null);
					}
					
					function isDropDownVisible()
					{
						return _dropDownListJQuery.is(":visible");
					}
					
					function bindItemEvents()
					{
						jQuery("li", _dropDownListJQuery).not("ul").not("span").not("[dataType='optgroup']").each(
							function()
							{
								var itemJQuery = jQuery(this);
								itemJQuery.click(
									function(clickEvent)
									{
										// Stops the click event propagating to the Container and the Container.onClick firing
										clickEvent.stopPropagation();
										
										dropdownList_onItemClick(itemJQuery);
									});
								
								itemJQuery.mouseover(
									function()
									{
										dropdownList_onItemMouseOver(itemJQuery);
									});
									
								itemJQuery.mouseout(
									function()
									{
										dropdownList_onItemMouseOut(itemJQuery);
									});
							});			
					}

					function bindDocumentClickEvent()
					{
						$(document).click(
							function(clickEvent)
							{
								var $target = $(clickEvent.target);
								var $insideBox = $target.parents().filter(function ()
									{ 
										return this === _containerJQuery[0]; 
									});
								//if clicked inside and visible hide the box else hide the box
								if($insideBox.length) {
									clickEvent.stopPropagation();
								}
								else {
									dropdownListHide();
								}
							});
					}
					
					function bindContainerClickEvent()
					{
						_containerJQuery.click(
							function()
							{
								container_onClick();
							});
					}

					function bindEvents()
					{
						_containerJQuery.keydown(
							function(keyEvent)
							{
								keyEvent.preventDefault();
								container_onKeyDown(keyEvent)
							});

						bindContainerClickEvent();
							
						bindDocumentClickEvent();
							
						bindItemEvents();
					}				
					
					function container_onClick()
					{
						if (_dropDownListJQuery.is(":hidden"))
						{
							toggleDropDownList(true);
						}
						else
						{
							toggleDropDownList(false);
						}
					}
					
					function dropdownListHide()
					{
						if (_dropDownListJQuery.is(":visible"))
						{
							toggleDropDownList(false);
						}
					}
					
					function dropdownList_onItemClick(itemJQuery)
					{
						setOriginalSelectItem(null, itemJQuery[0].dataValue); 
						
						toggleDropDownList(false);
					}
					
					function dropdownList_onItemMouseOver(itemJQuery)
					{
						toggleItemHighlight(_lastItemSelectedJQuery, false);
						
						toggleItemHighlight(_lastItemHoveredJQuery, false);
						
						toggleItemHighlight(itemJQuery, true);
					}
					
					function dropdownList_onItemMouseOut(itemJQuery)
					{
						_lastItemHoveredJQuery = itemJQuery;
					}
					
					function container_onKeyDown(keyEvent)
					{
						switch (keyEvent.which)
						{
							case 33:
								//Page Up
							case 36:
								//Home
								selectValue(":first");
								break;
							
							case 34:
								//Page Down
							case 35:
								//End
								selectValue(":last");
								break;

							case 37:
								//Left
								selectValue(":previous");
								break;
								
							case 38:
								//Up
								if (keyEvent.altKey)
								{
									// alt-up
									// If DDL is hidden, then it is shown and vice-versa
									toggleDropDownList(!(isDropDownVisible()));
								}
								else
								{
									selectValue(":previous");
								}
								break;

							case 39:
								//Right
								selectValue(":next");
								break;
								
							case 40:
								//Down
								if (keyEvent.altKey)
								{
									toggleDropDownList(!(isDropDownVisible()));
								}
								else
								{
									selectValue(":next");
								}
								break;
								
							case 27:
							case 9:
								// Tab
							case 13:
								// Escape
								toggleDropDownList(false);
								break;

						}
					}
					
				}
			});
	}

