/*
*	mo's Dom tree script
*	build a collapsable tree like navigation with dom elements
*	mo@momche.net
*/

if( !Object.prototype.createContext )
{
	Object.prototype.createContext = function( sMethod )
	{
		var hNewContext = this
		return function() { hNewContext[ sMethod ].apply( hNewContext, arguments ) }
	}
}

cTreeMenu = function( sTreeId )
{
	this.sTreeId = sTreeId
	var hTreeObject = document.getElementById( this.sTreeId )
	hTreeObject.treeMenu = this

	var sOnInit = hTreeObject.getAttribute( 'oninit' )
	if( sOnInit )
	{
		sOnInit = sOnInit.replace( '()', '' )
		this.onInit = eval( sOnInit )
		this.onInit()
	}
}

cTreeMenu.prototype = new Object()

cTreeMenu.CS_NAME = 'modomtree'
cTreeMenu.CS_DESCRIPTION = 'dom tree component'
cTreeMenu.CN_COUNT = 0
cTreeMenu.CB_EDITABLE = true

cTreeMenu.CBF_ROOT = 0x0
cTreeMenu.CBF_LEAF = 0x1
cTreeMenu.CBF_NODE = 0x2
cTreeMenu.CBF_REMOTE = 0x4
cTreeMenu.CBF_REMOTELOADED = 0x8

cTreeMenu.init = function()
{
	var hULs = document.getElementsByTagName( 'ul' )
	for( var nI = 0; nI < hULs.length; nI++ )
	{
		var hUL = hULs[ nI ]
		if( hUL.className == 'moTreeMenu' )
		{
			cTreeMenu.setTypeModifier( getSubNodeByName( hUL, 'li' ), cTreeMenu.CBF_ROOT )
			cTreeMenu.initMenu( hUL )
			if( !hUL.id )
			{
				hUL.id = cTreeMenu.CS_NAME + ( cTreeMenu.CN_COUNT++ )
			}
			return new cTreeMenu( hUL.id )
		}
	}
}

cTreeMenu.initMenu = function( hMenuEl )
{
	var hItems = hMenuEl.childNodes
	var sClassSuffix
	var sDisplay
	var bRemoteItem
	for( var nI = 0; nI < hItems.length; nI++ )
	{
		var hItem = hItems.item( nI )
		if( hItem.nodeType == document.ELEMENT_NODE )
		{
			if( cTreeMenu.initMenuItem( hItem ) )
			{
				var hSubMenu = getSubNodeByName( hItem, 'ul' )
				cTreeMenu.initMenu( hSubMenu )
			}
		}
	}
}

cTreeMenu.initMenuItem = function( hItem )
{
	cTreeMenu.initTypeModifier( hItem )

	var bRemoteItem = false
	var hSubMenu = getSubNodeByName( hItem, 'ul' )

	if( hItem.getAttribute( 'remoteitem' ) )
	{
		if( hItem.getAttribute( 'remoteitem' ).toString() == 'true' )
		{
			cTreeMenu.setTypeModifier( hItem, cTreeMenu.CBF_REMOTE )
		}
	}

	if( hSubMenu != null || cTreeMenu.getTypeModifier( hItem, cTreeMenu.CBF_REMOTE ) )
	{
		cTreeMenu.setTypeModifier( hItem, cTreeMenu.CBF_NODE )
	}
	else
	{
		cTreeMenu.setTypeModifier( hItem, cTreeMenu.CBF_LEAF )
	}

	cDomEvent.addEvent( hItem, 'click', cTreeMenu.onItemClick )

	if( cTreeMenu.getTypeModifier( hItem, cTreeMenu.CBF_NODE ) || cTreeMenu.getTypeModifier( hItem, cTreeMenu.CBF_REMOTE ) )
	{
		if( !cTreeMenu.getTypeModifier( hItem, cTreeMenu.CBF_REMOTE ) )
		{
			sDisplay = hSubMenu.style.display.toLowerCase()
			hSubMenu.style.display = ( sDisplay == 'none' ) ? 'none' : 'block'
			sClassSuffix = ( sDisplay == 'block' ) ? 'Closed' : 'Open'
		}
		else
		{
			sClassSuffix = 'Closed'
		}
		hItem.className = 'menuItem'+sClassSuffix
	}
	else
	{
		hItem.className = 'menuItem'
		cDomEvent.addEvent( hItem, 'dblclick', cTreeMenu.startEditMenuItem )
	}
	cDomEvent.addEvent( hItem, 'keyup', cTreeMenu.onItemKeyUp )

	if( hSubMenu != null )
	{
		return true
	}
	else
	{
		return false
	}
}

