/** * @author Sven Kutzner * @copyright 2010 Sven Kutzner * @license GNU Lesser General Public License */ function AdvancedPageMenu(menuId, activeMenuItem, style, direction, icons) { if(style != 'popup' && style != 'list') style = 'popup'; if(direction != 'down' && direction != 'up') direction = 'down'; this.activeMenuItem = activeMenuItem; this.icons = icons; this.style = style; this.direction = direction; this.menuId = menuId; this.menus = new Array(); this.menuItems = new Array(); /** * Returns the offset of an element. */ this.getOffset = function(element) { var offsetLeft = element.offsetLeft; var offsetTop = element.offsetTop; while ((element = element.offsetParent) != null) { offsetLeft += element.offsetLeft; offsetTop += element.offsetTop; } return {'left' : offsetLeft, 'top' : offsetTop}; } this.ucfirst = function(str) { return str.substr(0,1).toUpperCase() + str.substr(1,str.length); } this.positionPopupMenu = function(id) { // check if there is a submenu for the current menu if(!this.menus[id]) return; var menuItem = this.menuItems[id]; var target = document.getElementById('displayMenuItem-'+id); var offset = this.getOffset(target); var top = offset.top; var left = offset.left; // direction of the popup menu if(this.direction == 'up') { top -= this.menus[id].menu.offsetHeight; if(menuItem.parentId != 0) { left += target.offsetWidth; top += target.offsetHeight; } } else { // down is currently the default behaviour if(menuItem.parentId == 0) { top += target.offsetHeight; } else { left += target.offsetWidth; } } this.menus[id].menu.style.top = top+'px'; this.menus[id].menu.style.left = left+'px'; } this.nodeMouseOver = function(e, id) { this.positionPopupMenu(id); this.showMenu(id); } this.nodeMouseOut = function(e, id) { this.hideMenu(id); } this.menuMouseOver = function(e, id) { this.showMenu(id); } this.menuMouseOut = function(e, id) { this.hideMenu(id); } this.showMenu = function(id) { if(!this.menus[id]) return; var parentId = this.menuItems[id].parentId; this.menus[id].menu.style.visibility = ''; if(parentId != 0) { this.showMenu(parentId); } } this.hideMenu = function(id) { if(!this.menus[id]) return; var parentId = this.menuItems[id].parentId; this.menus[id].menu.style.visibility = 'hidden'; if(parentId != 0) { this.hideMenu(parentId); } } this.mouseOut = function(id) { this.hideMenu(menuId, id); } this.menuToggle = function(e, id) { // TODO: properly implement list style menu } this.openMenu = function(id) { // see menuToggle } this.closeMenu = function(id) { // see menuToggle } this.createMenu = function(id) { var menu = document.createElement('div'); var menuInner = document.createElement('div'); var menuList = document.createElement('ul'); menu.className = 'pageMenu advanced'+this.ucfirst(menuId); menu.style.zIndex = '50'; menu.style.position = 'absolute'; menu.style.visibility = 'hidden'; menu.style.top = '-1000px'; menu.style.left = '-1000px'; menuInner.className = 'pageMenuInner'; menu.appendChild(menuInner); menuInner.appendChild(menuList); document.body.appendChild(menu); Event.observe(menu, 'mouseover', this.menuMouseOver.bindAsEventListener(this, id)); Event.observe(menu, 'mouseout', this.menuMouseOut.bindAsEventListener(this, id)); var result = new Object(); result['menu'] = menu; result['menuInner'] = menuInner; result['list'] = menuList; result['open'] = false; return result; } this.createMenuItem = function(id) { var menuItem = this.menuItems[id]; // create list item var node = document.createElement('li'); node.id = 'displayMenuItem-'+id; node.className = menuItem.node.className; // add anchor var link = document.createElement('a'); link.href = menuItem.link; node.appendChild(link); // add icon if(menuItem.icon != null) { var icon = document.createElement('img'); icon.src = menuItem.icon; link.appendChild(icon); } // add title var title = document.createElement('span'); title.innerHTML = menuItem.title; link.appendChild(title); // bind events Event.observe(node, 'mouseover', this.nodeMouseOver.bindAsEventListener(this, id)); Event.observe(node, 'mouseout', this.nodeMouseOut.bindAsEventListener(this, id)); return node; } this.addMenu = function(parentId, node) { var id = node.id.replace(this.menuId+'Item-',''); if(this.style == 'popup') { // return if this is a first level item if(parentId == 0) return; if(!this.menus[parentId]) { this.menus[parentId] = this.createMenu(parentId); var parentNode = document.getElementById('displayMenuItem-'+parentId); if(!parentNode.className.include('withChildren')) { parentNode.className += ' withChildren'; // update the icon if(this.menuItems[parentId].parentId != 0) parentNode.getElementsByTagName('span')[0].style.backgroundImage = 'url("'+this.icons.arrow+'")'; } } if(node) { var newNode = this.createMenuItem(id); this.menus[parentId].list.appendChild(newNode); } } else if(this.style == 'list') { var actionButton = document.createElement('img'); actionButton.src = this.icons.plus; this.menuItems[id]['button'] = actionButton; Event.observe(actionButton, 'click', this.menuToggle.bindAsEventListener(this, id)); node.insertBefore(actionButton, document.getElementById(this.menuId+'Link-'+id)); } } this.addMenuItem = function(parentId, node) { var id = node.id.replace(this.menuId+'Item-',''); var icon = document.getElementById(this.menuId+'Icon-'+id); var title = document.getElementById(this.menuId+'Title-'+id); var link = document.getElementById(this.menuId+'Link-'+id); this.menuItems[id] = new Object(); this.menuItems[id]['id'] = id; this.menuItems[id]['parentId'] = parentId; this.menuItems[id]['icon'] = (icon != null) ? icon.src : null; this.menuItems[id]['title'] = (title != null) ? title.innerHTML : ""; this.menuItems[id]['link'] = (link != null) ? link.href : ""; this.menuItems[id]['node'] = node; if(parentId == 0 && this.style == 'popup') { // specifiy new node id node.id = 'displayMenuItem-'+id; // add events Event.observe(node, 'mouseover', this.nodeMouseOver.bindAsEventListener(this, id)); Event.observe(node, 'mouseout', this.nodeMouseOut.bindAsEventListener(this, id)); } else { this.addMenu(parentId, node); } this.parseMenuItems(id); } this.parseMenuItems = function(itemId) { var root = document.getElementById(this.menuId+'Items-'+itemId); if(root != null) { var childCount = root.childNodes.length; var childNode = null; for(var i=0; i < childCount; i++) { childNode = root.childNodes[i]; if(childNode.nodeName == 'LI') { this.addMenuItem(itemId, childNode); } } } } this.init = function() { this.parseMenuItems(0); if(this.stlye == 'list') this.openMenu(this.activeMenuItem); } }