jQuery表格排序

Posted

技术标签:

【中文标题】jQuery表格排序【英文标题】:jQuery table sort 【发布时间】:2011-03-10 18:30:21 【问题描述】:

我有一个非常简单的 4 列 html 表格:

Facility Name, Phone #, City, Specialty

我希望用户能够仅按设施名称城市进行排序。

如何使用 jQuery 编写代码?

【问题讨论】:

我的投票 - TinyTable 【参考方案1】:

我遇到了这个,并认为我会投入 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 年

对于那些感兴趣的人,我提供了一个ES6 Plain javascript solution here。

【讨论】:

只是一个警告:第 4 行 - 扩展 dom 元素被认为是不好的做法 - perfectionkills.com/whats-wrong-with-extending-the-dom 太棒了!请注意,如果您在 tds 中有链接,例如&lt;a href="#"&gt;Test&lt;/a&gt; 排序与&lt;a... 有关。要仅按文本排序,您需要将最后一行的 html() 更改为 text() @wubblyjuggly - 你试过什么?目前该表使用单元格数据(例如 html 值)来确定数据类型(即数字或字符串)。因为日期字符串有多种格式,所以编写一个通用的日期检测器/解析器是不切实际的(如果你确切地知道你想要支持什么格式,你可以重写comparer(..))。同时,如果您使用yyyy-MM-dd,“string”排序将为您排序数据。例如jsbin.com/pugedip/1 这个例子对我来说非常适合我选择的解决方案没有。选择的答案对我不起作用;我不确定是不是因为我使用的是 thead/tbody(没有这些标签的 jsfiddle 确实有效)。 @NickGrealy 你是对的,我在评论中的建议正是被拒绝的编辑。比较jsfiddle.net/gn1vtcLq/2(我的版本)和jsfiddle.net/0a15ky9u(你的版本)。多次单击“性别”标题以查看 ID 或名称随后在您的版本中更改顺序,而在我的版本中保持它们的初始顺序。【参考方案2】:

如果你想避免所有的花里胡哨,那么我可以建议this simple sortElements plugin。用法:

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;

        );

    );

And a demo.(点击“城市”和“设施”列标题进行排序)

【讨论】:

由于插件的位置发生了变化,演示被破坏了。我已经分叉了一个fixed jsfiddle to demo sortElements,它至少似乎对我有用:) @999 也许你可以更新你的答案以链接到固定的演示? 如果一个页面上有多个表格怎么办?我分叉了 jsfiddle jsfiddle.net/CM8bT 我收到这个错误Error: illegal character html 不完全一样,我也有thead 和tboy,你能帮我解决这个问题吗? 在区分大小写的情况下,上述功能将不起作用。在这个插件中'a'!='A'。如果将文本转换为大写或小写然后检查和比较,它将起作用。例如:而不是 $.text([a]) == $.text([b]) 使用 $.text([a]).toUpperCase() == $.text([b]).toUpperCase() 将修复它。 很快你会发现排序根本不是一个特定于表的问题——当你这样做时,这里是my teeny-tiny jQuery plug-in,它将按升序或降序对列表、表格、div 或其他任何内容进行排序.我还使用它来按货币或年份等不同的数据类型进行排序 - 只需提供您自己的函数来返回要排序的数据。 (我喜欢将这些函数分开,并给它们起有意义的名称,以构建我自己的小库,其中包含特定于我正在构建的解决方案的“排序方式”。)【参考方案3】:

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

非常简单...只要确保您使用 DOM 替换路线(IE,构建表格并让 DataTables 重新格式化它),然后确保使用 &lt;thead&gt;&lt;tbody&gt; 格式化您的表格,否则它不会工作。这是唯一的问题。

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

DataTables 的奖励积分以获得完整的 ThemeRoller 支持....

我在使用 tablesorter 时也很幸运,但它并不那么容易,文档记录也不是很好,而且只有好的功能。

【讨论】:

+1 在 NuGet 上可用:nuget.org/List/Packages/jquery.datatables【参考方案4】:

我们刚刚开始使用这个漂亮的工具: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>

【讨论】:

【参考方案5】:

我的回答是“小心”。许多 jQuery 表格排序插件只对传递给浏览器的内容进行排序。在许多情况下,您必须记住,表是动态数据集,可能包含数以亿计的数据行。

你确实提到你只有 4 列,但更重要的是,你没有提到我们在这里讨论的行数。

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

不过,在直接回答您的问题时,我遇到的最好的排序插件是 Ingrid。我不喜欢这个附加组件的原因有很多(“不必要的花里胡哨......”正如你所说的那样),但它在排序方面的最佳功能之一是它使用 ajax,并且不不要假设在它进行排序之前您已经将所有数据传递给它。

我认识到这个答案对于您的要求可能是多余的(并且晚了 2 年多),但是当我所在领域的开发人员忽略这一点时,我确实很生气。所以我希望其他人能接受它。

我现在感觉好多了。

【讨论】:

【参考方案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

【讨论】:

这个非常简单的表格排序器可以很好地处理动态表格数据(php + MariaDB)。谢谢!【参考方案7】:

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

&lt;div&gt;&lt;/div&gt;

在每个&lt;th&gt; 中,以便您有一个设置图标的地方。

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();
    

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

【讨论】:

【参考方案8】:

下面的图表可能有助于决定使用哪个:http://blog.sematext.com/2011/09/19/top-javascript-dynamic-table-libraries/

【讨论】:

【参考方案9】:

@Nick Grealy 的answer 很棒,但它没有考虑到表头单元格的rowspan 属性(可能其他答案也没有)。这是对@Nick Grealy 的答案的改进,它解决了这个问题。也基于this answer(感谢@Andrew Orlov)。

我还用custom one 替换了$.isNumeric 函数(感谢@zad),以使其适用于较旧的jQuery 版本。

要激活它,请将class="sortable" 添加到&lt;table&gt; 标记。

$(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 您可以将比较器功能替换为比较日期的功能,请参见例如***.com/questions/10636779/jquery-date-sorting 太棒了,我已经尝试了几十个分拣机,你的是唯一适合我的。顺便说一句,我的日期是文本格式(2020.02.23),所以这对我来说不是问题【参考方案10】:

对于 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;

【讨论】:

【参考方案11】:

您可以使用提供排序、过滤和分页功能的 jQuery 插件 (breedjs):

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')
    );
  );
);

Working example on fiddle

【讨论】:

【参考方案12】:

这个不会挂起浏览器/s,易于进一步配置:

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

【讨论】:

这似乎是最好的解决方案。它不需要插件。您可以删除第一行,然后在准备好的文档中粘贴 $('th.sortable').click( ... ) 块。给表头排序的类,你就完成了。 【参考方案13】:

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

并将其与https://***.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 = "";
        );
    

【讨论】:

【参考方案14】:

另一种对 HTML 表格进行排序的方法。 (基于W3.JS HTML Sort

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

【讨论】:

【参考方案15】:

我的投票! jquery.sortElements.jssimple 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 do código 一条鳕鱼更好! 所有时间中所有表格的功能...看看!DEMO

【讨论】:

除了看不懂一个词,强烈建议不要.live()

以上是关于jQuery表格排序的主要内容,如果未能解决你的问题,请参考以下文章

jQuery插件 tablesorter 表格排序 使用说明

jQuery插件 tablesorter 表格排序 使用说明

可排序的表格 jQuery

jQuery 可滚动、可排序、可过滤的表格

非常好用的jQuery表格排序插件

表格排序器 jQuery hack