/********************************************************************************
 * This file is a part of the software:
 *
 *	enugene 0.9.8.6-beta  (c) Copyright 2007-2009 by Bogdan Vojska
 *	package: enugene 0.9.8.6-beta
 *
 *	developed for Joomla! 1.5
 *	
 *	www.bogdan-vojska.eu
 *	enugene@bogdan-vojska.eu
 *
 * LICENCE:
 *	Permission is hereby granted, free of charge, to any person obtaining a
 *	copy of this software using it subject to the following conditions:
 *	
 *	The enuGene software version 0.9.1-beta is for free use to any webdesigner or other 
 *	creative working people using it as part of a web site, controling a web 
 *	site's menus. The web site may be as well commercial as private. For realizing 
 *	this usage the software may be copied and distributed free of charge.
 *	
 *	The programs code is not free for any changing without another special license 
 *	or agreement with the above noticed developer. The program or its parts are not 
 *	free for any kind of commercial or noncommercial reselling, or anykind of use as 
 *	codepart inside other programs without a otherwise expressly by the developer 
 *	agreed licence.
 *
 *	The above copyright notice and this permission notice shall be included
 *	in all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 *	OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 *	DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
 *	ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *	DEALINGS IN THE SOFTWARE.
 *
 * NOTICE:
 *	
 *	There is no guaratee for any compatibility to browsers below the IE 5.5 age. 
 *	Targeted browsers are full W3C standard compatible browsers.
*/

