/* 
 * MedidMenu : Drop Down menu
 * Requirements: prototype.js
 * Author: Frodo Larik <frodo@medid.eu>
 *
 */
var MedidMenu = Class.create();

MedidMenu.prototype = {
	initialize: function(menu_domid,show_effects) {
		if (!menu_domid) { menu_domid = 'medid_menu' }

      // fancy dandy menus?
      this.effects = ( show_effects ? true : false )

      // Track the currently active menu
	   this.currentMenu = null;
	
	   // Get al the first level <li> from the menu
	   var lis = $(menu_domid).getElementsByClassName('menubar')
	   
	   // Initialize all the submenus
	   for ( var i=0; i<lis.length;i++) {
		   var submenu   = lis[i].getElementsByTagName('ul').item(0)
		   var head_link = lis[i].getElementsByTagName('a').item(0)
		
		   // set the event handlers for the submenu
		   if ( submenu && head_link ) {
			   this.setMenuProps(submenu,head_link)
		   }
		   // if no submenu, make sure other submenus get hidden on hovering
		   else {
			   head_link.onmouseover = function() { mmenu.hide(); }
			}
		}
	},
	
	// show the submenu
	show: function(head_link) {
		var submenu = head_link.parentNode.getElementsByTagName('ul').item(0)
		this.effects ? 
		   new Effect.Appear(submenu,{ duration: 0.2 }) :
			submenu.setStyle({visibility: "visible"})
	   this.currentMenu = submenu;
	},
	
	// hide the submenu
	hide: function() {
	   if (this.currentMenu != null ) {
		   this.effects ? 
		      this.currentMenu.hide() :
		      this.currentMenu.setStyle({visibility: "hidden"})
	      this.currentMenu = null;
	   }
	},
	
	// Set style and events for the (sub)menu
	setMenuProps: function(submenu,head_link) {
		
		// position the menu
		submenu.setStyle({ 
			left:       this.findPosX(head_link) + "px",
			top:        this.findPosY(head_link) + parseInt(head_link.parentNode.getStyle('height')) + "px",
			display:    this.effects ? 'none' : 'block',
			visibility: this.effects ? 'visible' : 'hidden'
	   });
		
		// create the onmouseover function for the head_link
		head_link.onmouseover = function(e) {
			mmenu.hide()
			mmenu.show(this)
			return true
		}

		// create the onclick function for the head_link
		head_link.onclick = function(e) {
		if (mmenu.currentMenu == null) {
				mmenu.show(this)
			} else {
				mmenu.hide();
			}
			return true;
		}

		// hide the menu if we go out
		submenu.onmouseout = function(e) {
			if (!e) e = window.event;
			if (mmenu.checkMouseLeave(this,e)) {
				mmenu.hide();
			}
			return true
		}
	},
	
	// find x and y position in javascript: 
	// http://blog.firetree.net/2005/07/04/javascript-find-position/
	findPosX: function(obj){
		var curleft = 0;
		if (obj.offsetParent) {
			while (1) {
				curleft+=obj.offsetLeft;
				if (!obj.offsetParent) {
					break;
				}
				obj=obj.offsetParent;
			}
		} else if (obj.x) {
			curleft+=obj.x;
		}
		return curleft;
	},
	
	findPosY: function(obj) {
		var curtop = 0;
		if (obj.offsetParent) {
			while (1) {
				curtop+=obj.offsetTop;
				if (!obj.offsetParent) {
					break;
				}
				obj=obj.offsetParent;
			}
		} else if (obj.y) {
			curtop+=obj.y;
		}
		return curtop;
	},
	
	/* containsDOM, checkMouseEnter, checkMouseLeave:
	 * http://www.faqts.com/knowledge_base/view.phtml/aid/1606
    *
	 *	How can I distinguish onmouseover/out of child elements from those of the parent element (IE4 /NN6)?
	 *	Why does my layer's onmouseover/out fire when the mouse moves over a child element (IE4 /NN6)?
	 *	Why does my layer's onmouseover/out fire when the mouse moves over a child element (IE4 /NN6)?
	 */
	containsDOM: function(container, containee) {
	  var isParent = false;
	  do {
	    if ((isParent = container == containee))
	      break;
	    containee = containee.parentNode;
	  }
	  while (containee != null);
	  return isParent;
	},
	
	
	checkMouseEnter: function(element, e) {
		if (element.contains && e.fromElement ) {
			return !element.contains(e.fromElement);
		} else if (e.relatedTarget) {
			return !this.containsDOM(element, e.relatedTarget);
		}
	},
	
	checkMouseLeave: function(element, e) {
		if (element.contains && e.toElement) {
			return !element.contains(e.toElement);
		} else if (e.relatedTarget) {
			return !this.containsDOM(element, e.relatedTarget);
		}
	}
}
