97

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

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

4

16 回答 16

201

只是重新审视一个旧的解决方案,我想我会在它的 5 周年纪念日给它改头换面!

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

快速解释

  1. click向所有标题 ( ) 单元格添加事件th...
  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 语法并使用 and 的替代Array.from方法Element.closest

IE

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));
    }
};
于 2018-03-01T01:46:28.717 回答
82

我写了一些代码,它将按行对表格进行排序,假设只有一个<tbody>并且单元格没有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);

如果您不想做出上述假设,则需要考虑在每种情况下您希望如何表现。(例如,将所有内容合二为一<tbody>或将所有前面的colspan值相加,等等)

然后,您可以将其附加到您的每个表中,例如假设标题在<thead>

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

然后调用makeAllSortable onload


它在桌子上工作的示例小提琴

于 2013-01-10T22:15:06.637 回答
48

Nick Grealy 接受的答案很好,但如果您的行位于标签内,则行为有点古怪<tbody>(第一行从未排序,排序后的行最终位于 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) );
于 2018-12-21T06:53:39.273 回答
8

它不仅仅是“排序”,而是 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 一样强大和快速的。

于 2013-01-10T21:43:40.270 回答
8

我知道使用 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);
});
于 2016-06-14T14:15:37.473 回答
4

您可以处理 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},
//...
于 2013-01-10T21:46:11.877 回答
4

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

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

于 2016-06-04T19:23:44.363 回答
3

按单元格对表格行进行排序。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>

于 2017-02-07T02:12:39.540 回答
1

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

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>

于 2018-08-03T01:22:59.133 回答
1

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

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
    })
})
于 2021-11-18T12:34:21.020 回答
1

具有 :hover 箭头效果的表格排序。只需将类添加到要排序的每一列.order的元素中<th>

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>

于 2021-11-18T17:32:44.947 回答
0

如果您的表格没有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>

于 2018-05-16T14:13:52.523 回答
0

在页面加载时对 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
}

在此处输入图像描述

于 2019-01-29T10:00:53.460 回答
0

我已经编辑了此处示例之一的代码以使用 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);
于 2020-11-16T18:43:32.180 回答
0

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

于 2020-12-09T16:10:06.107 回答
0

我非常感谢接受的答案jedwards 的修复,但我也发现它们的可读性很差。所以这是我的重构和详细版本:

// 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 管理控制台中对列进行排序。

于 2021-11-11T00:02:32.887 回答