/*	EventCache Version 1.0
	Copyright 2005 Mark Wubben

	Provides a way for automagically removing events from nodes and thus preventing memory leakage.
	See <http://novemberborn.net/javascript/event-cache> for more information.
	
	This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
*/

/*	Implement array.push for browsers which don't support it natively.
	Please remove this if it's already in other code */
if(Array.prototype.push == null){
	Array.prototype.push = function(){
		for(var i = 0; i < arguments.length; i++){
			this[this.length] = arguments[i];
		};
		return this.length;
	};
};

/*	Event Cache uses an anonymous function to create a hidden scope chain.
	This is to prevent scoping issues. */

var EventCache = function(){
	var listEvents = [];
	
	return {
		listEvents : listEvents,
	
		add : function(node, sEventName, fHandler, bCapture){
			listEvents.push(arguments);
		},
	
		flush : function(){
			var i, item;
			for(i = listEvents.length - 1; i >= 0; i = i - 1){
				item = listEvents[i];
				
				if(item[0].removeEventListener){
					item[0].removeEventListener(item[1], item[2], item[3]);
				};
				
				/* From this point on we need the event names to be prefixed with 'on" */
				if(item[1].substring(0, 2) != "on"){
					item[1] = "on" + item[1];
				};
				
				if(item[0].detachEvent){
					item[0].detachEvent(item[1], item[2]);
				};
				
				item[0][item[1]] = null;
			};
		}
	};
}();
/* End EventCache */

/*
function addEvent(elm, evType, fn, useCapture) {
    // cross-browser event handling for IE5+, NS6 and Mozilla
    // By Scott Andrew
    if (elm.addEventListener) {
      elm.addEventListener(evType, fn, useCapture);
      return true;
    } else if (elm.attachEvent) {
      var r = elm.attachEvent('on' + evType, fn);
      return r;
    } else {
      elm['on' + evType] = fn;
    }
}
*/

// Marlon's combination of Scott and Simon's work
function addEvent(elem, evType, func, useCapture)
{
  if( elem.addEventListener )
  {
  	// Marlon: the W3C DOM approach
    // window.alert("W3C approach");  	
    elem.addEventListener(evType, func, useCapture);
    return true;
  }
  else if( elem.attachEvent )
  {
    // Marlon: the IE DOM approach
    // window.alert("IE approach");  	
    var r = elem.attachEvent("on" + evType, func);
    return r;
  }
  else
  {
    // Marlon: Simon's approach
    // window.alert("Simon's approach");
    var onEvt = "on" + evType;
    var elOldEvFuncs = elem;

    if( (typeof elem[onEvt]) != 'function' )
    {
      elem[onEvt] = func;
    }
    else
    {
      elem[onEvt] = function()
      {
        elOldEvFuncs();
        func();
      }
    }
  }
}

/** Erik Nielsen
 * 
 * DHTML javascript menu
 * Adapted from Modern Web Design ISBN: 0-9579218-9-6
 *
 * usage: 
 * In the html page the menu is layed out as (nested) unordered list(s)
 * i.e: <ul><li>option 1</li><li>option 2<ul><li>suboption2.1</li></ul></li></ul>
 * This can then be styled with css.
 * The outermost ul needs an id (i.e: myID). 
 * The menu can be initialized by the following code:
 * 				dynMenu('myID', 300);
 * This code can be placed in the load event of the window. 
 * It is possible to create more then one menu on a page, each with it's own id. 
 * The number 300 is the amount of milliseconds the menu stays open after the mouse
 * leaves the menu item. Since this is used to cancel superfluous mouseout events it's 
 * better not to set it to zero.
*/
dynMenu = function () {
	function mout(el){ 
	  for (var i = 0; i < el.childNodes.length; i++) {
	    var node = el.childNodes[i];
	    if (node.nodeName.toLowerCase() == 'ul') {
	      node.style.display = 'none';
	    }
	  }
	};

	function mover(e, targetElement) {
	  var el = window.event ? targetElement : e ? e.currentTarget : null;
	  if (!el) return;
	  clearTimeout(el.outTimeout);
	  for (var i = 0; i < el.childNodes.length; i++) {
	    var node = el.childNodes[i];
	    if (node.nodeName.toLowerCase() == 'ul') {
	      node.style.display = 'block';
	    }
	  }
	};

  function menuInst(menuID, retentionTime){
    var retTime = retentionTime;
    var mainList = document.getElementById(menuID);
    var mainListItems = mainList.getElementsByTagName('li');
    for(var i=0; i<mainListItems.length; i++){
      listItem = mainListItems[i];
      if(listItem.getElementsByTagName('ul').length > 0){
        
 			  for (var j = 0; j < listItem.childNodes.length; j++) {
			    var node = listItem.childNodes[j];
			    if (node.nodeName.toLowerCase() == 'ul') {
			      node.style.display = 'none';
			    }
			  }
			  
        var fn = getMoverFor(listItem);
        addEvent(listItem, 'mouseover', fn, false);
        if (EventCache) EventCache.add(listItem, 'mouseover', fn);
        fn = getMoutFor(listItem);
        addEvent(listItem, 'mouseout', fn, false);
        if (EventCache) EventCache.add(listItem, 'mouseout', fn);
      }
    }

		function getMoverFor(node){
		  return function(e) {mover(e, node); };
		};
	
		function getMoutFor(node){
		  return function(e) {callMout(e, node);};
		};
	
		function callMout(e, targetElement) {
		  var el = window.event ? targetElement : e ? e.currentTarget : null;
		  if (!el) return;
		  el.outTimeout = setTimeout(function() {mout(el);}, retTime);
		};
  };
  return menuInst;
}();

function setMenus(){
  new dynMenu('menuToTest', 120);
};

addEvent(window, 'load', setMenus, false);
addEvent(window, 'unload', EventCache.flush, false);

