0

I can not make this piece of code work:

$("a.expand_all").on("click",function(){
    $(this).text('Hide');
    $('.answer').each(function () {
        $(this).slideDown(150, function () {
            $(this).show();
        });
    });
}, function () {
    $(this).text('Expand');
    $('.answer').each(function () {
        $(this).slideUp(150, function () {
            $(this).hide();
        });
    });
});

I'm trying to collapse expend multiple divs, but nothing happens on click event. I 'm using latest jQuery 1.10.1

6
  • do you have a dom ready handler ? $(document).ready(function(){ }) around the jquery code ? Commented Oct 18, 2013 at 21:26
  • Are any of your elements (like a.expand_all) added dynamically by jQuery? Commented Oct 18, 2013 at 21:27
  • @EthanBrown How does that matter ? OP has used delegation correctly. Commented Oct 18, 2013 at 21:28
  • I may be mistaken, but it may not work because you are calling both halves of the click event at the same time? Commented Oct 18, 2013 at 21:39
  • Actually, no they aren't. jsfiddle to demonstrate: jsfiddle.net/Jammerwoch/sRnkw/1 Commented Oct 18, 2013 at 21:39

2 Answers 2

1

It looks to me like you're using jQuery's .on method incorrectly. That method has some overloads, but none of them (sensibly) takes two functions.

If I understand what you're trying to do correctly, you just want to toggle some answer elements when a <a> tag is clicked. What you really need to do is have some way of determining if your answers are expanded or not. There are multiple ways to do that, but I've chosen to use a data element:

<a class="expand_all" href="#" data-collapsed="true">expand</a>
<p class="answer">I'm an answer!</a>
<p class="answer">Another answer</a>

Then your JavaScript can be simplified thusly:

$('a.expand_all').on("click",function(){
    if( $(this).data('collapsed') ) {
        $(this).text('hide').data('collapsed','');
        $('.answer').slideDown(150);
    } else {
        $(this).text('expand').data('collapsed','true');
        $('.answer').slideUp(150);
    }
});

I simplified some of your constructs as well. In particular, in your code:

$('.answer').each(function () {
    $(this).slideDown(150, function () {
        $(this).show();
    });
});

The .each is unnecessary. Just applying a jQuery method is essentially equivalent to calling .each. You rarely need to use .each. So that simplifies to this:

$('.answer').slideDown(150, function () {
    $(this).show();
});

Then, .slideDown shows the element before it starts, so there's no need to call .show a second time. So we can get rid of the callback, simplifying all of this to:

$('.answer').slideDown(150);

You can see all of this in action here:

http://jsfiddle.net/Jammerwoch/sRnkw/5/

Lastly, the reason I asked whether any of your elements are dynamically added is because if they are, the way you are attaching them won't work. That is, the jQuery selectors run once, and then don't get re-run when you add new elements. So you have to be more clever. That's described in the jsfiddle above. Let me know if you need more clarification on that point.

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

Comments

1

That doesn't look like valid event binding to me, having the two functions there.

HTML - I added a div wrapper for event delegation

<div class="expando_content">
<a class="expand_all" href="#">Expand</a>

    <p class="answer">I'm an answer!</a>
        <p class="answer">Another answer</a>
            <p>Dynamically added "expand more" goes below...it won't work :(</p>
            <div id="thing"></div>
        </p>
    </p>
</div>

JS - moved the toggling functionality inside one function.

$(".expando_content").on("click", ".expand_all", function () {

    if (!$('.answer').is(':visible')) {
        $(this).text('Hide');
        $('.answer').each(function () {
            $(this).slideDown(150, function () {
                $(this).show();
            });
        });
    } else {
        $(this).text('Expand');
        $('.answer').each(function () {
            $(this).slideUp(150, function () {
                $(this).hide();
            });
        });
    }
});

$('<a class="expand_all" href="#">expand more</a>').appendTo($('#thing'));

jsFiddle

1 Comment

Thank you, I have used both suggestions and came up with working solution: ' $("a.expand_all").on("click",function(){ if (!$('.answer').is(':visible')) { $(this).attr('data-hint','Hide All'); $('.answer').slideDown(150); } else { $(this).attr('data-hint','Expand All'); $('.answer').slideUp(150); } });'

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.