views:

91

answers:

4

I've got some code on my site that displays a list of articles on a blog as follows (there will be multiple objects with the same category):

<ul class="article category1">
   <li> etc
   <li>
</ul>
<ul class="article category2">
   <li> etc
   <li>
</ul>
<ul class="article category3">
   <li> etc
   <li>
</ul>

I've got some jQuery code that filters the list so you only get one category displayed as follows:

$("#showall").click(function() {
    $("ul.article").show('fast');
});
$("#showcategory1").click(function() {
    $("ul.article.category1").show('fast');
    $("ul.article").not("ul.category1").hide('fast');
});

When you click on the relevant link, i.e.

<a id="showall">All</a>
<a id="category1">Category 1</a>

Currently I've got about 9 categories to deal with and so 10 snippets of jQuery which seems horribly inefficient (it is horribly inefficient). I have no idea how to generalise the code so that it takes in the ID (or perhaps the class) of the anchor and then applies it to the relevant lists. Any help please?

Thanks!


A: 

Handler functions for events are passed an event object (and the element that fired the event is also passed in as this). You can use that to get the id, and then operate from there - if necessary using the DOM traversal functions in the jQuery library to work your way to the proper list.

Amber
A: 

Try this (untested, but should give you an idea):

$("a[id^=category]").click(function() {
    $("ul." + $(this).attr("id")).show("fast").siblings().hide("fast");
});
Michael Dean
+1 Beat me to the `.siblings` point.
phoffer
He isn't trying to click on the articles, there are separate links that control which articles to display.
Ned Batchelder
+1  A: 

You can commonalize the code by working from a list of categories:

$("#showall").click(function() {
    $("ul.article").show('fast');
});

var cats = "food cars books";
$.each(cats.split(" "),
    function(cat) {
        $("#show"+cat).click(function() {
            $("ul.article."+cat).show('fast');
            $("ul.article").not("ul."+cat).hide('fast');
        });
    });

This doesn't change the runtime behavior, just reduces the amount of code needed to create the functions in the first place. The key idea here is that the jQuery selectors don't have to be literal strings, they can be constructed from literals and variables.

Ned Batchelder
If you use `.siblings`, you can chain the last 2 lines together to be `$("ul.article."+cat).show('fast').siblings().hide('fast');`
phoffer
Thanks, that's awesome :)Heads up that .each(cats.split(" "), function(cat)) should be changed to .each(cats.split(" "), function(i, cat)) to make this work.
Josh
A: 

You could use $(".class").click isntead of $("#showcategory1").click for the trigger, use the id to select a specific article, and use .siblings.hide() to hide all the other articles.

phoffer