tags:

views:

376

answers:

3

I'm working through a jQuery book and am currently on the chapter of table sorting. Using the example code in the book I've set up the following test scenario, when I click on a column heading it correctly sorts the data one way (ascending), but when I click on the same column heading again nothing happens (I'm expecting the data to be sorted descending on the 2nd click).

Can anybody take a look at the sample code below and tell me why this is?

HTML:

<table class="sortable">
 <thead>  
  <tr>
    <th class="sort-alpha"><strong>Flat number</strong></th>
    <th class="sort-alpha"><strong>Tenant name</strong></th>
  </tr>
 </thead>
  <tbody>
   <tr>
    <td>83</td>
    <td>Rachel Prouse</td>
   </tr>
   <tr>
    <td>79</td>
    <td>Natalie Charles</td>
   </tr>
  </tbody>
</table>

jQuery:

$(document).ready(function () {

    $('table.sortable').each(function() {

        var $table = $(this);
        $('th', $table).each(function(column) {
             var $header = $(this);
             if ($header.is('.sort-alpha')) {

                $header
                    .addClass('clickable')
                    .hover(
                        function() { $header.addClass('hover') }, 
                        function() { $header.removeClass('hover');
                        })
                    .click(function() {
                        var rows = $table.find('tbody > tr').get();
                        rows.sort(function(a, b) {
                            var keyA = $(a).children('td').eq(column).text().toUpperCase();
                            var keyB = $(b).children('td').eq(column).text().toUpperCase();
                            if (keyA < keyB) return -1;
                            if (keyA > keyB) return 1;
                            return 0;
                        });

                        $.each(rows, function(index, row) {
                            $table.children('tbody').append(row);
                        });
                    });
             }
        });
    });
});
A: 

Just track if user click same column again and if, do a rows.reverse(); before your $.each loop

ex

if ($(this).hasClass('desc')) 
{
    rows.reverse();
    $(this).removeClass('desc');
}
else
{
    $(this).addClass('desc');
}
walming
A: 

The return statements in your sort function control the sort order. That said, you'll need to keep track of ascending or descending at the column level, and then change them accordingly. For example...

var asc = true;

if(asc) {   //Ascending
  if (keyA < keyB) return -1;
  if (keyA > keyB) return 1;
}
else {    //Descending
  if (keyA < keyB) return 1;
  if (keyA > keyB) return -1;
}
return 0;
Josh Stodola
+2  A: 

Something like the following will do it. Here's a Working Demo

$(function () {

    $('table.sortable').each(function() {

        var $table = $(this);
        $('th', $table).each(function(column) {
             var $header = $(this);
             if ($header.hasClass('.sort-alpha')) {

                $header
                    .addClass('clickable')
                    .hover(
                        function() { $header.addClass('hover') }, 
                        function() { $header.removeClass('hover');
                        })
                    .click(function() {
                        $header.hasClass('asc')? 
                          $header.removeClass('asc').addClass('desc'): 
                          $header.removeClass('desc').addClass('asc');
                        var rows = $table.find('tbody > tr').get();

                        rows.sort(function(a, b) {
                            var keyA = $(a).children('td').eq(column).text().toUpperCase();
                            var keyB = $(b).children('td').eq(column).text().toUpperCase();

                            if (keyA > keyB) {
                                return ($header.hasClass('asc')) ? 1 : -1;
                              }
                            if (keyA < keyB) {
                              return ($header.hasClass('asc')) ? -1 : 1;
                            }
                            return 0;                       
                        });

                        $.each(rows, function(index, row) {
                            $table.find('tbody').append(row);
                        });
                    });
             }
        });
    });
});
Russ Cam
you might want to put the Sort Direction class on the table instead of the header, as it applies to the table.
Russ Cam