Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery sortColumns plugin: How to sort correctly with rowspan

Following this post jQuery table sort (github link: https://github.com/padolsey/jQuery-Plugins/blob/master/sortElements/jquery.sortElements.js), I am successfully sort columns, however it does not work in the case of rowspan: For example, case like this

 Grape      3,096,671M
            1,642,721M
 Apple      2,602,750M
            3,122,020M

When I click on the second column, it try to sort

 Apple      2,602,750M
            1,642,721M
 Grape      3,096,671M
            3,122,020M

(Expected result should be that it should only sort within each rowspan

 Grape      1,642,721M
            3,096,671M
 Apple      2,602,750M
            3,122,020M

or

 Grape      3,096,671M
            1,642,721M
 Apple      3,122,020M
            2,602,750M

)

so either which as you can see is not correct, please any jQuery guru help me fix this problem. Here is my code

var inverse = false;
function sortColumn(index){
    index = index + 1;
    var table = jQuery('#resultsTable');
    table.find('td').filter(function(){
        return jQuery(this).index() == index;
    }).sortElements(function(a, b){
        a = convertToNum($(a).text());
        b = convertToNum($(b).text());

        return (
            isNaN(a) || isNaN(b) ?
            a > b : +a > +b
            ) ?
        inverse ? -1 : 1 :
        inverse ? 1 : -1;
    },function(){
        return this.parentNode;
    });
    inverse = !inverse;
}
function convertToNum(str){
    if(isNaN(str)){
        var holder = "";
        for(i=0; i<str.length; i++){                                
            if(!isNaN(str.charAt(i))){
                holder += str.charAt(i);
            }
        }
        return holder;
    }else{
        return str;
    }
}

Question:

1.How do I sort this with rowspan. THE NUMBER OF ROWSPAN IS NOT ALWAYS THE SAME. The above example both Grape and Apple have rowspan of 2, but this is not always the case.

2.Can any explain this syntax:

 return (
            isNaN(a) || isNaN(b) ?
            a > b : +a > +b
            ) ?
        inverse ? -1 : 1 :
        inverse ? 1 : -1;

So I can see that if either a or b is not a number, then do string comparison otherwise do number comparison, but I dont understand the

inverse ? -1 : 1 :
inverse ? 1 : -1;

Test cases

<table id="resultsTable">
        <thead>
            <tr>
                <th>Fruit</th>
                <th onclick="sortColumn(1)">Quantity</th>
                <th onclick="sortColumn(2)">Rate</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td rowspan="4">Grape</td>
                <td>15</td>
                <td>5</td>
            </tr>
            <tr>
                <td>4</td>
                <td>2</td>
            </tr>
            <tr>
                <td>88</td>
                <td>1</td>
            </tr>
            <tr>                    
                <td>11</td>
                <td>3</td>
            </tr>
            <tr>
                <td rowspan="3">Melon</td>
                <td>21</td>
                <td>2</td>
            </tr>
            <tr>
                <td>2</td>
                <td>0</td>
            </tr>
            <tr>
                <td>35</td>
                <td>1</td>
            </tr>
            <tr>
                <td rowspan="6">Melon</td>
                <td>24</td>
                <td>5</td>
            </tr>
            <tr>
                <td>66</td>
                <td>2</td>
            </tr>
            <tr>
                <td>100</td>
                <td>4</td>
            </tr>
            <tr>
                <td>21</td>
                <td>1</td>
            </tr>
            <tr>
                <td>65</td>
                <td>3</td>
            </tr>
            <tr>
                <td>2</td>
                <td>0</td>
            </tr>
        </tbody>
 <table>
like image 217
Thang Pham Avatar asked Oct 15 '12 15:10

Thang Pham


1 Answers

Conditions for the code to work:

  • Columns containing tds with rowspan must all be on the left of the table
  • All the tds in these columns must have a rowspan, even if it's 1
  • The groups of rows to sort are made with the rightmost of these columns (but it can easily be changed)

jsFiddle: http://jsfiddle.net/5GrAC/77/

var inverse = false;

function sortColumn(index) {
    var trs = $('#resultsTable > tbody > tr'),
        nbRowspans = trs.first().children('[rowspan]').length,
        offset = trs.first().children('[rowspan]').last().offset().left;

    var tds = trs.children('[rowspan]').each(function() {
        $(this).data('row', $(this).parent().index());
        $(this).data('column', $(this).index());
        $(this).data('offset', $(this).offset().left)
    }).each(function() {
        if($(this).data('offset') != offset)
            return;

        var rowMin = $(this).data('row'),
            rowMax = rowMin + parseInt($(this).attr('rowspan'));

        trs.slice(rowMin, rowMax).children().filter(function() {
            return $(this).index() == index + $(this).parent().children('[rowspan]').length - nbRowspans;
        }).sortElements(function(a, b) {
            a = convertToNum($(a).text());
            b = convertToNum($(b).text());

            return (
                isNaN(a) || isNaN(b) ?
                a > b : +a > +b
                ) ?
            inverse ? -1 : 1 :
            inverse ? 1 : -1;
        }, function() {
            return this.parentNode;
        });
    });

    var trs = $('#resultsTable > tbody > tr');
    tds.each(function() {
        if($(this).parent().index() != $(this).data('row'))
            $(this).insertBefore(trs.eq($(this).data('row')).children().eq($(this).data('column')));
    });

    inverse = !inverse;
}

Quick explanations:

  • Finding all tds with rowspan
  • Positions of these tds are saved, including left offset
  • These tds are filtered by their original offset to work only with the rightmost ones
  • trs related to each kept td are sorted using the wanted column
  • All tds with rowspan are finally moved back to their original position if necessary

About question 2, I will only complete bartlaarhoven's answer by saying, the code can also be written like the following:

return (
        (isNaN(a) || isNaN(b) ? a > b : +a > +b) ? 1 : -1
    ) * (inverse ? -1 : 1);

You can easily read that inverse is used to inverse the result.

like image 101
Newbo.O Avatar answered Sep 28 '22 17:09

Newbo.O