views:

740

answers:

2

I have a Zend Framework (PHP) web application that has a table with a lot of rows.

  • 99.9% of the time, the user will take action on the first or second row.
  • 00.1% of the time, the user will need to go back and take action on a different row.

So I only really need to display the first few rows on page load, and keep the rest available for the sake of history.

I would like to shorten the table somehow. I'm thinking, using jQuery, maybe do something where the first 5 rows are displayed (the rest are hidden), and at the bottom of the table, there is a link to display 5 more rows.

alt text

What do you think? How could I achieve this with jQuery?

+1  A: 

Sure you could do this with jQuery. I would probably do it this way:

<table>
<tbody id="new">
  <tr>...</tr> <!-- x5 -->
  <tr><td><a href="#" id="toggle">Show Old</a></td></tr>
</tbody>
<tbody id="old">
  ...
</tbody>
</table>

Load them hidden with CSS:

#old { display: none; }

and:

$(function() {
  $("#toggle").click(function() {
    if ($("#old").is(":hidden")) {
      $(this).text("Hide Old");
    } else {
      $(this).text("Show Old");
    }
    $("#old").slideToggle();
    return false;
  });
});

The jQuery hide/show effects can be a bit strange with table components however. If so change the CSS to this:

#old.hidden { display: none; }

and:

$(function() {
  $("toggle").click(function() {
    if ($("#old").hasClass("hidden")) {
      $(this).text("Hide Old");
    } else {
      $(this).text("Show Old");
    }
    $(this).toggleClass("hidden");
    return false;
  });
});

Of course you don't get the nice effects this way.

cletus
Of course, the downside is you need to load all those rows and then hide them. Wouldn't some ajax thingy be better practice for bandwidth usage? :)
Rimian
Agree, and have you noticed StackOverflow does the same client side processing to hide your ignored tags?
Pool
+4  A: 

This is how I would do this (demo here):

Script

var numShown = 5; // Initial rows shown & index
var numMore = 5; // Increment
var numRows = $('table').find('tr').length; // Total # rows

$(document).ready(function(){
 // Hide rows and add clickable div
 $('table')
  .find('tr:gt(' + (numShown - 1) + ')').hide().end()
  .after('<div id="more">Show <span>' + numMore + '</span> More</div>');

 $('#more').click(function(){
  numShown = numShown + numMore;
  // no more show more if done
  if ( numShown >= numRows ) $('#more').remove();
  // change rows remaining if less than increment
  if ( numRows - numShown < numMore ) $('#more span').html(numRows - numShown);
  $('table').find('tr:lt('+numShown+')').show();
 })

})
fudgey
that's exactly what I was trying to do. thanks!
Andrew
What does the `.end()` do, following the `.hide()` ?
Cheeso
`.end()` reverts the selection to the previous one... so in this case the selector goes back to `$('table')`. Read more about it here (http://docs.jquery.com/Traversing/end), there is also the `.andSelf()` selector (http://docs.jquery.com/Traversing/andSelf)
fudgey