function clsEnugeneDOM (parent) {
	this.parent = '';
	this.util = {
		/**
		* gets a dom-object by id
		* @param string
		* @return object
		*/
		getObject : function (id) {
			var obj = null;
			if (document.all)
				obj = document.all[id];
			if (document.getElementById (id))
				obj = document.getElementById (id);
			return obj;
		},
		
		isIe : function () {
			if (document.all) 
				return true; 
			else 
				return false;
		},
		
		set_Property : function (obj, name, value, attr) {
			if (this.isIe( )) {
				if (attr == 'important') attr = '!' + attr;
				obj.style.setAttribute( 'cssText', name + ':' + value + attr + ';', 0);
			} else {
				obj.style.setProperty( name, value, attr);
			}
		},

		
		/**
		* @param obj:		DOM object reference
		* @return integer	width of the DOM object 
		*					or that of his firstChild 
		*					or zero
		*/
		getWidth : function (obj) {
			var width = obj.offsetWidth;
			if (width > 0)
				return width;
			if (!obj.firstChild || obj.firstChild.offsetHeight === undefined)
				return 0;
			return obj.lastChild.offsetLeft - obj.firstChild.offsetLeft + enugene.DOM.util.getWidth (obj.lastChild);
		},
		
		/**
		* @param obj:		DOM object reference
		* @return integer	height of the DOM object 
		*					or that of his firstChild 
		*					or zero
		*/
		getHeight : function (obj) {
			var height = obj.offsetHeight;	
		
			if (height > 0)
				return height;
			if (!obj.firstChild || obj.firstChild.offsetHeight === undefined)
				return 0;
			return obj.firstChild.offsetHeight;
		},
		
		/**
		* functions that obtain the coordinates of an HTML element
		* @param object obj:	DOM object reference
		* @return integer	X position to the most upper object (mostcase: <body>)
		*/
		getX : function (obj) {
			var x = 0;
			do {
				x += obj.offsetLeft;
				obj = obj.offsetParent;
			}
			while ( obj );
			return x;
		},
		
		/**
		* @param object obj	DOM object reference
		* @return integer
		*/
		getY : function (obj) {
			var y = 0;
			do {
				y += obj.offsetTop;
				obj = obj.offsetParent;
			}
			while (obj);
			return y;
		}
		
	}; // end enugene.DOM.util
	
	this.constructor =  {
		parent : '',
		wEL : 0,
		hEL : 0,
		wER : 0,
		hER : 0,
		util : {
		
			/**
			* Running dynamic mode the target frame for the  menu 
			* is the blockFrame, else the menus are positioned absolute 
			* into free floating frames.
			*
			* @return object target frame
			*/
			getMainFrame : function (targetObject, id, theme, positMode) {
				var blockHeight = '';
				var blockWidth = '';
				if (positMode == 'dynamic') {
					// blockFrame is the target frame for the mainmenu
					var blockFrame = enugene.DOM.util.getObject( id + '_blockFrame' );
					blockHeight = enugene.menus.elements[id].blockHeight;
					blockWidth = enugene.menus.elements[id].blockWidth;
					if (parseInt( blockHeight )) {
						blockFrame.style.height = blockHeight + 'px';
					} else {
						blockHeight == 'auto' ? blockFrame.style.height = 'auto' : blockFrame.style.height = '0px';
					}
					if (parseInt( blockWidth )) {
						blockFrame.style.width = blockWidth + 'px';
					} else {
						blockWidth == 'auto' ? blockFrame.style.width = 'auto' : blockFrame.style.width = '0px';
					}
					var returnFrame = blockFrame;
				} else {
					// blockFrame only neccessary to get the sizes
					var blockFrame = enugene.DOM.util.getObject( id + '_blockFrame' );
					var floatingFrame = document.createElement('div');
					floatingFrame.id = id + '_mainFrame';
					floatingFrame.style.position = 'absolute';
					floatingFrame.style.width = '0px';
					floatingFrame.style.height = '0px';
					if (positMode == 'horizontal') {
						floatingFrame.style.top = '0px';
						floatingFrame.style.left = enugene.DOM.util.getX( blockFrame ) + 'px';
					}
					if (positMode == 'vertical') {
						floatingFrame.style.top = enugene.DOM.util.getY( blockFrame ) + 'px';
						floatingFrame.style.left = '0px';
					}
					if (positMode == 'preset') {
						floatingFrame.style.top = '0px';
						floatingFrame.style.left = '0px';
					}
					var returnFrame = floatingFrame;
				}
				// the created or selected frame will be the
				// target for the menus
				return returnFrame;
			},
			
			getSubFrame : function (targetObject, id) {
				var returnFrame = document.createElement('div');
				returnFrame.id = id + '_subFrame';
				returnFrame.style.width = '0px';
				returnFrame.style.height = '0px';
				returnFrame.style.position = 'absolute';
				returnFrame.style.top = '0px';
				returnFrame.style.left = '0px';
				targetObject.appendChild( returnFrame );
				return returnFrame;
			}
		}, // end constructor.util
		menu : {
			parent : '',
			getBox : function (id) {
				var cssSelector = '';
				var theme = enugene.menus.elements[id].theme;
				var type = enugene.menus.elements[id].type;
				var bgImg = enugene.menus.elements[id].backgroundImage;
				
				var newObj = document.createElement('div');
				newObj.id = id;
				newObj.className = theme + 'Menu';
				newObj.theme = theme;
				newObj.currentItem = '';
				newObj.topMenuId = enugene.menus.elements[id].topMenuId;
				newObj.parentMenuId = enugene.menus.elements[id].parentMenuId;
				newObj.style.clear = 'both';
				if (type == 'main') {
					newObj.style.position = 'relative';
				} else {
					newObj.style.position = 'absolute';
					newObj.style.visibility = 'hidden';
					newObj.style.zIndex = 100;
				}
				if (bgImg) newObj.style.backgroundImage = 'url(' + bgImg + ')';
				return newObj;
			},
			
			setEvents : function (objTar, id) {
				var theme = enugene.menus.elements[id].theme;
				var type = enugene.menus.elements[id].type;
				switch (type) {
					default :
						if (enugene.DOM.util.isIe()) {
							objTar.style.cursor = 'hand';
							objTar.onmouseover = new Function( "enugene.DOM.eventHandler.mouse.menus.overMenu( this )" );
							objTar.onmouseout = new Function( "enugene.DOM.eventHandler.mouse.menus.menuOut( this )" );
						} else {
							objTar.style.cursor = 'pointer';
							objTar.onmouseover = function(){ enugene.DOM.eventHandler.mouse.menus.overMenu( this ); };
							objTar.onmouseout = function(){ enugene.DOM.eventHandler.mouse.menus.menuOut( this ); };
						}
					break;
				}
			},
			create : function(id) {
				var menu = this.getBox(id);
				this.setEvents( menu, id );
				return menu;
			},
			
			/**
			* return the block or main frame for mainmenus
			* or the sub frame for submenus
			*/
			getMenuFrame : function ( targetObject, id, positMode ) {
				var type = enugene.menus.elements[id].type;
				var theme = enugene.menus.elements[id].theme;
				if (type == 'main') {
					var menuFrame = enugene.DOM.constructor.util.getMainFrame( targetObject, id, theme, positMode );
				} else {
					var menuFrame = enugene.DOM.constructor.util.getSubFrame( targetObject, id );
				}
				return menuFrame;
			},
			
			/**
			* Appends a new menu to menuFrame.
			* Returns the created menu object to 
			* be filled with items.
			*/
			append : function (targetObject, id) {
				var modId = enugene.menus.elements[id].moduleId;
				var positMode = enugene.menus.menutypes[modId].positMode;
				var newObj = this.create( id );
				enugene.menus.elements[id].domObject = newObj;
				// menu frame is either the blockFrame or the free 
				// floating mainFrame. They were appended to DOM by
				// their getters.
				var menuFrame = this.getMenuFrame( targetObject, id, positMode );
				// hook the generated menu into the frame
				menuFrame.appendChild(newObj);
				// dynamic mode positioned menus don't need to be
				// appended, they were appended to the menutypes 
				// blockFrame. The blockFrame is part of the 
				// document since construction by in PhP.
				if (menuFrame.id.split('_')[1] != 'blockFrame') {
					targetObject.appendChild(menuFrame);
				}
				return newObj;
			}
		},
		item : {
			parent : '',
			// Create all items box including the className and background image
			getBox : function (id) {
				var cssSelector = '';
				var theme = enugene.menus.elements[id].theme;
				var type = enugene.menus.elements[id].type;
				var orient = enugene.themes[theme].menuOrientation;
				var setImportant = enugene.themes[theme].setImportant || '';
				var bgImg = enugene.menus.elements[id].backgroundImage;
				
				// css className
				switch (type) {
					case 'separator' :
						cssSelector = theme + 'Separator';
					break;
					default :
						cssSelector = theme + 'MenuItem';
						// Get the inner Elem sizes - by set to zero they won't be generated.  
						// Separator has no such elems.
						this.wEL = enugene.themes[theme].iELwidth;
						this.hEL = enugene.themes[theme].iELheight;
						this.wER = enugene.themes[theme].iERwidth;
						this.hER = enugene.themes[theme].iERheight;
					break;
				}
				
				// Standard button container
				var newObj = document.createElement('div');
				newObj.id = id;
				newObj.className = cssSelector;
				newObj.theme = theme;
				newObj.topMenuId = enugene.menus.elements[id].topMenuId;
				newObj.myMenuId = enugene.menus.elements[id].myMenuId;
				if (orient.charAt(0) == 'h') enugene.DOM.util.set_Property(newObj, "float", "left", setImportant);
				else enugene.DOM.util.set_Property(newObj, "float", "none", setImportant);
				if (bgImg) newObj.style.backgroundImage = 'url(' + bgImg + ')';
				return newObj;
			},
			
			setElemL : function(targetObj, type, itemId) {
				if ((this.hEL + this.wEL) == 0) return '';
				var theme = enugene.menus.elements[itemId].theme;
				var newObj = document.createElement('div');
				newObj.id = itemId + 'L';
				newObj.className = theme + 'MenuItemL';
				newObj.theme = theme;
				newObj.parentId = enugene.menus.elements[itemId].id;
				targetObj.appendChild(newObj);
				return newObj;
			},
			
			setElemT : function(targetObj, type, itemId) {
				var theme = enugene.menus.elements[itemId].theme;
				var newObj = document.createElement('div');
				newObj.id = itemId + 'T';
				newObj.className = theme + 'MenuItemT';
				newObj.theme = theme;
				newObj.parentId = enugene.menus.elements[itemId].id;
				targetObj.appendChild(newObj);
				return newObj;
			},
			
			setElemR : function(targetObj, type, itemId) {
				if ((this.hER + this.wER) == 0) return '';
				var theme = enugene.menus.elements[itemId].theme;
				var newObj = document.createElement('div');
				newObj.id = itemId + 'R';
				newObj.className = theme + 'MenuItemR';
				newObj.theme = theme;
				newObj.parentId = enugene.menus.elements[itemId].id;
				targetObj.appendChild(newObj);
				return newObj;
			},

			setEvents : function (objTar, type, id) {
				var topMenuId = enugene.menus.elements[id].topMenuId;
				var myMenuId = enugene.menus.elements[id].myMenuId;
				var theme = enugene.menus.elements[id].theme;
				switch (type) {
					case 'separator' :
						if (enugene.DOM.util.isIe()) {
							objTar.style.cursor = 'hand';
							objTar.onmouseover = new Function( "enugene.DOM.eventHandler.mouse.menus.overItem( this,'" + theme + "','" + topMenuId + "')" );
						} else {
							objTar.style.cursor = 'pointer';
							objTar.onmouseover = function(){ enugene.DOM.eventHandler.mouse.menus.overItem ( this, theme, topMenuId ); };
						}
					break;
					default :
						if (enugene.DOM.util.isIe()) {
							objTar.style.cursor = 'hand';
							objTar.onmouseover = new Function( "enugene.DOM.eventHandler.mouse.menus.overItem( this,'" + theme + "','" + topMenuId + "' )" );
							objTar.onmousedown = new Function( "enugene.DOM.eventHandler.mouse.menus.mouseDown( this,'" + theme + "','" + myMenuId + "' )" );
							objTar.onmouseup = new Function( "enugene.DOM.eventHandler.mouse.menus.mouseUpItem( this )" );
						} else {
							objTar.style.cursor = 'pointer';
							objTar.onmouseover = function(){ enugene.DOM.eventHandler.mouse.menus.overItem ( this, theme, topMenuId ); };
							objTar.onmousedown = function(){ enugene.DOM.eventHandler.mouse.menus.mouseDown ( this, theme, myMenuId ); };
							objTar.onmouseup = function(){ enugene.DOM.eventHandler.mouse.menus.mouseUpItem ( this ); };
						}
					break;
				}
			},
			
			// create item
			create : function(id, type) {
				var item = this.getBox(id);
				this.setEvents( item, type, id );
				if (type != 'separator') this.setElemL( item, type, id );
				this.setElemT( item, type, id );
				if (type != 'separator') this.setElemR( item, type, id );
				return item;
			},
			
			//append item
			append : function (targetObj, id) {
				var type = enugene.menus.elements[id].type;
				var newObj = this.create( id, type );
				newObj.myMenuId = targetObj.id;
				// set the first item as current
				if (!targetObj.currentItem) targetObj.currentItem = id;
				enugene.menus.elements[id].domObject = newObj;
				targetObj.appendChild(newObj);
				return newObj;
			}
		},
		
		// create mainmenu (menutype) and the associated submenus
		create : function (targetObj) {
			var objMenus = enugene.menus;
			var authItemsCount = 0;
			var mty = '';
			var mnu = '';
			var menu = '';
			if (!targetObj) targetObj = document.body;
			
			for (var mty in objMenus.menutypes) {
				for (var mnu in objMenus.menutypes[mty].menus) {
					menu = objMenus.menutypes[mty].menus[mnu];
					var newMenu = this.menu.append( targetObj, menu.id );
					authItemsCount = 0;
					for (var itemId in menu.items) {
						if (!enugene.menus.elements[itemId].userAuth) continue;
						++authItemsCount;
						var newItem = this.item.append( newMenu, itemId );
						newMenu.appendChild(newItem);
					}
					// no item with a an authorized link for this menu? 
					// - remove menu and its blockFrame from doc
					if (authItemsCount == 0) {
						var bF = enugene.DOM.util.getObject(menu.id + '_blockFrame');
						if (bF) {
							bF.parentNode.removeChild( bF );
						}
					}
				}
			}
			this.init();
		},
		
		/**
		* init menus after construction
		*/
		init : function () {
			var menuItem = '';
			var topMenuItem = '';
			var arrMnu = enugene.startup.menutypes;
			// user given topLevelItemId does not exist in elements? 
			// menu not active - set the first menu from arrMnu active
			if (!enugene.menus.elements[enugene.menus.topLevelItemId]) {
				enugene.menus.topLevelMenuId = enugene.menus.menutypes[arrMnu[0]].mainMenuId;
				enugene.menus.topLevelItemId = enugene.menus.menutypes[arrMnu[0]].topItemId;
			}
			// registrate the loaded menutypes (mainmenus)
			for (var x = 0; x < arrMnu.length; x++) {
				enugene.menus.loadedMenus[x] = enugene.menus.menutypes[arrMnu[x]].mainMenuId;
			}
			// when the document is loaded by a frontsite request 
			// set the active menu item, or leave the startItem empty
			// if the document is loaded first time
			if (enugene.startup.startItemId) {
				// Start by Joomla default startItem '1' ? - replace it with the enugene set one.
				if (enugene.startup.startItemId == 'mgenIt1') {
					// if item 1 does exist then take it anycase as startitem
					// else, if item 1 is pressed, enuGene would take the toplevel
					// item even if it is not the the site first start.
					if (enugene.menus.elements['mgenIt1']) enugene.menus.topLevelItemId = 'mgenIt1';
					enugene.menus.activeItemId = enugene.menus.topLevelItemId;
					enugene.startup.startItemId = enugene.menus.topLevelItemId;
				} else {
					enugene.menus.activeItemId = enugene.startup.startItemId;
				}
			} else {
				enugene.menus.activeItemId = enugene.menus.topLevelItemId;
				enugene.startup.startItemId = enugene.menus.topLevelItemId;
/*
				enugene.menus.activeItemId = enugene.menus.activateItemId = enugene.menus.topLevelItemId;
				enugene.menus.activateMenuId = enugene.menus.elements[enugene.menus.activateItemId].myMenuId;
				enugene.menus.util.setItemCurrent(enugene.menus.activateMenuId, enugene.menus.activateItemId, '', '');
				enugene.DOM.properties.setDOMProperties( enugene.menus.elements );
				return;
*/
			}
			// the document was required by enugene - get the mainmenu caller id
			var topItemId = enugene.menus.util.get_caller_ItemId( enugene.menus.activeItemId, 0 );
			// topItemId empty ? No menu with the activeItemId is active
			topItemId ? topMenuItem = enugene.menus.elements[topItemId] : topMenuItem = enugene.menus.elements[enugene.menus.activeItemId];
			if (topMenuItem) {
				// tell him which item to activate
				enugene.menus.activateMenuId = topMenuItem.topMenuId;
				enugene.menus.activateItemId = topItemId;
			} else {
				enugene.menus.activateMenuId = enugene.menus.topLevelMenuId;
				enugene.menus.activateItemId = enugene.menus.topLevelItemId;
				enugene.menus.activeItemId = enugene.menus.topLevelItemId;
			}
			enugene.menus.util.setItemCurrent(enugene.menus.activateMenuId, enugene.menus.activateItemId, '', '');
			enugene.DOM.properties.setDOMProperties( enugene.menus.elements );
		}
	};
	
	this.eventHandler = {
		mouse : {
			menus : {
				/**
				* @params string id
				* @params object obj
				* @return void
				*/
				mouseUpItem : function (obj) {
					var item = enugene.menus.elements[obj.id];
					var link = ''; 
					var target = '_self';
					
					var theme = enugene.menus.elements[obj.id].theme;
					var hasSub = enugene.menus.elements[obj.id].child;
					if (hasSub && enugene.themes[theme].clickOpen) return;
				
					link = item.link;
					target = item.target;
				
					if (link) {
						window.open (link, target);
					}
				},

				/**
				* This function is taken for mouse button down events at a menu item
				* @param object obj
				* @param string theme
				* @return void
				*/
				mouseDown : function (obj, theme, menuId) {
					var theme = enugene.menus.elements[obj.id].theme;
					var objActItem = enugene.menus.elements[obj.id];
					var actItemMenu = objActItem.parentMenuObject();
					if (objActItem.child && enugene.themes[theme].clickOpen) {
						enugene.menus.perform.hide.childs( enugene.menus.currentMenu.menuObject );
						enugene.menus.perform.show.menu( obj, objActItem.child );
						enugene.DOM.properties.setDOMProperties( enugene.menus.elements );
					}
					enugene.menus.activeItemId = obj.id
				},

				/**
				* This function is called when the mouse moves out of a menu
				* @param object obj
				* @param integer delayTime
				* @return void
				*/
				menuOut : function (obj) {
					var theme = enugene.menus.elements[obj.id].theme;
					var delayTime = enugene.themes[theme].delayMenuClose;
					enugene.globals.menuTimeout = window.setTimeout( "enugene.menus.perform.hide.timeout()", delayTime );
				},

				/**
				* This function is called when the mouse moves out of a menu item
				* @return void
				*/
				overMenu : function (obj) {
					window.clearTimeout( enugene.globals.menuTimeout );
				},
				
				/**
				* @param	obj:	the pressed menuitem
				* @param	theme:	The global css selector theme
				* @param	orient: menu's orientation
				* @return void
				*/
				overItem : function (obj, theme, topMenuId) {
					window.clearTimeout( enugene.globals.menuTimeout );
					//if no action item - clear timeout and leave
					if (enugene.menus.util.getAction(obj.id) != 'normal') return;
					var lastMenuObject = '';
					var menuItem = enugene.menus.elements[obj.id];
					var menuObject = menuItem.parentMenuObject();
					if (!menuObject) return;
				
					var objMyMenu = enugene.menus.elements[obj.myMenuId];
					var noMenuChange = (obj.myMenuId == enugene.menus.currentMenu.id);
					// move within the same item? - set item current, show menu and leave
					if (obj.id == objMyMenu.currentItem && noMenuChange) {
						if (menuItem.child && !enugene.themes[menuItem.theme].clickOpen) {
							enugene.menus.perform.show.menu (obj, menuItem.child );
						}
					} else {
						// move wthin the same menu?
						if (noMenuChange) {			
							if (!enugene.themes[menuItem.theme].clickOpen) enugene.menus.perform.hide.childs(objMyMenu);
						} else {
							if (enugene.menus.currentItem.id && enugene.menus.util.isInMenuChain( enugene.menus.currentItem.id, obj.id )) {
								enugene.menus.perform.hide.subs.levelDown(objMyMenu.topMenuId, objMyMenu.sublevel);
							} else {
								enugene.menus.perform.hide.subs.all( );
							}
						}
						// open menu if it has
						if (menuItem.child && !enugene.themes[menuItem.theme].clickOpen) {
							enugene.menus.perform.show.menu ( obj, menuItem.child );
						}
					}
					enugene.menus.util.setItemCurrent(menuObject.id, obj.id, obj.className, '');
					enugene.DOM.properties.setDOMProperties( enugene.menus.updateList );
				}
			}
		}
	};
	this.constructor.parent = this;
	this.constructor.menu.parent = this.constructor;
	this.constructor.item.parent = this.constructor;
	this.parent = enugene;
} // end clsEnugeneDOM

