tipo de tabla jQuery

177

Tengo una tabla HTML muy simple con 4 columnas:

Facility Name, Phone #, City, Specialty

Quiero que el usuario pueda ordenar por nombre de instalación y ciudad solamente.

¿Cómo puedo codificar esto usando jQuery?

Tony Noriega
fuente
Mi voto - TinyTable
redsquare 01 de

Respuestas:

152

Si desea evitar todas las campanas y silbatos, entonces puedo sugerir este simple sortElementscomplemento . 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;

        });

    });

Y una demo. (haga clic en los encabezados de columna "ciudad" y "instalación" para ordenar)

James
fuente
66
La demostración se rompió porque la ubicación del complemento había cambiado. He bifurcado un jsfiddle fijo para los elementos de demostración que al menos parece funcionar para mí :) @ 999 ¿tal vez podría actualizar su respuesta para vincular a la demostración fija?
Jake Worrell
2
¿Qué pasa si tiene varias tablas en una página? Bifurqué el jsfiddle jsfiddle.net/CM8bT
Marc
1
Recibo este error, Error: illegal characterel html no es exactamente el mismo, también tengo thead y tboy, ¿me pueden ayudar con esto por favor?
pahnin
1
La función anterior no funcionará en caso de mayúsculas y minúsculas. En este complemento 'a'! = 'A'. Funcionaría si convierte el texto a mayúsculas o minúsculas y luego verifica y compara. Por ejemplo: en lugar de $.text([a]) == $.text([b])usar $.text([a]).toUpperCase() == $.text([b]).toUpperCase()lo arreglará.
NBK
1
Muy pronto descubrirá que la clasificación no es un problema específico de la tabla: cuando lo haga, aquí está mi pequeño jQuery plug-in que clasificará las listas, tablas, divs o cualquier otra cosa, en orden ascendente o descendente. También lo he usado para ordenar por diferentes tipos de datos, como moneda o año, solo proporcione su propia función que devuelve los datos para ordenar. (Me gusta mantener esas funciones separadas, y darles nombres significativos, para construir mi propia pequeña biblioteca de "formas de ordenar las cosas" que son específicas de la solución que estoy construyendo.)
mindplay.dk
184

Encontré esto, y pensé en tirar mis 2 centavos. Haga clic en los encabezados de columna para ordenar de forma ascendente, y nuevamente para ordenar de manera descendente.

  • Funciona en Chrome, Firefox, Opera e IE (8)
  • Solo usa JQuery
  • ¿Tiene orden alfabético y numérico - ascendente y descendente

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

** Actualización: 2018

Nick Grealy
fuente
10
¡Fantástico! Solo tenga en cuenta que si tiene enlaces en tds, por ejemplo, <a href="#">Test</a>la clasificación se refiere a <a.... Para ordenar por texto solo necesita cambiar html()en la última línea a text().
Kai Noack
1
@wubblyjuggly: ¿qué has intentado? Actualmente, la tabla utiliza los datos de la celda (por ejemplo, el valor html) para determinar el tipo de datos (es decir, número o cadena). Debido a que las cadenas de fecha vienen en muchos formatos, no es práctico escribir un detector / analizador de fecha genérico (podría reescribirlo comparer(..)si supiera exactamente qué formato desea admitir). Mientras tanto, si usa yyyy-MM-dd" string", la ordenación ordenará los datos por usted. por ejemplo jsbin.com/pugedip/1
Nick Grealy
1
Este ejemplo funcionó perfectamente para mí donde la solución elegida no funcionó. La respuesta elegida no funcionó para mí; No estoy seguro de si es porque estoy usando un thead / tbody o no (el jsfiddle, sin estas etiquetas, funcionó).
RalphTheWonderLlama
1
Gracias @ Jan, ¡he incorporado tu sugerencia en la solución!
Nick Grealy
1
@NickGrealy Tienes razón mis sugerencias en el comentario donde exactamente la edición rechazada. Compare jsfiddle.net/gn1vtcLq/2 (mi versión) con jsfiddle.net/0a15ky9u (su versión). Haga clic en el encabezado "Sexo" varias veces para ver los ID o nombres que cambian posteriormente de orden en su versión, manteniendo su orden inicial en mi versión.
Markus s
39

