128 votes

Trier un tableau HTML avec JavaScript

Je suis à la recherche d'une solution de tri de tableaux (en JavaScript), mais je n'arrive pas à en trouver une qui convienne. J'ai juste besoin qu'elle trie chaque colonne par ordre alphabétique. Il n'est pas nécessaire d'ignorer le code, les chiffres ou de travailler avec des devises. Il suffit d'un clic sur l'en-tête de la colonne pour la faire passer du tri a-z/z-a.

Quelqu'un connaît-il une solution vraiment simple comme celle-ci ?

276voto

Nick G Points 1689

Je revisite juste une ancienne solution Je me suis dit que j'allais lui donner un coup de jeune pour ses 5 ans d'existence !

  • Javascript pur (ES6)
  • Effectue un tri alpha et numérique - ascendant et descendant
  • Travaux en Chrome , Firefox , Safari (et IE11 (voir ci-dessous)

Explication rapide

  1. ajouter un click à tous les en-têtes ( th ) des cellules...
  2. pour l'actuel table trouver toutes les rangées (sauf la première)...
  3. trier les lignes, en fonction de la valeur de la colonne cliquée...
  4. insérez les lignes dans le tableau, dans le nouvel ordre.

    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>


Support d'IE11 (non-ES6)

Si vous souhaitez prendre en charge IE11, vous devrez abandonner la syntaxe ES6 et utiliser d'autres solutions que les éléments suivants Array.from y Element.closest .

c'est-à-dire

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

Ventilation des fonctions du comparateur

Par souci de brièveté, j'ai compacté les comparer() fonction. C'est un peu complexe/difficile à lire, alors le voici à nouveau éclaté/formaté/commenté.

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

87voto

Paul S. Points 20115

J'ai écrit un code qui permet de trier une table par ligne, en supposant qu'il n'y ait qu'une seule ligne. <tbody> et les cellules n'ont pas de 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);

Si vous ne voulez pas faire les hypothèses ci-dessus, vous devez réfléchir à la façon dont vous voulez vous comporter dans chaque circonstance. (par exemple, tout mettre dans un <tbody> ou additionner tous les éléments précédents colspan valeurs, etc.)

Vous pourriez alors l'attacher à chacune de vos tables, par exemple en supposant que les titres sont dans <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]);
}

puis en invoquant makeAllSortable onload .


Exemple violon d'elle travaillant sur une table.

70voto

jedwards Points 7769

Réponse acceptée de Nick Grealy est génial mais se comporte un peu bizarrement si vos rangées sont à l'intérieur d'un fichier <tbody> (la première ligne n'est jamais triée et, après le tri, les lignes se retrouvent en dehors de la balise tbody, ce qui peut entraîner une perte de formatage).

Il s'agit cependant d'une solution simple :

Il suffit de changer :

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

8voto

AfikDeri Points 1127

La meilleure façon que je connaisse pour trier un tableau HTML avec javascript est la fonction suivante.

Il suffit de lui passer l'identifiant de la table que vous souhaitez trier et le numéro de la colonne sur la ligne. Il suppose que la colonne que vous triez est numérique ou contient des nombres et il effectuera un remplacement regex pour obtenir le nombre lui-même (idéal pour les devises et autres nombres contenant des symboles).

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

En utilisant l'exemple :

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

7voto

BLSully Points 3045

Il fait BEAUCOUP plus que "juste trier", mais dataTables.net fait ce dont vous avez besoin. Je l'utilise quotidiennement, il est bien supporté et TRÈS rapide (il nécessite jQuery).

http://datatables.net/

DataTables est un plug-in pour la bibliothèque Javascript jQuery. Il s'agit d'un outil très flexible, basé sur les principes de l'amélioration progressive, qui permet d'ajouter des contrôles d'interaction avancés à tout tableau HTML.

Google Visualizations est une autre option, mais nécessite un peu plus de configuration que dataTables, mais ne requiert PAS de framework/librairie particulier (autre que google.visualizations) :

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

Et il existe d'autres options... surtout si vous utilisez l'un des autres frameworks JS. Dojo, Prototype, etc. ont tous des plugins "d'amélioration des tableaux" utilisables qui fournissent au minimum une fonctionnalité de tri des tableaux. Beaucoup offrent plus, mais je répète... je n'en ai pas encore rencontré un aussi puissant et aussi RAPIDE que datatables.net.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X