/*
 * n2menu 0.10 - Copyright (c) 2007 Cristian Libardo
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * Usage example:
 *
 *	<script type="text/javascript" src="/Js/jquery-1.2.1.pack.js"></script>
 *	<script type="text/javascript" src="/Js/n2menu.js"></script>
 * 	<script type="text/javascript">
 *		$(document).ready(function(){
 *			$("#myMenuRootId").n2menu();
 *		});
 *	</script>
 *
 *	<!-- the unordered list defines the menu structure -->
 *	
 *	<ul id='myMenuRootId'>
 *		<li>
 *			<a href="#">just a link</>
 *			<ul>
 *				<!-- this is a submenu, when expanded it's moved below the topmost ul -->
 *				<li>...</li>
 *			</ul>
 *		</li>
 *		<li><a href="#">just another link</></li>
 *	</ul>
 *
 *	<!-- expanded submenues are moved here -->
 *	
 */

(function($){
    $.fn.n2menu = function(options) {
        for(var i=0; i<this.length; ++i){
            var menuRoot = this.get(i);

            // defaults
            menuRoot.n2m = {
                delay: 0,
                container: null,
                current: null,
                expandTo: ".current"
            };
            if(options) {
                $.extend(menuRoot.n2m, options);
            }
            if(!menuRoot.n2m.container)
                menuRoot.n2m.container = $(menuRoot).wrap("<div class='n2menu'></div>").parent().get(0);


            var initBranchRecursive = function(el, trail){
	            el.container = menuRoot.n2m.container;
	            var q = $(el);
	            if(q.is("ul")){
		            trail.push(el);
		            el.level = trail.length;
		            el.excludes = trail.slice();
		            q.addClass("level" + el.level);
		            initExpansion(q);
	            }
	            q.children().each( function(){
		            initBranchRecursive(this, trail);
	            });
	            if(q.is("ul"))
		            trail.pop();
	            if(q.is(menuRoot.n2m.expandTo))
		            menuRoot.n2m.current = q.get(0);
            }


            var initExpansion = function(ulQ){
	            var liQ = ulQ.parent();
	            if(!liQ.is(".n2menu"))
	            {
		            var li = liQ.get(0);
		            var ul = ulQ.get(0);
		            li.opens = ul;
		            ul.opener = li;
		            liQ.addClass("expandable").hover(onMouseOver, onMouseOut);
			    liQ.addClass("expandable").focus(onFocus, onBlur);
	            }
            }
            
            
            var onMouseOver = function(){
	            var li = this;
	            var q = $(li);
	            q.addClass("hover");
	            if(menuRoot.n2m.delay > 0) {
		            setTimeout(function(){
			            if(q.is(".hover")){
				            removePreviouslyExpanded(q);
				            expand(q);
			            }
		            }, menuRoot.n2m.delay);
	            }
	            else {
		            removePreviouslyExpanded(q);
		            expand(q);
	            }
            }
            	    
            	    
            var onMouseOut = function(){
	            $(this).removeClass("hover");
            }


	    var onFocus = function(){
	            var li = this;
	            var q = $(li);
	            q.addClass("focus");
	            if(menuRoot.n2m.delay > 0) {
		            setTimeout(function(){
			            if(q.is(".focus")){
				            removePreviouslyExpanded(q);
				            expand(q);
			            }
		            }, menuRoot.n2m.delay);
	            }
	            else {
		            removePreviouslyExpanded(q);
		            expand(q);
	            }
            }
            	    
            	    
            var onBlur = function(){
	            $(this).removeClass("focus");
            }


            var expand = function(q){
	            var li = q.get(0);
	            if(li.opens){
		            $(li.opens).remove().appendTo(li.container).addClass("subMenu");
		            q.addClass("expanded");
	            }
            }


            var removePreviouslyExpanded = function(q){
	            var li = q.get(0);
	            $(li.container).children(".subMenu").not(li.opens.excludes).each(function(){
		            var ul = this;
		            $(ul).removeClass("subMenu").remove().appendTo(ul.opener);
		            $(ul.opener).removeClass("expanded");
	            });
            }
            
            
            var expandToCurrentRecursive = function(q){
	            if(q.is(".n2menu"))
		            return;
	            else if (q.is("ul")) {
		            expandToCurrentRecursive(q.parent());
	            } else if (q.is("li")) {
		            expandToCurrentRecursive(q.parent());
		            expand(q);
		            q.addClass("trail");
	            } else
		            return;
            }


            var init = function(menuContainer){
	            $(menuContainer).each(function(){
		            var excludes = new Array();
    		        
		            initBranchRecursive(menuContainer, excludes);
    		        
		            if(menuRoot.n2m.expandTo != null)
			            expandToCurrentRecursive($(menuRoot.n2m.expandTo));
	            });
	            $(menuContainer).addClass("initialized");
            }

	        init(menuRoot.n2m.container);
        }
    };
})(jQuery);
