/// dhtml dropdown
/// uses X - cross-browser library (cross-browser.com) (GNU LGPL)

var DropDownLists;

function WebControls_DropDownList_Init()
{
	xAddEventListener(window, "load", WebControls_DropDownList_Setup);
}

function WebControls_DropDownList_Setup()
{
	var count = WebControls_DropDownList_Controls.length;
	var DropDownLists = new Array(count);

	for( var i = 0; i < count; i++ ) 
	{
		var o = WebControls_DropDownList_Controls[i];
		DropDownLists[i] = new DropDown(o);
	}
}

function DropDown(settings)
{
	this.expanded		= false;
	this._activeItem	= null;
	this._activeIndex	= -1;

	this.input			= xGetElementById(settings.input);
	this.orgValue		= xGetElementById(settings.orgValue);
	this.display		= xGetElementById(settings.display);
	this.container		= xGetElementById(settings.container);
	this.itemContainer	= xGetElementById(settings.itemContainer);
	this.items			= xGetElementsByTagName("li", this.itemContainer);

	this.input.dropDown		= this;
	this.container.dropDown = this;

	this.itemContainer.dropDown	= this;
	this.itemContainer.parentNode.removeChild(this.itemContainer);
	document.body.appendChild(this.itemContainer);

	this.applyDefaultStyles();
	
	xAddEventListener(this.container,		"mousedown",	DropDown.eventHandlers.mousedown);
	xAddEventListener(this.container,		"mousedown",	DropDown.eventHandlers.focus);
	xAddEventListener(this.itemContainer,	"mouseup",		DropDown.eventHandlers.mouseup);
	xAddEventListener(this.display,			"keydown",		DropDown.eventHandlers.keydown);
	xAddEventListener(this.display,			"blur",			DropDown.eventHandlers.blur);
	xAddEventListener(this.display,			"mousewheel",	DropDown.eventHandlers.mousewheel);
	xAddEventListener(document,				"mousewheel",	DropDown.eventHandlers.mousewheel);
		
	for (var i=0; i < this.items.length; i++)
	{
		var item = this.items[i];
		if ( item.firstChild != null && item.firstChild.nodeName == 'A' ) 
		{ 
			xAddEventListener(item, "mousedown", function(e) { xStopPropagation(e); });
			item = item.firstChild; 
		}
		xAddEventListener(item, "mouseover", DropDown.eventHandlers.mouseover);
		unselectable(item);
	}
}

// current opened dropdown
DropDown.activeInstance = null;

DropDown.eventHandlers = 
{
	mousedown: function(e)
	{
		var a = DropDown.activeInstance;
		var d = DropDown.eventHandlers.getDropDown(e);
		var t = DropDown.eventHandlers.getEventTarget(e);

		// Hide other active dropdowns
		if (a && a != d) { a.hideItems(); xStopPropagation(e);}

		if (d && t.tagName != "scrollbar")
		{
			// Hide if drop is active, expanded and event came from display or container box
			if (a == d && d.expanded && (t == d.container || t == d.display )) { d.hideItems(); }
			// Show items 
			else { d.showItems(); }
			xStopPropagation(e);
		}
	},

	mouseup: function(e)
	{
		//debug("mouseup", e);
		var t = DropDown.eventHandlers.getEventTarget(e);
		var d = DropDown.eventHandlers.getDropDown(e);
		if ( d && t.tagName != "scrollbar" )
		{
			d.selectActive(true); 
			d.hideItems(); 
			xStopPropagation(e);
		}
		
	},

	mouseover: function(e)
	{
		var d = DropDown.activeInstance;
		if (d) 
		{ 
			var item = DropDown.eventHandlers.getEventTarget(e);
			d.setActiveItem(item); 
		}
	},

	focus: function(e) 
	{
		var d = DropDown.eventHandlers.getDropDown(e);
		if (d) 
		{
			d.display.focus(); 
			// Add focus class to handle lack of css-focus selector
			if (xOp6Dn||xIE4Up) { addClassName(d.display, DropDown.prototype.focusClassName); }
			xPreventDefault(e); 
		}
	},

	blur: function(e) 
	{
		var d = DropDown.eventHandlers.getDropDown(e);
		// Remove focus class
		if (d && (xOp6Dn||xIE4Up)) { removeClassName(d.display, DropDown.prototype.focusClassName); }
	},
	
	keydown:	function (e) 
	{
		var d = DropDown.eventHandlers.getDropDown(e);
		ev = new xEvent(e);
		var select = true;
		if (d) 
		{
			var kc = ev.keyCode;

			if ( ev.altKey )
			{
				switch (kc) 
				{
					case 38:	// up
					case 40:	// down
						if (d.expanded)
							d.hideItems();
						else
							d.showItems();
						break;
				}
			}
			else
			{
				switch (kc) 
				{
					case 33:	// page up
					case 36:	// home
						d.activateFirst();
						break;
					case 34:	// page down
					case 35:	// end
						d.activateLast();
						break;
					case 38:	// up
					case 37:	// left
						d.activatePrevious();
						break;
					case 39:	// right
					case 40:	// down
						d.activateNext();
						break;
					case 13: // enter
						break;
					case 27: // escape
						select = false;
						d.hideItems();
						break;
					default:
						select = d.activateByChar( String.fromCharCode(kc) );
						break;
				}
			}

			// commit on enter or if moved and not expanded
			if (select) { d.selectActive( kc == 13 ); }
			
			if ( kc == 13 || kc == 9) { d.hideItems(); }
			else { xPreventDefault(e); }
		}
	},
	
	mousewheel:	function (e) 
	{
		var d = DropDown.eventHandlers.getDropDown(e);
		if (d && e.wheelDelta)
		{
			if ( !d.expanded )
			{
				if (e.wheelDelta < 0) {d.activateNext(); }
				else {d.activatePrevious(); }
				d.selectActive();
				xPreventDefault(e);
			}
			xStopPropagation(e);
		}
	},
	
	getEventTarget:	function(e)
	{
		if (e) { return e.target || window.event.srcElement; }
		return null;
	},
	
	getDropDown:	function (e) 
	{
		var el = DropDown.eventHandlers.getEventTarget(e);
		while (el != null && el.dropDown == null)
			el = el.parentNode;

		if (el)
			return el.dropDown;
		return null;
	}
};

