Eu tenho uma tabela HTML muito simples com 4 colunas:
Facility Name, Phone #, City, Specialty
Desejo que o usuário possa classificar apenas por Nome da instalação e Cidade .
Como posso codificar isso usando jQuery?
Eu tenho uma tabela HTML muito simples com 4 colunas:
Facility Name, Phone #, City, Specialty
Desejo que o usuário possa classificar apenas por Nome da instalação e Cidade .
Como posso codificar isso usando jQuery?
Respostas:
Se você quiser evitar todos os sinos e assobios, posso sugerir este sortElements
plugin simples . 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 uma demo. (clique nos cabeçalhos das colunas "cidade" e "instalação" para classificar)
Error: illegal character
o html não é exatamente o mesmo, também tenho thead e tboy, você pode me ajudar com isso, por favor?
$.text([a]) == $.text([b])
usar, $.text([a]).toUpperCase() == $.text([b]).toUpperCase()
será corrigido.
Me deparei com isso, e pensei em jogar meus 2 centavos. Clique nos cabeçalhos das colunas para classificar em ordem crescente e novamente para classificar em ordem 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>
td
s, por exemplo, <a href="#">Test</a>
a classificação diz respeito a <a...
. Para classificar apenas por texto, você precisa alterar html()
na última linha para text()
.
comparer(..)
se souber exatamente qual formato deseja suportar). Enquanto isso, se você yyyy-MM-dd
" string
" usar , a classificação ordenará os dados para você. por exemplo jsbin.com/pugedip/1
De longe, o mais fácil que eu usei é: http://datatables.net/
Surpreendentemente simples ... apenas certifique-se de seguir a rota de substituição do DOM (IE, construindo uma tabela e permitindo que o DataTables a reformate) e certifique-se de formatar sua tabela <thead>
e <tbody>
ou ela não funcionará. Essa é a única pegadinha.
Também há suporte para AJAX, etc. Como em todos os códigos realmente bons, também é MUITO fácil desativar tudo. Você ficaria surpreso com o que poderia usar. Comecei com uma DataTable "vazia" que classificou apenas um campo e depois percebi que alguns dos recursos eram realmente relevantes para o que estou fazendo. Os clientes adoram os novos recursos.
Pontos de bônus para DataTables para suporte completo ao ThemeRoller ....
Eu também tive sorte com o tablesorter, mas não é tão fácil, nem tão bem documentado e possui apenas recursos ok.
Acabamos de começar a usar esta ferramenta: https://plugins.jquery.com/tablesorter/
Há um vídeo sobre seu uso em: http://www.highoncoding.com/Articles/695_Sorting_GridView_Using_JQuery_TableSorter_Plug_in.aspx
$('#tableRoster').tablesorter({
headers: {
0: { sorter: false },
4: { sorter: false }
}
});
Com uma mesa simples
<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>
Minha resposta seria "tenha cuidado". Muitos complementos de classificação de tabelas do jQuery classificam apenas o que você passa para o navegador. Em muitos casos, você deve ter em mente que as tabelas são conjuntos dinâmicos de dados e podem conter um zilhão de linhas de dados.
Você menciona que possui apenas 4 colunas, mas, muito mais importante, não menciona quantas linhas estamos falando aqui.
Se você passar 5000 linhas para o navegador a partir do banco de dados, sabendo que a tabela de banco de dados real contém 100.000 linhas, minha pergunta é: qual é o sentido de tornar a tabela classificável? Para fazer uma classificação adequada, você precisará enviar a consulta de volta ao banco de dados e permitir que o banco de dados (uma ferramenta realmente projetada para classificar dados) faça a classificação por você.
Em resposta direta à sua pergunta, o melhor complemento de classificação que eu me deparei é a Ingrid. Há muitas razões pelas quais eu não gosto desse complemento ("sinos e assobios desnecessários ..." como você o chama), mas um de seus melhores recursos em termos de classificação é que ele usa ajax e não Não presuma que você já passou todos os dados antes de fazer sua classificação.
Reconheço que esta resposta provavelmente é um exagero (e com mais de 2 anos de atraso) para seus requisitos, mas fico aborrecido quando os desenvolvedores da minha área ignoram esse ponto. Então, espero que outra pessoa compreenda.
Eu me sinto melhor agora.
Adoro essa resposta aceita, no entanto, raramente você obtém requisitos para classificar html e não precisa adicionar ícones indicando a direção da classificação. Peguei o exemplo de uso da resposta de aceitação e o corrigi rapidamente, simplesmente adicionando bootstrap ao meu projeto e adicionando o seguinte código:
<div></div>
dentro de cada um <th>
para que você tenha um lugar para definir o ícone.
setIcon(this, inverse);
do uso da resposta aceita, abaixo da linha:
th.click(function () {
e adicionando o 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();
}
Aqui está uma demonstração . - Você precisa executar a demonstração no Firefox ou IE ou desativar a verificação do tipo MIME do Chrome para que a demonstração funcione. Depende do plug-in sortElements, vinculado pela resposta aceita, como um recurso externo. Apenas um alerta!
Esta é uma boa maneira de classificar uma tabela:
$(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>
O violino pode ser encontrado aqui:
https://jsfiddle.net/e3s84Luw/
A explicação pode ser encontrada aqui: https://www.learningjquery.com/2017/03/how-to-sort-html-table-using-jquery-code
Aqui está um gráfico que pode ser útil para decidir qual usar: http://blog.sematext.com/2011/09/19/top-javascript-dynamic-table-libraries/
A resposta de @Nick Grealy é ótima, mas não leva em consideração os possíveis rowspan
atributos das células do cabeçalho da tabela (e provavelmente as outras respostas também não o fazem). Aqui está uma melhoria da resposta de @Nick Grealy que corrige isso. Com base nesta resposta também (obrigado @Andrew Orlov).
Também substituí a $.isNumeric
função por uma personalizada (obrigado @zad) para fazê-la funcionar com versões mais antigas do jQuery.
Para ativá-lo, adicione class="sortable"
à <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;
};
Você pode usar um plugin jQuery ( breedjs ) que fornece classificação, filtro e paginação:
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')
});
});
});
Este não desliga o navegador, é 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()
}
À resposta de James, mudarei apenas a função de classificação para torná-la mais universal. Dessa forma, ele classificará o texto em ordem alfabética e os 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;
}
Outra abordagem para classificar a tabela HTML. (com base na classificação HTML do 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>
Acabei usando a resposta de Nick (a mais popular, mas não aceita) https://stackoverflow.com/a/19947532/5271220
e combinou-o com o https://stackoverflow.com/a/16819442/5271220, mas não quis adicionar ícones ou fontawesome ao projeto. Os estilos CSS para sort-column-asc / desc Eu fiz cores, preenchimentos, bordas arredondadas.
Também o modifiquei para ir por classe e não por qualquer, para podermos controlar quais são classificáveis. Isso também pode ser útil mais tarde, se houver duas tabelas, embora mais modificações precisem ser feitas para isso.
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"; ...
... mais abaixo no 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);
});
funções:
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 = "";
});
}
Meu voto! jquery.sortElements.js e jquery simples
Muito simples, muito fácil, obrigado 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 better!
Função para Todas as tabelas em todos os Th em todos os tempos ... Olha!
DEMO
.live()
.