Event.observe( window, "load", function() {
	document.getElementsByClassName( "JSMenu_Root" ).each( function( list ) {
		JSMenu.prepare( list );
	});
});

JSMenu =
{
	supportedNodes: /^(ul|li|div)$/i,

	MENU:  "JSMenu",
	LABEL: "JSMenu_Label",
	ITEMS: "JSMenu_Items",

	classify: function( node )
	{
		var result = "Unknown";

		[ JSMenu.MENU, JSMenu.LABEL, JSMenu.ITEMS ].each( function( name ) {
			var regex = new RegExp( "(^|\\s)" + name + "(\\s|$)" );

			if ( node.className.match( regex ) ) {
				result = name;
				throw $break;
			} // if
		});

		return result;
	}, // classify()

	isAlwaysOpen: function ( node )
	{
		return node.className.match( /(^|\s)JSMenu_AlwaysOpen(\s|$)/ );
	}, // isAlwaysOpen()

	checkForAutoExpansion: function( node )
	{
		var link = null;

		$A( node.childNodes ).each( function( child ) {
			switch( child.nodeName.toLowerCase() ) {
				case "a":
					link = child;
					break;

				default:
					node.removeChild( child );
			} // switch
		});

        var re = null;

        try {
            re = new RegExp( "^" + link.href, "i" );
        } catch ( e ) {
            // There is a problem with link.href, for some reason, on Explorer.
        } // try-catch

		// The browser is current pointed at this menu item, then we want to
		// open up the menu tree to this point.
		if ( window.location.href.match( re ) ) { // new RegExp( "^" + link.href, "i" ) ) ) {
			// Our parent will be an li.JSMenu_Items element.
			node.parentNode.cascadeShow();
        }
	}, // checkForAutoExpansion()

	prepareByClass: function( node, noExpander )
	{
		switch ( JSMenu.classify( node ) ) {
			// li
			case JSMenu.MENU:
				Object.extend( node, JSMenu.Extensions );
				JSMenu.prepare( node, JSMenu.isAlwaysOpen( node ) );

				break;

			// div
			case JSMenu.LABEL:
				if ( noExpander == false )
					Object.extend( node, JSMenu.ExpanderExtensions );

				break;

			// ul
			case JSMenu.ITEMS:
				Object.extend( node, JSMenu.ItemsExtensions );
				node.parentNode.setItems( node );
				JSMenu.prepare( node );

				// If this submenu list has no elements, remove it!
				if ( node.childNodes.length == 0 )
					node.parentNode.parentNode.removeChild( node.parentNode );

				break;

			// the actual links:
			// <li><a href="...">Menu Item</a></li>
			default:
				if ( node.nodeName.toLowerCase() == "li" )
					JSMenu.checkForAutoExpansion( node );
		} // switch
	}, // prepareByClass()

	prepare: function( parent, noExpander )
	{
		noExpander = noExpander || false;

		$A( parent.childNodes ).each( function( child ) {
			if ( JSMenu.supportedNodes.test( child.nodeName ) ) {
				JSMenu.prepareByClass( child, noExpander );

				child.onmousedown = function() { return false };
			} else {
				parent.removeChild( child );
			} // if-else
		});
	} // prepare()
} // JSMenu

JSMenu.Extensions =
{
	_items: null,

	setItems: function( o ) { this._items = o },
	items:    function() { return this._items },

	cascadeShow: function()
	{
		try {
			this.parentNode.cascadeShow();
		} catch ( e ) {
		}
	}, // cascadeShow()

	toggleItemsVisibility: function()
	{
		if ( this._items != null )
			this._items.toggleVisibility();
	} // showItems()
} // JSMenu.Extensions

JSMenu.ExpanderExtensions =
{
	onclick: function()
	{
		this.parentNode.toggleItemsVisibility();
	} // onclick()
} // JSMenu.ExpanderExtensions

JSMenu.ItemsExtensions =
{
	cascadeShow: function()
	{
		this.show();
		this.parentNode.cascadeShow();
	}, // cascadeShow()

	show: function()
	{
		this.style.display = "block";
	}, // show()

	hide: function()
	{
		this.style.display = "none";
	}, // hide()

	toggleVisibility: function()
	{
		if ( this.style.display == "block" )
			this.hide();
		else
			this.show();
	} // toggleVisibility()
} // JSMenu.ItemsExtensions
