Writing multiple toggle links in JQuery

Saturday, October 18th, 2008

I was just working with this so thought I would write and quick a quick blog post about it. It was covered a bit on http://www.learningjquery.com/2006/09/slicker-show-and-hide but hidden in the comments so I though I would bring it out for all to see. Thanks to Scott for the original explanation.

 Most of you will know the basic JQuery function for toggling an item open or closed…

$(document).ready(function() {
$('[class^=toggle-item]').hide();
$('a.link').click(function() {
$('.toggle-item-').toggle();
});
});

Pretty straight forward stuff, once the page has loaded hide all elements on the page that have the class “toggle-item”, grab the link with class=”button” and use this to toggle the element with class=”toggle-item” open and closed, done deal. But what about if we want to do this for multiple items on the page and not call each item on its own and create a bunch of unnecessary code, we need a way to dynamically pick each element we want to show and hide.

One option is to use the JQuery ‘^’ selector, basically enabling us to pick any elements that begin with the class we choose e.g.

$('[class^=link]')

Would pick any elements on the page that begin with class=”link…”. Using this we can add out unique identifier to the element to signify it as being individual. So lets look at this a little deeper, say you have three elements on the page you want to show/hide, you’ll have three links to perform each action.

< a href="#" class="link1" >Link 1< / a >
< a href="#" class="link2" >Link 2< /a >
< a href="#" class="link3" >Link 3< /a >

Content
Content
Content

First thing we are going to do is hide all the elements on the page, using the JQuery selector above we close all the elements that begin with the class “toggle-item”

$(document).ready(function() {
$('[class^=toggle-item]').hide();
});

Next we tell the DOM which links perform the toggle action. Again using the JQuery selector we grab all the links on the page that begin with the class “link”. We then create a variable that wraps the link itself in an object and get the class of the particular link that was clicked.