DropDown.prototype.activeClassName		= "Active";
DropDown.prototype.focusClassName		= "Focus";

DropDown.prototype.showItems  = function() 
{
	if ( !this.expanded )
	{
		this.itemContainer.style.display = "block";
		var margin		= 5;
//		var position	= xOffsetTop(this.container);
		var position	= absoluteTop(this.container);
		// Heights
		var scroll		= xScrollTop(this.conatiner);
		var top			= position - scroll;
		var container	= xHeight(this.container);
		var client		= xClientHeight();
		var drop		= xHeight(this.itemContainer);
		var bottom		= client - top - container;
		
		if ( bottom > drop ) { position += container; }
		else
		{
			if ( top > bottom ) 
			{ 
				if ( drop > top ) 
				{ 
					drop = xHeight(this.itemContainer, top - margin); 
					setOverflow(this.itemContainer, true);
				}
				position -= drop;
			}
			else 
			{
				if ( drop > bottom ) { drop = xHeight(this.itemContainer, bottom - margin); }
				position += container;
			}
		}
		xTop(this.itemContainer, position );
		xLeft(this.itemContainer, absoluteLeft(this.container));
		
		DropDown.activeInstance = this;
		this.expanded = true;
		this.activateSelected();
		xAddEventListener(document, "mousedown",	DropDown.eventHandlers.mousedown, true);
		xAddEventListener(window,	"scroll",		DropDown.eventHandlers.mousedown, false);
		xAddEventListener(window,	"resize",		DropDown.eventHandlers.mousedown, false);
	}
}

DropDown.prototype.hideItems  = function() 
{
	if ( this.expanded )
	{
		this.itemContainer.style.display = "none";
		this.expanded = false;
		DropDown.activeInstance = null;

		xRemoveEventListener(document,	"mousedown",	DropDown.eventHandlers.mousedown, true);
		xRemoveEventListener(window,	"scroll",		DropDown.eventHandlers.mousedown, false);
		xRemoveEventListener(window,	"resize",		DropDown.eventHandlers.mousedown, false);
	}
}

DropDown.prototype.setActiveItem = function(item) 
{
	while ( item != null && item.tagName != "LI" ) { item = item.parentNode }
	var index = this.indexOf(item);
	if ( index >= 0 ) {	this._setActive(index, item); }
}

DropDown.prototype.indexOf = function(item) 
{
	for (var i=0; i < this.items.length; i++) 
		if ( this.items[i] == item ) { return i; } 

	return -1;
}

DropDown.prototype.setActiveIndex = function(index) 
{
	if ( index < 0 )
		index = 0;
	else if ( index >= this.items.length )
		index = this.items.length-1;
	
	this._setActive(index, this.items[index]);
}

DropDown.prototype._setActive = function(index, item) 
{
	this.clearActive();
	this._activeIndex	= index;
	this._activeItem	= item;
	addClassName(item, this.activeClassName);
}


DropDown.prototype.clearActive  = function() 
{
	this._activeIndex	= -1;
	this._activeItem	= null;
	var c = this.activeClassName;
	map(this.items, function(el) { removeClassName(el,c) });
}


DropDown.prototype.activateSelected = function() 
{
	var value = this.input.value;
	if ( value != "" )
	{
		for (var i=0; i < this.items.length; i++) 
		{
			var item = this.items[i];
			if ( getAttribute(item, "value") == value ) { this._setActive(i, item); return; } 
		}
	}
}

DropDown.prototype.activateNext  = function() 
{
	this.setActiveIndex(this._activeIndex+1);
}

DropDown.prototype.activatePrevious  = function() 
{
	this.setActiveIndex(this._activeIndex-1);
}

DropDown.prototype.activateFirst  = function() 
{
	this.setActiveIndex(0);
}

DropDown.prototype.activateLast  = function() 
{
	this.setActiveIndex(this.items.length-1);
}

DropDown.prototype.activateByChar = function(c)
{
	var pos = this._activeIndex + 1;
	
	for (var i=0; i < this.items.length; i++) 
	{
		if ( pos < 0 || pos >= this.items.length ) { pos = 0; }
		var item = this.items[pos];
		if ( item.innerText.indexOf(c) == 0 ) {  this._setActive(pos, item); return true; } 
		pos++;
	}
	return false;
}

DropDown.prototype.selectActive = function(commit) 
{
	if (this._activeItem)
	{
		this.input.value	= getAttribute(this._activeItem, "value");
		var text = this._activeItem.textContent || this._activeItem.innerText;
		this.display.value	= text.trim();
	}
	this.display.focus();
	if ( commit && this.input.value != this.orgValue.value)
		dispatchEvent(this.input, "change");
}

DropDown.prototype.applyDefaultStyles  = function() 
{
	unselectable(this.container);
	unselectable(this.display);
	xWidth(this.itemContainer, xWidth(this.container));
	this.itemContainer.style.position		= "absolute";
	this.itemContainer.style.listStyleType	= "none";
	xZIndex(this.itemContainer, 9999);
}
