/**
 *  A special ldxUrl method. 
 *  This method replaces the ldxUrl method from the framework, because
 *  this website does some url rewriting and this results in a wrong
 *  url being returned by ldxUrl()
 */
var specialLdxUrl = function(component)
{
    var pathname = '/';
    var search = document.location.search;
    if (search.length == 0) search = '?px_ldx='+component;
    else search += '&px_ldx='+component;
    return pathname + search;
}

/**
 *  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();

    // if we have a profile banner, we should close it
    var banner = document.getElementById('profilebanner');
    if (banner) banner.style.visibility = 'hidden';

    // 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;

    // if we have a profile banner, we should show it again
    var banner = document.getElementById('profilebanner');
    if (banner) banner.style.visibility = 'visible';

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

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

/**
 *  Function to initialize the dropdowns
 */
function initializeDropdowns() 
{
    // install our own ldx handler
    window.ldxUrl = specialLdxUrl;
    
    // skip if already initialized
    if (dropdowns.length > 0) return;
    
    // leap out if dom not ready
    if (!document.getElementById('menu_information')) 
    {
        // dom is not ready, but reschedule the initialization
        setTimeout(initializeDropdowns, 100);
    }
    else
    {
        // dom is ready, find the dropdowns
        dropdowns = {
            home:        new Dropdown('home'),
            profile:    new Dropdown('profile'),
            forum:        new Dropdown('forum'),
            food:        new Dropdown('food'),
            members:    new Dropdown('members'),
            clubs:        new Dropdown('clubs'),
            information:new Dropdown('information')
        };
    }
}

/**
 *    Onload and ondomready handlers to initialize the dropdown menus
 */
registerHandler(window, 'load', initializeDropdowns);
registerHandler(window, 'domready', initializeDropdowns);

/**
 *  Also try to initialize them right away
 */
initializeDropdowns();