我有一个非常简单的HTML表,有4列:

Facility Name, Phone #, City, Specialty

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

我如何使用jQuery编码这个?


当前回答

@Nick Grealy的回答很好,但它没有考虑到表头单元格可能的行跨度属性(可能其他答案也没有这样做)。下面是对@Nick Grealy的回答的改进,解决了这个问题。也是基于这个答案(谢谢@Andrew Orlov)。

我也替换了$。isNumeric函数带有自定义的函数(感谢@zad),以使其适用于较旧的jQuery版本。

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

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

其他回答

我偶然发现了这个,就想发表我的意见。单击列标题进行升序排序,再单击列标题进行降序排序。

适用于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纯Javascript解决方案。

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

并将其与https://stackoverflow.com/a/16819442/5271220结合起来,但不想在项目中添加图标或fontawesome。对于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 = "";
        });
    }

我喜欢这个公认的答案,但是,很少有人要求对html进行排序,而且不需要添加图标来指示排序方向。我采取了接受答案的用法示例,并通过简单地添加bootstrap到我的项目来快速修复,并添加以下代码:

<div></div>

在每个<th>,这样你就有一个地方来设置图标。

setIcon(逆);

从公认答案的用法,在线下:

th。点击(函数(){

并通过添加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 Plugin,由接受的答案链接,作为一个外部资源。提醒一下!

@Nick Grealy的回答很好,但它没有考虑到表头单元格可能的行跨度属性(可能其他答案也没有这样做)。下面是对@Nick Grealy的回答的改进,解决了这个问题。也是基于这个答案(谢谢@Andrew Orlov)。

我也替换了$。isNumeric函数带有自定义的函数(感谢@zad),以使其适用于较旧的jQuery版本。

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

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

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

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

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

直接回答你的问题,我遇到过的最好的排序插件是Ingrid。我不喜欢这个附加组件的原因有很多(你称之为“不必要的铃铛和哨子……”),但它在排序方面最好的特性之一是它使用ajax,并且不假设在它进行排序之前已经将所有数据传递给它。

我意识到这个答案对于您的需求来说可能有些过分(并且晚了2年),但是当我所在领域的开发人员忽视这一点时,我确实很恼火。所以我希望有人能注意到。

我现在感觉好多了。