javascript - jQuery sortColumns plugin: How to sort correctly with rowspan - Stack Overflow

Following this post jQuery table sort (github link: .sortElements.js), I am successfully sort columns,

Following this post jQuery table sort (github link: .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 parison otherwise do number parison, 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>

Following this post jQuery table sort (github link: https://github./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 parison otherwise do number parison, 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>
Share Improve this question edited May 23, 2017 at 10:28 CommunityBot 11 silver badge asked Oct 15, 2012 at 15:30 Thang PhamThang Pham 38.7k79 gold badges208 silver badges289 bronze badges 2
  • @Newbo.O: It should only sort within each rowspan. I have updated my question with expected result. – Thang Pham Commented Oct 18, 2012 at 0:47
  • Sort only within a rowspan or: sort each rowspan group and then sort groups according to first value? – Robert Koritnik Commented Oct 19, 2012 at 11:38
Add a ment  | 

2 Answers 2

Reset to default 3 +500

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/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 plete 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.

Considering question 1, try this code:

var inverse = false;
var curRowSpan = 0;
var curIndex = 0;
var doRowSpan = false;
function sortColumn(index){
    index = index + 1;
    var table = jQuery('#resultsTable');
    table.find('td').filter(function() {
        var result = false;
        // if it is a column before the sorting column, watch the rowSpan
        if (curRowSpan == 0 && jQuery(this).index() < index && jQuery(this).attr("rowspan") > 1) {
            curRowSpan = jQuery(this).attr("rowspan");
            doRowSpan = true;
            // we are not in the sorting column so we can safely continue
            continue;
        }

        if(!doRowSpan) curIndex = index - (curRowSpan?1:0);
        else curIndex = index;

        if(jQuery(this).index() == curIndex) {
            // we are at the sorting column
            if(curRowSpan > 0) {
                curRowSpan--;
            }
            // set this to false for the following row
            doRowSpan = false;
            result = true;
        }

        return result;
    }).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;
        }
    }

Considering question 2; let's deduct where it es from. First of all we would like to check whether a > b, and, as you already saw correctly, we make a difference between string parison and number parison.

We would then simply give:

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

This checks whether a > b (either string-wise or number-wise) and then returns 1 on true and -1 on false.

Now we insert the inverse parameter, which should inverse the result. This means that if inverse == true, then 1 bees -1 and -1 bees 1. In code, this bold piece of text would replace each occurrence of 1 with inverse ? -1 : 1 and each occurrence of -1 with inverse ? 1 : -1. Which is exactly what is done in the resulting code.

UPDATE: Added doRowSpan in the code because it should not adapt the index if we are in the <tr> that contains the rowspan-td.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745599826a4635335.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信