Ordinamento tabella jQuery


178

Ho una tabella HTML molto semplice con 4 colonne:

Facility Name, Phone #, City, Specialty

Voglio che l'utente sia in grado di ordinare solo per Nome struttura e Città .

Come posso codificare questo usando jQuery?


Il mio voto - TinyTable
redsquare

Risposte:


152

Se vuoi evitare tutte le campane e fischietti, allora posso suggerire questo semplice sortElementsplugin . Uso:

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;

        });

    });

E una demo. (fai clic sulle intestazioni di colonna "città" e "struttura" per ordinare)


6
La demo è stata interrotta perché la posizione del plugin era cambiata. Ho biforcuto un jsfiddle fisso per demo sortElements che almeno sembra funzionare per me :) @ 999 forse potresti aggiornare la tua risposta per collegarti alla demo fissa?
Jake Worrell,

2
Cosa succede se si hanno più tabelle su una pagina? Ho biforcuto jsfiddle jsfiddle.net/CM8bT
Marc

1
Ricevo questo errore Error: illegal characterl'html non è esattamente lo stesso, ho anche thead e tboy, puoi aiutarmi con questo per favore?
pahnin,

1
La funzione sopra non funzionerà in caso di maiuscole / minuscole. In questo plugin 'a'! = 'A'. Funzionerebbe se converte il testo in maiuscolo o minuscolo e quindi controlla e confronta. Ad esempio: Invece di $.text([a]) == $.text([b])utilizzare $.text([a]).toUpperCase() == $.text([b]).toUpperCase()lo risolverà.
NBK,

1
Molto presto scoprirai che l'ordinamento non è affatto un problema specifico della tabella - quando lo fai, ecco il mio plug-in jQuery per ragazzi che ordinerà elenchi, tabelle, div o qualsiasi altra cosa, in ordine crescente o decrescente. L'ho anche usato per ordinare in base a diversi tipi di dati come valuta o anno - basta fornire la propria funzione che restituisce i dati per ordinare. (Mi piace tenere separate quelle funzioni e dare loro nomi significativi, per costruire la mia piccola libreria di "modi per ordinare le cose" che sono specifici per la soluzione che sto costruendo.)
mindplay.dk

185

Mi sono imbattuto in questo e ho pensato di buttare i miei 2 centesimi. Fare clic sulle intestazioni di colonna per ordinare in ordine crescente e di nuovo per ordinare in ordine decrescente.

  • Funziona su Chrome, Firefox, Opera E IE (8)
  • Utilizza solo JQuery
  • Fa l'ordinamento alfa e numerico - crescente e decrescente

