jQuery表排序


Answers:


151

如果您想避免所有麻烦,那么我建议使用这个简单的sortElements插件。用法:

var table = $('table');

$('.sortable th')
    .wrapInner('<span title="sort this column"/>')
    .each(function(){

        var th = $(this),
            thIndex = th.index(),
            inverse = false;

        th.click(function(){

            table.find('td').filter(function(){

                return $(this).index() === thIndex;

            }).sortElements(function(a, b){

                if( $.text([a]) == $.text([b]) )
                    return 0;

                return $.text([a]) > $.text([b]) ?
                    inverse ? -1 : 1
                    : inverse ? 1 : -1;

            }, function(){

                // parentNode is the element we want to move
                return this.parentNode; 

            });

            inverse = !inverse;

        });

    });

和演示。(单击“城市”和“设施”列标题进行排序)


6
该演示已损坏,因为插件的位置已更改。我为演示sortElements分叉了一个固定的jsfiddle,这似乎至少对我有用:) @ 999也许您可以更新答案以链接到该固定的演示?
杰克·沃雷尔

2
如果页面上有多个表怎么办?我分叉了jsfiddle jsfiddle.net/CM8bT
Marc

1
我收到这个错误,Error: illegal character但html并不完全相同,我也有thead和tboy,请问您能帮我这个忙吗?
pahnin 2012年

1
在区分大小写的情况下,以上功能将不起作用。在这个插件中'a'!='A'。如果将文本转换为大写或小写,然后进行检查和比较,则可以使用。例如:代替$.text([a]) == $.text([b])使用$.text([a]).toUpperCase() == $.text([b]).toUpperCase()将对其进行修复。
NBK

1
很快,您会发现排序根本不是一个特定于表的问题-当您这样做时,这是我的小巧jQuery插件,它将按升序或降序对列表,表,div或其他内容进行排序。我还用它来对不同的数据类型(例如货币或年份)进行排序-仅提供您自己的函数即可返回要排序的数据。(我喜欢将这些功能分开,并给它们赋予有意义的名称,以构建自己的小库,以“排序方式”特定于我正在构建的解决方案。)
mindplay.dk 2014年

183

我碰到了这个,以为我会捐出2美分。单击列标题以升序排序,然后再次以降序排序。

  • 适用于Chrome,Firefox,Opera和IE(8)
  • 仅使用JQuery
  • 进行字母和数字排序-升序和降序

