1

I have a table like this:

<table>
  <tr>
    <td><input type="button" title="Toggle" value="Show" id="btn534534" class="toggle" />    </td>
    <td>some data about ID 534534</td>
  </tr>
  <tr id="row534534" class="hiddenRow">
    <td colspan="2">some hidden data about ID 534534 that must show/hide with toggle</td>
  </tr>
  <tr>
    <td><input type="button" title="Toggle" value="Show" id="btn2423434" class="toggle" /></td>
    <td>some data about ID 2423434</td>
  </tr>
  <tr id="row2423434" class="hiddenRow">
    <td colspan="2">some hidden data about ID 2423434that must show/hide with toggle</td>
  </tr>
  <!-- many more rows here -->
</table>

There are MANY "sets" of rows like the above. One row of the table is visible for each "set" of rows. The second row with class "hiddenRow" is hidden on page load by JQuery like this:

$("tr.hiddenRow").hide();

Now I want each button to toggle visibility of the row immediately after it. Note that the INPUT in the visible row, and the TR of the hidden row share a unique ID. I want to have the button onclick call a JQuery function and pass the ID so that JQuery knows which row to toggle.

Any ideas? I can't find any examples of this online.

4 Answers 4

3

This should do the trick:

$(document).ready(function() {
    $(".toggle").click(function() {
        $(this).closest('tr').next('tr.hiddenRow').toggle(); 
    });
});

http://jsfiddle.net/DU8rd/1 (Thanks Šime Vidas)

Note: This doesn't pass the ID as you indicated, but it does create the behavior you described.

Sign up to request clarification or add additional context in comments.

4 Comments

closest('tr') is more appropriate since you don't need all the parents but just the TR element
@ŠimeVidas Can you make a fiddle (fork mine) demonstrating this? It didn't work when I tried it.
Careful of tagless class selectors - they're expensive in CPU cycles. Take a look at how JQuery implements them behind the scenes in IE... it's not pretty.
Nathan's code is working perfectly. But it would be nice to know how to do the ID-parameter version for future reference.
1

I prefer @Nathan's solution, but if the DOM relationship would become more complicated, you would do it like so:

$('#tableID input.toggle').click(function() {
    $('#row' + this.id.replace('btn', '')).toggle();
});

Live demo: http://jsfiddle.net/pHKat/1/


Update: The same thing as above, but using event delegation:

$('#tableID').click(function(e) {
    if (!$(e.target).hasClass('toggle')) { return; }
    $('#row' + e.target.id.replace('btn', '')).toggle();
});

This code has one additional line of code, but performance-wise, this code is better, since only one event handler is bound (to the table element). For comparison, my original solution (above) binds one event handler per each button.

14 Comments

Two issues here: 1) Use 'tr.toggle' or it will be slow in IE for larger documents, 2) If the table is dynamic - if JS can add and remove row pairs - you'll want to use a .live('click', function... instead of .click().
@Chris 1. Yes, a more specific selector is definitively better 2. Yes, for dynamic tables. I'll stick to my assumption that the table is static. (I try to avoid live when possible since it executes selector queries every time an click event (in this case) happens)
@Chris & @Šime - $('#tableID').delegate('input.toggle','click', fn) - the best of both worlds ;)
@gnarf Very cool, had not come across .delegate(). The name is unfortunately confusing, but the functionality is a great performance win. api.jquery.com/delegate
@gnarf $('#tableID').delegate('input.toggle','click', fn) is equivalent to $('#tableID').each(function() { $('input.toggle', this).live('click', fn); }); It uses live() internally. I believe, live() should be avoided if possible.
|
0

My first suggestion when you say:

"MANY ... hidden on page load" is that you're using Javascript to do CSS's job, and it's either already causing or going to cause you a performance problem. Define:

tr.hiddenRow {
    display: none;
}

in your stylesheet, and get rid of the on page load code.