cTreeMenu.prototype.onItemEdit = function( hItem, sNewValue, sOldValue )
{
	return true
}

cTreeMenu.prototype.onBeforeItemOpen = function( hItem )
{
	return true
}

cTreeMenu.prototype.onBeforeItemClose = function( hItem ) {}

cTreeMenu.prototype.onAppendItem = function( hItem ) {}
cTreeMenu.prototype.onRemoveItem = function( hItem ) {}

cTreeMenu.prototype.onBeforeItemLoad = null

cTreeMenu.prototype.loadItemData = function( hItem )
{
	if( this.bLoading )
	{
		alert( 'data is still loading...' )
	}
	this.hCurrentItem = hItem
	if( !this.hServerRequest )
	{
		this.hServerRequest = XmlHttp.create()
	}

	var hMenuItem = document.createElement( 'li' )
	hMenuItem.appendChild( document.createTextNode( 'loading...' ) )
	cTreeMenu.appendItem( hMenuItem, this.hCurrentItem )

	var sURL = ''
	var sRequest = ''

	var hItemURLData = null
	if( this.onBeforeItemLoad != null )
	{
		hItemURLData = this.onBeforeItemLoad( hItem )
	}

	if( hItemURLData != null )
	{
		sURL = hItemURLData.url
		sRequest = hItemURLData.request
	}
	else
	{
		sURL = 'load.php'
		sRequest = ''
		sRequest += 'itemid=' + hItem.id
	}

	this.bLoading = true
	this.hServerRequest.open( 'POST', sURL, true )
	this.hServerRequest.onreadystatechange = this.createContext( 'onItemDataLoaded' )
	this.hServerRequest.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' )
	this.hServerRequest.send( sRequest )
}


cTreeMenu.prototype.onItemDataLoaded = function()
{
	if( this.hServerRequest.readyState == 4 )
	{
		this.bLoading = false
		cTreeMenu.clearSubMenu( this.hCurrentItem )
		cTreeMenu.setTypeModifier( this.hCurrentItem, cTreeMenu.CBF_NODE )
		cTreeMenu.createNodeFromXML( this.hCurrentItem, this.hServerRequest.responseXML.documentElement )
		cTreeMenu.openItem( this.hCurrentItem )
		cTreeMenu.setTypeModifier( this.hCurrentItem, cTreeMenu.CBF_REMOTELOADED )
		var hSubMenu = getSubNodeByName( this.hCurrentItem, 'ul' )
		cTreeMenu.initMenu( hSubMenu )
	}
}

