(function() {
	var _activeMenu  = null;
	
	document.onclick = function(e) {
		if(!_activeMenu) return;
		
		if (!e) var e = window.event;
		var target = (e.target) ? e.target : e.srcElement;

		if(target.className != multilevelmenu.settings.menuClass &&
			target.className != multilevelmenu.settings.upButtonClass &&
			target.className != multilevelmenu.settings.downButtonClass) {
			_activeMenu.hide();
			_activeMenu = null;
		}
	};
	
	multilevelmenu = function(classname, options) {
		multilevelmenu.settings = multilevelmenu.defaults;
		for(var o in options) {
			multilevelmenu.settings[o] = options[o];
		}
		
		var tabs = getElementsByClass(classname);
	
		for(var i = 0; i < tabs.length; i++) {
			new multilevelmenu.menu(tabs[i], null);
		}
	};
	
	multilevelmenu.defaults = {
		menuClass           : 'menu_container',
		parentChoiceClass	: 'parentoption',
		upButtonClass       : 'upbutton',
		downButtonClass     : 'downbutton',
		maxOptions          : 20,
		hoverTimeout        : 250,
		scrollSpeed         : 2,
		scrollTimeout       : 80,
		submenuIndent		: '50px',
		debugMode			: 1
	};
	
	multilevelmenu.static_id = 0;
	
	multilevelmenu.menu = function(a, parent) {
		var _this			= this;
		var _anchor			= a;
		var _container		= null;
		var _parent			= parent || null;
		var _activeChild	= null;
		var _count			= 0;
		var _timeoutId		= 0;
		var _scrollIndex	= 0;
		var _scrollEnd		= 0;
		var _choices		= null;
		var _id				= null;
		
		this.getId = function() {
			return _id;
		};
		
		this.hide = function() {
			if(_activeChild) {
				_activeChild.hide();
				_activeChild = null;
			}
	
			if(_container) {
				_container.style.display = 'none';
			}
		};
	
		this.show = function() {
			if(_container) {
				_container.style.display = 'block';
			}
		};
	
		this.scrollDown = function(timeout) {
			if(_scrollEnd < _count - 1) {
				var adjust = (_scrollEnd + multilevelmenu.settings.scrollSpeed > _count - 1)? _count - _scrollEnd - 1 : multilevelmenu.settings.scrollSpeed;
				_scrollIndex += adjust;
	
				for(var i = _scrollIndex - adjust; i < _scrollIndex; i++) {
					_choices[i].style.display = 'none';
				}
	
				for(var i = _scrollEnd + 1; i <= _scrollEnd + adjust; i++) {
					_choices[i].style.display = 'block';
				}
	
				_scrollEnd += adjust;
	
				var newTimeout = (timeout - 1 < 10)? 10 : timeout - 1;
				_timeoutId = setTimeout(function() {
					_this.scrollDown(newTimeout);
				}, timeout);
			}
		};
	
		this.skipToBottom = function() {
			_scrollEnd = _count - 1;
			_scrollIndex = (_count - multilevelmenu.settings.maxOptions < 0)? 0 : _count - multilevelmenu.settings.maxOptions;
			this.adjustViewable();
		}
	
		this.scrollUp = function(timeout) {
			if(_scrollIndex > 0) {
				var adjust = (_scrollIndex - multilevelmenu.settings.scrollSpeed < 0)? 0 - _scrollIndex : 0 - multilevelmenu.settings.scrollSpeed;
				_scrollEnd += adjust;
	
				for(var i = _scrollEnd + 1; i <= _scrollEnd - adjust; i++) {
					_choices[i].style.display = 'none';
				}
	
				for(var i = _scrollIndex + adjust; i < _scrollIndex; i++) {
					_choices[i].style.display = 'block';
				}
	
				_scrollIndex += adjust;
	
				var newTimeout = (timeout - 1 < 10)? 10 : timeout - 1;
				_timeoutId = setTimeout(function() {
					_this.scrollUp(newTimeout);
				}, timeout);
			}
		};
	
		this.skipToTop = function() {
			_scrollIndex = 0;
			_scrollEnd = multilevelmenu.settings.maxOptions - 1;
			this.adjustViewable();
		}
	
		this.stopScroll = function() {
			clearTimeout(_timeoutId);
		};
	
		this.adjustViewable = function() {
			for(var i in _choices) {
				var choice = _choices[i];
	
				if(choice.getAttribute('name') == 'scroll') { continue; }
	
				if(i >= _scrollIndex && i <= _scrollEnd) {
					choice.style.display = 'block';
				}
				else {
					choice.style.display = 'none';
				}
			}
		};
		
		function _setupMenu() {
			var submenus = getChildrenElements(_anchor, 'ul');
	
			for(var i in submenus) {
				_container = submenus[i];
				_container.className = multilevelmenu.settings.menuClass;
	
				_choices = getChildrenElements(_container, 'li');
				_count = _choices.length;
	
				for(var j in _choices) {
					_setupMenuChoice(_choices[j]);
				}
			}
	
			if(!_container) { return; }
	
			if(!_parent) {
				_container.style.top = _anchor.offsetHeight - 1 + 'px',
				_container.style.left = '0';
				_container.style.borderTop = 'none';
			}
			else {
				_container.style.left = multilevelmenu.settings.submenuIndent;
			}
	
			if(_count > multilevelmenu.settings.maxOptions) {
				_scrollEnd = multilevelmenu.settings.maxOptions - 1;
				_this.adjustViewable();
	
				var downBtn = document.createElement('li');
				downBtn.setAttribute('name', 'scroll');
				downBtn.setAttribute('title', 'click to skip to bottom');
				downBtn.className = multilevelmenu.settings.downButtonClass;
	
				downBtn.onmouseover = function() {
					_this.scrollDown(multilevelmenu.settings.scrollTimeout);
				};	
				downBtn.onmouseout = function() {
					_this.stopScroll();
				};
				downBtn.onclick = function(e) {
					_this.skipToBottom();
					
					if (!e) var e = window.event;
					e.cancelBubble = true;
					if (e.stopPropagation) e.stopPropagation();
				};
	
				_container.appendChild(downBtn);
	
				var upBtn = document.createElement('li');
				upBtn.setAttribute('name', 'scroll');
				upBtn.setAttribute('title', 'click to skip to top');
				upBtn.className = multilevelmenu.settings.upButtonClass;
	
				upBtn.onmouseover = function() {
					_this.scrollUp(multilevelmenu.settings.scrollTimeout);
				};
				upBtn.onmouseout = function() {
					_this.stopScroll();
				};
				upBtn.onclick = function(e) {
					_this.skipToTop();
					
					if (!e) var e = window.event;
					e.cancelBubble = true;
					if (e.stopPropagation) e.stopPropagation();
				};
	
				_container.insertBefore(upBtn, _container.firstChild);
			}
		}
	
		function _setupMenuChoice(choice) {
			var _menus = new Array();
			var id = ++multilevelmenu.static_id;
	
			var childMenus = getChildrenElements(choice, 'ul');
			if(childMenus.length > 0 && _menus[id] == undefined) {
				choice.setAttribute('id', id);
				choice.className = multilevelmenu.settings.parentChoiceClass;
	
				_menus[id] = new multilevelmenu.menu(choice, _this);
			}
	
			var childLinks = getChildrenElements(choice, 'a');
			for(var i in childLinks) {
				choice.setAttribute('title', childLinks[i].innerHTML);
				if(childLinks[i].getAttribute('href')) {
					choice.onclick = function(e) {
						window.location = childLinks[i].getAttribute('href');
						
						if (!e) var e = window.event;
						e.cancelBubble = true;
						if (e.stopPropagation) e.stopPropagation();
	
						return false;
					};
	
					break;
				}
			}
	
			choice.onmouseover = function() {
				t = setTimeout(function() {
					if(_activeChild && _activeChild.getId() != id) {
						_activeChild.hide();
					}
	
					if(!_activeChild || _activeChild.getId() != id) {
						var oSubmenu = null;
						if(_menus[id] != undefined) {
							oSubmenu = _menus[id];
							oSubmenu.show();
						}
	
						_activeChild = oSubmenu;
					}
				}, multilevelmenu.settings.hoverTimeout);
			};
	
			choice.onmouseout = function() {
				clearTimeout(t);
			};
		}
		
		(function initialize() {
			_id = _anchor.getAttribute('id');
			_setupMenu();
	
			if(!_parent) {
				_anchor.onmouseover = function(){
					_timeoutId = setTimeout(function() {
						if(_activeMenu && _activeMenu != _this) {
							_activeMenu.hide();
						}
	
						_activeMenu = _this;
						_this.show();
					}, multilevelmenu.settings.hoverTimeout);
				};
	
				_anchor.onmouseout = function(){
					clearTimeout(_timeoutId);
				};
			}
		})();
	};
		
	function getChildrenElements(element, childTagName) {
		var children = new Array();
	
		if(element.childNodes) {
			for(var i = 0; i < element.childNodes.length; i++) {
				var child = element.childNodes[i];
				if(child.tagName && child.tagName.toLowerCase() == childTagName.toLowerCase()) {
					children.push(child);
				}
			}
		}
	
		return children;
	}
	
	function getElementsByClass(searchClass,node,tag) {
		var classElements = new Array();
	
		node = node || document;
		tag = tag || '*';
	
		var els = node.getElementsByTagName(tag);
		var elsLen = els.length;
		var pattern = new RegExp('(^|\\\\s)'+searchClass+'(\\\\s|$)');
	
		for (var i = 0; i < elsLen; i++) {
			if ( pattern.test(els[i].className) ) {
				classElements.push(els[i]);
			}
		}
	
		return classElements;
	}
})();