$('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>

** Aggiornamento: 2018


10
Fantastico! Basta notare che se si hanno collegamenti in tds, ad esempio <a href="#">Test</a>l'ordinamento riguarda <a.... Per ordinare solo per testo, è necessario modificare html()l'ultima riga in text().
Kai Noack,

1
@wubblyjuggly - cosa hai provato? Attualmente la tabella utilizza i dati della cella (ad es. Valore html) per determinare il tipo di dati (ovvero numero o stringa). Poiché le stringhe di date sono disponibili in molti formati, non è pratico scrivere un rilevatore / parser di date generico (potresti riscrivere comparer(..)se sapessi esattamente quale formato desideri supportare). Nel frattempo, se utilizzi yyyy-MM-dd, l '" string" ordinamento ordinerà i dati per te. ad es. jsbin.com/pugedip/1
Nick Grealy,

1
Questo esempio ha funzionato perfettamente per me dove la soluzione scelta non ha funzionato. La risposta scelta non ha funzionato per me; Non sono sicuro se è perché sto usando un thead / tbody o no (il jsfiddle, senza questi tag, ha funzionato).
RalphTheWonderLlama,

1
Grazie @Jan, ho incorporato il tuo suggerimento nella soluzione!
Nick Grealy,

1
@NickGrealy Hai ragione i miei suggerimenti nel commento in cui esattamente la modifica rifiutata. Confronta jsfiddle.net/gn1vtcLq/2 (la mia versione) con jsfiddle.net/0a15ky9u (la tua versione). Fai clic più volte sull'intestazione "Sesso" per visualizzare gli ID o i nomi che successivamente cambiano l'ordine nella tua versione, mantenendo il loro ordine iniziale nella mia versione.
markus s

39

Di gran lunga il più semplice che ho usato è: http://datatables.net/

Sorprendentemente semplice ... basta assicurarsi se si va il percorso di sostituzione DOM (IE, la costruzione di un tavolo e lasciando DataTables riformattarlo) quindi assicurarsi di formattare la vostra tavola con <thead>e <tbody>o non funzionerà. Questo è l'unico gotcha.

C'è anche il supporto per AJAX, ecc. Come per tutti i pezzi di codice davvero buoni, è anche MOLTO facile spegnerlo. Saresti sorpreso di ciò che potresti usare, però. Ho iniziato con una DataTable "nuda" che ordinava solo un campo e poi mi sono reso conto che alcune delle funzionalità erano davvero rilevanti per quello che sto facendo. I clienti AMANO le nuove funzionalità.

Punti bonus a DataTables per il supporto completo di ThemeRoller ....

Ho anche avuto buona fortuna con tableorter, ma non è così facile, non altrettanto ben documentato e ha solo funzioni ok.


4
D'accordo, è un bel plug-in ricco di funzionalità, ma probabilmente eccessivo in termini di complessità e dimensioni per ciò che l'OP richiede.
Redsquare

2
+1 per essere disponibile su NuGet: nuget.org/List/Packages/jquery.datatables
Frank van Eykelen

1
Sono anche d'accordo, datatables.net è il miglior selezionatore di tabelle / cercapersone / cercatore. Le sue ricche funzionalità mi hanno fatto risparmiare un sacco di tempo. Mi dispiace solo per il tempo che ho trascorso nel tentativo di integrare il plugin tablesorter2 nei miei codici prima di scoprire i database ...
Logan,

2
So che questo è un vecchio thread, ma questa risposta è ancora valida. Probabilmente il plugin più semplice che abbia mai usato. Ci sono voluti 5 minuti per alzarmi e ordinare il mio tavolo. Grazie!
Trucktech,

Molto facile da configurare, il migliore che abbia mai usato.
Rog,

18

Abbiamo appena iniziato a utilizzare questo strumento slick: https://plugins.jquery.com/tablesorter/

C'è un video sul suo uso su: http://www.highoncoding.com/Articles/695_Sorting_GridView_Using_JQuery_TableSorter_Plug_in.aspx

    $('#tableRoster').tablesorter({
        headers: {
            0: { sorter: false },
            4: { sorter: false }
        }
    });

Con un tavolo semplice

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

15

La mia risposta sarebbe "state attenti". Molti componenti aggiuntivi di ordinamento di tabelle jQuery ordinano solo ciò che si passa al browser. In molti casi, è necessario tenere presente che le tabelle sono insiemi di dati dinamici e potrebbero contenere potenzialmente miliardi di righe di dati.

Dici che hai solo 4 colonne, ma soprattutto, non menzioni di quante righe stiamo parlando qui.

Se si passano 5000 righe al browser dal database, sapendo che la tabella di database effettiva contiene 100.000 righe, la mia domanda è: qual è il punto nel rendere ordinabile la tabella? Per fare un corretto ordinamento, dovresti rispedire la query al database e lasciare che il database (uno strumento effettivamente progettato per ordinare i dati) faccia l'ordinamento per te.

In risposta diretta alla tua domanda, il miglior componente aggiuntivo per l'ordinamento che ho incontrato è Ingrid. Ci sono molti motivi per cui non mi piace questo componente aggiuntivo ("campane e fischietti inutili ..." come lo chiami tu), ma una delle sue migliori caratteristiche in termini di ordinamento, è che usa ajax e non supponiamo che tu abbia già passato tutti i dati prima che faccia il suo ordinamento.

Riconosco che questa risposta è probabilmente eccessiva (e oltre 2 anni di ritardo) per le tue esigenze, ma mi annoio quando gli sviluppatori nel mio campo trascurano questo punto. Quindi spero che qualcun altro lo raccolga.

Mi sento meglio ora.


7

Questo è un bel modo di ordinare una tabella:

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

Il violino può essere trovato qui:
https://jsfiddle.net/e3s84Luw/

La spiegazione è disponibile qui: https://www.learningjquery.com/2017/03/how-to-sort-html-table-using-jquery-code


Questo semplicissimo tableorter funziona molto bene con dati di tabella dinamici (php + MariaDB). Grazie!
Ciao, il

6

Adoro questa risposta accettata, tuttavia, raramente hai requisiti per ordinare HTML e non devi aggiungere icone che indicano la direzione di ordinamento. Ho preso l'esempio di utilizzo della risposta di accettazione e l'ho risolto rapidamente aggiungendo semplicemente bootstrap al mio progetto e aggiungendo il seguente codice:

<div></div>

all'interno di ciascuno in <th>modo da avere un posto per impostare l'icona.

setIcon(this, inverse);

dall'uso della risposta accettata, sotto la riga:

th.click(function () {

e aggiungendo il metodo 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();
    }

Ecco una demo . - Devi eseguire la demo in Firefox o IE o disabilitare il controllo del tipo MIME di Chrome affinché la demo funzioni. Dipende dal plug-in sortElements, collegato dalla risposta accettata, come risorsa esterna. Solo un avviso!



2

La risposta di @Nick Grealy è ottima, ma non tiene conto dei possibili rowspanattributi delle celle dell'intestazione della tabella (e probabilmente anche le altre risposte non lo fanno). Ecco un miglioramento della risposta di @Nick Grealy che lo risolve. Anche sulla base di questa risposta (grazie @Andrew Orlov).

Ho anche sostituito la $.isNumericfunzione con una personalizzata (grazie a @zad) per farlo funzionare con le versioni precedenti di jQuery.

Per attivarlo, aggiungi class="sortable"al <table>tag.

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

Che dire se si ordina per data?
wubblyjuggly,

@wubblyjuggly è possibile sostituire la funzione di confronto con uno che mette a confronto le date, si veda ad esempio stackoverflow.com/questions/10636779/jquery-date-sorting
Dennis Golomazov

1
Bravo, ho provato decine di selezionatori, il tuo è l'unico che funziona per me. A proposito, le mie date sono in formato testo (2020.02.23), quindi non è un problema per me
Manny Ramirez,

2

È possibile utilizzare un plug-in jQuery ( breedjs ) che fornisce ordinamento, filtro e impaginazione:

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

Esempio di lavoro sul violino


2

Questo non blocca il / i browser / i, facilmente configurabile ulteriormente:

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

1
Questa sembra la soluzione migliore. Non richiede un plugin. La prima riga che puoi eliminare, quindi nel documento pronto incolla il blocco $ ('th.sortable'). Click (...). Dai alle intestazioni della tabella la classe ordinabile e il gioco è fatto. <th class = 'ordinabile> titolo </th>. Funziona affascinante per colonne con testo o numeri.
Pizzamonster,

1

Alla risposta di James, cambierò la funzione di ordinamento solo per renderla più universale. In questo modo ordinerà il testo in ordine alfabetico e numeri come numeri.

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

1

Un altro approccio per ordinare la tabella HTML. (basato sull'ordinamento HTML W3.JS )

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


1

Ho finito per usare la risposta di Nick (la più popolare ma non accettata) https://stackoverflow.com/a/19947532/5271220

e combinato con https://stackoverflow.com/a/16819442/5271220 ma non volevo aggiungere icone o fontawesome al progetto. Gli stili CSS per sort-column-asc / desc ho fatto colore, riempimento, bordo arrotondato.

L'ho anche modificato per andare in classe anziché in qualsiasi modo in modo da poter controllare quali sono ordinabili. Questo potrebbe tornare utile in seguito se ci sono due tabelle, anche se è necessario apportare ulteriori modifiche.

corpo:

 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"; ...

... più in basso nel corpo

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

funzioni:

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

-4

Il mio voto! jquery.sortElements.js e jquery semplice
Molto semplice, molto facile, grazie 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
Un merluzzo migliore! Funzione per tutte le tabelle in tutti i Th di tutti i tempi ... Guardalo!
DEMO


3
A parte il fatto di non essere in grado di capire una parola, lo sconsiglio vivamente .live().
incarnato il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.