jQuery sortColumns插件:如何使用rowspan正确排序

时间:2012-10-15 15:30:43

标签: javascript jquery html

在这篇帖子jQuery table sort(github链接:https://github.com/padolsey/jQuery-Plugins/blob/master/sortElements/jquery.sortElements.js)之后,我成功地对列进行排序,但是在rowspan的情况下它不起作用:例如,像这样的情况

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

当我点击第二列时,它会尝试排序

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

预期结果应该是它应该只在每个行数范围内排序

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

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

所以 你可以看到哪些不正确,请任何jQuery大师帮我解决这个问题。这是我的代码

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;
    }
}

问题:

1.如何使用rowspan对其进行排序。 ROWSPAN的数量并不总是相同。以上示例Grape和Apple的行距为2,但情况并非总是如此。

2.可以解释这种语法:

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

所以我可以看到,如果a或b不是数字,那么做字符串比较否则做数字比较,但我不明白

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

测试用例

<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>

2 个答案:

答案 0 :(得分:3)

代码的工作条件:

  • 包含tdrowspan的列必须全部位于表的左侧
  • 这些列中的所有td必须都有rowspan,即使它是1
  • 要排序的行组使用最右边的列进行排序(但可以轻松更改)

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;
}

快速解释:

  • 使用td
  • 查找所有rowspan
  • 保存这些td的位置,包括左偏移
  • 这些td已按其原始offset进行过滤,仅适用于最右边的<{li}
  • 与每个保留tr相关的
  • td使用想要的列
  • 进行排序
  • 如果有必要,td的所有rowspan最终都会移回原来的位置

关于问题2,我只会说完bartlaarhoven的答案,代码也可以写成如下:

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

您可以轻松阅读inverse用于反转结果。

答案 1 :(得分:2)

考虑问题1,请尝试以下代码:

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;
        }
    }

考虑问题2;让我们从中扣除它的来源。首先我们想检查一下&gt; b,并且,正如您已经正确看到的那样,我们在字符串比较和数字比较之间做了区别。

然后我们会简单地给出:

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

这检查是否&gt; b(以字符串方式或数字方式)然后在true上返回1,在false上返回-1。

现在我们插入inverse参数,该参数应反转结果。这意味着如果inverse == true,则1变为-1,-1变为1 。在代码中,这段大胆的文字会将每个1替换为inverse ? -1 : 1,每次出现-1替换为inverse ? 1 : -1。这正是在生成的代码中完成的操作。

更新:在代码中添加了doRowSpan,因为如果我们位于包含rowspan - <tr>的{​​{1}}中,则不应调整索引。< / p>