$('th').click(function(){
    var table = $(this).parents('table').eq(0)
    var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
    this.asc = !this.asc
    if (!this.asc){rows = rows.reverse()}
    for (var i = 0; i < rows.length; i++){table.append(rows[i])}
})
function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index)
        return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
    }
}
function getCellValue(row, index){ return $(row).children('td').eq(index).text() }
table, th, td {
    border: 1px solid black;
}
th {
    cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
    <tr><th>Country</th><th>Date</th><th>Size</th></tr>
    <tr><td>France</td><td>2001-01-01</td><td>25</td></tr>
    <tr><td><a href=#>spain</a></td><td>2005-05-05</td><td></td></tr>
    <tr><td>Lebanon</td><td>2002-02-02</td><td>-17</td></tr>
    <tr><td>Argentina</td><td>2005-04-04</td><td>100</td></tr>
    <tr><td>USA</td><td></td><td>-6</td></tr>
</table>

**更新:2018年


10
太棒了!请注意,如果您在tds中有链接,例如<a href="#">Test</a>排序涉及<a...。要仅按文本排序,您需要html()在最后一行更改为text()
Kai Noack

1
@wubblyjuggly-您尝试了什么?当前,该表使用单元格数据(例如html值)来确定数据类型(即数字或字符串)。由于日期字符串有多种格式,因此编写通用的日期检测器/解析器是不切实际的(comparer(..)如果您确切知道要支持的格式,则可以重写)。同时,如果您使用yyyy-MM-dd,则“ string”排序将为您排序数据。例如jsbin.com/pugedip/1
Nick Grealy

1
在选择的解决方案无效的情况下,此示例对我来说非常有效。我不确定是否是因为我是否使用thead / tbody(没有这些标签的jsfiddle确实起作用了)。
RalphTheWonderLlama

1
感谢@Jan,我已将您的建议纳入解决方案中!
尼克·格莱利

1
@NickGrealy您对我的建议的评论完全正确,该评论正是被拒绝的编辑。将jsfiddle.net/gn1vtcLq/2(我的版本)与jsfiddle.net/0a15ky9u(您的版本)进行比较。多次单击“性别”标题,以查看ID或名称随后在您的版本中更改顺序,同时将其初始顺序保留在我的版本中。
markus

39

到目前为止,我使用过的最简单的方法是:http : //datatables.net/

惊人的简单...只要确定您是否走了DOM替换路线(即,建立表并让DataTables重新格式化),然后确保使用<thead>和格式化表,<tbody>否则将不起作用。那是唯一的陷阱。

还支持AJAX等。与所有非常好的代码一样,将其全部关闭也非常容易。不过,您会惊讶于您可能会使用什么。我从一个“裸”数据表开始,该数据表仅对一个字段进行了排序,然后意识到某些功能与我正在做的事情确实相关。客户喜欢这些新功能。

奖励指向DataTables,以提供对ThemeRoller的全面支持...。

我也对tablesorter感到很幸运,但是它几乎不那么容易,没有很好的文档记录,并且只有不错的功能。


4
同意它是一个很好的功能丰富的插件,但是对于OP所需的复杂性和大小而言,可能会过分杀伤。
redsquare


1
我也同意,datatables.net是那里最好的表排序器/分页器/搜索器。它的丰富功能为我节省了大量时间。我只后悔我花了很多时间试图将tablesorter2插件集成到我的代码中,然后才发现数据表...
Logan

2
我知道这是一个旧线程,但是此答案仍然适用。可能是我用过的最简单的插件。花了5分钟来整理它并整理我的桌子。谢谢!
Trucktech

设置非常容易,最好的就是我用过的。
罗格

18

我们刚刚开始使用此工具:https : //plugins.jquery.com/tablesorter/

有关其使用的视频,请访问:http : //www.highoncoding.com/Articles/695_Sorting_GridView_Using_JQuery_TableSorter_Plug_in.aspx

    $('#tableRoster').tablesorter({
        headers: {
            0: { sorter: false },
            4: { sorter: false }
        }
    });

用简单的桌子

<table id="tableRoster">
        <thead> 
                  <tr>
                    <th><input type="checkbox" class="rCheckBox" value="all" id="rAll" ></th>
                    <th>User</th>
                    <th>Verified</th>
                    <th>Recently Accessed</th>
                    <th>&nbsp;</th>
                  </tr>
        </thead>

15

我的回答是“小心”。许多jQuery表排序加载项仅对传递给浏览器的内容进行排序。在许多情况下,您必须记住,表是动态数据集,并且可能包含成千上万行数据。

您确实提到只有4列,但更重要的是,您没有提及我们在此处讨论的行数。

如果您从数据库向浏览器传递5000行,并知道实际的数据库表包含100,000行,那么我的问题是:使表可排序有什么意义?为了进行适当的排序,您必须将查询发送回数据库,然后让数据库(实际上是用于对数据进行排序的工具)为您进行排序。

但是,直接回答您的问题时,遇到的最好的排序附加组件是Ingrid。我不喜欢这个插件有很多原因(如您所说的“不必要的钟声……”),但是就排序而言,它的最佳功能之一就是它使用了ajax,并且没有假设您在进行排序之前已经将所有数据传递给它。

我认识到,对于您的要求而言,这个答案可能过于严格(并且迟了2年以上),但是当我所在领域的开发人员忽略了这一点时,我一定会感到恼火。因此,我希望其他人对此有所了解。

我现在感觉好多了。


6

我喜欢这个公认的答案,但是,很少有人会要求您对html进行排序,而不必添加指示排序方向的图标。我以接受答案的用法示例为例,并通过将引导程序添加到我的项目中并添加以下代码来快速修复该问题:

<div></div>

在每个<th>图标的内部,以便您可以放置​​图标。

setIcon(this, inverse);

从接受的答案的用法,在下面的行中:

th.click(function () {

并通过添加setIcon方法:

function setIcon(element, inverse) {

        var iconSpan = $(element).find('div');

        if (inverse == false) {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('icon-white icon-arrow-up');
        } else {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('icon-white icon-arrow-down');
        }
        $(element).siblings().find('div').removeClass();
    }

这是一个演示。-您需要在Firefox或IE中运行该演示,或者禁用Chrome的MIME类型检查以使该演示正常工作。它取决于通过接受的答案链接的sortElements插件作为外部资源。只是一个提示!


6

这是对表格进行排序的好方法:

$(document).ready(function () {
                $('th').each(function (col) {
                    $(this).hover(
                            function () {
                                $(this).addClass('focus');
                            },
                            function () {
                                $(this).removeClass('focus');
                            }
                    );
                    $(this).click(function () {
                        if ($(this).is('.asc')) {
                            $(this).removeClass('asc');
                            $(this).addClass('desc selected');
                            sortOrder = -1;
                        } else {
                            $(this).addClass('asc selected');
                            $(this).removeClass('desc');
                            sortOrder = 1;
                        }
                        $(this).siblings().removeClass('asc selected');
                        $(this).siblings().removeClass('desc selected');
                        var arrData = $('table').find('tbody >tr:has(td)').get();
                        arrData.sort(function (a, b) {
                            var val1 = $(a).children('td').eq(col).text().toUpperCase();
                            var val2 = $(b).children('td').eq(col).text().toUpperCase();
                            if ($.isNumeric(val1) && $.isNumeric(val2))
                                return sortOrder == 1 ? val1 - val2 : val2 - val1;
                            else
                                return (val1 < val2) ? -sortOrder : (val1 > val2) ? sortOrder : 0;
                        });
                        $.each(arrData, function (index, row) {
                            $('tbody').append(row);
                        });
                    });
                });
            });
            table, th, td {
            border: 1px solid black;
        }
        th {
            cursor: pointer;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
        <tr><th>id</th><th>name</th><th>age</th></tr>
        <tr><td>1</td><td>Julian</td><td>31</td></tr>
        <tr><td>2</td><td>Bert</td><td>12</td></tr>
        <tr><td>3</td><td>Xavier</td><td>25</td></tr>
        <tr><td>4</td><td>Mindy</td><td>32</td></tr>
        <tr><td>5</td><td>David</td><td>40</td></tr>
    </table>

小提琴可以在这里找到:https :
//jsfiddle.net/e3s84Luw/

可以在这里找到说明:https : //www.learningjquery.com/2017/03/how-to-sort-html-table-using-jquery-code



2

@Nick Grealy的回答很好,但是它没有考虑rowspan表头单元格的可能属性(可能其他答案也没有这样做)。这是对@Nick Grealy答案的改进,从而解决了该问题。也基于此答案(感谢@Andrew Orlov)。

我还用自定义$.isNumeric函数替换了该函数(感谢@zad),以使其与较旧的jQuery版本一起使用。

要激活它,添加class="sortable"<table>标签。

$(document).ready(function() {

    $('table.sortable th').click(function(){
        var table = $(this).parents('table').eq(0);
        var column_index = get_column_index(this);
        var rows = table.find('tbody tr').toArray().sort(comparer(column_index));
        this.asc = !this.asc;
        if (!this.asc){rows = rows.reverse()};
        for (var i = 0; i < rows.length; i++){table.append(rows[i])};
    })

});

function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index);
        return isNumber(valA) && isNumber(valB) ? valA - valB : valA.localeCompare(valB);
    }
}
function getCellValue(row, index){ return $(row).children('td').eq(index).html() };

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function get_column_index(element) {
    var clickedEl = $(element);
    var myCol = clickedEl.closest("th").index();
    var myRow = clickedEl.closest("tr").index();
    var rowspans = $("th[rowspan]");
    rowspans.each(function () {
        var rs = $(this);
        var rsIndex = rs.closest("tr").index();
        var rsQuantity = parseInt(rs.attr("rowspan"));
        if (myRow > rsIndex && myRow <= rsIndex + rsQuantity - 1) {
            myCol++;
        }
    });
    // alert('Row: ' + myRow + ', Column: ' + myCol);
    return myCol;
};

如果按日期排序该怎么办?
wubblyjuggly

@wubblyjuggly,您可以将比较器函数替换为比较日期的函数,请参见例如stackoverflow.com/questions/10636779/jquery-date-sorting
Dennis Golomazov

1
太棒了,我已经尝试了数十种分选机,您的分选机是唯一对我有用的分选机。顺便说一句,我的日期是文本格式(2020.02.23),所以这对我来说不是问题
Manny Ramirez

2

您可以使用提供排序,过滤和分页的jQuery插件(品种):

HTML:

<table>
  <thead>
    <tr>
      <th sort='name'>Name</th>
      <th>Phone</th>
      <th sort='city'>City</th>
      <th>Speciality</th>
    </tr>
  </thead>
  <tbody>
    <tr b-scope="people" b-loop="person in people">
      <td b-sort="name">{{person.name}}</td>
      <td>{{person.phone}}</td>
      <td b-sort="city">{{person.city}}</td>
      <td>{{person.speciality}}</td>
    </tr>
  </tbody>
</table>

JS:

$(function(){
  var data = {
    people: [
      {name: 'c', phone: 123, city: 'b', speciality: 'a'},
      {name: 'b', phone: 345, city: 'a', speciality: 'c'},
      {name: 'a', phone: 234, city: 'c', speciality: 'b'},
    ]
  };
  breed.run({
    scope: 'people',
    input: data
  });
  $("th[sort]").click(function(){
    breed.sort({
      scope: 'people',
      selector: $(this).attr('sort')
    });
  });
});

小提琴上的工作示例


2

这个不会挂断浏览器,可以进一步轻松配置:

var table = $('table');

$('th.sortable').click(function(){
    var table = $(this).parents('table').eq(0);
    var ths = table.find('tr:gt(0)').toArray().sort(compare($(this).index()));
    this.asc = !this.asc;
    if (!this.asc)
       ths = ths.reverse();
    for (var i = 0; i < ths.length; i++)
       table.append(ths[i]);
});

function compare(idx) {
    return function(a, b) {
       var A = tableCell(a, idx), B = tableCell(b, idx)
       return $.isNumeric(A) && $.isNumeric(B) ? 
          A - B : A.toString().localeCompare(B)
    }
}

function tableCell(tr, index){ 
    return $(tr).children('td').eq(index).text() 
}

1
这似乎是最好的解决方案。它不需要插件。您可以删除第一行,然后在文档中准备粘贴$('th.sortable')。click(...)块。给表头一个可排序的类,您就完成了。<th class ='sortable> title </ th>。适用于带有文本或数字的列。
pizzamonster

1

对于James的回应,我只会更改排序功能以使其更具通用性。这样,它将对字母和数字(如数字)进行排序。

if( $.text([a]) == $.text([b]) )
    return 0;
if(isNaN($.text([a])) && isNaN($.text([b]))){
    return $.text([a]) > $.text([b]) ? 
       inverse ? -1 : 1
       : inverse ? 1 : -1;
}
else{
    return parseInt($.text([a])) > parseInt($.text([b])) ? 
      inverse ? -1 : 1
      : inverse ? 1 : -1;
}

1

排序HTML表的另一种方法。(基于W3.JS HTML排序

/* Facility Name */
$('#bioTable th:eq(0)').addClass("control-label pointer");
/* Phone # */
$('#bioTable th:eq(1)').addClass("not-allowed");
/* City */
$('#bioTable th:eq(2)').addClass("control-label pointer");
/* Specialty */
$('#bioTable th:eq(3)').addClass("not-allowed");


var collection = [{
  "FacilityName": "MinION",
  "Phone": "999-8888",
  "City": "France",
  "Specialty": "Genetic Prediction"
}, {
  "FacilityName": "GridION X5",
  "Phone": "999-8812",
  "City": "Singapore",
  "Specialty": "DNA Assembly"
}, {
  "FacilityName": "PromethION",
  "Phone": "929-8888",
  "City": "San Francisco",
  "Specialty": "DNA Testing"
}, {
  "FacilityName": "iSeq 100 System",
  "Phone": "999-8008",
  "City": "Christchurch",
  "Specialty": "gDNA-mRNA sequencing"
}]

$tbody = $("#bioTable").append('<tbody></tbody>');

for (var i = 0; i < collection.length; i++) {
  $tbody = $tbody.append('<tr class="item"><td>' + collection[i]["FacilityName"] + '</td><td>' + collection[i]["Phone"] + '</td><td>' + collection[i]["City"] + '</td><td>' + collection[i]["Specialty"] + '</td></tr>');
}
.control-label:after {
  content: "*";
  color: red;
}

.pointer {
  cursor: pointer;
}

.not-allowed {
  cursor: not-allowed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.w3schools.com/lib/w3.js"></script>
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet" />
<p>Click the <strong>table headers</strong> to sort the table accordingly:</p>

<table id="bioTable" class="w3-table-all">
  <thead>
    <tr>
      <th onclick="w3.sortHTML('#bioTable', '.item', 'td:nth-child(1)')">Facility Name</th>
      <th>Phone #</th>
      <th onclick="w3.sortHTML('#bioTable', '.item', 'td:nth-child(3)')">City</th>
      <th>Specialty</th>
    </tr>
  </thead>
</table>


1

我最终使用了尼克的答案(最受欢迎但未被接受)https://stackoverflow.com/a/19947532/5271220

并将其与https://stackoverflow.com/a/16819442/5271220组合在一起,但不想在项目中添加图标或字体。我对sort-column-asc / desc的CSS样式进行了颜色,填充,圆角边框处理。

我还修改了它以按类而不是按类进行,以便我们可以控制哪些是可排序的。如果有两个表,稍后也可以派上用场,尽管为此需要做更多修改。

身体:

 html += "<thead>\n";
    html += "<th></th>\n";
    html += "<th class=\"sort-header\">Name <span></span></i></th>\n";
    html += "<th class=\"sort-header\">Status <span></span></th>\n";
    html += "<th class=\"sort-header\">Comments <span></span></th>\n";
    html += "<th class=\"sort-header\">Location <span></span></th>\n";
    html += "<th nowrap class=\"sort-header\">Est. return <span></span></th>\n";
    html += "</thead>\n";
    html += "<tbody>\n"; ...

...深入身体

$("body").on("click", ".sort-header", function (e) {
    var table = $(this).parents('table').eq(0)
    var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
    this.asc = !this.asc
    if (!this.asc) { rows = rows.reverse() }
    for (var i = 0; i < rows.length; i++) { table.append(rows[i]) }

    setIcon(e.target, this.asc);
});

功能:

function comparer(index) {
        return function (a, b) {
            var valA = getCellValue(a, index), valB = getCellValue(b, index)
            return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
        }
    }

    function getCellValue(row, index) {
        return $(row).children('td').eq(index).text()
    }

    function setIcon(element, inverse) {

        var iconSpan = $(element).find('span');

        if (inverse == true) {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('sort-column-asc');
            $(iconSpan)[0].innerHTML = " &#8593 " // arrow up
        } else {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('sort-column-desc');
            $(iconSpan)[0].innerHTML = " &#8595 " // arrow down 
        }

        $(element).siblings().find('span').each(function (i, obj) {
            $(obj).removeClass();
            obj.innerHTML = "";
        });
    }

-3

我的票!jquery.sortElements.js简单的jquery
非常简单,非常容易,感谢nandhp ...

            $('th').live('click', function(){

            var th = $(this), thIndex = th.index(), var table = $(this).parent().parent();

                switch($(this).attr('inverse')){
                case 'false': inverse = true; break;
                case 'true:': inverse = false; break;
                default: inverse = false; break;
                }
            th.attr('inverse',inverse)

            table.find('td').filter(function(){
                return $(this).index() === thIndex;
            }).sortElements(function(a, b){
                return $.text([a]) > $.text([b]) ?
                    inverse ? -1 : 1
                    : inverse ? 1 : -1;
            }, function(){
                // parentNode is the element we want to move
                return this.parentNode; 
            });
            inverse = !inverse;     
            });

Dei uma melhorada docódigo
一个鳕鱼更好! 所有时间所有Th中的所有表的功能...看!
演示


2
除了无法理解一个单词外,我强烈建议您反对.live()
化身为
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.