cTreeMenu.createNodeFromXML = function( hParentItem, hXMLRootNode )
{
	var hItems = hXMLRootNode.childNodes
	var hMenuItem = null
	var hItemLink = null
	for( var nI = 0; nI < hItems.length; nI++ )
	{
		if( hItems[ nI ].nodeType == document.ELEMENT_NODE )
		{
			hItemLink = document.createElement( 'a' )
			hItemLink.href = '#'
			hItemLink.appendChild( document.createTextNode( getNodeText( hItems[ nI ].getElementsByTagName( 'text' )[ 0 ] ) ) )
			hMenuItem = document.createElement( 'li' )
			hMenuItem.className = 'menuItem'
			hMenuItem.appendChild( hItemLink )
			for( var nJ = 0; nJ < hItems[ nI ].attributes.length; nJ++ )
			{
				hMenuItem.setAttribute( hItems[ nI ].attributes[ nJ ].nodeName.toString(), hItems[ nI ].attributes[ nJ ].nodeValue.toString() )
			}
			cTreeMenu.appendItem( hMenuItem, hParentItem )
			if( hItems[ nI ].getElementsByTagName( 'subtree' ).length > 0 )
			{
				cTreeMenu.createNodeFromXML( hMenuItem, hItems[ nI ].getElementsByTagName( 'subtree' )[ 0 ] )
			}
		}
	}
}

cTreeMenu.getTypeModifier = function( hItem, nBFModifier )
{
	var nBF = parseInt( hItem.getAttribute( 'nodetype' ) )
	return ( ( nBF & nBFModifier ) > 0 )
}

cTreeMenu.setTypeModifier = function( hItem, nBFModifier )
{
	var nBF = parseInt( hItem.getAttribute( 'nodetype' ) )
	hItem.setAttribute( 'nodetype', nBF | nBFModifier )
}

cTreeMenu.removeTypeModifier = function( hItem, nBFModifier )
{
	var nBF = parseInt( hItem.getAttribute( 'nodetype' ) )
	hItem.setAttribute( 'nodetype', nBF & !nBFModifier )
}

cTreeMenu.initTypeModifier = function( hItem )
{
	hItem.setAttribute( 'nodetype', 0 )
}


cTreeMenu.appendItem = function( hNewItem, hParent )
{
	var hSubMenu = getSubNodeByName( hParent, 'ul' )
	if( !hSubMenu )
	{
		hSubMenu = document.createElement( 'ul' )
		hParent.appendChild( hSubMenu )
	}
	hSubMenu.appendChild( hNewItem )
}

cTreeMenu.removeItem = function( hItem, hParent )
{
	hItem.parentNode.removeChild( hItem )
}

cTreeMenu.toggleItem = function( hActiveItem )
{
	var bRemoteItem = false
	if( cTreeMenu.getTypeModifier( hActiveItem, cTreeMenu.CBF_NODE ) || cTreeMenu.getTypeModifier( hActiveItem, cTreeMenu.CBF_REMOTE ) )
	{
		var hSubMenu = getSubNodeByName( hActiveItem, 'ul' )
		if( cTreeMenu.getTypeModifier( hActiveItem, cTreeMenu.CBF_REMOTE ) && !cTreeMenu.getTypeModifier( hActiveItem, cTreeMenu.CBF_REMOTELOADED ) )
		{
			sDisplay = 'none'
		}
		else
		{
			sDisplay = hSubMenu.style.display.toLowerCase()
		}
		if( sDisplay == 'block' )
		{
			cTreeMenu.closeItem( hActiveItem )
		}
		else
		{
			cTreeMenu.openItem( hActiveItem )
		}
		return true
	}
	return false
}

cTreeMenu.openItem = function( hItem )
{
	var hMenu = cTreeMenu.getMenuItemMenu( hItem )
	var bOpen = false
	if( hMenu.treeMenu.onBeforeItemOpen )
	{
		bOpen = hMenu.treeMenu.onBeforeItemOpen( hItem )
	}
	if( !bOpen )
	{
		return
	}
	if( cTreeMenu.getTypeModifier( hItem, cTreeMenu.CBF_REMOTE ) )
	{
		if( !cTreeMenu.getTypeModifier( hItem, cTreeMenu.CBF_REMOTELOADED ) )
		{
			hMenu.treeMenu.loadItemData( hItem )
			return
		}
	}
	var hSubMenu = getSubNodeByName( hItem, 'ul' )
	if( hSubMenu )
	{
		hSubMenu.style.display = 'block'
		hItem.className = 'menuItem' + 'Open'
	}
}