////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////

function clsEnugeneKernel () {

	this.objects = {
		clsGlobals : function () {
			this.menuTimeout = null;
		},
		
		clsCurrentItem : function () {
			this.id = '';
			this.objtype = 'currentItem';
			this.theme = '';
			this.category = '';
			this.className = '';
			this.menuId = '';
			this.child = '';
			this.objChild = new Object();
			this.domObject = new Object();
		},
		
		clsSavedItem : function () {
			this.id = '';
			this.className = '';
			this.theme = '';
		},

		clsCurrentMenu : function () {
			this.id = '';
			this.menuObject = '';
			this.domObject = '';
		}
	};
	
	this.clsEnugeneUtil = function () {
		this.getMgenId = function (id) {
			var objtype = enugene.menus.elements[id].objtype
			switch (objtype) {
				case 'menuItem' :
					return 'mgenIt' + id;
				break;
				case 'menu' :
					return 'M' + id;
				break;
			}
		};
		
		this.getAction = function (id) {
			var itemtype = enugene.menus.elements[id].itemtype
			switch (itemtype) {
				case 'component' :
					return 'normal';
				break;
				case 'separator' :
					return 'normal';
				break;
				default:
					return 'normal';
			}
		};
		
		/**
		* @param string menuId	Id of the menu which item are to reset.
		* @return void
		*/
		this.resetItemStyles = function (objMenu) {
			if (!objMenu) return;
			var menuItems = objMenu.items;
			if (objMenu.itemCount > 0) {
				var x;
				for (x in menuItems) {
					menuItems[x].domObject.className = menuItems[x].className;
				}
			}
		};
		
		/**
		* @param	string menuId			menu of the item to activate
		* @param	string itemId			item which is to activate
		* @param	string className		the style which is used when recovering the menuitem
		* @param	string hoverClassName 	is the css-style-classname which is used 
		* 									when displaying the menuitem.
		* @return void
		*/
		this.setItemCurrent = function (menuId, itemId, className, hoverClassName) {
			var menuItem = enugene.menus.elements[itemId];
			var menuObject = enugene.menus.elements[menuId];
			if (enugene.menus.currentItem.id) var currentItemId = enugene.menus.currentItem.id;
			else var currentItemId = itemId;
			var currentItem = enugene.menus.elements[currentItemId];
			var theme = menuObject.theme;

			if (!hoverClassName) hoverClassName = theme + 'MenuItem_Hover';
			if (!className) className = theme + 'MenuItem' ;
			
			// Reset item: menus not used before? Or not the same theme? - no reset to previous.
			if (enugene.menus.savedItem.id) {
				if (enugene.menus.savedItem.theme == menuObject.theme) {
					enugene.menus.currentItem.menuObject.style.className = enugene.menus.savedItem.className;
					enugene.menus.updateList[enugene.menus.currentItem.id] = enugene.menus.elements[enugene.menus.currentItem.id];
				} else {
					// but reset to saved item theme normal className
					enugene.menus.currentItem.menuObject.style.className = enugene.menus.savedItem.theme + 'MenuItem' ;
					enugene.menus.updateList[enugene.menus.savedItem.id] = enugene.menus.elements[enugene.menus.savedItem.id];
				}
			}
		
			if (menuItem) {
				if (menuItem.itemtype == 'separator') return;
				
				enugene.menus.savedItem.id = menuItem.id;
				enugene.menus.savedItem.className = menuItem.className;
				enugene.menus.savedItem.theme = menuItem.theme;
		
				// Change the item objects class name and put it on stack
				// to update the DOM element. Put the menu item on the
				// DOM execution stack.
				menuItem.style.className = hoverClassName;
				enugene.menus.updateList[menuItem.id] = enugene.menus.elements[menuItem.id];

				// set the recent item as current one
				enugene.menus.currentItem.id = itemId;
				enugene.menus.currentItem.theme = theme;
				enugene.menus.currentItem.className = menuItem.className;
				enugene.menus.currentItem.menuId = menuObject.id;
				enugene.menus.currentItem.topMenuId = menuObject.topMenuId;
				enugene.menus.currentItem.topItemId = menuObject.topItemId;
				enugene.menus.currentItem.child = menuItem.child;
				enugene.menus.currentItem.objChild = enugene.menus.elements[menuItem.child];
				enugene.menus.currentItem.domObject = menuItem.domObject;
				enugene.menus.currentItem.menuObject = enugene.menus.elements[itemId];
			}
		
			if (menuObject) {
				enugene.menus.currentMenu.id = menuObject.id;
				enugene.menus.currentMenu.menuObject = menuObject;
				enugene.menus.currentMenu.domObject = menuObject.domObject;
			}
		};
		
		/**
		* @param string menuId: id of the current menu
		* @return string
		*/
		this.get_caller_ItemId = function (itemId, sublevel) {
			var parentItemId = '';
			// find the caller item
			if (enugene.menus.elements[itemId])
				var menuObject = enugene.menus.elements[enugene.menus.elements[itemId].myMenuId];
			else
				return '';
			do {
				parentItemId = enugene.menus.elements[itemId].parentItemId;
				if (parentItemId == "mgenIt" + '0') return enugene.menus.elements[itemId].id;
				itemId = parentItemId;
			} while (menuObject.parentItemId != "mgenIt" + '0' || menuObject.sublevel <= sublevel);
			return itemId;
		};
		
		/**
		* @param	actItemId string 	the id of the pressed menuitem
		* @param	lastItemId string 	the id of the just left menuitem
		* @return	boolean 		if the given itemId is in chain true else false
		*/
		this.isInMenuChain = function (lastItemId, actItemId) {
			var callerId = false;
			var inChain = false;
			var lastItem = enugene.menus.elements[lastItemId];
			var actItem = enugene.menus.elements[actItemId];
			if (lastItem.topItemId() == actItem.topItemId()) return true;
			return false;
		};
		
		/**
		* Returns the id level menu item which leads 
		* the chain to the current menu
		* @param string itemId
		* @return string
		*/
		this.getItem_inChain = function (itemId, level) {
			var item = '';
			var menu = '';
			var topItemId = '';
			if (itemId && itemId != '0') {
				item = enugene.menus.elements[itemId];
				menu = enugene.menus.elements[item.myMenuId];
				if (menu.sublevel == '0') return item.id;
				if (menu.starterChain) { 
					topItemId = menu.starterChain.split(';')[level];
				} else {
					topItemId = item.topItemId();
				}
			} else {
				topItemId = 0;
			}
			return topItemId;
		};
		
	}; //clsEnugeneUtil
	
	this.clsEnugenePerformer = function (parent) {
		this.parent = parent;
		this.show = {
			/**
			* @param object obj			the menu item DOM object that opens up the subMenu
			* @param string idSub		the id of the sub menu to be shown
			* @return object
			*/
			menu : function (obj, idSub) {
				var objSubMenu = enugene.menus.elements[idSub];
				objSubMenu.starterChain = objSubMenu.starterChain + obj.id + ';';
				objSubMenu.visibility = 'visible';
				enugene.menus.updateList[idSub] = enugene.menus.elements[idSub];
				return objSubMenu;
			}
		};
		this.hide = {
			parent : '',
			/**
			* Hides all submenus on menuOut event if timeout is reached.
			* For instant closure mouseOverItem() is responsible.
			* @return void
			*/
			timeout : function () {
				var currentMenu;
				currentMenu = enugene.menus.currentMenu.menuObject;
				var objTopMenu = enugene.menus.elements[currentMenu.topMenuId];
				enugene.menus.activateMenuId = objTopMenu.id;
				var parentItemId = currentMenu.parentItemId;
				var topCallerId = enugene.menus.util.getItem_inChain(enugene.menus.currentItem.id, 0 );
				this.subs.all( );
				var menuId = enugene.menus.elements[enugene.menus.activeItemId].myMenuId;
				this.parent.parent.util.resetItemStyles( objTopMenu );
				if (objTopMenu.items[enugene.menus.activeItemId]) {
					// button pressed - set anycase
					enugene.menus.activateItemId = enugene.menus.activeItemId;
					enugene.menus.activateMenuId = menuId;
				} else {
					// REDIRECTION to topmenu - only once
					if (!enugene.menus.activateItemId) enugene.menus.activateItemId = topCallerId;
					enugene.menus.activateMenuId = enugene.menus.elements[enugene.menus.activateItemId].myMenuId;
				}
				enugene.menus.util.setItemCurrent(enugene.menus.activateMenuId, enugene.menus.activateItemId, '', '');
				enugene.DOM.properties.setDOMProperties( enugene.menus.elements );
			},
			
			/**
			* Hides a single menu.
			* objMenu is the enugene.menus object of the menu to be hidden
			* @param object objMenu
			* @return void
			*/
			menu : function (objMenu) {
				// is mainmenu?
				if (objMenu.topMenuId == objMenu.id) 
					return;
				// Don't close the toplevel menu
				if (objMenu.sublevel == '0') 
					return;
				objMenu.visibility = 'hidden';
				this.childs( objMenu );
				objMenu.starterChain = '';
				this.parent.parent.util.resetItemStyles( objMenu );
				enugene.menus.updateList[objMenu.id] = enugene.menus.elements[objMenu.id];
			},
			
			/**
			* Hide all my child menus
			* @param object objMenu
			* @return void
			*/
			childs : function (objMenu) {
				var x;
				var id = '';
				for (x in objMenu.items) {
					if (objMenu.items[x].child) {
						id = objMenu.items[x].child;
						this.menu(enugene.menus.elements[id]);
					}
				}
			},
			
			subs : {
				parent : '',
				/**
				* Hide all submenus
				* @param string all
				* @return void
				*/			
				all : function () {
					var id;
					var isMenu = false;
					var isSub = false;
					for (id in enugene.menus.elements) {
						isMenu = (enugene.menus.elements[id].objtype == 'menu');
						isSub = (enugene.menus.elements[id].type == 'sub');
						if (isMenu && isSub) {
							this.parent.menu( enugene.menus.elements[id] );
						}
					}
				},
				
				/**
				* Hide all menu with a higher sublevel number
				* @param string mainmenuId
				* @param integer sublevel
				* @return void
				*/
				levelDown : function (mainmenuId, sublevel) {
					var x;
					var id = '';
					for (x in enugene.menus.elements) {
						sbl = enugene.menus.elements[x].sublevel;
						id = enugene.menus.elements[x].topMenuId;
						if (id == mainmenuId && sbl > sublevel) {
							this.parent.menu( enugene.menus.elements[x] );
						}
					}
				}
			}, // subs
			
			items : {
				set_transparent : function (menuItems, arg) {
					switch (arg) {
					case 'box' :
						for (var x in menuItems) {
							var setImportant = enugene.themes[menuItems[x].theme].setImportant || 'important';
							enugene.DOM.util.set_Property(menuItems[x].domObject, "background-color", "transparent", setImportant);
							enugene.DOM.util.set_Property(menuItems[x].domObject, "border-color", "transparent", setImportant);
						}
						break;
					case 'background' :
						for (var x in menuItems) {
							var setImportant = enugene.themes[menuItems[x].theme].setImportant || 'important';
							enugene.DOM.util.set_Property(menuItems[x].domObject, "background-color", "transparent", setImportant);
						}
						break;
					case 'all' : 
						for (var x in menuItems) {
							var setImportant = enugene.themes[menuItems[x].theme].setImportant || 'important';
							enugene.DOM.util.set_Property(menuItems[x].domObject, "visibility", "hidden", setImportant);
						}
						break;
					default :
					}
				}
			}
		}; // hide
		this.hide.subs.parent = this.hide;
		this.hide.parent = this;
	}; // clsEnugenePerformer
	
	this.clsEnugeneMenuProperties = function (parent) {
		this.parent = parent;
		
		/**
		* Creates the content of the inner item elements to the left and right
		* of the text element.
		* @param object objItem
		* @param object elemObjRef
		* @param string img
		* @param string width
		* @param string height
		*/
		this.append_imgElemContent = function ( objItem, elemObjRef, img, width, height ) {
			var newSpan = document.createElement('span');
			var newObj= document.createElement('img');
			img = img ? img : img = '';
			newObj.id = elemObjRef.id + 'img';
			newObj.style.width = width + 'px';
			newObj.style.height = height + 'px';
			newObj.style.border = '0px solid transparent';
			newObj.style.zIndex = '100';
			newObj.src = img;
			newSpan.appendChild(newObj);
			elemObjRef.appendChild(newSpan);
		};
		
		/**
		* All inner elements have to be included by a <span> for align them centered!
		*/
		this.getTextElem = function (objItem, elemObjRef) {
			var text = '';
			var menuId = objItem.parentMenuObject.id;
			var itemId = objItem.id;
			var theme = objItem.theme;
			var bdo = 'ltr';
			
			text = enugene.menus.elements[itemId].elemT;
			if (text === undefined) text = '';
			if (enugene.themes[theme].bdodir == 'rtl') {
				bdo = 'rtl';
			}
			if (elemObjRef.childNodes.length == 0 ){
				var newSpan = document.createElement('span');
				var newBdo = document.createElement('bdo');
				var newTextNode = document.createTextNode(text);
				newBdo.dir = bdo;
				newBdo.appendChild(newTextNode);
				newSpan.style.zIndex = '100';
				newSpan.appendChild(newBdo);
				elemObjRef.appendChild(newSpan);
			} else {
				elemObjRef.childNodes[0].childNodes[0].childNodes[0].nodeValue = text;
			}
		};
		
		/**
		* @param object objItem
		* @param object elemObjRef
		* @param string width
		* @param string height
		* @param string state
		* @param string itemPos
		*/
		this.getImgElem = function (objItem, elemObjRef, state, width, height, itemPos) {
			var strReturn = '';
			var img = '';
			var itemId = objItem.id;
			var theme = objItem.theme;
			if (isNaN( width )) width = '0';
			if (isNaN( height )) height = '0';

			if (width == '0' && height == '0') return '';
			// the case user set one size zero to make the
			// elem unvisible for a distinct state
			if (width == '0' || height == '0') 
				elemObjRef.style.display = 'none';
			else
				elemObjRef.style.display = 'block';
			if (enugene.menus.elements[itemId]) {
				if (state) {
					img = enugene.menus.elements[itemId][ 'elem' + itemPos + '_Hover'] || enugene.themes[objItem.theme][ 'itemImg' + itemPos + '_Hover'];
				} else {
					img = enugene.menus.elements[itemId][ 'elem' + itemPos] || enugene.themes[objItem.theme][ 'itemImg' + itemPos];
				}
			}
			if (!img) {
				return '';
			} else {
				if (elemObjRef.childNodes.length == 0 || !enugene.DOM.util.getObject(itemId + itemPos + 'img')){
					this.append_imgElemContent( objItem, elemObjRef, img, width, height );
				} else {
					elemObjRef.childNodes[0].childNodes[0].style.width = width + 'px';
					elemObjRef.childNodes[0].childNodes[0].style.height = height  + 'px';
					elemObjRef.childNodes[0].childNodes[0].src = img;
				}
			}
		};
		
		/**
		* The elemT always gets the text content, defined by joomla
		* as item 'name' in the jos_menu table. The text comes over 
		* MgenMenuConstructor->appendItemElem() directly into the elemT property.
		*
		* The application icon comes from jos_menu table, where it 
		* is defined as the 'menu_image' parameter. The image comes 
		* over MgenEnugeneMenus->create_array_profile() - pack_items() to the enugene_menus table.
		* It is noticed to there as item content param. From there it travels
		* over MgenMenuConstructor->parseItems() as 'jos_menu_image' into the 
		* enugene.menus[menu]items object cluster. This way each item can access the
		* image defined by the joomla menu manager.
		*
		* The foldericon is a enugene user defined style parameter. It is recorded 
		* as 'var' recorset and comes over MgenMenuConstructor->collect_theme_params() 
		* into the enugene.themes[theme] object cluster. This way it is a theme 
		* related parameter.
		*
		* Image priorities:
		* First the joomla defined menu_image is taken. Then the theme wide enugene 
		* images are used - if a folderimage is declared it will be prefered to
		* all other images. - If the image container size is set to zero the
		* container won't be constructed. 
		*
		* @param objItem:	the enugene.menus object of the menuitem
		* @param state:		string '_Hover' or empty controling the style at mouseover
		* @return void
		*/
		this.set_itemElems = function (objItem, state ) {
			var elemObjRef = '';
			var orient = '';
			var width = '';
			var height = '';
			var innerHtml = '';
			var objItemWidth = '';
			
			var getMgenId = '';
			var folderElem = enugene.themes[objItem.theme].folderElement;
			var menu = objItem.parentMenuObject();
			if (menu) objItemWidth = enugene.themes[menu.theme].mIwidth;
			
			if (state) { 
				state = '_Hover';
			} else {
				state = '';
			}
			
		
			// Left item element
			elemObjRef = enugene.DOM.util.getObject( objItem.id + 'L' );
			if (elemObjRef && objItem.type != 'separator') {
				elemObjRef.className = objItem.className + 'L' + state;
				if (state) {
					width = enugene.themes[elemObjRef.theme].iELHoverwidth;
					height = enugene.themes[elemObjRef.theme].iELHoverheight;
				} else {
					width = enugene.themes[elemObjRef.theme].iELwidth;
					height = enugene.themes[elemObjRef.theme].iELheight;
				}
				if (width == '0' || (parseInt( width ) && width != 'auto')) elemObjRef.style.width = width + 'px';
				if (height == '0' || (parseInt( height ) && height != 'auto')) elemObjRef.style.height = height + 'px';
				this.getImgElem (objItem, elemObjRef, state, width, height, 'L');
				if (menu && menu.orient().charAt(0) == 'v' && enugene.themes[elemObjRef.theme].itemOrder == 'center') {
					if (objItemWidth == 'auto' || !objItemWidth) {
						enugene.DOM.util.set_Property(elemObjRef, "display", "inline", "important");
						enugene.DOM.util.set_Property(objItem.domObject, "text-align", "center", "important");
					}
				}
			}
		
			// Text item element
			elemObjRef = enugene.DOM.util.getObject( objItem.id + 'T' );
			if (elemObjRef) {
				elemObjRef.className = objItem.className + 'T' + state;
				this.getTextElem ( objItem, elemObjRef);
				if (menu && menu.orient().charAt(0) == 'v' && enugene.themes[elemObjRef.theme].itemOrder == 'center') {
					if (objItemWidth == 'auto' || !objItemWidth) {
						enugene.DOM.util.set_Property(elemObjRef, "display", "inline", "important");
						enugene.DOM.util.set_Property(objItem.domObject, "text-align", "center", "important");
					}
				}
			}
			
			//The right item element - if no size no elems are constructed
			elemObjRef = enugene.DOM.util.getObject( objItem.id + 'R' );
			if (elemObjRef && objItem.type != 'separator') {
				elemObjRef.className = objItem.className + 'R' + state;
				if (state) {
					width = enugene.themes[elemObjRef.theme].iERHoverwidth;
					height = enugene.themes[elemObjRef.theme].iERHoverheight;
				} else {
					width = enugene.themes[elemObjRef.theme].iERwidth;
					height = enugene.themes[elemObjRef.theme].iERheight;
				}
				if (width == '0' || (parseInt( width ) && width != 'auto')) elemObjRef.style.width = width + 'px';
				if (height == '0' || (parseInt( height ) && height != 'auto')) elemObjRef.style.height = height + 'px';
				this.getImgElem ( objItem, elemObjRef, state, width, height, 'R' );
				var objItemHoverWidth = enugene.themes[elemObjRef.theme].mIHoverwidth;
				// Prevent the right elem expanding the item to the menu width
				// if the menu orient is 'h' and no item width is set. In this 
				// case the items are meant to be each as wide as the text is.
				if (menu && menu.orient().charAt(0) == 'h' && enugene.themes[elemObjRef.theme].itemOrder == 'left') {
					if (!objItemWidth || !objItemHoverWidth)
						enugene.DOM.util.set_Property(elemObjRef, "float", "left", "important");
					if (objItemWidth == 'auto' || objItemHoverWidth == 'auto') 
						enugene.DOM.util.set_Property(elemObjRef, "float", "left", "important");
				}
				if (menu && menu.orient().charAt(0) == 'v' && enugene.themes[elemObjRef.theme].itemOrder == 'center') {
					if (objItemWidth == 'auto' || !objItemWidth) {
						enugene.DOM.util.set_Property(elemObjRef, "display", "inline", "important");
						enugene.DOM.util.set_Property(objItem.domObject, "text-align", "center", "important");
					}
				}
			}
		}; // itemElems

		/**
		* @param 	objItem: 	the enugene.menus.elements object of the menuItem
		* @return void
		*/
		this.set_item = function (objItem) {
			var	arrObjClassName = '';
			objRef = objItem.domObject;
			// .type is the jos_menu type
			if (objItem.type == 'separator' && objItem.backgroundImage) {
				objRef.style.backgroundImage = 'url(' + enugene.menus.elements[objItem.id].backgroundImage + ')';
				objRef.style.backgroundColor = 'transparent';
				objRef.style.backgroundRepeat = 'no-repeat';
				objRef.style.backgroundPosition = 'center';
			}
			this.set_itemElems(objItem, false);
			if (objItem.style.className) {
				objRef.className = objItem.style.className;
				arrObjClassName = objItem.style.className.split('_');
				if (arrObjClassName[1] == 'Hover') {
					this.set_itemElems(objItem, true)
				}
			}
		}; // item
		
		/**
		* Evaluate the menu size values and transfer them to the
		* DOM affecting .style collection.
		*/
		this.eval_menuSize = function (obj, maxMenuWidth) {
			// transfer all sizes to the elements .style colletion
			// to be processed as DOM elements affecting value.
			if (parseInt(obj.width))
				obj.style.width = obj.width;
			if (parseInt(obj.height))
				obj.style.height = obj.height;
		};
		
		/**
		* @param string idSub 		Id of the submenu with the orgin to calculate
		* @param string menuItemId	Id of the menu calling Item 
		* @return void
		*/
		this.setSubMenuPosition = function (idSub, menuItemId) {
			var orient = '';
			var top = '';
			var left = '';
			var subMenuWidth;
			var subMenuHeight;
			var subMenuTop;
			var subMenuLeft;
			var parentMenuHeight;
			var parentMenuTop;
			var menuItemLeft;
			var menuItemTop;
			var menuItemWidth;
			var menuItemHeight;	
			var parentMenu_orient;
			
			var mgenMenus_subMenu = enugene.menus.elements[idSub];
			// only the 'dynamic' mode is set full automatically - if 'preset' do nothing
			if (!mgenMenus_subMenu || enugene.themes[mgenMenus_subMenu.theme].positMode == 'preset') return;
			
			subMenuWidth = enugene.DOM.util.getWidth( mgenMenus_subMenu.domObject );
			subMenuHeight = enugene.DOM.util.getHeight( mgenMenus_subMenu.domObject );
		
			var mgenMenus_MenuItem = enugene.menus.elements[menuItemId];
			if (!mgenMenus_subMenu) return;
		
			menuItemWidth = enugene.DOM.util.getWidth( mgenMenus_MenuItem.domObject );
			menuItemHeight = enugene.DOM.util.getHeight( mgenMenus_MenuItem.domObject );
			menuItemTop = enugene.DOM.util.getY( mgenMenus_MenuItem.domObject );
			menuItemLeft = enugene.DOM.util.getX( mgenMenus_MenuItem.domObject );
		
			var mgenMenus_parentMenu = mgenMenus_MenuItem.parentMenuObject();
			parentMenuHeight = enugene.DOM.util.getHeight( mgenMenus_parentMenu.domObject );
			parentMenuTop = enugene.DOM.util.getY( mgenMenus_parentMenu.domObject );
		
			var topMenu = enugene.DOM.util.getObject( mgenMenus_subMenu.topMenuId );
			mainLeft = enugene.DOM.util.getX( topMenu );
			mainTop = enugene.DOM.util.getY( topMenu );
			
			orient = enugene.themes[mgenMenus_subMenu.theme].menuOrientation;
			var parentMenu_orient = enugene.themes[mgenMenus_parentMenu.theme].menuOrientation;
		
			if (parentMenu_orient.charAt(0) == 'h') { //if the parentMenu is horizontal
				if (orient.charAt(1) == 'b') { //subMenu's popup direction goes downwards
					subMenuTop = parentMenuTop + parentMenuHeight;
				} else { //subMenu's popup direction goes 'u'pwards
					subMenuTop = parentMenuTop - subMenuHeight;
				}
				if (orient.charAt(2) == 'r') { //subMenu popups is in right direction
					subMenuLeft = menuItemLeft;
				} else { // subMenu popups in 'l'eft direction
					subMenuLeft = menuItemLeft - subMenuWidth;
				}
				if (orient.charAt(2) == 'c') { //subMenu popups centered
					subMenuLeft = menuItemLeft + ((menuItemWidth - subMenuWidth) / 2)
				}
			} else { //the ParentMenu.orient is vertical		
				if (orient.charAt(1) == 'b') { //subMenu's popup direction goes downwards
					if (orient.charAt(2) == 'c') { //subMenu popups centered
						subMenuTop = menuItemTop + menuItemHeight;
					} else {
						subMenuTop = menuItemTop;
					}
				} else { //subMenu's popup direction goes 'u'pwards
					if (orient.charAt(2) == 'c') { //subMenu popups centered
						subMenuTop = menuItemTop - subMenuHeight;
					} else {
						subMenuTop = menuItemTop + menuItemHeight - subMenuHeight;
					}
				}
				if (orient.charAt(2) == 'r') {//subMenu opens in 'r'ight direction
					subMenuLeft = menuItemLeft + menuItemWidth;
				} else { // subMenu's align is in 'l'eft direction
					subMenuLeft = menuItemLeft - subMenuWidth;
				}
				if (orient.charAt(2) == 'c') { //subMenu popups centered
					subMenuLeft = menuItemLeft + ((menuItemWidth - subMenuWidth) / 2)
				}
			}
			if (isNaN( subMenuTop )) subMenuTop = 0;
			if (isNaN( subMenuLeft )) subMenuLeft = 0;
			mgenMenus_subMenu.top = subMenuTop;
			mgenMenus_subMenu.left = subMenuLeft;
		};
		
		/**
		* Calculates optional parameters to the basic position coordinates 
		* to get the final menu position.
		* The calculations are affected upon the .style cluster properties 
		* of the elements object. All values to take affected on the DOM 
		* elements were prior collected there.
		* 
		* Later only the properties collected in the style cluster 
		* are affected on the DOM elements.
		*
		* @param obj object
		* @param domObj object
		* @return void
		*/
		this.eval_menuPosition = function (obj) {
			var disTop = 0;
			var disLeft = 0;
			var positioning = enugene.menus.menutypes[obj.moduleId].positMode;
			if (obj.type == 'sub') this.setSubMenuPosition( obj.id, obj.parentItemId);
			if (obj) {
				if (parseInt(obj.disleft)) disLeft = obj.disleft;
				if (parseInt(obj.distop)) disTop = obj.distop;
				switch (positioning) {
				case 'preset' :
					if (obj.top == '0' || parseInt(obj.top)) 
						obj.style.top = obj.top + disTop;
					if (obj.left == '0' || parseInt(obj.left))
						obj.style.left = obj.left + disLeft;
					break;
				case 'horizontal' :
					if (parseInt(obj.left) || obj.left =='0') {
						obj.style.left = obj.left + disLeft;
					}
					if (obj.top == '0' || parseInt(obj.top)) 
						obj.style.top = obj.top + disTop;
					break;
				case 'vertical' :
					if (obj.left == '0' || parseInt(obj.left))
						obj.style.left = obj.left + disLeft;
					if (parseInt(obj.top) || obj.top =='0') {
						obj.style.top = obj.top + disTop;
					}
					break;
				default: //dynamic mode is default
					if (parseInt(obj.left) || obj.left =='0') {
						obj.style.left = obj.left + disLeft;
					}
					if (parseInt(obj.top) || obj.top =='0') {
						obj.style.top = obj.top + disTop;
					}
				}
			}
		};
		
		/**
		* Affect the menus.elements.style collected sizes on the
		* DOM elements.
		* Don't force a value here: if no JS size is set, the css will do!
		* So if the JS value is empty here leave it empty. Else all css 
		* settings or the native DOM HTML order will be overridden.
		*
		* The sizes feeded here are mainly the result of the 'obj' type style 
		* recordsets.
		*/
		this.set_menuSize = function (menuObjRef, domObject) {
			var unit = 'px';
			var menuWidth = menuObjRef.style.width;
			var menuHeight = menuObjRef.style.height;
		
			if (menuWidth == '0') {
				domObject.style.width = '0px';
			} else {
				if (menuWidth) {
					if (parseInt( menuWidth ))
						domObject.style.width = menuWidth + unit;
					if (menuWidth == 'auto')
						domObject.style.width = menuWidth;
				}
			}
			
			if (menuHeight == '0') {
				domObject.style.height = '0px';
			} else {
				if (menuHeight) {
					if (parseInt( menuHeight ))
						domObject.style.height = menuHeight + unit;
					if (menuObjRef.style.height == 'auto')
						domObject.style.height = menuHeight;
				}
			}
		};
		
		/**
		* Affect the menus.elements.style collected position on the
		* DOM elements.
		* The position values realized here are the 'obj' recordset controlled 
		* ones, or they were set by 'setSubMenuPosition()'.
		* If left out the css controlled position or the native HTML order is taken. 
		*
		* Forcing a value here affects the menu to be positioned anycase to this value.
		*/
		this.set_menuPosition = function (menuObjRef, domObject) {
			var unit = 'px';
			var menuTop = menuObjRef.style.top;
			var menuLeft = menuObjRef.style.left;

			if (menuTop == '0') {
				domObject.style.top = '0px';
			} else {
				// empty? - do nothing.
				if (menuTop) {
					if (parseInt( menuTop ))
						domObject.style.top = menuTop + unit;
					if (menuObjRef.style.top == 'auto')
						domObject.style.top = menuTop;
				}
			}
			if (menuLeft == '0') {
				domObject.style.left = '0px';
			} else {
				if (menuLeft) {
					if (parseInt( menuLeft ))
						domObject.style.left = menuLeft + unit;
					if (menuObjRef.style.left == 'auto')
						domObject.style.left = menuLeft;
				}
			}
		};

		/**
		* @param array arrMenus		array with references to the menu objects in enugene.menus.elements
		* @return void
		*/
		this.set_menu = function (menuObjRef) {
			var domObject = '';
			var x = '';
			var prop = '';
			var unit = 'px';
			var menuWidth = '';
			var mWunit = '';
			var jsVars = '';
			var maxMenuWidth = parseInt( enugene.themes[menuObjRef.theme].maxMenuWidth );
			var setImportant = enugene.themes[menuObjRef.theme].setImportant;
			
			if (!enugene.menus.elements[menuObjRef.id]) return;
			
			domObject = menuObjRef.domObject;
			
			if (menuObjRef.style.className) domObject.className = menuObjRef.style.className;
			
			this.eval_menuPosition( menuObjRef);
			this.eval_menuSize( menuObjRef, maxMenuWidth);
			
			// restrict to maxMenuWidth setting if the offsetWidth is greater
			// in such case try to calc any item margin or menu padding away
			var menuObjW = enugene.DOM.util.getWidth( menuObjRef.domObject );
			if (maxMenuWidth && (!menuObjRef.style.width || menuObjW > maxMenuWidth)) {
				if (menuObjW > maxMenuWidth) menuObjRef.style.width = Math.abs( maxMenuWidth - (menuObjW - maxMenuWidth) );
			}

			// set obj related background image
			if (menuObjRef.backgroundImage) {
				var img = 'url(' + menuObjRef.backgroundImage + ')';
				enugene.DOM.util.set_Property( domObject, "background-image", img, setImportant );
			}
			
			// set the menu item visibility
			var argument = enugene.menus.elements[menuObjRef.id].hideMenuItems;
			if (argument) {
				enugene.menus.perform.hide.items.set_transparent( menuObjRef.items, argument );
			}
			
			this.set_menuSize( menuObjRef, domObject);
			this.set_menuPosition( menuObjRef, domObject);
			
		}; // menu
		
		/**
		* @param obj   enugene.menus.elements
		* @return boolean
		*/
		this.setDOMProperties = function (obj) {
			var x = '';
			var menuObjRef = '';
			var arrMenus = new Array( );
			var i = 0;
			for (x in obj) {
				menuObjRef = obj[x];
				if (!menuObjRef || !menuObjRef.domObject.id) {
					continue;
				}
				if (menuObjRef.objtype == 'menuItem') {
					this.set_item( enugene.menus.elements[x] );
					menuObjRef.style = new Object();
				}
				if (menuObjRef.objtype == 'menu') {
					arrMenus[i] = menuObjRef;
					++i;
				}
			}
			for(i = 0; i < arrMenus.length; ++i) {
				this.set_menu(arrMenus[i]);
				if (arrMenus[i].visibility) {
					arrMenus[i].domObject.style.visibility = arrMenus[i].visibility;
				}
				arrMenus[i].style = new Object();
			}
			arrMenus = null;
			enugene.menus.updateList = new Object( );
			return true;
		}; // clsEnugeneMenuProperties
	}
} // clsEnugeneKernel


