2

I have a number of info panels sharing the same class which I wish to show/hide using the slideToggle function. The content of the panel is pulled in dynamically through json. so Ibelevide I must use the 'live' and not 'bind' function? The following code will toggle all the panels simultaneously. I wish only one panel to toggle at a time.

$('a.sc-info-toggle').live('click', function() {
    $('.sc-info').slideToggle();
    return false;
});

Many thanks

casperOne
  • 73,706
  • 19
  • 184
  • 253
James
  • 1,355
  • 3
  • 14
  • 38
  • 1
    So just update your last question... – Naftali Jan 03 '12 at 15:37
  • 4
    What does your HTML look like? – David Brainer Jan 03 '12 at 15:38
  • This is not the question I have answered. I see you changed your question after you solve your first issue. This is not the correct way to ask another question. I suggest revert this question to original version, accept one of your answer that solves your question and ask another question which refers this question. – Emre Erkan Jan 04 '12 at 12:20

10 Answers10

3

You don't have to use .each() because jQuery applies your function to matched elements by default and you have to put return false; where click event occures. So this might be what you're trying to do:

$('a.sc-info-toggle').live('click', function(event) {
  $('.sc-info').slideToggle();
  return false;
});
Emre Erkan
  • 8,433
  • 3
  • 48
  • 53
2

You are returning false from withing the .each() callback, not from within the .live() callback:

$('a.sc-info-toggle').each(function(){ 
    $(this).live('click', function(event) {
        $('.sc-info').slideToggle();
        return false;
    });         
});

According to the documentation, returning false from the .each() callback:

We can break the $.each() loop at a particular iteration by making the callback function return false. Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.

And returning false from the .live callback basically cancels the default action of the underlying event.

And by the way, .live() is now deprecated and you should use .on() (in jQuery 1.7+) and .delegate() in older versions.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
2

live is deprecated. You want to use on instead

 $(document).on('click', 'a.sc-info-toggle', function() {
    $('.sc-info').slideToggle();
    return false;
 });

You haven't stated what the relationship is between the anchor that was clicked, and the panel you want to slide. If the panel is right next to the anchor, this should work:

 $(document).on('click', 'a.sc-info-toggle', function() {
    $(this).next('.sc-info').slideToggle();
    return false;
 });

Ideally, try to identify some container—say, a div with id of foo—which will always contain all of these anchors, and select on that instead of document.

 $("#foo").on('click', 'a.sc-info-toggle', function() {
    $('.sc-info').slideToggle();
    return false;
 });

