// throwaway function to avoid errors associated with undefined function calls
// used like '(func || _)(my_args);' instead of just 'func(my_args);'
var _ = function(){};
// undefined test, since ie likes to die if testing for an undefined variable
// in a boolean context
var undef = function(x){return (typeof x === "undefined");};



// cross-browser add event listener
var addEventListener = function(elem, evt, callback, capture)
{
// hope for standards compliance
	if(elem.addEventListener)
	{
		elem.addEventListener(evt, callback, capture);
	}
// expect ie instead
	else if(elem.attachEvent)
	{
		elem.attachEvent((window.opera ? "" : "on") + evt, callback);
	}
// allow for old browsers
	else
	{
		elem["on" + evt] = callback;
	}
};


// cross-browser remove event listener
var removeEventListener = function(elem, evt, callback, capture)
{
// hope for standards compliance
	if(elem.removeEventListener)
	{
		elem.removeEventListener(evt, callback, capture);
	}
// expect ie instead
	else if(elem.detachEvent)
	{
		elem.detachEvent((window.opera ? "" : "on") + evt, callback);
	}
	else
// allow for old browsers
	{
		elem["on" + evt] = _;
	}
};


// cross-browser stop event propogation
var stopPropogation = function(evt)
{
	evt.cancelBubble = true; // works in ie, no effect otherwise
	(evt.stopPropogation || _)(); // no effect in ie, works otherwise
};


// cross-browser window positioning
var getCurrentWidth = function()
{
	return (document.documentElement.clientWidth ||
			document.body.clientWidth);
};
var getCurrentHeight = function()
{
	return (document.documentElement.clientHeight ||
			document.body.clientHeight);
};
var getScrollLeft = function()
{
	return (document.documentElement.scrollLeft ||
			document.body.scrollLeft);
};
var getScrollTop = function()
{
	return (document.documentElement.scrollTop ||
			document.body.scrollTop);
};


// cross-browser style property accessor that works even if the property was not
// set by javascript
var getCSSProperty = function(elem, property)
{
	if(elem.currentStyle)
	{
		var prev = 0;
		var next = property.indexOf('-');
		while(next != -1)
		{
			property = property.substring(prev, next) +
				property.charAt(next + 1).toUpperCase() +
				property.substring(next + 2);
			prev = next;
			next = property.indexOf('-');
		}
		return (elem.currentStyle[property] || '');
	}
	else if(document.defaultView.getComputedStyle)
	{
		var style = document.defaultView.getComputedStyle(elem, null)
				.getPropertyValue(property);
		return (style || elem.style[property] || '');
	}
	return '';
};


// cross-browser node traversal
var getNextSibling = function(current, ignore, regex)
{
	var sibling = current.nextSibling;
	regex = regex || ((ignore == null || ignore == "") ? null :
			new RegExp("\\b(" + arguments[1] + ")\\b", "i"));

	while(sibling != null && ((regex != null && regex.test(sibling.tagName)) ||
			sibling.nodeType != 1))
	{
		sibling = sibling.nextSibling;
	}

	return sibling;
};
var getPrevSibling = function(current, ignore, regex)
{
	var sibling = current.previousSibling;
	regex = regex || ((ignore == null || ignore == "") ? null :
			new RegExp("\\b(" + arguments[1] + ")\\b", "i"));

	while(sibling != null && ((regex != null && regex.test(sibling.tagName)) ||
			sibling.nodeType != 1))
	{
		sibling = sibling.previousSibling;
	}

	return sibling;
};
var getFirstChild = function(current, ignore)
{
	var child = current.firstChild;
	if(child != null)
	{
		var regex = (ignore == null || ignore == "") ? null :
				new RegExp("\\b(" + arguments[1] + ")\\b", "i");
		if((regex != null && regex.test(child.tagName)) || child.nodeType != 1)
		{
			return getNextSibling(child, null, regex);
		}
	}
	return child;
};
var getLastChild = function(current, ignore)
{
	var child = current.lastChild;
	if(child != null)
	{
		var regex = (ignore == null || ignore == "") ? null :
				new RegExp("\\b(" + arguments[1] + ")\\b", "i");
		if((regex != null && regex.test(child.tagName)) || child.nodeType != 1)
		{
			return getPrevSibling(child, null, regex);
		}
	}
	return child;
};



// menu stuff
var menu =
{
    element : document.getElementById("menu"),
    active : false
};

// Show Sub Menu
menu.ssm = function(e)
{
    e = (e || event);
    var target = (e.target || e.srcElement);
    
    if(target.tagName == "A" && target.nextSibling)
    {
        if(menu.active != target.parentNode)
        {
            menu.hsm();
            menu.active = target.parentNode;
        }

        for(var i=0; i<menu.active.childNodes.length; ++i)
        {
            var node = menu.active.childNodes[i];
            if(node.tagName == "DIV")
            {
                node.style.display = "block";
            }
        }
    }

    stopPropogation(e);
};

// Hide Sub Menu
menu.hsm = function()
{
    if(menu.active)
    {
        for(var i=0; i<menu.active.childNodes.length; ++i)
        {
            var node = menu.active.childNodes[i];
            if(node.tagName == "DIV")
            {
                node.style.display = "none";
            }
        }
        menu.active = false;
    }
};


menu.init = function()
{
    var nodes = [];
    var rxp = new RegExp("\\S");
    for(var i=0; i<this.element.childNodes.length; ++i)
    {
        var node = this.element.childNodes[i];
        var txt = (node.textContent || node.text || node.innerHTML || '');
        if(rxp.test(txt))
        {
            addEventListener(node, "mouseover", this.ssm, false);
        }
    }
    addEventListener(document.body, "mouseover", this.hsm, false);
};



menu.init();



// Function to make external links open in a new window/tab
//  thanks to http://www.sitepoint.com/article/standards-compliant-world/
//  and http://jaspan.com/external-links-in-new-window-without-target
function externalLinks()
{
    var anchors = document.getElementsByTagName("a");
    for(var i=0; i<anchors.length; ++i)
    {
        var anchor = anchors[i];
        if(anchor.getAttribute("rel") == "external")
        {
            anchor.target="_blank";
        }
    }
}