I'd use the following to implement your button code:

$('input.toggle').live('click', function(ev) {
    var id = this.id.substr(3);
    var row = $('#row' + id);
    if (row.hasClass('hiddenRow'))
        row.removeClass('hiddenRow');
    else
        row.addClass('hiddenRow');
});

If row IDs aren't necessary for other functions, you could reduce the size of your HTML by getting rid of the ID on both the input and the tr, then implement toggle with DOM-walking:

$('input.toggle').live('click', function(ev) {
    var row = $(this).parents('tr').next('tr');
    if (row.hasClass('hiddenRow'))
        row.removeClass('hiddenRow');
    else
        row.addClass('hiddenRow');
});

Edit: Hadn't come across jsfiddle before - that's sort of fun. Here you go: http://jsfiddle.net/z6rAe/

Updating again to include my corrections to Šime's answer - why doesn't StackOverflow do code in comments?

$('#tableID').click(function(ev) {
    if (!$(ev.target).hasClass('toggle')) { return; }
    $(ev.target.id.replace('btn', '#row')).toggle();
});

http://jsfiddle.net/7Dy5s/3/

6 Comments

@Chris You can easily reduce those 6 lines of code to just one line: $('#row' + this.id.substr(3)).toggleClass('hiddenRow'); 1. There is no need for those local variables since you're using them only once, 2. Instead of the if-else statement just use toggleClass()
@Šime Agreed, but it's much easier to test and teach when you break things down into smaller steps. Otherwise a newer coder can make a simple typo, end up with an error, and be left with this single massive complex operation and no clue where to start to fix it.
When I say MANY I mean a max of 100 hidden rows, so performance isn't a huge deal, but I would prefer the most elegant solution that I could reuse in another situation, say, where the data to be toggled happens to NOT be adjacent to the button, and where the row ID is critical.
@Chris In cases when we have lot's of code, that probably is true. But in this case, the code is simple enough. I don't think that beginners would have problems with that line of code I posted above.
@Blackcoil - you have both solutions here. You'll want to keep the .hasClass() since you presumably want to toggle the message on the button as well. Take a look at the jsfiddle I posted as part of the answer.
|
-2

use a custom method like this one:

    <script type="text/javascript">
        function viewToggle(id){
            $('#'+id).slideToggle(500);
        }
    </script>

And then have each button call the function above passing in the value of the id you would like to toggle the view of:

<table>
  <tr>
    <td><input type="button" onclick="viewToggle('row534534');" title="Toggle" value="Show" id="btn534534" class="toggle" />    </td>
    <td>some data about ID 534534</td>
  </tr>
  <tr id="row534534" class="hiddenRow">
    <td colspan="2">some hidden data about ID 534534 that must show/hide with toggle</td>
  </tr>
  <tr>
    <td><input type="button" onclick="viewToggle('row2423434');" title="Toggle" value="Show" id="btn2423434" class="toggle" /></td>
    <td>some data about ID 2423434</td>
  </tr>
  <tr id="row2423434" class="hiddenRow">
    <td colspan="2">some hidden data about ID 2423434that must show/hide with toggle</td>
  </tr>
  <!-- many more rows here -->
</table>

9 Comments

@Nerd I don't see why one would define a separate function, when the function can easily be passed as an argument into jQuery's click method.
I agree with previous commenter.
@gnarf I get down voted for using onclick, but the original poster doesn't get down voted for using tables? If you're going to be an HTML snob, don't be selective. ;) In the code I took this from, I had used the function because I had several nested elements that I wanted to toggle views on, some were tables and others were divs nested in the table structure. This way I didn't need to write 2 selectors. And the whole report (html + js) was being output from a C# program... and most of all - old habits die hard.
This is tabular data, therefore I use a table. I'm not using a table for UI layout but for displaying tabular data.
As a promise to the community, I will read up on unobtrusive javascript before responding to anymore jquery questions.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.