Search code examples
jquerycssmenusubmenuabsolute

Push content from absolute menu with Jquery


Hi i need to make a menu with 3 levels.

When you hover the first level sub-menu is displaying under the 1 level inline-block. I will use later flex to make it responsive.

Then it will be the same with the third level.

This is how it is supposed to look like :

enter image description here

So now i'm almost good but i can figured out why my menu is bugging.

You can find the jsfiddle here :

https://jsfiddle.net/z1cepma4/

ANy idea how i can solve this problem?

Thanks in advance for your help


      var $level1 = $('#nav li');
		  var $level2 = $('#nav li ul');
		  var $level3 = $('#nav li ul li ul');
		  var $pagecontent = $('#fakecontent');
		  var hoverTimeout = '';
      var leaveTimeout = '';
    
    
    
		  $level1.mouseenter(function() {
		  	
		  
		  var $thislevel2 = $(this).children('ul').first();
		  	
		  	console.log('hover level 1 val : ' + $(this).text());
		  	
		  	
		  	clearTimeout(leaveTimeout);
	        // 1.
	        hoverTimeout = setTimeout(function() {
	          // 2. Another submenu open
	          if( $thislevel2.is(':visible') ) {
	          console.log('level 2 visible');
	            // if new hovered li has megamenu, hide old menu and show the new, otherwise slide everything back up
	            if( $thislevel2.length ) {
	              // stop any other hoverTimeouts triggered through guick back-and-forth hovering
	              clearTimeout(hoverTimeout); 
	              $thislevel2.filter(':visible').stop(true, true).hide();
	              $thislevel2.stop(true, true).show();
	              
	              console.log('level 2 - parti 1');
	            } else {
	              $thislevel2.filter(':visible').stop(true, true).slideUp(500);
	              $pagecontent.stop(true, true).animate({ paddingTop: '0'}, 500);
	                 console.log('level 2 - parti 2');
	            }
	          } else {
		          
	            console.log('level 2 not visible');
	            if( $thislevel2.length ) {
		          
		          
	              // stop any other hoverTimeouts triggered through guick back-and-forth hovering
	              clearTimeout(hoverTimeout); 
	              $thislevel2.stop(true, true).show();
	              
	           
	              /* 16.5em is the set height of the megamenu + negative margin of nav ul */
	              $pagecontent.stop(true, true).animate({ marginTop: '10em'}, 500);
	            }
	          }
	        }, 200);
    	}); //$level1 mouseenter
	      
	     $level1.mouseleave(function() {
	      clearTimeout(hoverTimeout);
	      leaveTimeout = setTimeout(function() {
	        if( $level2.is(':visible') ) {
	          $level2.filter(':visible').stop(true, true).slideUp(500);
	          $pagecontent.stop(true, true).animate({ marginTop: '0'}, 500);
	        }
	      }, 200);
	    });
   #fakeheader,
#fakecontent{
  width:100%;
   height:150px;
  background:red;
  position:relative
  }
#nav {position: relative;}
#nav li {
    list-style:none;
    float: left;
}
#nav li a {
    display: block;
    padding: 8px 12px;
    text-decoration: none;
}
#nav li a:hover {
  color:red;
	color:#FFF;
	opacity:1;
}

/* Targeting the first level menu */
#nav {  
   
    min-width:850px;
    background:#fff;
    display: block;
    height: 34px;
    z-index: 100;
    position: relative;
    left: 0;
    margin: 0;
    padding: 0;
    width:100%;
}
#nav > li > a {
  color:#000;
}


/* Targeting the second level menu */
#nav li ul {
    color: #333;
    display: none;
    position: absolute; 
    left: 0;
    margin: 0;
    padding: 0;
    width:100%;
}
#nav li ul li {
    display: inline;
}
#nav li ul li a {
    background: #fff;
    border: none;
    line-height: 34px;
    margin: 0;
    padding: 0 8px 0 10px;
}
#nav li ul li a:hover {
    color:red;
    opacity:1;
}

#nav li ul li:hover>a{color:red;}

/* Third level menu */
#nav li ul li ul{
    top: 0;
    left: 0;
    margin: 0;
    padding: 0;
    width:100%;
}
ul.child {
background-color:#FFF;  
}
/* A class of current will be added via jQuery */
#nav li.current > a {
    color:red;
    float:left;
}

/*
#nav li:hover > ul.child {
    left:0;
    top:34px;
    display:inline;
    position:absolute;
    text-align:left;
}
#nav li:hover > ul.grandchild  {
    display:block;
}*/
#nav > li:hover > a{color:red;}
#nav > li > a > li:hover > a{color:red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="fakeheader">Header
</div>
<div id="#menu-categories">

<ul id="nav">
    <li>
        <a href="#">Quoi manger/Ou dormir...</a>
        <ul class="child">
            <li><a href="#">Associations</a>
                <ul class="child">
                    <li><a href="#">Associations 3</a></li>
                    <li><a href="#">Associations 3</a></li>
                    <li><a href="#">Associations 3</a></li>
                </ul>
            </li>
            <li><a href="#">Autre</a>
                <ul class="child">
                    <li><a href="#">Autre 3</a></li>
                    <li><a href="#">Autre 3</a></li>
                    <li><a href="#">Autre 3</a></li>
                </ul>
            </li>
        </ul>
    </li>
    <li>
        <a href="#">Quoi faire...</a>
        <ul class="child">
            <li><a href="#">Associations</a>
                <ul class="child">
                    <li><a href="#">Culturelle</a></li>
                    <li><a href="#">Culturelle</a></li>
                    <li><a href="#">Culturelle</a></li>
                </ul>
            </li>
            <li><a href="#">Associations</a>
                <ul class="child">
                    <li><a href="#">Culturelle</a></li>
                    <li><a href="#">Culturelle</a></li>
                    <li><a href="#">Culturelle</a></li>
                </ul>
            </li>
        </ul>
    </li>
   
</ul>
</div>
<div id="fakecontent">
Content
</div>


Solution

  • Use a combination of toggle and animate:

    $('#nav').addClass('active');
    
    $('#nav li').hover(function() {
      $(this).find('> ul').toggleClass('active');
      var visible = $('#menu-categories').find('ul.active').length;
      $('#menu-categories').animate({
        'height': visible * 35
      }, {
        queue: false
      });
      $(this).find('> ul').slideToggle();
    
    })
    

    demo: https://jsfiddle.net/rw6L4nqq/1/