De lejos, el más fácil que he usado es: http://datatables.net/

Increíblemente simple ... solo asegúrese de ir a la ruta de reemplazo DOM (es decir, construir una tabla y dejar que DataTables la vuelva a formatear), luego asegúrese de formatear su tabla con <thead>y<tbody> o no va a funcionar. Esa es la única trampa.

También hay soporte para AJAX, etc. Como con todas las piezas de código realmente buenas, también es MUY fácil desactivarlo todo. Sin embargo, te sorprendería lo que podrías usar. Comencé con un DataTable "desnudo" que solo clasificó un campo y luego me di cuenta de que algunas de las características eran realmente relevantes para lo que estoy haciendo. Los clientes aman las nuevas características.

Puntos de bonificación a DataTables para soporte completo de ThemeRoller ...

También he tenido buena suerte con el clasificador de tablas, pero no es tan fácil, no está tan bien documentado y solo tiene características correctas.

bpeterson76
fuente
44
Estuvo de acuerdo en que es un buen complemento rico en funciones, sin embargo, posiblemente exagere en términos de complejidad y tamaño para lo que requiere el OP.
redsquare
2
+1 por estar disponible en NuGet: nuget.org/List/Packages/jquery.datatables
Frank van Eykelen
1
También estoy de acuerdo, datatables.net es el mejor clasificador / paginizador / buscador de tablas que existe. Sus características ricas me ahorraron mucho tiempo. Solo me arrepiento del tiempo que pasé tratando de integrar el complemento tablesorter2 a mis códigos antes de conocer las tablas de datos ...
Logan
2
Sé que este es un hilo viejo pero esta respuesta aún se aplica. Probablemente el complemento más fácil que he usado. Tomó 5 minutos para levantarlo y ordenar mi mesa. ¡Gracias!
Trucktech
Muy fácil de configurar, mejor que he usado.
Rog
18

Recién comenzamos a usar esta herramienta ingeniosa: https://plugins.jquery.com/tablesorter/

Hay un video sobre su uso en: http://www.highoncoding.com/Articles/695_Sorting_GridView_Using_JQuery_TableSorter_Plug_in.aspx

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

Con una mesa simple

<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>
Ravi Ram
fuente
15

Mi respuesta sería "ten cuidado". Muchos complementos de ordenación de tablas jQuery solo clasifican lo que pasa al navegador. En muchos casos, debe tener en cuenta que las tablas son conjuntos de datos dinámicos y que podrían contener miles de millones de líneas de datos.

Usted menciona que solo tiene 4 columnas, pero mucho más importante, no menciona cuántas filas estamos hablando aquí.

Si pasa 5000 líneas al navegador desde la base de datos, sabiendo que la tabla de base de datos real contiene 100,000 filas, mi pregunta es: ¿cuál es el punto de hacer que la tabla sea ordenable? Para hacer una ordenación adecuada, debe enviar la consulta de vuelta a la base de datos y dejar que la base de datos (una herramienta realmente diseñada para ordenar datos) haga la clasificación por usted.

Sin embargo, en respuesta directa a su pregunta, el mejor complemento de clasificación que he encontrado es Ingrid. Hay muchas razones por las que no me gusta este complemento ("campanas y silbidos innecesarios ..." como lo llamas), pero una de sus mejores características en términos de género es que usa ajax y no No asuma que ya le pasó todos los datos antes de que haga su clasificación.

Reconozco que esta respuesta es probablemente exagerada (y con más de 2 años de retraso) para sus requisitos, pero me molesta cuando los desarrolladores en mi campo pasan por alto este punto. Así que espero que alguien más se dé cuenta.

Me siento mejor ahora.

cartbeforehorse
fuente
7

Esta es una buena manera de ordenar una tabla:

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

El violín se puede encontrar aquí:
https://jsfiddle.net/e3s84Luw/

La explicación se puede encontrar aquí: https://www.learningjquery.com/2017/03/how-to-sort-html-table-using-jquery-code

