urbz
urbz

Reputation: 2667

Expand/collapse multiple table rows with a more elegant solution

I have a page where I have multiple tables with data.

Fiddle:

DEMO


The <th> is in a <tr> with a class name and each of the rows have similar naming...

rowToClick1 rowToClick2

...and so forth.


Inside a for loop, where I generate data dynamically - I have <tr>'s with class names and similar to above they are named...

rowToExpand1 rowToExpand2

...and so forth.


Currently, my solution is working for expanding/collapsing these tables, but it is really ugly:

$('.rowToClick1').click(function () {
    $(this).find('span').text(function (_, value) {
        return value == '-' ? '+' : '-';
    });
    $(".rowToExpand1").toggle();
});

$('.rowToClick2').click(function () {
    $(this).find('span').text(function (_, value) {
        return value == '-' ? '+' : '-';
    });
    $(".rowToExpand2").toggle();
});

// Many more similar functions repeatedly, up to 20+ ..

How can I do this more efficiently?

Note: I don't want the tables to expand/collapse at the same time, but individually (like I do now).

Thanks in advance.

Upvotes: 1

Views: 3549

Answers (3)

David Thomas
David Thomas

Reputation: 253358

I'd suggest:

// binding the event to the 'th':
$('th').click(function () {
    // finding the contained 'span' element, manipulating its text (as before):
    $(this).find('span').text(function (_, value) {
            return value == '-' ? '+' : '-';
        // finding the closest 'thead' (in which the 'th' elements are contained:
        }).closest('thead')
        // finding the sibling 'tbody' element:
        .next('tbody')
        // finding the 'tr' descendants:
        .find('tr')
        // toggling their visibility:
        .toggle();
});

JS Fiddle demo.

The above works if you have only one <tbody> element; if you should have multiple elements that approach doesn't work (due to the use of next()); should there be (potentially) more <tbody> elements then you could instead use nextAll():

$('th').click(function () {
    $(this).find('span').text(function (_, value) {
            return value == '-' ? '+' : '-';
        }).closest('thead').nextAll('tbody').find('tr').toggle();
});

JS Fiddle demo.

References:

Upvotes: 5

xdebug
xdebug

Reputation: 1188

$('tr[class^="rowToClick"]').click(function () {
    $(this).find('span').text(function (_, value) {
        return value == '-' ? '+' : '-';
    });
    var className = $(this).attr("class");
    var id = className.replace("rowToClick","");
    $(".rowToExpand"+id).toggle();
});

Upvotes: 0

superUntitled
superUntitled

Reputation: 22537

Take a look at this...

http://jsfiddle.net/72TFR/2/

$('tr[class^="rowToClick"]').click(function () {
    // remove all non-numbers from the class with regex
    theNumber = $(this).attr('class').replace(/\D/g,'');
    // append the variable to the class name
    $(".rowToExpand"+theNumber).toggle();
});

Take a look at the documentation:

tr[class^="rowToClick"] : http://api.jquery.com/attribute-starts-with-selector/

Upvotes: 0

Related Questions