Sortowanie tabeli HTML za pomocą JavaScript

Szukam rozwiązania sortowania tabeli (w JavaScript), ale nie mogę jeszcze znaleźć odpowiedniego. Muszę tylko posortować każdą kolumnę Alfabetycznie. Nie musi ignorować żadnego kodu ani żadnych liczb ani pracować z walutą. Wystarczy kliknąć na nagłówku kolumny przełącza go z sortowane a-z/z-A.

Czy ktoś zna takie proste rozwiązanie?

Author: Willi Mentzel, 2013-01-11

9 answers

[[10]}po prostu przeglądając stare rozwiązanie , pomyślałem, że dam mu lifting na ~5-letnią rocznicę!

  • zwykły Javascript (ES6)
  • czy sortowanie alfanumeryczne-rosnąco i malejąco
  • Działa w Chrome, Firefox, Safari (i IE11 , patrz niżej)

Szybkie wyjaśnienie

  1. Dodaj zdarzenie click do wszystkich komórek nagłówka (th)...
    1. dla bieżącego table, Znajdź wszystkie wiersze (z wyjątkiem pierwszego)...
    2. sortowanie wierszy na podstawie wartości klikniętej kolumny...
    3. Wstaw wiersze z powrotem do tabeli, w nowej kolejności.

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><th>Cost</th></tr>
    <tr><td>France</td><td>2001-01-01</td><td><i>2,500</i></td><td>$1.23</td></tr>
    <tr><td><a href=#>spain</a></td><td><i>2005-05-05</i></td><td></td><td></td></tr>
    <tr><td><b>Lebanon</b></td><td><a href=#>2002-02-02</a></td><td><b>-17</b></td><td>$0.04</td></tr>
    <tr><td><i>Argentina</i></td><td>2005-04-04</td><td><a href=#>1,000</a></td><td>$3</td></tr>
    <tr><td>USA</td><td></td><td>-6</td><td>$1,238.00</td></tr>
</table>
<i><b>N.B.</b> Currencies are not yet parsed...</i>

Obsługa IE11 (nie-ES6)

Jeśli chcesz wspierać IE11, musisz porzucić składnię ES6 i dodać polyfills dla Array.from, Array.forEach oraz Element.closest.

Tzn.

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.from(document.querySelectorAll('th')).forEach(function(th) { th.addEventListener('click', function() {
        var 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(function(tr) { table.appendChild(tr) });
    })
});
 24
Author: Nick Grealy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-07 23:42:50

Napisałem kod, który posortuje tabelę po wierszu, zakładając, że tylko jedna <tbody> i komórki nie mają 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);

Jeśli nie chcesz przyjąć powyższych założeń, musisz zastanowić się, jak chcesz zachować się w każdej sytuacji. (np. umieścić wszystko w jednym <tbody> lub dodać wszystkie poprzedzające colspan wartości itp.)

Możesz następnie dołączyć to do każdej z tabel, np. zakładając, że tytuły są w <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]);
}

A następnie wywołanie makeAllSortable onload .


Przykład fiddle pracy na stole.

 67
Author: Paul S.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-10 22:45:22

Robi znacznie więcej niż "tylko sortowanie", ale dataTables.net robi to, czego potrzebujesz. Używam go codziennie i jest dobrze obsługiwany i bardzo szybki (wymaga jQuery)

Http://datatables.net/

DataTables jest wtyczką do biblioteki jQuery Javascript. Jest to bardzo elastyczne narzędzie, oparte na fundamentach progressive enhancement, które doda zaawansowane kontrolki interakcji do dowolnej tabeli HTML.

Wizualizacje Google to kolejna opcja, ale wymaga trochę więcej konfiguracji niż dataTables, ale nie wymaga żadnego konkretnego frameworka / biblioteki (inne niż google.wizualizacje):

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

I są inne opcje... zwłaszcza jeśli używasz jednego z innych frameworków JS. Dojo, Prototype, etc wszystkie mają użyteczne wtyczki "table enhancement", które zapewniają minimalną funkcjonalność sortowania tabeli. Wielu zapewnia więcej, ale powtórzę...I ' ve yet to come przez jeden tak potężny i tak szybki jak datatables.net.

 6
Author: BLSully,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-10 21:50:05

Najlepszym sposobem, jaki znam, aby sortować tabelę HTML za pomocą javascript jest następująca funkcja.

Po prostu podaj id tabeli, którą chcesz posortować i numer kolumny w wierszu. zakłada, że sortowana kolumna jest numeryczna lub ma w niej Liczby i zrobi regex replace, aby uzyskać sam numer(świetny dla walut i innych liczb z symbolami).

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

Przykład:

$(function(){
    // pass the id and the <td> place you want to sort by (td counts from 0)
    sortTable('table_id', 3);
});
 5
Author: AfikDeri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-14 14:15:37

Możesz mieć do czynienia z tablicą json i funkcją sort. Jest to dość łatwa do utrzymania struktura do manipulowania(np: sortowanie).

Nieprzetestowane, ale mam pomysł. To obsługowałoby wielokrotne porządkowanie i sekwencyjne porządkowanie, jeśli przechodzisz do tablicy, w której umieszczasz kolumny w kolejności, w jakiej powinny być uporządkowane.
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
}

Teraz wyobraźmy sobie, że musisz zamawiać według lastname, potem name, I wreszcie według wieku.

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

Powinno to skutkować czymś w rodzaju:

{name: 'Jack', lastname: 'Ahrl', age: 20},
{name: 'Jack', lastname: 'Ahrl', age: 22},
//...
 2
Author: Frederik.L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-10 23:00:37

Oto kompletny przykład użycia czystego JavaScript. Algorytm używany do sortowania to w zasadzie BubbleSort . Oto Skrzypce .

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

Możesz również sprawdzić źródło tutaj: https://github.com/wmentzel/table-sort

 2
Author: Willi Mentzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-05 12:19:13

Sortowanie wierszy tabeli według komórki. 1. Trochę prostsze i ma pewne funkcje. 2. Rozróżnij "numer" i "ciąg" podczas sortowania 3. Add toggle to sort by 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;       
          }         
    }
}

Poniżej przykład 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>

 1
Author: Gwanshic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-07 06:56:30

W przypadku, gdy twoja tabela nie zawiera th s, a tylko td s (z nagłówkami), możesz wypróbować następujące rozwiązanie, które opiera się na odpowiedzi Nicka Grealy ' ego powyżej:

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>
 0
Author: Apolo Radomer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-16 14:13:52

Inne podejście do sortowania tabeli HTML. (na podstawie 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>
 0
Author: Yi-Ting Liu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-03 01:22:59