This will potentially be more efficient since you won't be listening to every single click that happens on your document, but just the ones that happen inside of foo.

Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • You'll also want to prevent default on the anchor click rather than return false. They'll both work, but one is a better practice than the other. – Greg Pettit Jan 03 '12 at 15:45
  • @GregPettit - are you sure? I thought returning false from a jQuery handler *was* the standard way to prevent default. – Adam Rackis Jan 03 '12 at 15:49
  • @AdamRackis I really should keep a couple of source links to back up my claims, so no I can't say I'm 100% sure. Certainly a lot of examples in the wild and on jQuery's own site have `return false`, but this is more out of habit than good practice. My understanding is that returning false will allow the event to bubble (before returning false at the end). Preventing default will stop the event from even bubbling, giving a performance benefit. Plus, I just find it more elegant: `event.preventDefault()` is certainly explicit. ;-) Just have to pass the event into the function. – Greg Pettit Jan 03 '12 at 16:29
  • @Greg - you've [got it backwards](http://css-tricks.com/return-false-and-prevent-default/) :) - return false does both, preventDefault only prevents the default action. (To stop bubbling without return false you'd also have to call `stopPropagation()` or set `cancelBubble = true` for IE) – Adam Rackis Jan 03 '12 at 16:35
  • @AdamRackis I like CSS-Tricks, but Chris Coyier is not a reliable authority on JS. And the article HE links to didn't help me much. ;-) But since I wasn't 100% sure to begin with and you've raised some doubts, I'll definitely do some more research before making the same recommendation. I can say for a certainty that I've seen articles recommending e.preventDefault() and have seen other SO users recommend it. But I can't say with honesty anymore that my confidence isn't shaken. ;-) – Greg Pettit Jan 03 '12 at 16:40
  • @Greg - well preventDefault is the standard way of preventing the default action. No question there. And it'll still work with jQuery—it's standard after all. But jQuery gives you the option of returning false to do *this*, and also prevent bubbling. Here's a link to a blog by T.J. Crowder, one of the top JS people on SO http://blog.niftysnippets.org/2011/11/story-on-return-false.html – Adam Rackis Jan 03 '12 at 16:44
  • @AdamRackis going to get my conversation warning... ;-) http://stackoverflow.com/questions/1357118/javascript-event-preventdefault-vs-return-false -- it only does both in jQuery. Also, if you use e.preventDefault() at the beginning of a function, you are guaranteeing prevention of the event regardless of errors in the handler. So there are reasons to prefer it (or not!), but I was wrong about the bubbling and performance gains. – Greg Pettit Jan 03 '12 at 16:46
  • @Greg - threads only get flagged after 20 comments, and this is at 8 and almost over since I essentially agree with you. If bubbling is not a concern (and it seldom is) and you're worried about errors in your handler, then preventDefault as the first line is probably a **good idea**. If you do care about bubbling, *and you're using jQuery*, then returning false is probably a good idea. Canceling bubbling in a cross browser way is a huge pain (stopPropagation doesn't work on old ie). The highly rated answer in that Q seems to agree with what I wrote above, doesn't it? – Adam Rackis Jan 03 '12 at 16:54
  • 1
    @AdamRackis Yup, it seems to. I have that pleasant feeling of having improved my knowledge... thanks for that! – Greg Pettit Jan 03 '12 at 16:57
1

Happy New year, Dude, why are you using each loop it's really not needed, make it simle as follow:

$('a.sc-info-toggle').live('click', function(event) {

// $(this) will return the link which is clicked

    $(this).find('.sc-info').slideToggle();
       return false;

  });
Mehul Hingu
  • 1,240
  • 1
  • 9
  • 12
  • Hi thanks, if I do as you say every panel with the class .sc-info toggles simultaneously. Any other thoughts? – James Jan 03 '12 at 15:27
0

the command return false; will only quit the .each loop. Also, inside the .live you slideToggle ALL of the .sc-info's on that page, instead of just the one that relates to the button you clicked on.

  $('a.sc-info-toggle').live('click', function(event) {
    $(**the.div.you.need**).slideToggle()
  });
Rodik
  • 4,054
  • 26
  • 49
0

live binds event handlers to elements matching a selector, whether they exist now or in the future. So using each here is kind of silly. This does the same:

$('a.sc-info-toggle').live('click', function(event) {
    $('.sc-info').slideToggle()
    return false;
});
Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
0

You dont need the each(), jQuery will handle that as the selector will return an array, also return false should be within the live() callback:

$('a.sc-info-toggle').live('click', function() {
    $('.sc-info').slideToggle();
    return false;
});         

However if you're using the latest version of jQuery (1.7+) use the .on() method. Else I'd recommend using .delegate() if possible as its more efficient. See https://stackoverflow.com/a/4579154/978306

Community
  • 1
  • 1
nav
  • 3,035
  • 1
  • 20
  • 24
0

Instead of:

$('.sc-info').slideToggle();

You need to target the .sc-info that is relative to the toggle.

For example if your html looked like this:

<a href="#" class="sc-info-toggle">Toggle</a>
<div class="sc-info">
    <p>Content</p>
</div>

You could use this:

$('a.sc-info-toggle').live('click', function() {
    $(this).next('.sc-info').slideToggle();
    return false;
 });

If the toggle is inside of the content then use .parent() instead of .next().

Hope that helps :)

will
  • 4,557
  • 6
  • 32
  • 33
  • thanks for your help. I tryed your suggestion but no joy. The html is
  • ​Info​​
  • ​....
  • – James Jan 03 '12 at 15:50
  • Try $(this).parent().next('.sc-info').slideToggle(); – ridecar2 Jan 03 '12 at 16:03
  • That did the trick. Thanks ridecar2 and everyone for their help. – James Jan 03 '12 at 16:10