$(document).ready(function() {
$('[class^=toggle-item]').hide();
$('[class^=link]').click(function() {
var $this = $(this);
var x = $this.attr("className");
});

Now we have this all we need to do is append of unique class identifier using the variable to the toggle item so its relates to the link that was clicked e.g.

$(document).ready(function() {
$('[class^=toggle-item]').hide();
$('[class^=link]').click(function() {
var $this = $(this);
var x = $this.attr("className");
$('.toggle-item-' + x).toggle();
return false;
});
});

And there you have it, you can now traverse the DOM and pick out all the toggles you need in one simple bit of Jquery.

26 Comments

  1. November 14th, 2008 at 9:27 am

    Hi!

    Very interesting post about JQuery!

  2. Robby

    February 1st, 2009 at 3:51 am

    Hi,
    I have implemented your code and it works fine but I cant get it to work with a checkbox :->

    Problem being that the jquery code negates the normal Tick in the checkbox . . seems to be using the checkbox as (a href) Any Clues Robby

  3. Stéphane

    March 9th, 2009 at 2:24 am

    Thanks a lot for that, it spared me hours of research.

    It’s a shame that jQuery lacks so much in documentation. You should write a book. :-)

  4. March 11th, 2009 at 3:35 am

    Nice. Thanks for a clean concise post on this! Like Stephane said…you spared me hours of research (and aggravation).

  5. KeepingYouAwake

    April 3rd, 2009 at 7:53 pm

    This is perfect! I wanted to change the text so that instead of saying “read more…” once expanded, it could say the more appropriate “close” or something, so I added a basic conditional:

    $(document).ready(function() {
    $(‘[class^=toggle-item]‘).hide();
    $(‘[class^=link]‘).click(function() {
    var $this = $(this);
    if($this.attr(“alt”)==”"){
    $this.html(‘Close’);
    $this.attr({alt: “toggled”});
    }
    else if ($this.attr(“alt”)==”toggled”){
    $this.html(‘Read more…’);
    $this.attr({alt: “”});
    };
    var x = $this.attr(“className”);
    $(‘.toggle-item-’ + x).toggle();
    return false;
    });
    });

  6. April 15th, 2009 at 1:49 pm

    Great stuff, it’s nice to see people expanding on this and making it readily available

  7. April 16th, 2009 at 2:29 pm

    Very Cool, and definitely useful. Cheers.

  8. May 15th, 2009 at 11:55 pm

    May I make things a bit more complicated? Suppose, I have the following:

    $(‘[class^=toggle-item-link4]‘).hide();

    $(‘[class^=toggle-item-link5]‘).hide();

    $(‘[class^=toggle-item-link6]‘).hide();

    $(‘[class^=toggle-item-link7]‘).hide();

    $(‘[class^=toggle-item-link8]‘).hide();

    $(‘[class^=toggle-item-link9]‘).hide();

    $(‘[class^=toggle-item-link10]‘).hide();

    $(‘[class^=link]‘).click(function() {
    var $this = $(this);
    var x = $this.attr(“className”);
    alert(x);
    $(‘.toggle-item-’ + x).toggle();
    return false;
    });

    I want
    Link 4
    to be visible if only link3 is clicked. It will work like an accordion basically. Any help?

  9. May 27th, 2009 at 5:34 pm

    I ended up writing some server side code to have a conditional loop. It works but I am not 100% there. So, I need to set

    $(‘[class^=toggle-item-link5]‘).val(”);

    the toggle-item-link5 comes from:

    var y = this.id.replace(‘addNew’, “”);

    how can I append toggle-item-link to y ?

  10. June 4th, 2009 at 5:28 pm

    So glad I found this post. Thank you very much for the clean code! It works great for my purposes.

  11. Marc
  12. July 17th, 2009 at 2:29 am

    How would you make only one div visible at a time?

  13. tribbun

    September 8th, 2009 at 6:43 pm

    thanks very much! appreciated!

  14. Krrrrnel

    October 21st, 2009 at 3:28 pm

    Brilliant! Thanks a lot.

  15. violet

    November 4th, 2009 at 1:28 am

    Ok, first of all, awesome post. Second, I need some help…

    I have 2 columns. On the left is where thumbnails will display, on the right are the links to show/hide div’s on the left.

    Ok, so you click on a link on the right, on the left a div appears. In the div are 4 thumb nails, you mouse over a thumbnail, and then a larger version appears.

    Ok, so I DO have this working, however, I am having to duplicate a LOT of code each time I want to show/hide the divs and each time I want to show/hide thumbnail images. I consolidated my hidden divs, but I can’t get the toggles to work doing something similar (as seen with multiple link tutorials).

    Here is my code:
    Javascript:

    $(document).ready(function() {
    $('[id^=pwnbox]').hide();
    $('[id^=big]').hide();

    $('#toggle1').click(function() {
    $('#pwnbox1').slideToggle(400);
    $('#pwnbox2').hide(300);
    return false;
    });

    $('#toggle2').click(function() {
    $('#pwnbox2').slideToggle(400);
    $('#pwnbox1').hide(300);
    return false;
    });

    $('#togglebig1').mouseover(function() {
    $('#big1').show(400);
    return false;
    }).mouseout(function() {
    $('#big1').hide(400);
    });
    $('#togglebig1-2').mouseover(function() {
    $('#big1-2').show(400);
    return false;
    }).mouseout(function() {
    $('#big1-2').hide(400);
    });
    $('#togglebig1-3').mouseover(function() {
    $('#big1-3').show(400);
    return false;
    }).mouseout(function() {
    $('#big1-3').hide(400);
    });
    $('#togglebig1-4').mouseover(function() {
    $('#big1-4').show(400);
    return false;
    }).mouseout(function() {
    $('#big1-4').hide(400);
    });

    $('#togglebig2').mouseover(function() {
    $('#big2').show(400);
    return false;
    }).mouseout(function() {
    $('#big2').hide(400);
    });

    });

    My HTML code:

    Mouseover a thumbnail to view a larger image

    CHAMPION INDUSTRIAL CONTRACTORS, INC. has worked closely with Kaiser Permanente on numerous Medical Office Buildings throughout the Central Valley. Design/build projects include Medical Office Buildings in Manteca, Modesto, and Selma.

    CHAMPION INDUSTRIAL CONTRACTORS, INC. has worked closely with Kaiser Permanente on numerous Medical Office Buildings throughout the Central Valley. Design/build projects include Medical Office Buildings in Manteca, Modesto, and Selma.

    Projects

    Kaiser Permanente
    Del Rio

  16. November 10th, 2009 at 1:25 am

    Hi Violet,

    Yes that does seem like a lot of duplicate code. I won’t have a chance to look at this though as I am away travelling. Hopefully someone else can help you.

  17. November 27th, 2009 at 7:07 pm

    I see this in your code, and I’ve seen other people do this with jquery too, but I don’t understand why people do it.

    var $this = $(this);
    var x = $this.attr("className");

    what’s the point of making the variable $this when it doesn’t make the code smaller or more understandable.

    why couldn’t you just do this:

    var x = ($this).attr("className");

    and leave out:
    var $this = $(this);

  18. Dan

    February 22nd, 2010 at 4:34 am

    Thanks for the great example!

    I have one small problem: if the anchor has more than one class, e.g. <a class="link foo"…, then "[name^=value]" does not work. Is there a work around for this?

  19. Marco

    February 25th, 2010 at 5:39 pm

    A demo would be useful! :)
    I’m struggling with the simplest part now: how to write the html code to hide / show the div?

  20. Omercan

    March 12th, 2010 at 2:25 am

    For the ones asking for a demo, I think here’s how the html would look like according to the above jquery :

    First
    Second
    Third
    This is the first item.
    This is the second item.
    This is the third item.

  21. March 13th, 2010 at 4:31 pm

    Absolutely superb post! I was exactly the info I needed!

  22. ah.

    March 27th, 2010 at 5:14 pm

    This code is terrific. I’ve implemented it with some success, but have one problem. Using multiple links and multiple divs, the toggle function will turn on each individual div, but it will not close whichever div is currently open. I solved this by adding a hide function to the onclick event and all is well except when you click the same link that is already open. Doing this merely hides and shows the said div rather than reversing its toggle state.

    So is there a way to build in an if/than function that checks for this and corrects? My code is below:


    /* JQUERY SMOOTH HIDE/DISPLAY CONTENT ONCLICK */
    $(document).ready(function() {
    // hides the ribbon as soon as the DOM is ready
    // (a little sooner than page load)
    $('div[class^=ribbon-]').hide();
    // loop through links and build function
    $('a[class^=link]').click(function() {
    $('div[class^=ribbon-]').hide('fast');
    var $this = $(this);
    var x = $this.attr("className");
    $('.ribbon-' + x).toggle(400);
    return false;
    });
    });

    And the HTML:

    Home
    Projects
    Videos
    Archives
    Editors

    PROJECTS
    VIDEOS
    ARCHIVES


  23. April 8th, 2010 at 5:21 pm

    [...] Writing multiple toggle links in JQuery – olliekav.com (tags: jquery toggle) [...]

  24. Lee

    April 15th, 2010 at 9:52 pm

    Spent days researching show/hide to find the best method and you have it by a mile. A HUGE thank you to you.

  25. Lee

    July 22nd, 2010 at 7:41 pm

    Just wanted to say thank you for this “tut”, i was the same as the user above, could not find what i was looking for/to do. Then i did another google only to find this page and BINGO! just what i wanted to do…

    What i had been doing was just like you said above:
    “But what about if we want to do this for multiple items on the page and not call each item on its own and create a bunch of unnecessary code”

    “bunch of unnecessary code”:

    $(document).ready(function(){
    $(“#open1″).click(function(event){
    $(“#block1″).slideFadeToggle(“slow”);
    event.preventDefault();
    });
    $(“#close1″).click(function(event){
    $(“#block1″).slideFadeToggle(“slow”);
    event.preventDefault(); });
    $(“#open3″).click(function(event){
    $(“#block3″).slideFadeToggle(“slow”);
    event.preventDefault(); });
    $(“#close3″).click(function(event){
    $(“#block3″).slideFadeToggle(“slow”);
    event.preventDefault(); }); });

    So yea my code was/is so not the way to do it, sure it works and gets the job done but not when you think about what jQuery was intended for. “Wright Less, Do More”

    So thanks dude, im off to code this into my site !

  26. Lee

    July 22nd, 2010 at 9:16 pm

    Delete the above post and this one then, you need to make it clear to people that:

    toggle-item- on each thing they would like to show and hide, should be set to, lets say: toggle-item-link1.

    So in other words make sure each “toggle-item-” your hiding and showing has a name of:

    “toggle-item-link1″

    The “link1″ needs to match the class=”link1″ that called it, so dont just use “toggle-item” and/or “toggle-item-” because that wont work.

    Got it ?!?

Leave a comment

XHTML ALLOWED: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>