Julian
fuente
Este clasificador de tablas muy simple funciona muy bien con datos de tablas dinámicas (php + MariaDB). ¡Gracias!
yello
6

Me encanta esta respuesta aceptada, sin embargo, rara vez tienes requisitos para ordenar html y no tienes que agregar iconos que indiquen la dirección de clasificación. Tomé el ejemplo de uso de la respuesta de aceptación y lo arreglé rápidamente simplemente agregando bootstrap a mi proyecto y agregando el siguiente código:

<div></div>

dentro de cada uno <th>para que tenga un lugar para configurar el icono.

setIcon(this, inverse);

del Uso de la respuesta aceptada, debajo de la línea:

th.click(function () {

y agregando el método 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();
    }

Aquí hay una demostración . - Necesita ejecutar la demostración en Firefox o IE, o deshabilitar la comprobación de tipo MIME de Chrome para que la demostración funcione. Depende del complemento sortElements, vinculado por la respuesta aceptada, como un recurso externo. Sólo un aviso!


fuente
2

La respuesta de @Nick Grealy es excelente, pero no tiene en cuenta los posibles rowspanatributos de las celdas del encabezado de la tabla (y probablemente las otras respuestas tampoco lo hacen). Aquí hay una mejora de la respuesta de @Nick Grealy que corrige eso. Basado en esta respuesta también (gracias @Andrew Orlov).

También he reemplazado la $.isNumericfunción por una personalizada (gracias @zad) para que funcione con versiones anteriores de jQuery.

Para activarlo, agréguelo class="sortable"a la <table>etiqueta.

$(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;
};
Dennis Golomazov
fuente
¿Qué pasa si estás ordenando por fecha?
wubblyjuggly
@wubblyjuggly puede reemplazar la función de comparación por una que compare fechas, consulte, por ejemplo, stackoverflow.com/questions/10636779/jquery-date-sorting
Dennis Golomazov
1
Bravo, he probado docenas de clasificadores, el tuyo es el único que funciona para mí. Por cierto, mis fechas están en formato de texto (2020.02.23), así que no es un problema para mí
Manny Ramirez
2

Puede usar un complemento jQuery ( breedjs ) que proporciona clasificación, filtro y paginación:

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

Ejemplo de trabajo en violín

Joao Paulo
fuente
2

Este no cuelga el / los navegador / s, más fácil de configurar:

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() 
}
rapaz
fuente
1
Esta parece la mejor solución. No requiere un complemento. La primera línea que puede eliminar, luego en su documento listo pegue el bloque $ ('th.sortable'). Haga clic (...). Dé a los encabezados de tabla la clase ordenable y ya está. <th class = 'sortable> title </th>. Funciona encantador para columnas con texto o números.
pizzamonster
1

A la respuesta de James, solo cambiaré la función de clasificación para hacerlo más universal. De esta manera, ordenará el texto alfabéticamente y los números como números.

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;
}
Kaloyan Iliev
fuente
1

Otro enfoque para ordenar la tabla HTML. (basado en W3.JS HTML Sort )

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

Penny Liu
fuente
1

Terminé usando la respuesta de Nick (la más popular pero no aceptada) https://stackoverflow.com/a/19947532/5271220

y lo combiné con https://stackoverflow.com/a/16819442/5271220 pero no quise agregar iconos o fontawesome al proyecto. Los estilos CSS para sort-column-asc / desc hice color, relleno, borde redondeado.

También lo modifiqué para ir por clase en lugar de por cualquiera para poder controlar cuáles se pueden ordenar. Esto también podría ser útil más adelante si hay dos tablas, aunque sería necesario realizar más modificaciones para eso.

cuerpo:

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

... más abajo en el cuerpo

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

funciones:

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 = "";
        });
    }
Skwirl ciego
fuente
-4

¡Mi voto! jquery.sortElements.js y jquery simple
Muy simple, muy fácil, gracias 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
One cod mejor! Función para todas las tablas en todo Th en todos los tiempos ... ¡Míralo!
MANIFESTACIÓN

Filipe Rudá
fuente
3
Además de no poder entender una palabra, recomendaría encarecidamente que no .live().
Encarnado el