1

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.

urbz
  • 2,663
  • 1
  • 19
  • 29

3 Answers3

5

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:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • This is exactly what I want. I don't need class names anymore, since they were only delegated to make my script work. Thank you! – urbz May 27 '14 at 14:13
  • You're very welcome indeed, I'm glad to have helped! :) – David Thomas May 27 '14 at 14:16
  • Ok, this works fine! But how can I expand rows in the top and the bottom? Example: I have a table with 50 rows. When the page is loaded, the table shows rows 20-25. The rows 1-19 and 26-50 should be rolled out by cklicking links above/under row 20 and 25... You know, what I mean? – Dong3000 Dec 16 '15 at 16:22
0
$('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();
});
xdebug
  • 1,178
  • 12
  • 16
0

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/

superUntitled
  • 22,351
  • 30
  • 83
  • 110
  • Thank you @superUntitled for the answer, but I don't need class names anymore since they were only delegated for the purpose of making my script work. – urbz May 27 '14 at 14:14