tags:

views:

160

answers:

2

Hi folks

I'm just starting out with jQuery. I want to make a simple 'ul' dropdown menu to improve my understanding. The basic flow is this:

'ul.menu li ul' has display:none >> on hover of li, get & store height of 'this' ul >> set height of 'this' ul to 0 >> set display to block >> animate height to original stored height

I know there are already some great plugins for dropdowns, but I really want to roll my own to get a better understanding of jQuery.

So far I have managed the following, very badly done (see live version here - http://jsbin.com/eduvi):


var $j = jQuery.noConflict();
$j(document).ready(function(){

// Get height of current hidden ul

        $j("ul.menu li").hover(function() { 
          getHeight($j("ul", this).height()); 
        });
// Set height to 0px    

    $j('ul.menu li').hover(function() { 
    $j("ul", this).css({"height":"0px"});
});

// Set display to block 

    $j('ul.menu li').hover(function() { 
    $j("ul", this).css({"display":"block"});
});

// Animate height to stored height  

    $j('ul.menu li').hover(function getHeight(h) { 
    $j('ul:first', this).stop().animate({ "height" : "100%" } , 400 );
});

// Display height of current hidden ul

    function getHeight(h) {
      $j("div.test").text("The height for the hidden ul is " + h + "px."); }
  });


I'd like to know how do I get it to use the stored original height, in place of that 100%.

And secondly, I'm sure this can all be condensed down to just a few lines, but don't really have a clue how to do that yet.

Any help very much appreciated!

UPDATE: OK, so I'm ALMOST there. I used the code Marve posted as a base and worked in the other bits. The only thing that's not working is I need to reset the height of the hidden UL, at the end of everything, to it's original height, and set it's display to none, so it's ready to be hovered again. Any ideas why it won't work?


$j('ul.menu > li').hover(
    function() { var ulHeight = $j('ul', this).height(); $j(this).children('ul').css({height: 0}).stop().animate({height: ulHeight}, 400); },
    function() { $j(this).children('ul').stop().animate({height: 0}, 400).css({height: ulHeight, display:none});   }
);


+2  A: 

here's a simple css tip to help you:

use $('ul.menu > li') instead of just$('ul.menu li')

This will make the hover only target the menu under the list item you are hovering over.

codedude
+2  A: 

It's great that you're learning jQuery and using this problem to do it. Kudos for that!

I think you're over-engineering the solution to the problem. Take a look at two built-in jQuery functions that help remove some of the effort from the solution: slideDown and slideUp. You'll undoubtedly find many more helpful functions in the jQuery documentation. This snippet of code does much of what you posted already:

$j(document).ready(function() {
    $j('ul.menu > li').hover(
        function() { $j(this).children('ul').stop(true, true).slideDown(); },
        function() { $j(this).children('ul').stop(true, true).slideUp(); }
    );
});

The snippet doesn't handle the sub menus you have in your HTML sample, but given your desire to learn, it shouldn't be a stretch to implement it.

Also see the docs on stop.

Marve
Thanks, I actually started out with those, but the problem is that you can't use the stop function with them, so you get a problem if you do numerous rollovers, as the menu will count each one and execute it. So I decided to go for this route so I can use animate. Also, I'm planning on maybe making additional sub menus fly out horizontally, so again I'll need to use animate for that.
Sam
Agreed that you may have to use `.animate` for the sub menus, but I'm not sure I follow on why using the slide functions doesn't work at least for the top level. Note: I modified the selectors inside the hover functions for my code snippet to ensure only a direct descendant menu will be animated.
Marve
It's kinda the same thing mentioned here - http://jqueryfordesigners.com/broken-repeating-animations/ - if you repeatedly roll over the menu, then move away, it'll continue to fire.
Sam
Ahh, the solution to that lies in the parameters passed to `.stop`. Check out the updated snippet in my answer.
Marve
Great, I didn't realise you could pass parameters to stop, so that's a very useful thing to know, cheers.I still would like to know how to sort my original idea though, as I would like to use it as a framework for all my menus, and therefore might prefer to have the hidden UL coming into view some other way, so having it animate would be a big help with that, as I can simply change the animation parameters for different effects. I guess my main thing is to learn how to get something, store it, and recall it for use later, such as the hidden UL height I mentioned in my original code.
Sam