【问题标题】:Sorting HTML table with JavaScript使用 JavaScript 对 HTML 表格进行排序
【发布时间】:2012-12-25 10:08:11
【问题描述】:

我正在寻找一个表格排序解决方案(在 JavaScript 中),但我似乎还找不到合适的解决方案。我只需要它按字母顺序对每一列进行排序。它不需要忽略任何代码或任何数字或使用货币。只需单击列标题即可将其从排序的 a-z/z-a 切换。

有没有人知道这样一个非常简单的解决方案?

【问题讨论】:

    标签: javascript sorting html-table


    【解决方案1】:

    刚刚重温 an old solution,我想我会在它的 5 周年纪念日对其进行整容!

    • 纯 Javascript (ES6)
    • 是否进行字母和数字排序 - 升序和降序
    • 适用于 ChromeFirefoxSafari(和 IE11,见下文)

    快速解释

    1. 向所有标题 (th) 单元格添加 click 事件...
    2. 对于当前table,查找所有行(第一行除外)...
    3. 根据单击列的值对行进行排序...
    4. 以新的顺序将行重新插入表中。

    const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent;
    
    const comparer = (idx, asc) => (a, b) => ((v1, v2) => 
        v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
        )(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
    
    // do the work...
    document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
        const table = th.closest('table');
        Array.from(table.querySelectorAll('tr:nth-child(n+2)'))
            .sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
            .forEach(tr => table.appendChild(tr) );
    })));
    table, th, td {
        border: 1px solid black;
    }
    th {
        cursor: pointer;
    }
    <table>
        <tr><th>Country</th><th>Date</th><th>Size</th></tr>
        <tr><td>France</td><td>2001-01-01</td><td><i>25</i></td></tr>
        <tr><td><a href=#>spain</a></td><td><i>2005-05-05</i></td><td></td></tr>
        <tr><td><b>Lebanon</b></td><td><a href=#>2002-02-02</a></td><td><b>-17</b></td></tr>
        <tr><td><i>Argentina</i></td><td>2005-04-04</td><td><a href=#>100</a></td></tr>
        <tr><td>USA</td><td></td><td>-6</td></tr>
    </table>

    IE11 支持(非 ES6)

    如果您想支持 IE11,则需要放弃 ES6 语法并使用 Array.fromElement.closest 的替代方法。

    var getCellValue = function(tr, idx){ return tr.children[idx].innerText || tr.children[idx].textContent; }
    
    var comparer = function(idx, asc) { return function(a, b) { return function(v1, v2) {
            return v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2);
        }(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
    }};
    
    // do the work...
    Array.prototype.slice.call(document.querySelectorAll('th')).forEach(function(th) { th.addEventListener('click', function() {
            var table = th.parentNode
            while(table.tagName.toUpperCase() != 'TABLE') table = table.parentNode;
            Array.prototype.slice.call(table.querySelectorAll('tr:nth-child(n+2)'))
                .sort(comparer(Array.prototype.slice.call(th.parentNode.children).indexOf(th), this.asc = !this.asc))
                .forEach(function(tr) { table.appendChild(tr) });
        })
    });
    

    比较器功能分解

    为了简洁起见,我压缩了comparer() 函数。它有点复杂/难以阅读,所以在这里再次分解/格式化/注释。

    // Returns a function responsible for sorting a specific column index 
    // (idx = columnIndex, asc = ascending order?).
    var comparer = function(idx, asc) { 
    
        // This is used by the array.sort() function...
        return function(a, b) { 
    
            // This is a transient function, that is called straight away. 
            // It allows passing in different order of args, based on 
            // the ascending/descending order.
            return function(v1, v2) {
    
                // sort based on a numeric or localeCompare, based on type...
                return (v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2)) 
                    ? v1 - v2 
                    : v1.toString().localeCompare(v2);
            }(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
        }
    };
    

    【讨论】:

    • 请注意,如果标题行包含在 元素中,则语句 th.parentNode.parentNode 将失败。我建议使用“var table = th.closest('table');”。请注意,在 IE11/Edge 中似乎没有实现 Element.closest()。
    • 对像我这样的javascript新手的评论,因为我已经浪费了很多时间来理解为什么它对我不起作用。因此,如果您只是将此脚本放在
    • @NickGrealy 感谢您提供优美的代码!这个名称叫什么:this.asc = !this.asc
    • 是否有处理 $ 或其他货币等前缀的解决方案?
    • 如果您的行位于&lt;tbody&gt; 标记内并且此答案起作用,请参阅this tweak 对此答案。
    【解决方案2】:

    假设只有一个&lt;tbody&gt; 并且单元格没有colspan,我编写了一些代码来按行对表格进行排序。

    function sortTable(table, col, reverse) {
        var tb = table.tBodies[0], // use `<tbody>` to ignore `<thead>` and `<tfoot>` rows
            tr = Array.prototype.slice.call(tb.rows, 0), // put rows into array
            i;
        reverse = -((+reverse) || -1);
        tr = tr.sort(function (a, b) { // sort rows
            return reverse // `-1 *` if want opposite order
                * (a.cells[col].textContent.trim() // using `.textContent.trim()` for test
                    .localeCompare(b.cells[col].textContent.trim())
                   );
        });
        for(i = 0; i < tr.length; ++i) tb.appendChild(tr[i]); // append each row in order
    }
    // sortTable(tableNode, columId, false);
    

    如果您不想做出上述假设,则需要考虑您希望在每种情况下的行为方式。 (例如,将所有内容放入一个 &lt;tbody&gt; 或将所有前面的 colspan 值相加,等等)

    然后您可以将其附加到您的每张桌子上,例如假设标题在&lt;thead&gt;

    function makeSortable(table) {
        var th = table.tHead, i;
        th && (th = th.rows[0]) && (th = th.cells);
        if (th) i = th.length;
        else return; // if no `<thead>` then do nothing
        while (--i >= 0) (function (i) {
            var dir = 1;
            th[i].addEventListener('click', function () {sortTable(table, i, (dir = 1 - dir))});
        }(i));
    }
    
    function makeAllSortable(parent) {
        parent = parent || document.body;
        var t = parent.getElementsByTagName('table'), i = t.length;
        while (--i >= 0) makeSortable(t[i]);
    }
    

    然后调用makeAllSortableonload


    示例fiddle 在桌子上工作。

    【讨论】:

    • 啊,我对隐藏表的错误。现在就试试这个。只是为了澄清一下,我会将makeAllSortable() 添加到正文 onload 正确吗?
    • 是的,重新复制现在的代码,因为我编辑了它。还要确保你理解我所做的假设。
    • @lucas572 它目前仅根据.textContent.trim() 做出决定(不会根据复选框状态等进行更改)。如果您想以其他方式决定,请在.sort 中教它。
    • @PaulS。非常感谢,非常有用。我在所有浏览器上都测试过,效果很好,除了IE10,你知道为什么吗?
    • 回答我自己,我在MDN 中找到了选项的用法,所以使用numeric: true 一个,你会很好地处理数字,即使是在字符串中。将.localeCompare(b.cells[col].textContent.trim()) 替换为.localeCompare(b.cells[col].textContent.trim(), undefined, {numeric: true})
    【解决方案3】:

    Nick Grealy's accepted answer 很棒,但如果您的行位于 &lt;tbody&gt; 标记内,则行为有点古怪(第一行从未排序,排序后的行最终位于 tbody 标记之外,可能会丢失格式)。

    不过,这是一个简单的修复方法:

    只是改变:

    document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
      const table = th.closest('table');
      Array.from(table.querySelectorAll('tr:nth-child(n+2)'))
        .sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
        .forEach(tr => table.appendChild(tr) );
    

    到:

    document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
      const table = th.closest('table');
      const tbody = table.querySelector('tbody');
      Array.from(tbody.querySelectorAll('tr'))
        .sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
        .forEach(tr => tbody.appendChild(tr) );
    

    【讨论】:

    • 完美修复!我遇到了问题,因为我的桌子上有&lt;tbody&gt;,这解决了它
    • 你绝对救了我!我试图在没有任何运气的情况下解决同样的问题。这是 tbody 标签/修复第一行问题的非常干净的解决方案。
    • 如果我在 to_html 中使用了格式化程序,我的浮点数已被转换为字符串,这使得上述排序功能无法正常工作。是否可以升级代码,以便将 lambda x: '{0:.3f}%'.format(x*100) 产生的字符串转换回浮点数,以便正确排序?
    • 我可以通过使用 parseFloat 来修复浮点的字符串格式,在这种情况下我已经修改了你的 1 行: (parseFloat(getCellValue(asc ? a : b, idx)), parseFloat(getCellValue( asc ? b : a, idx))。问题是对于 non-float_as_string 列,parseFloat 将返回 NaN,这将不允许进行排序。我正在努力修复您的代码,以便它可以在解析之前检查 isNaN 的 parseFloat。跨度>
    【解决方案4】:

    它不仅仅是“排序”,而是 dataTables.net 可以满足您的需求。我每天都使用它,并且得到很好的支持并且非常快(需要 jQuery)

    http://datatables.net/

    DataTables 是 jQuery Javascript 库的插件。它是一个高度灵活的工具,以渐进增强为基础,可为任何 HTML 表格添加高级交互控件。

    Google Visualizations 是另一种选择,但需要比 dataTables 更多的设置,但不需要任何特定的框架/库(google.visualizations 除外):

    http://code.google.com/apis/ajax/playground/?type=visualization#table

    还有其他选择...特别是如果您使用其他 JS 框架之一。 Dojo、Prototype 等都有可用的“表格增强”插件,至少提供表格排序功能。许多提供更多,但我会重申...我还没有遇到过像 datatables.net 一样强大和快速的。

    【讨论】:

    • 嗯,我会看看那个。虽然希望有一个 javascript 解决方案,但是如果这可行的话,嘿!我对一些人唯一担心的是,当表格中有 HTML 时,他们会感到困惑,这是否只是阅读 HTML 而并不真正关心它在看什么?还是会尝试忽略它?
    • 嗯,从技术上讲,它是 JavaScript。 jQuery 只不过是一个 JS 框架……不是魔法。 DataTables 在处理一些 HTML 方面非常好,但是,您可能需要编写一个自定义排序器(在他的网站上记录)
    • @BLSully:listjs.com 呢?我读到数据表非常厚实,在某些情况下是拍摄小鸟的大标准
    • @AdrienBe:不错的建议!以前没碰过那个。将不得不看看它如何处理非常大的数据集。我之前在 DataTables 中运行了 15,000 多行,它的性能在现代浏览器中仍然可以接受。但我肯定会同意,对于某些问题,DataTables 可能太大了。 ListJS 看起来是个不错的选择(并且还允许您使用除表格以外的 html)
    • @BLSully:今天一直在用,感觉还可以,这里有一个非常简单的例子让你开始stackoverflow.com/questions/20528593/…
    【解决方案5】:

    我知道使用 javascript 对 HTML 表进行排序的最佳方法是使用以下函数。

    只需将您要排序的表的 ID 和行上的列号传递给它。它假定您正在排序的列是数字列或其中包含数字,并将执行正则表达式替换以获取数字本身(非常适合货币和其他带有符号的数字)。

    function sortTable(table_id, sortColumn){
        var tableData = document.getElementById(table_id).getElementsByTagName('tbody').item(0);
        var rowData = tableData.getElementsByTagName('tr');            
        for(var i = 0; i < rowData.length - 1; i++){
            for(var j = 0; j < rowData.length - (i + 1); j++){
                if(Number(rowData.item(j).getElementsByTagName('td').item(sortColumn).innerHTML.replace(/[^0-9\.]+/g, "")) < Number(rowData.item(j+1).getElementsByTagName('td').item(sortColumn).innerHTML.replace(/[^0-9\.]+/g, ""))){
                    tableData.insertBefore(rowData.item(j+1),rowData.item(j));
                }
            }
        }
    }
    

    使用示例:

    $(function(){
        // pass the id and the <td> place you want to sort by (td counts from 0)
        sortTable('table_id', 3);
    });
    

    【讨论】:

    • 我喜欢这个解决方案,但是使用 sort() 不是更快吗?
    • 为什么你需要在 jQuery 中放置一个匿名函数来调用你的函数?不能直接打sortTable('table_id', 3)吗?
    【解决方案6】:

    您可以处理 json 数组和 sort 函数。这是一个非常容易操作的可维护结构(例如:排序)。

    未经测试,但这是这个想法。如果您传入一个数组,在该数组中按它们应该排序的顺序放置列,那将支持多重排序和顺序排序。

    var DATA_TABLE = {
        {name: 'George', lastname: 'Blarr', age:45},
        {name: 'Bob', lastname: 'Arr', age: 20}
        //...
    };
    
    function sortDataTable(arrayColNames, asc) { // if not asc, desc
        for (var i=0;i<arrayColNames.length;i++) {
            var columnName = arrayColNames[i];
            DATA_TABLE = DATA_TABLE.sort(function(a,b){
                if (asc) {
                    return (a[columnName] > b[columnName]) ? 1 : -1;
                } else {
                    return (a[columnName] < b[columnName]) ? 1 : -1;
                }
            });
        }
    }
    
    function updateHTMLTable() {
        // update innerHTML / textContent according to DATA_TABLE
        // Note: textContent for firefox, innerHTML for others
    }
    

    现在假设您需要按姓氏排序,然后是姓名,最后是年龄。

    var orderAsc = true;
    sortDataTable(['lastname', 'name', 'age'], orderAsc);
    

    它应该导致类似:

    {name: 'Jack', lastname: 'Ahrl', age: 20},
    {name: 'Jack', lastname: 'Ahrl', age: 22},
    //...
    

    【讨论】:

    • 我有一个相当长的表,大约 200 行并且还在增长。您认为这种方法会比其他答案更快吗?
    【解决方案7】:

    这是一个使用纯 JavaScript 的完整示例。用于排序的算法基本上是BubbleSort。这是Fiddle

       <!DOCTYPE html>
    <html lang="de">
    <head>
    <meta charset="UTF-8">
    
    <script type="text/javascript">
        function sort(ascending, columnClassName, tableId) {
            var tbody = document.getElementById(tableId).getElementsByTagName(
                    "tbody")[0];
            var rows = tbody.getElementsByTagName("tr");
    
            var unsorted = true;
    
            while (unsorted) {
                unsorted = false
    
                for (var r = 0; r < rows.length - 1; r++) {
                    var row = rows[r];
                    var nextRow = rows[r + 1];
    
                    var value = row.getElementsByClassName(columnClassName)[0].innerHTML;
                    var nextValue = nextRow.getElementsByClassName(columnClassName)[0].innerHTML;
    
                    value = value.replace(',', '.'); // in case a comma is used in float number
                    nextValue = nextValue.replace(',', '.');
    
                    if (!isNaN(value)) {
                        value = parseFloat(value);
                        nextValue = parseFloat(nextValue);
                    }
    
                    if (ascending ? value > nextValue : value < nextValue) {
                        tbody.insertBefore(nextRow, row);
                        unsorted = true;
                    }
                }
            }
        };
    </script>
    </head>
    <body>
        <table id="content-table">
            <thead>
                <tr>
                    <th class="id">ID <a
                        href="javascript:sort(true, 'id', 'content-table');">asc</a> <a
                        href="javascript:sort(false, 'id', 'content-table');">des</a>
                    </th>
                    <th class="country">Country <a
                        href="javascript:sort(true, 'country', 'content-table');">asc</a> <a
                        href="javascript:sort(false, 'country', 'content-table');">des</a>
                    </th>
                    <th class="some-fact">Some fact <a
                        href="javascript:sort(true, 'some-fact', 'content-table');">asc</a>
                        <a href="javascript:sort(false, 'some-fact', 'content-table');">des</a>
                    <th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td class="id">001</td>
                    <td class="country">Germany</td>
                    <td class="some-fact">16.405</td>
                </tr>
                <tr>
                    <td class="id">002</td>
                    <td class="country">France</td>
                    <td class="some-fact">10.625</td>
                </tr>
                <tr>
                    <td class="id">003</td>
                    <td class="country">UK</td>
                    <td class="some-fact">15.04</td>
                </tr>
                <tr>
                    <td class="id">004</td>
                    <td class="country">China</td>
                    <td class="some-fact">13.536</td>
                </tr>
            </tbody>
        </table>
    </body>
    </html>
    

    您也可以从这里查看源代码:https://github.com/wmentzel/table-sort

    【讨论】:

      【解决方案8】:

      按单元格对表格行进行排序。 1.简单一点,有一些特点。 2. 排序时区分“数字”和“字符串” 3. 增加切换按ASC、DESC排序

      var index;      // cell index
      var toggleBool; // sorting asc, desc 
      function sorting(tbody, index){
          this.index = index;
          if(toggleBool){
              toggleBool = false;
          }else{
              toggleBool = true;
          }
      
          var datas= new Array();
          var tbodyLength = tbody.rows.length;
          for(var i=0; i<tbodyLength; i++){
              datas[i] = tbody.rows[i];
          }
      
          // sort by cell[index] 
          datas.sort(compareCells);
          for(var i=0; i<tbody.rows.length; i++){
              // rearrange table rows by sorted rows
              tbody.appendChild(datas[i]);
          }   
      }
      
      function compareCells(a,b) {
          var aVal = a.cells[index].innerText;
          var bVal = b.cells[index].innerText;
      
          aVal = aVal.replace(/\,/g, '');
          bVal = bVal.replace(/\,/g, '');
      
          if(toggleBool){
              var temp = aVal;
              aVal = bVal;
              bVal = temp;
          } 
      
          if(aVal.match(/^[0-9]+$/) && bVal.match(/^[0-9]+$/)){
              return parseFloat(aVal) - parseFloat(bVal);
          }
          else{
                if (aVal < bVal){
                    return -1; 
                }else if (aVal > bVal){
                      return 1; 
                }else{
                    return 0;       
                }         
          }
      }
      

      下面是html示例

                  <table summary="Pioneer">
      
                      <thead>
                          <tr>
                              <th scope="col"  onclick="sorting(tbody01, 0)">No.</th>
                              <th scope="col"  onclick="sorting(tbody01, 1)">Name</th>
                              <th scope="col"  onclick="sorting(tbody01, 2)">Belong</th>
                              <th scope="col"  onclick="sorting(tbody01, 3)">Current Networth</th>
                              <th scope="col"  onclick="sorting(tbody01, 4)">BirthDay</th>
                              <th scope="col"  onclick="sorting(tbody01, 5)">Just Number</th>
                          </tr>
                      </thead>
      
                      <tbody id="tbody01">
                          <tr>
                              <td>1</td>
                              <td>Gwanshic Yi</td>
                              <td>Gwanshic Home</td>
                              <td>120000</td>
                              <td>1982-03-20</td>
                              <td>124,124,523</td>
                          </tr>
                          <tr>
                              <td>2</td>
                              <td>Steve Jobs</td>
                              <td>Apple</td>
                              <td>19000000000</td>
                              <td>1955-02-24</td>
                              <td>194,523</td>
                          </tr>
                          <tr>
                              <td>3</td>
                              <td>Bill Gates</td>
                              <td>MicroSoft</td>
                              <td>84300000000</td>
                              <td>1955-10-28</td>
                              <td>1,524,124,523</td>
                          </tr>
                          <tr>
                              <td>4</td>
                              <td>Larry Page</td>
                              <td>Google</td>
                              <td>39100000000</td>
                              <td>1973-03-26</td>
                              <td>11,124,523</td>
                          </tr>
                      </tbody>
                  </table>
      

      【讨论】:

        【解决方案9】:

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

        var collection = [{
          "Country": "France",
          "Date": "2001-01-01",
          "Size": "25",
        }, {
          "Country": "spain",
          "Date": "2005-05-05",
          "Size": "",
        }, {
          "Country": "Lebanon",
          "Date": "2002-02-02",
          "Size": "-17",
        }, {
          "Country": "Argentina",
          "Date": "2005-04-04",
          "Size": "100",
        }, {
          "Country": "USA",
          "Date": "",
          "Size": "-6",
        }]
        
        for (var j = 0; j < 3; j++) {
          $("#myTable th:eq(" + j + ")").addClass("control-label clickable");
          $("#myTable th:eq(" + j + ")").attr('onClick', "w3.sortHTML('#myTable', '.item', 'td:nth-child(" + (j + 1) + ")')");
        }
        
        $tbody = $("#myTable").append('<tbody></tbody>');
        
        for (var i = 0; i < collection.length; i++) {
          $tbody = $tbody.append('<tr class="item"><td>' + collection[i]["Country"] + '</td><td>' + collection[i]["Date"] + '</td><td>' + collection[i]["Size"] + '</td></tr>');
        }
        .control-label:after {
          content: "*";
          color: red;
        }
        
        .clickable {
          cursor: pointer;
        }
        <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="myTable" class="w3-table-all">
          <thead>
            <tr>
              <th>Country</th>
              <th>Date</th>
              <th>Size</th>
            </tr>
          </thead>
        </table>

        【讨论】:

          【解决方案10】:

          另一个紧凑但可读的解决方案: 它只需要将.order 类添加到要排序的每一列的&lt;th&gt; 元素中

          document.querySelectorAll('th.order').forEach(th_elem => {
              let asc=true
              const index = Array.from(th_elem.parentNode.children).indexOf(th_elem)          
              th_elem.addEventListener('click', (e) => {              
                  const arr = [... th_elem.closest("table").querySelectorAll('tbody tr')]
                  arr.sort( (a, b) => {
                      const a_val = a.children[index].innerText
                      const b_val = b.children[index].innerText                   
                      return (asc) ? a_val.localeCompare(b_val) : b_val.localeCompare(a_val)
                  })
                  arr.forEach(elem => {                   
                      th_elem.closest("table").querySelector("tbody").appendChild(elem)
                  })
                  asc = !asc
              })
          })
          

          【讨论】:

          • 非常感谢这个漂亮的解决方案!我只需要切掉表的第一行以防止对 TH 进行排序... const arr = [... th_elem.closest("table").querySelectorAll('tbody tr')].slice(1 )
          【解决方案11】:

          带有 :hover 箭头效果的表格排序。只需将 .order 类添加到要排序的每一列的 &lt;th&gt; 元素中

          function table_sort() {
            const styleSheet = document.createElement('style')
            styleSheet.innerHTML = `
                  .order-inactive span {
                      visibility:hidden;
                  }
                  .order-inactive:hover span {
                      visibility:visible;
                  }
                  .order-active span {
                      visibility: visible;
                  }
              `
            document.head.appendChild(styleSheet)
          
            document.querySelectorAll('th.order').forEach(th_elem => {
              let asc = true
              const span_elem = document.createElement('span')
              span_elem.style = "font-size:0.8rem; margin-left:0.5rem"
              span_elem.innerHTML = "▼"
              th_elem.appendChild(span_elem)
              th_elem.classList.add('order-inactive')
          
              const index = Array.from(th_elem.parentNode.children).indexOf(th_elem)
              th_elem.addEventListener('click', (e) => {
                document.querySelectorAll('th.order').forEach(elem => {
                  elem.classList.remove('order-active')
                  elem.classList.add('order-inactive')
                })
                th_elem.classList.remove('order-inactive')
                th_elem.classList.add('order-active')
          
                if (!asc) {
                  th_elem.querySelector('span').innerHTML = '▲'
                } else {
                  th_elem.querySelector('span').innerHTML = '▼'
                }
                const arr = Array.from(th_elem.closest("table").querySelectorAll('tbody tr'))
                arr.sort((a, b) => {
                  const a_val = a.children[index].innerText
                  const b_val = b.children[index].innerText
                  return (asc) ? a_val.localeCompare(b_val) : b_val.localeCompare(a_val)
                })
                arr.forEach(elem => {
                  th_elem.closest("table").querySelector("tbody").appendChild(elem)
                })
                asc = !asc
              })
            })
          }
          
          table_sort()
          <table>
            <thead>
              <tr>
                <th class="order">Country</th>
                <th class="order">Date</th>
                <th class="order">Size</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>France</td>
                <td>2001-01-01</td>
                <td><i>25</i></td>
              </tr>
              <tr>
                <td><a href=#>spain</a></td>
                <td><i>2005-05-05</i></td>
                <td></td>
              </tr>
              <tr>
                <td><b>Lebanon</b></td>
                <td><a href=#>2002-02-02</a></td>
                <td><b>-17</b></td>
              </tr>
              <tr>
                <td><i>Argentina</i></td>
                <td>2005-04-04</td>
                <td><a href=#>100</a></td>
              </tr>
              <tr>
                <td>USA</td>
                <td></td>
                <td>-6</td>
              </tr>
            </tbody>
          </table>

          【讨论】:

            【解决方案12】:

            如果您的表没有 ths 而只有 tds(包括标题),您可以尝试以下基于 Nick Grealy 的回答:

            const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent;
            
            const comparer = (idx, asc) => (a, b) => ((v1, v2) => 
                v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
                )(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
            
            // do the work...
            document.querySelectorAll('tr:first-child td').forEach(td => td.addEventListener('click', (() => {
                const table = td.closest('table');
                Array.from(table.querySelectorAll('tr:nth-child(n+2)'))
                    .sort(comparer(Array.from(td.parentNode.children).indexOf(td), this.asc = !this.asc))
                    .forEach(tr => table.appendChild(tr) );
            })));
            @charset "UTF-8";
            @import url('https://fonts.googleapis.com/css?family=Roboto');
            
            *{
              font-family: 'Roboto', sans-serif;
              text-transform:capitalize;
              overflow:hidden;
              margin: 0 auto;
              text-align:left;
            }
            
            table {
            	color:#666;
            	font-size:12px;
            	background:#124;
            	border:#ccc 1px solid;
            	-moz-border-radius:3px;
            	-webkit-border-radius:3px;
            	border-radius:3px;
              border-collapse: collapse;
              width: 100%;
            }
            
            table td {
            	padding:10px;
            	border-top: 1px solid #ffffff;
            	border-bottom:1px solid #e0e0e0;
            	border-left: 1px solid #e0e0e0;
            	background: #fafafa;
            	background: -webkit-gradient(linear, left top, left bottom, from(#fbfbfb), to(#fafafa));
            	background: -moz-linear-gradient(top,  #fbfbfb,  #fafafa);
              width: 6.9in;
            }
            
            table tbody tr:first-child td
            {
            	background: #124!important;
              color:#fff;
            }
            
            table tbody tr th
            {
              padding:10px;
              border-left: 1px solid #e0e0e0;
            	background: #124!important;
              color:#fff;
            }
            <table>
                    <tr><td>Country</td><td>Date</td><td>Size</td></tr>
                    <tr><td>France</td><td>2001-01-01</td><td><i>25</i></td></tr>
                    <tr><td>spain</td><td>2005-05-05</td><td></td></tr>
                    <tr><td>Lebanon</td><td>2002-02-02</td><td><b>-17</b></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>

            【讨论】:

              【解决方案13】:

              在页面加载时对 html 表格列进行排序

              var table = $('table#all_items_table');
              var rows = table.find('tr:gt(0)').toArray().sort(comparer(3));
              for (var i = 0; i < rows.length; i++) {
                  table.append(rows[i])
              }
              function comparer(index) {
                  return function (a, b) {
                      var v1= getCellValue(a, index),
                      v2= getCellValue(b, index);
                      return $.isNumeric(v2) && $.isNumeric(v1) ? v2 - v1: v2.localeCompare(v1)
                  }
              }
              
              
              function getCellValue(row, index) {
                  return parseFloat($(row).children('td').eq(index).html().replace(/,/g,'')); //1234234.45645->1234234
              }
              

              【讨论】:

                【解决方案14】:

                <!DOCTYPE html>
                <html>
                <head>
                <style>
                  table, td, th {
                    border: 1px solid;
                    border-collapse: collapse;
                  }
                  td , th {
                    padding: 5px;
                    width: 100px;
                  }
                  th {
                    background-color: lightgreen;
                  }
                </style>
                </head>
                <body>
                
                <h2>JavaScript Array Sort</h2>
                
                <p>Click the buttons to sort car objects on age.</p>
                
                <p id="demo"></p>
                
                <script>
                var nameArrow = "", yearArrow = "";
                var cars = [
                  {type:"Volvo", year:2016},
                  {type:"Saab", year:2001},
                  {type:"BMW", year:2010}
                ];
                yearACS = true;
                function sortYear() {
                  if (yearACS) {
                    nameArrow = "";
                    yearArrow = "?";
                    cars.sort(function(a,b) {
                      return a.year - b.year;
                    });
                    yearACS = false;
                  }else {
                    nameArrow = "";
                    yearArrow = "?";
                    cars.sort(function(a,b) {
                      return b.year - a.year;
                    });
                    yearACS = true;
                  }
                  displayCars();
                }
                nameACS = true;
                function sortName() {
                  if (nameACS) {
                    nameArrow = "?";
                    yearArrow = "";
                    cars.sort(function(a,b) {
                      x = a.type.toLowerCase();
                      y = b.type.toLowerCase();
                      if (x > y) {return 1;}
                      if (x < y) {return -1};
                      return 0;
                    });
                    nameACS = false;
                  } else {
                    nameArrow = "?";
                    yearArrow = "";
                    cars.sort(function(a,b) {
                      x = a.type.toUpperCase();
                      y = b.type.toUpperCase();
                      if (x > y) { return -1};
                      if (x <y) { return 1 };
                      return 0;
                    });
                    nameACS = true;
                  }
                  displayCars();
                }
                
                displayCars();
                
                function displayCars() {
                  var txt = "<table><tr><th onclick='sortName()'>name " + nameArrow + "</th><th onclick='sortYear()'>year " + yearArrow + "</th><tr>";
                  for (let i = 0; i < cars.length; i++) {
                    txt += "<tr><td>"+ cars[i].type + "</td><td>" + cars[i].year + "</td></tr>";
                  }
                  txt += "</table>";
                  document.getElementById("demo").innerHTML = txt;
                }
                
                </script>
                
                </body>
                </html>

                【讨论】:

                【解决方案15】:

                我已编辑此处示例之一的代码以使用 jquery。 它仍然不是 100% jquery。关于这两个不同版本的任何想法,例如每个版本的优缺点是什么

                function column_sort() {
                    getCellValue = (tr, idx) => $(tr).find('td').eq( idx ).text();
                
                    comparer = (idx, asc) => (a, b) => ((v1, v2) => 
                        v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
                        )(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
                    
                    table = $(this).closest('table')[0];
                    tbody = $(table).find('tbody')[0];
                
                    elm = $(this)[0];
                    children = elm.parentNode.children;
                    Array.from(tbody.querySelectorAll('tr')).sort( comparer(
                        Array.from(children).indexOf(elm), table.asc = !table.asc))
                        .forEach(tr => tbody.appendChild(tr) );
                }
                
                table.find('thead th').on('click', column_sort);
                

                【讨论】:

                  【解决方案16】:

                  我非常感谢accepted answerjedwards' fix,但我也发现它们的可读性很差。所以这是我的重构和详细版本:

                  // Remember that strings are false positives for isNaN
                  const isEmptyOrNaN = (obj) => obj === "" || isNaN(obj);
                  
                  const getCellValueInColumn = (tr, columnIdx) =>
                    tr.children[columnIdx].innerText || tr.children[columnIdx].textContent;
                  
                  const compareCellValues = (cellValue1, cellValue2) => {
                    return isEmptyOrNaN(cellValue1) || isEmptyOrNaN(cellValue2)
                      ? cellValue1.toString().localeCompare(cellValue2)
                      : cellValue1 - cellValue2;
                  };
                  
                  const compareFnFactory = (columnIdx, ascending) => (firstEl, secondEl) => {
                    const cellValue1 = getCellValueInColumn(firstEl, columnIdx);
                    const cellValue2 = getCellValueInColumn(secondEl, columnIdx);
                    return ascending
                      ? compareCellValues(cellValue1, cellValue2)
                      : compareCellValues(cellValue2, cellValue1);
                  };
                  
                  document.querySelectorAll("th").forEach((th) =>
                    th.addEventListener("click", () => {
                      const table = th.closest("table");
                      const tbody = table.querySelector("tbody");
                      const columnIdx = Array.from(th.parentNode.children).indexOf(th);
                      const compareFn = compareFnFactory(columnIdx, (this.ascending = !this.ascending));
                      Array.from(tbody.querySelectorAll("tr"))
                        .sort(compareFn)
                        .forEach((tr) => tbody.appendChild(tr));
                    })
                  );
                  

                  如果您发现任何多余的空格或括号,不必要的缩进等,那是因为我已经将代码格式化为更漂亮。

                  我已将此代码包装在一个:

                  javascript: (function () {
                    // Code here
                  })();
                  

                  并将其放入书签中,所以现在我可以在 Keycloak 管理控制台中对列进行排序。

                  【讨论】:

                    猜你喜欢
                    相关资源
                    最近更新 更多
                    热门标签