1

I'm rather new to jQuery and I'm trying to make a cool little menu effect where when the user hovers over a element (#nav li) it will animate to a larger width, which will reveal the full background image. Each of the menu items has a ID to explicitly set a width (since they are all different in size), so #nav1 might be 80px whereas #nav2 is 90px. So I found this: How to get all of the IDs with jQuery? and that helped me to create a array but now I'm having problem figuring out how to insert it into the animation. I figured I would need to do a each or for loop. But like I said I'm rather new to jQuery and am having some problems.

So basically I'd like the variable chgWidth to return the width() of the currently hovered #nav and then I would plug that variable into the animate except I would add 30px for instance, or on the hover off I would subtract 30px.

Any idea? Here is my current code...

$(function(){ 
var chgWidth = $("#nav [id]").map(function(id) {
       return this.id;
       });

       $.each(chgWidth,function(n,value){
        $('#nav li').hover(function() {
            $(this).stop(0,1).animate({"width" : chgWidth+"px" });
        },
        function(){
            $(this).stop(0,1).animate({ "width" : chgWidth+"px" });
        });

});

Sample HTML

<div id="menu">
    <ul id="nav">
        <li id="nav1"><a alt="" href="#">home</a></li>
        <li id="nav2"><a alt="" href="#">about us</a></li>
        <li id="nav3"><a alt="" href="#">weddings & events</a></li>
        <li id="nav4"><a alt="" href="#">gallery</a></li>
        <li id="nav5"><a alt="" href="#">accolades</a></li>
        <li id="nav6"><a alt="" href="#">blog</a></li>
        <li id="nav7"><a alt="" href="#">contact us</a></li>
    </ul>
</div>

Sample CSS:

#menu { width: 100%; overflow: hidden; padding:0px 0px; background: #ffc4a0;}
#nav { position: relative; left: 50%; float: left;}
#nav li { position: relative; right: 50%; float: left; padding: 0 5px; margin: 0 5px; overflow:hidden; }
#nav1 { width:55px; }
#nav2 { width:80px; }
#nav3 { width:175px; }
#nav4 { width:60px; }
#nav5 { width:85px; }
#nav6 { width:40px; }
#nav7 { width:100px; }
#nav li a { color: #ffffff; text-decoration: none; font: bold 16px Verdana, Arial, Helvetica, sans-serif; }

Based on the answer I got this is what I ended up doing and it seems to work good (Thanks to Joel and krdluzni):

$(function(){
    $("#nav [id]").each(function(){
        $(this).hover(function() {
            $(this).stop(0,1).animate({"width" : "+=30" });
        },
        function(){
            $(this).stop(0,1).animate({ "width" : "-=30" });
        });
    });
});
2
  • So you have something like this: #nav1 { width:90px: } ... <div id="nav1">...</div>. Could you give an example of the actual HTML (and/or CSS) code Commented Aug 31, 2009 at 20:47
  • yeah, I'll update it in a second. Commented Aug 31, 2009 at 21:12

3 Answers 3

1

jQuery as of a short while ago accepts a += like syntax for widths and other numeric values in animate. See the second last paragraph in the overview (and the examples as well) here: http://docs.jquery.com/Effects/animate#paramsdurationeasingcallback

Sign up to request clarification or add additional context in comments.

1 Comment

Wow, that is so simple it makes me feel stupid... ;) Thanks!
0

You don't actually need to get the ids in an array so much as you need to assign an animation to each element in nav that has an id.

Instead of mapping the ids to your chgWidth variable, use each to iterate over the collection of elements and set each one individually.

$(function(){ 
    $("#nav [id]").each(function(){
        $(this).hover(function() {
            $(this).stop(0,1).animate({"width" : this.id+"px" });
        },
        function(){
            $(this).stop(0,1).animate({ "width" : this.id+"px" });
        });
    });
});

When you use each to iterate over a collection of elements, the this context is set to the current iterating element.

4 Comments

Thanks for the quick response. Hmm, okay, I guess I could see not using an array, however, I still need to get the width that is set for that element (using width() I assume) and then add or subtract a set amount of pixels. And I'm not seeing a way to do that here. It doesn't seem like I can chain this.id.width() (maybe a stupid idea, IDK)...
I think Joel misunderstood when you wrote "Each of the menu items has a ID to explicitly set a width" - He took that to mean the ID of each element is the width of that element. Try $(this).width() to get the width of the current element in the each() function.
You should give krdluzni the "Accepted Answer". His is more useful than mine (plus pointing out a neat trick for jquery animations). I did misunderstand what you had written before, though I'm glad you were able to make use of what I wrote.
I'd vote for both if I could but as I can't I voted for yours and did a answer is helpful for his.
-1

No each function is required! If a selector returns multiple elements, all of the elements recieve the function chained to them.

This is almost right:

$("li #nav").hover(
    function()
    {
        $(this).stop(0,1).animate({"width" : this.width()+30 });
        //save original width somehow
    },
    function()
    {
        $(this).stop(0,1).animate({ "width" : this.width()-30 });
        //retrieve original width
    });
);

You just need to save the widths somehow. Perhaps they can be read from the CSS.

1 Comment

Yeah I did something like this originally, and it works great, until you interrupt the animate, because then it takes the current width, which isn't the original one anymore, and subtracts or adds the 30 pixels. So eventually if you hover on and off quickly enough everything will have a width of zero.. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.