cTreeMenu.closeItem = function( hItem )
{
	var hSubMenu = getSubNodeByName( hItem, 'ul' )
	hSubMenu.style.display = 'none'
	hItem.className = 'menuItem' + 'Closed'
}

cTreeMenu.clearSubMenu = function( hItem )
{
	cTreeMenu.removeTypeModifier( hItem, cTreeMenu.CBF_NODE )

	var bRemoteItem = false
	var hSubMenu = getSubNodeByName( hItem, 'ul' )

	if( hSubMenu != null )
	{
		while( hSubMenu.childNodes.length > 0 )
		{
			hSubMenu.removeChild( hSubMenu.childNodes[ 0 ] )
		}
	}
}

cTreeMenu.getMenuItemTextContainer = function( hItem )
{
	while( hItem != null && hItem.nodeType != document.TEXT_NODE && hItem.childNodes.length > 0 )
	{
		hItem = hItem.childNodes.item(0)
	}
	if( hItem )
	{
		return hItem.parentNode
	}
	else
	{
		return null
	}
}

cTreeMenu.getMenuItemText = function( hItem )
{
	while( hItem != null && hItem.nodeType != document.TEXT_NODE )
	{
		hItem = hItem.childNodes.item(0)
	}
	if( hItem )
	{
		return hItem.nodeValue
	}
	else
	{
		return null
	}
}


cTreeMenu.getPreviousMenuItem = function( hItem )
{
	var hSibling = getPrevNodeSibling( hItem )
	if( hSibling != null )
	{
		hSubMenu = getSubNodeByName( hSibling, 'ul' )
		while( hSubMenu && hSubMenu.style.display != 'none' )
		{
			hSibling = hSubMenu.lastChild.nodeType == document.ELEMENT_NODE ? hSubMenu.lastChild : getPrevNodeSibling( hSubMenu.lastChild )
			hSubMenu = getSubNodeByName( hSibling, 'ul' )
		}
	}
	else
	{
		hSubMenu = getParentByTagName( hItem, 'UL' )
		hSibling = getParentByTagName( hSubMenu, 'LI' )
	}
	return hSibling
}

cTreeMenu.getNextMenuItem = function( hItem )
{
	var hSibling
	var hOldSibling
	var hSubMenu = getSubNodeByName( hItem, 'ul' )

	if( hSubMenu != null && hSubMenu.style.display != 'none' )
	{
		hSibling = getSubNodeByName( hSubMenu, 'li' )
	}
	else
	{
		hOldSibling = hItem
		hSibling = getNextNodeSibling( hOldSibling )
		while( hSibling == null )
		{
			hSubMenu = getParentByTagName( hOldSibling, 'UL' )
			hOldSibling = getParentByTagName( hSubMenu, 'LI' )
			if( hOldSibling == null )
			{
				break
			}
			hSibling = getNextNodeSibling( hOldSibling )
		}
	}
	return hSibling
}

cTreeMenu.getMenuItemMenu = function( hItem )
{
	var hMenu = getParentByProperty( hItem, 'className', 'moTreeMenu' )
	return hMenu
}

cTreeMenu.changeMenuItem = function( hMenu, hItem, sNewData )
{
	hItem.replaceChild( hItem.childNodes( 0 ), document.createTextNode( sNewData ) )
}

cTreeMenu.editClose = function( hEdit, bCancelEdit )
{
	var hItem = hEdit.parentNode
	var hOriginalContainer = getNextNodeSibling( hEdit )
	var sNewValue = hEdit.value
	var sOldValue = hEdit.getAttribute( 'originalValue' )
	var hMenu = cTreeMenu.getMenuItemMenu( hItem )
	if( hMenu.treeMenu.onItemEdit )
	{
		bCancelEdit = bCancelEdit & hMenu.treeMenu.onItemEdit( hItem, sNewValue, sOldValue )
	}

	if( !bCancelEdit )
	{
		hOriginalContainer.innerHTML = sNewValue
	}
	hItem.removeChild( hEdit )
	hItem.removeAttribute( 'originalValue' )
	hOriginalContainer.style.display = 'inline'
	hOriginalContainer.focus()
}

