Grow your CSS skills. Land your dream job.

A beginner question in jquery.

  • # February 21, 2013 at 2:04 pm

    Hi,
    I m creating a dropdown menu with jquery which is working fine on two clicks however if you click on the link the third time if slides up and down itself. Can you tell me what mistake I m making and how to fix this. I dont want to add any more classes or ids in the markup. I m new to jquery so an explanation would be very helpfull.
    here is the code..

    < !DOCTYPE>




    # February 21, 2013 at 2:17 pm

    http://codepen.io/jshjohnson/pen/vetwc – Made a codepen for you

    # February 21, 2013 at 2:41 pm

    Try this:

    $(‘.sidebar li ul’).hide();

    $(‘.sidebar li’).click(function(){
    var $this = $(this);
    if (!$($this).hasClass(‘active’)) {
    $($this).addClass(‘active’);
    $(‘.active ul’).slideDown(700);
    } else {
    $(‘.active ul’).slideUp(700);
    $($this).removeClass(‘active’);
    }
    });

    CodePen: http://codepen.io/JoshBlackwood/pen/AFftr (sorry about the styles — I got bored and carried away . . . :-P )

    # February 21, 2013 at 2:50 pm

    Thanks jshjohnson for writing the codepen and thanks a lot JoshBlackwood , but since I m learning jquery , if you could please explain a little(in my script) WHY when you click on the link third time it slides up and down itself , would very helpfull for me to understand.

    # February 21, 2013 at 3:24 pm

    Ah, of course! Haha, I’m so used to just answering questions with a solution . . . not really used to the thread creator actually wanting to understand the problem! Let me see . . .

    It has to do with the construction of your code:

    $(‘.sidebar li’).click(function(){
    $(this).addClass(‘active’);
    $(‘.active ul’).slideDown(700);

    $(‘.active’).click(function(){
    $(‘.active ul’).slideUp(700);
    $(‘.active’).removeClass(‘active’);
    });
    });

    Here you have a event handler within another event handler. Basically, this tells the browser to fire **both** events when the item is clicked, one after the other, as there is no proper separation.

    You might put the second event handler in its own block, like so:

    $(‘.sidebar li’).click(function(){
    $(this).addClass(‘active’);
    $(‘.active ul’).slideDown(700);
    });

    $(‘.active’).click(function(){
    $(‘.active ul’).slideUp(700);
    $(‘.active’).removeClass(‘active’);
    });

    However, this still doesn’t work quite as expected — you’ll notice that the second event handler then doesn’t work at all. This is because the same item now has two event handlers on it — the second never has a chance to fire, I think. Someone more experienced might be able to explain it better.

    This is where “if“ statements within a click handler really come in handy:

    $(‘.sidebar li’).click(function(){
    var $this = $(this); // First, I set $(this) as a variable, so the browser only looks it up once, as we’ll be using it multiple times.
    if (!$($this).hasClass(‘active’)) { // Next, I check to make sure that this does NOT (note the ‘!’) have a class of ‘active’
    $($this).addClass(‘active’); // Since it doesn’t, let’s give it that class
    $(‘.active ul’).slideDown(700); // Now that it has the class, we can target that to slide the ul down
    } else { // If it DOES have the active class
    $(‘.active ul’).slideUp(700); // We slide it up
    $($this).removeClass(‘active’); // And remove the class
    }
    });

    Read the comments for an explanation of each line. The way this is set up, once the click handler is fired, the first thing it does is check if the item clicked is active. As long as it’s not, it shows the “ul“, then sets the clicked item as active. If it’s already active, it hides the “ul“ and resets the active class.

    Here’s an even more optimized version, which will prevent multiple items from having an active class, and only show one “ul“ expanded at a time:

    $(‘.sidebar li’).click(function(){
    var $this = $(this);
    if (!$($this).hasClass(‘active’)) {
    $($this).addClass(‘active’);
    $(‘.active ul’).slideDown(700);
    if ($($this).siblings(‘.active’)) { // New stuff! This checks to see if this item has any siblings that are active
    $(‘.active’).not($this).children(‘ul’).slideUp(700); // Then hides any child ul that isn’t a direct child of this item
    $(‘.active’).not($this).removeClass(‘active’); // And removes the active class on that (now hidden) element
    }
    } else {
    $(‘.active ul’).slideUp(700);
    $($this).removeClass(‘active’);
    }
    });

    Here’s a CodePen to demonstrate: http://codepen.io/JoshBlackwood/pen/CdvjJ

    I hope this helps you understand it better!

    # February 21, 2013 at 9:57 pm

    You are awesome Josh , you explained that really well, now I have a better understading of it, all thanks to you. And I have one more question in javascipt but I’ll create a new thread for it.

    # February 22, 2013 at 11:09 am

    Aw, shucks. I’m just glad to help!

Viewing 7 posts - 1 through 7 (of 7 total)

You must be logged in to reply to this topic.

*May or may not contain any actual "CSS" or "Tricks".