J'ai un tableau HTML très simple avec 4 colonnes:
Facility Name, Phone #, City, Specialty
Je veux que l'utilisateur puisse trier par nom d'installation et par ville uniquement.
Comment puis-je coder cela avec jQuery?
Si vous voulez éviter tout ce qu'il vous faut, permettez-moi de vous suggérer: ce simple plug-in sortElements
. Usage:
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;
});
});
Et une démo. (cliquez sur les en-têtes de colonne "ville" et "facilité" pour les trier)
Je suis tombé sur ça et j'ai pensé y mettre mes 2 centimes. Cliquez sur les en-têtes de colonne pour trier par ordre croissant, puis à nouveau pour trier par ordre décroissant.
$('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>
De loin, le plus simple que j'ai utilisé est: http://datatables.net/
Incroyablement simple ... assurez-vous simplement de choisir le chemin de remplacement du DOM (IE, construction d'un tableau et laisser DataTables le reformater), puis assurez-vous de formater votre tableau avec <thead>
et <tbody>
ou s'il a gagné ' t fonctionne. C'est à peu près le seul casse-tête.
AJAX est également pris en charge, etc. Comme avec tous les très bons morceaux de code, il est également TRÈS facile de tout désactiver. Vous seriez surpris de ce que vous pourriez utiliser, cependant. J'ai commencé avec un DataTable "nu" qui ne triait qu'un seul champ et me rendais compte que certaines fonctionnalités étaient vraiment pertinentes pour ce que je faisais. Les clients adorent les nouvelles fonctionnalités.
Points bonus pour DataTables pour une assistance complète de ThemeRoller ....
J'ai également eu de la chance avec tablesorter, mais ce n'est pas aussi facile, pas aussi bien documenté et il n'a que des fonctionnalités correctes.
Nous venons tout juste de commencer à utiliser cet outil astucieux: https://plugins.jquery.com/tablesorter/
Il existe une vidéo sur son utilisation à l'adresse suivante: http://www.highoncoding.com/Articles/695_Sorting_GridView_Using_JQuery_TableSorter_Plug_in.aspx
$('#tableRoster').tablesorter({
headers: {
0: { sorter: false },
4: { sorter: false }
}
});
Avec une simple table
<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> </th>
</tr>
</thead>
Ma réponse serait "fais attention". Un grand nombre d’add-ons de tri de table jQuery ne trient que ce que vous transmettez au navigateur. Dans de nombreux cas, vous devez garder à l'esprit que les tableaux sont des ensembles de données dynamiques et peuvent potentiellement contenir des millions de lignes de données.
Vous mentionnez que vous n'avez que 4 colonnes, mais plus important encore, vous ne mentionnez pas le nombre de lignes dont nous parlons ici.
Si vous transmettez 5 000 lignes au navigateur à partir de la base de données, sachant que la table de base de données contient 100 000 lignes, ma question est la suivante: à quoi sert-il de rendre la table triable? Pour effectuer un tri correct, vous devez renvoyer la requête à la base de données et laisser la base de données (un outil conçu pour trier les données) effectue le tri à votre place.
En réponse directe à votre question cependant, le meilleur complément de tri que j'ai rencontré est Ingrid. Il y a de nombreuses raisons pour lesquelles je n'aime pas cet add-on ("cloches et sifflets inutiles ..." comme vous l'appelez), mais l'une des meilleures caractéristiques en termes de tri, c'est qu'il utilise ajax, et ne le fait pas. Ne supposez pas que vous avez déjà passé toutes les données avant de faire le tri.
Je reconnais que cette réponse est probablement excessive (et sur 2 ans de retard) pour vos besoins, mais je suis ennuyé lorsque les développeurs de mon domaine négligent ce point. J'espère donc que quelqu'un d'autre le comprendra.
Je me sens mieux maintenant.
J'aime cette réponse acceptée, cependant, vous avez rarement des exigences pour trier le code HTML sans avoir à ajouter d'icônes indiquant la direction du tri. J'ai pris l'exemple d'utilisation de accept answer et corrigé cela rapidement en ajoutant simplement bootstrap à mon projet et en ajoutant le code suivant:
<div></div>
à l'intérieur de chaque <th>
afin que vous ayez un emplacement pour définir l'icône.
setIcon(this, inverse);
à partir de l'utilisation de la réponse acceptée, sous la ligne:
th.click(function () {
et en ajoutant la méthode 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();
}
Voici un démo . --Vous devez exécuter la démonstration dans Firefox ou IE ou désactiver la vérification du type MIME de Chrome pour que la démonstration fonctionne. Cela dépend du plugin sortElements, lié par la réponse acceptée, en tant que ressource externe. Juste un heads-up!
C'est une bonne façon de trier une table:
$(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>
Le violon peut être trouvé ici:
https://jsfiddle.net/e3s84Luw/
L'explication peut être trouvée ici: https://www.learningjquery.com/2017/03/how-to-sort-html-table-using-jquery-code
Voici un tableau qui peut être utile pour décider lequel utiliser: http://blog.sematext.com/2011/09/19/top-javascript-dynamic-table-libraries/
Celui-ci ne raccroche pas le/les navigateur (s), facile à configurer:
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()
}
Vous pouvez utiliser un plugin jQuery ( breedjs ) qui fournit un tri, un filtre et une pagination:
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')
});
});
});
Pour répondre à James, je ne changerai que la fonction de tri pour la rendre plus universelle. De cette façon, le texte sera trié par ordre alphabétique et par chiffres.
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;
}
La réponse de @Nick Grealy réponse est excellente, mais elle ne prend pas en compte les éventuels attributs rowspan
des cellules d'en-tête de la table (et les autres réponses ne le font probablement pas non plus). Voici une amélioration de la réponse de @Nick Grealy qui résout ce problème. Basé sur cette réponse aussi (merci @Andrew Orlov).
J'ai également remplacé la fonction $.isNumeric
par un personnalisé (merci @zad) pour le faire fonctionner avec les anciennes versions de jQuery.
Pour l'activer, ajoutez class="sortable"
à la balise <table>
.
$(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;
};
J'ai fini par utiliser la réponse de Nick (la plus populaire mais pas acceptée) https://stackoverflow.com/a/19947532/527122
et l'a combiné avec le https://stackoverflow.com/a/16819442/527122 mais n'a pas voulu ajouter d'icônes ou de polices de caractères au projet. Les styles CSS pour sort-colonne-asc/desc j'ai fait la couleur, le remplissage, la bordure arrondie.
Je l'ai également modifié pour qu'il soit classé par classe plutôt que par n'importe quel autre afin que nous puissions contrôler ceux qui sont triables. Cela pourrait également s'avérer utile plus tard s'il y a deux tables, bien que d'autres modifications soient nécessaires pour cela.
corps:
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"; ...
... plus bas dans le corps
$("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);
});
les fonctions:
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 = " ↑ " // arrow up
} else {
$(iconSpan).removeClass();
$(iconSpan).addClass('sort-column-desc');
$(iconSpan)[0].innerHTML = " ↓ " // arrow down
}
$(element).siblings().find('span').each(function (i, obj) {
$(obj).removeClass();
obj.innerHTML = "";
});
}
Une autre approche pour trier le tableau HTML. (basé sur tri 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>