admin管理员组

文章数量:1323730

I am trying to sort a table - so when a user clicks on the table heading, it will sort in ascending/descending order. I've got it to the point where I can sort the table based on the column value. However, I have groupings of table rows (two rows per table body), and I want to sort the columns based on the values in the columns of the first row of each table body, but when it reorders the table, it want it to reorder the table bodies, not the table rows.

<table width="100%" id="my-tasks" class="gen-table">
<thead>
    <tr>
        <th class="sortable"><p>Name</p></th>
        <th class="sortable"><p>Project</p></th>
        <th class="sortable"><p>Priority</p></th>
        <th class="sortable"><p>%</p></th>
    </tr>
</thead>

<tbody>
<tr class="sortable-row" id="44">
    <td><p>dfgdf</p></td><td><p>Test</p></td>
    <td><p>1</p></td><td><p>0</p></td>
</tr>
<tr>
    <td></td>
    <td colspan="3"><p>asdfds</p></td>
</tr>
</tbody>

<tbody>
<tr class="sortable-row" id="43">
    <td><p>a</p></td>
    <td><p>Test</p></td>
    <td><p>1</p></td>
    <td><p>11</p></td>
</tr>
<tr>
    <td></td>
    <td colspan="3"><p>asdf</p></td>
</tr>
</tbody>

<tbody>
<tr class="sortable-row" id="40">
    <td><p>Filter Tasks</p></td>
    <td><p>Propel</p></td>
    <td><p>10</p></td>
    <td><p>10</p></td>
</tr>
<tr>
    <td></td>
    <td colspan="3"><p>Add a button to filter tasks.</p></td>
</tr>
</tbody>
</table>

With the following javascript:

jQuery(document).ready(function () {
    jQuery('thead th').each(function(column) {
        jQuery(this).addClass('sortable').click(function() {

            var findSortKey = function($cell) {
                return $cell.find('.sort-key').text().toUpperCase() + ' ' + $cell.text().toUpperCase();
            };
            var sortDirection = jQuery(this).is('.sorted-asc') ? -1 : 1;

            var $rows = jQuery(this).parent().parent().parent().find('.sortable-row').get();
            jQuery.each($rows, function(index, row) {
                row.sortKey = findSortKey(jQuery(row).children('td').eq(column));
            });

            $rows.sort(function(a, b) {
                if (a.sortKey < b.sortKey) return -sortDirection;
                if (a.sortKey > b.sortKey) return sortDirection;
                return 0;
            });

            jQuery.each($rows, function(index, row) {
                jQuery('#propel-my-tasks').append(row);
                row.sortKey = null;
            });

            jQuery('th').removeClass('sorted-asc sorted-desc');
            var $sortHead = jQuery('th').filter(':nth-child(' + (column + 1) + ')');
            sortDirection == 1 ? $sortHead.addClass('sorted-asc') : $sortHead.addClass('sorted-desc');

            jQuery('td').removeClass('sorted').filter(':nth-child(' + (column + 1) + ')').addClass('sorted');

        });
    });
});

I am trying to sort a table - so when a user clicks on the table heading, it will sort in ascending/descending order. I've got it to the point where I can sort the table based on the column value. However, I have groupings of table rows (two rows per table body), and I want to sort the columns based on the values in the columns of the first row of each table body, but when it reorders the table, it want it to reorder the table bodies, not the table rows.

<table width="100%" id="my-tasks" class="gen-table">
<thead>
    <tr>
        <th class="sortable"><p>Name</p></th>
        <th class="sortable"><p>Project</p></th>
        <th class="sortable"><p>Priority</p></th>
        <th class="sortable"><p>%</p></th>
    </tr>
</thead>

<tbody>
<tr class="sortable-row" id="44">
    <td><p>dfgdf</p></td><td><p>Test</p></td>
    <td><p>1</p></td><td><p>0</p></td>
</tr>
<tr>
    <td></td>
    <td colspan="3"><p>asdfds</p></td>
</tr>
</tbody>

<tbody>
<tr class="sortable-row" id="43">
    <td><p>a</p></td>
    <td><p>Test</p></td>
    <td><p>1</p></td>
    <td><p>11</p></td>
</tr>
<tr>
    <td></td>
    <td colspan="3"><p>asdf</p></td>
</tr>
</tbody>

<tbody>
<tr class="sortable-row" id="40">
    <td><p>Filter Tasks</p></td>
    <td><p>Propel</p></td>
    <td><p>10</p></td>
    <td><p>10</p></td>
</tr>
<tr>
    <td></td>
    <td colspan="3"><p>Add a button to filter tasks.</p></td>
</tr>
</tbody>
</table>

With the following javascript:

jQuery(document).ready(function () {
    jQuery('thead th').each(function(column) {
        jQuery(this).addClass('sortable').click(function() {

            var findSortKey = function($cell) {
                return $cell.find('.sort-key').text().toUpperCase() + ' ' + $cell.text().toUpperCase();
            };
            var sortDirection = jQuery(this).is('.sorted-asc') ? -1 : 1;

            var $rows = jQuery(this).parent().parent().parent().find('.sortable-row').get();
            jQuery.each($rows, function(index, row) {
                row.sortKey = findSortKey(jQuery(row).children('td').eq(column));
            });

            $rows.sort(function(a, b) {
                if (a.sortKey < b.sortKey) return -sortDirection;
                if (a.sortKey > b.sortKey) return sortDirection;
                return 0;
            });

            jQuery.each($rows, function(index, row) {
                jQuery('#propel-my-tasks').append(row);
                row.sortKey = null;
            });

            jQuery('th').removeClass('sorted-asc sorted-desc');
            var $sortHead = jQuery('th').filter(':nth-child(' + (column + 1) + ')');
            sortDirection == 1 ? $sortHead.addClass('sorted-asc') : $sortHead.addClass('sorted-desc');

            jQuery('td').removeClass('sorted').filter(':nth-child(' + (column + 1) + ')').addClass('sorted');

        });
    });
});
Share Improve this question edited May 24, 2011 at 12:17 Cheeso 193k105 gold badges485 silver badges734 bronze badges asked May 24, 2011 at 1:56 v0idlessv0idless 9482 gold badges11 silver badges24 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 2

You need to sort the tbody elements, not the row elements. You said that yourself in your description of the problem, but your code actually sorts rows, not tbodies.

A secondary problem is that your sort treats everything as a string, which breaks when sorting 1-digit numeric strings ("2") against two-digit strings ("10").

To fix, replace this:

        var $rows = jQuery(this).parent().parent().parent()
            .find('.sortable-row').get();
        jQuery.each($rows, function(index, row) {
            row.sortKey = findSortKey(jQuery(row).children('td').eq(column));
        });

with this:

        var $tbodies = jQuery(this).parent().parent().parent()
            .find('.sortable-row').parent().get();
        jQuery.each($tbodies, function(index, tbody) {
            var x = findSortKey(jQuery(tbody).find('tr > td').eq(column));
            var z = ~~(x); // if integer, z == x
            tbody.sortKey = (z == x) ? z : x;
        });

And then replace $rows with $tbodies throughout your script, and row with tbody.

Example:
http://jsbin./oxuva5

I highly remend the jQuery plugin http://tablesorter./ instead of rolling your own.

It's fully featured and well supported.

本文标签: javascriptSorting tbody elements by column value with jQueryStack Overflow