cTreeMenu.editMenuItem = function( hItem )
{
	if( !cTreeMenu.CB_EDITABLE || !cTreeMenu.getTypeModifier( hItem, cTreeMenu.CBF_LEAF ) )
	{
		return false
	}

	var hEdit = document.createElement( 'input' )
	hEdit.type = 'text'
	hEdit.className = 'edit'
	hEdit.onblur = cTreeMenu.onEditBlur
	hEdit.onkeyup = cTreeMenu.onEditKeyUp

	var hOriginalContainer = cTreeMenu.getMenuItemTextContainer( hItem )
	hEdit.value = cTreeMenu.getMenuItemText( hItem )
	hEdit.setAttribute( 'originalValue', cTreeMenu.getMenuItemText( hItem ) )

	hOriginalContainer.style.display = 'none'
	hOriginalContainer.parentNode.insertBefore( hEdit, hOriginalContainer )
	hEdit.focus()
}

cTreeMenu.startEditMenuItem = function( event )
{
	cDomEvent.init( event )
	cTreeMenu.editMenuItem( getParentByTagName( cDomEvent.target, 'LI' ) )
}

//event handlers
cTreeMenu.onItemKeyUp = function( event )
{
	cDomEvent.init( event )
	var hSibling
	var hOldSibling
	var hLink
	var hSubMenu
	switch( cDomEvent.key )
	{
		case 113 :	//f2 key
					hSibling = getParentByTagName( cDomEvent.target, 'LI' )
					if( hSibling )
					{
						cTreeMenu.editMenuItem( hSibling )
					}
					break
		case 38:	//up key
					hSibling = cTreeMenu.getPreviousMenuItem( cDomEvent.target.parentNode )
					if( hSibling )
					{
 						hLink = getSubNodeByName( hSibling, 'a' )
						if( hLink )
						{
							hLink.focus()
						}
					}
					break
		case 40:	//down key
					hSibling = cTreeMenu.getNextMenuItem( cDomEvent.target.parentNode )
					if( hSibling )
					{
 						hLink = getSubNodeByName( hSibling, 'a' )
						if( hLink )
						{
							hLink.focus()
						}
					}
					break
	}
	if( event.preventDefault )
	{
		event.preventDefault()
	}
	event.cancelBubble = true
	event.returnValue = false
	return false
}

cTreeMenu.onEditKeyUp = function( event )
{
	cDomEvent.init( event )
	switch( cDomEvent.key )
	{
		case 27 :
					cTreeMenu.editClose( cDomEvent.target, true )
					break
		case 13 :
					cTreeMenu.editClose( cDomEvent.target, false )
					break
	}
}

cTreeMenu.onEditBlur = function( event )
{
	cDomEvent.init( event )
	cTreeMenu.editClose( cDomEvent.target, false )
}

cTreeMenu.onItemClick = function( event )
{
	cDomEvent.init( event )
	var hActiveItem = getParentByTagName( cDomEvent.target, 'LI' )
	if( cTreeMenu.getTypeModifier( hActiveItem, cTreeMenu.CBF_NODE ) )
	{
		if( cTreeMenu.toggleItem( hActiveItem ) )
		{
			if( event.preventDefault )
			{
				event.preventDefault()
			}
			event.cancelBubble = true
			event.returnValue = false
			return false
		}
	}
	else if( ( cTreeMenu.getTypeModifier( hActiveItem, cTreeMenu.CBF_LEAF ) ) )
	{
			if( event.preventDefault )
			{
				event.preventDefault()
			}
			event.cancelBubble = true
			event.returnValue = false
			return false
	}
}

cDomEvent.addEvent( window, 'load', cTreeMenu.init )