/**
 *  Method to attach an event handler to an element
 *  @param object       HTML element that the event should be attached to
 *  @param string       Name of the event, ie 'mouseover'
 *  @param function     Function that should be called when event occurs
 *  @return element | boolean
 */
function registerHandler(element, evType, fn)
{
    // check if this functionality is available anyway
    if (element.addEventListener) 
    {
        // just use the 'addEventListener' methode
        element.addEventListener(evType, fn, true);
        return false;
    } 
    else if (element.attachEvent)
    {
        // IE way of handling with events
        return element.attachEvent("on"+evType, fn);
    }
}

/** 
 *  Helper method to get the left & top position of the component
 *  @param  HTML element
 *  @return Position object with properties 'left' and 'right'
 */
function getPosition(element)
{
    // get the parent position
    if (!element.offsetParent)
    {
        return {
            left:   element.offsetLeft,
            top:    element.offsetTop
        }
    }
    else
    {
        var position = getPosition(element.offsetParent);
        position.left += element.offsetLeft;
        position.top += element.offsetTop;
        
        return position;
    }
}

/**
 *  Helper method to set the position of an HTML element.
 *  This method can be used to set that position of the element, based
 *  on the lefttop coordinates of the document, and thus not based on the
 *  offset-parent. This method only works for absolute positioned elements
 *  @param  HTML element
 *  @param  Left coordinate
 *  @param  Top coordinate
 */
function setPosition(element, left, top)
{
    // does the element have an offset-element?
    if (element.offsetParent)
    {
        // find the position of the offset parent
        var offset = getPosition(element.offsetParent);
        left -= offset.left;
        top -= offset.top;
    }
    
    // Change the position
    element.style.left = left + 'px';
    element.style.top = top + 'px';
}

/**
 *	Class represents a dropdown box
 *	@param	string	Name of the dropdown
 */
function Dropdown(name)
{
	// get the item and the dropdown
	this.menu = document.getElementById('menu_'+name);
	this.dropdown = document.getElementById('dropdown_'+name);
	
	// store original classname of menu
	this.originalClassname = this.menu.className;	
	
	// timer for opening the dropdown, and a timer for closing the dropdown
	this.openTimer = false;
	this.closeTimer = false;
	
	// register the handlers
	this.initHandler(this.menu);
	this.initHandler(this.dropdown);
}

/**
 *	Initialize the handler on a certain element
 *	@var	object	HTML element
 */
Dropdown.prototype.initHandler = function(el)
{
	// keep reference to this
	var self = this;
	
	// set up the handlers
	el.onmouseover = function() { self.mouseOverHandler(); }
	el.onmouseout = function() { self.mouseOutHandler(); }
	
	// register the same handlers for all child elements
	for (var i=0; i<el.childNodes.length; i++) 
	{
		// skip if this is not a valid element
		if (!el.childNodes[i].tagName) continue;
		
		// register handlers for child
		this.initHandler(el.childNodes[i]);
	}
}

/**
 *	Handler that is called when mouse moves over an item
 *	that triggers the opening of a dropdown
 */
Dropdown.prototype.mouseOverHandler = function()
{
	// cancel the timer that is going to close the dropdown
	if (this.closeTimer) 
	{
		// cancel and reset the timer
		clearTimeout(this.closeTimer);	
		this.closeTimer = false;
	}
	
	// do nothing if the dropdown is already open
	if (this.isOpen()) return;
	
	// skip if the dropdown is already scheduled for being opened
	if (this.openTimer) return;	
	
	// keep this reference
	var self = this;	

	// default delay for opening a dropdown
	var delay = 100;
	
	// check if any other menu is already open
	for (var name in dropdowns)
	{
		// if there is already an other dropdown opened, we do not need a delay
		if (dropdowns[name].isOpen()) delay = 0;
	}
	
	// the dropdown must be opened within a certain delay
	this.openTimer = setTimeout(function() 
	{
		// reposition and show the dropdown
		self.open();
	}, delay);
}

/**
 *	Handler that is called when mouse leaves a dropdown
 */
Dropdown.prototype.mouseOutHandler = function()
{
	// cancel a timer that is going to open the dropdown
	if (this.openTimer)
	{
		// cancel and reset timer
		clearTimeout(this.openTimer);
		this.openTimer = false;
	}
	
	// skip if this dropdown is not even open
	if (!this.isOpen()) return;
	
	// cancel if this dropdown is already scheduled for being closed
	if (this.closeTimer) return;
	
	// keep this reference
	var self = this;	
	
	// hide the dropdown in one second
	this.closeTimer = setTimeout(function()
	{
		// hide the dropdown
		self.close();
	}, 1000);
}

/**
 *	Check if the dropdown is open
 *	@return	boolean
 */
Dropdown.prototype.isOpen = function()
{
	return this.dropdown.style.display == 'block';
}

/**
 *	Function to open a dropdown right away
 */
Dropdown.prototype.open = function()
{
	// cancel all timers that will open or close this dropdown
	if (this.openTimer) clearTimeout(this.openTimer);
	if (this.closeTimer) clearTimeout(this.closeTimer);
	this.openTimeout = this.closeTimeout = false;

	// skip if dropdown is already open
	if (this.isOpen()) return;
	
	// close all other dropdowns
	for (var name in dropdowns) dropdowns[name].close();

	// reposition and show the dropdown
	var pos = getPosition(this.menu);
	setPosition(this.dropdown, pos.left, pos.top + this.menu.offsetHeight);
	this.dropdown.style.display = 'block';
	
	// make menu item active
	this.menu.className = 'active';
}

/**
 *	Function to close a dropdown
 */
Dropdown.prototype.close = function()
{
	// cancel all timers that will open or close this dropdown
	if (this.openTimer) clearTimeout(this.openTimer);
	if (this.closeTimer) clearTimeout(this.closeTimer);
	this.openTimeout = this.closeTimeout = false;
	
	// skip if dropdown is already closed
	if (!this.isOpen()) return;

	// hide
	this.dropdown.style.display = 'none';
	
	// restore classname of menu
	this.menu.className = this.originalClassname;
}

/**
 *	Associative array with all dropdowns
 *	@var	array
 */
var dropdowns = {};

/**
 *	Onload handler to initialize the dropdown menus
 */
registerHandler(window, 'load', function() {
	dropdowns = {
		product:	new Dropdown('product'),
		support:	new Dropdown('support'),
		about:		new Dropdown('about'),
		login:		new Dropdown('login')
		//license:	new Dropdown('license')
	};
});