[英]Javascript sort table column on click
我的意图是在单击th
时按升序对表列(仅单击的列)进行排序。 在进一步单击时,确切的表格列应按降序排列。
到目前为止我得到了什么:
表格正在排序,但单击时所有三列都在排序 - 我只希望对一列进行排序。
function sortTable(n) { var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0; table = document.getElementById("table"); switching = true; dir = "asc"; while (switching) { switching = false; rows = table.rows; for (i = 1; i < (rows.length - 1); i++) { shouldSwitch = false; x = rows[i].getElementsByTagName("TD")[n]; y = rows[i + 1].getElementsByTagName("TD")[n]; if (dir == "asc") { if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) { shouldSwitch = true; break; } } else if (dir == "desc") { if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) { shouldSwitch = true; break; } } } if (shouldSwitch) { rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); switching = true; switchcount ++; } else { if (switchcount == 0 && dir == "asc") { dir = "desc"; switching = true; } } } }
<table id="table"> <tr> <th onclick="sortTable(0)">Nummer</th> <th onclick="sortTable(1)">Land</th> <th onclick="sortTable(2)">Name</th> </tr> <tr> <td>2</td> <td>Rumänien</td> <td>Dan</td> </tr> <tr> <td>1</td> <td>Deutschland</td> <td>Aaron</td> </tr> <tr> <td>3</td> <td>USA</td> <td>Peter</td> </tr> </table>
对于描述来说,这看起来也太过分了。 如果您只想对行进行排序,那么该代码是几行:
function compareValues(a, b) {
// return -1/0/1 based on what you "know" a and b
// are here. Numbers, text, some custom case-insensitive
// and natural number ordering, etc. That's up to you.
// A typical "do whatever JS would do" is:
return (a<b) ? -1 : (a>b) ? 1 : 0;
}
function sortTable(colnum) {
// get all the rows in this table:
let rows = Array.from(table.querySelectorAll(`tr`));
// but ignore the heading row:
rows = rows.slice(1);
// set up the queryselector for getting the indicated
// column from a row, so we can compare using its value:
let qs = `td:nth-child(${colnum})`;
// and then just... sort the rows:
rows.sort( (r1,r2) => {
// get each row's relevant column
let t1 = r1.querySelector(qs);
let t2 = r2.querySelector(qs);
// and then effect sorting by comparing their content:
return compareValues(t1.textContent,t2.textContent);
});
// and then the magic part that makes the sorting appear on-page:
rows.forEach(row => table.appendChild(row));
}
神奇的部分作品,因为DOM节点可以在一个地方只存在,因此,如果您appendChild
它的东西,它就会不管它是在第一个地方移动。 因此,我们的排序在JS,然后我们运行appendChild
在有序,每一行仅仅是从移动“等。无论是”到,该装置后,我们通过每一行运行“孩子列表的末尾” rows
, presto:现在根据需要重新排序所有行。
当然,您仍然需要自己编写compareValues(a,b)
。 我不知道你想在那里做什么,因为也许你想要自然文本比较,或者你想要“如果值是数字,则作为数字进行比较,仅当它们不是作为文本进行比较时”等。
但是您应该做的一件事是不要使用 1998 事件处理。 不要使用onclick
,在 JS 端正确执行此操作。 所以在你的 HTML 中:
<tr>
<th>Nummer</th>
<th>Land</th>
<th>Name</th>
</tr>
然后在 JS 方面:
table.querySelectorAll(`th`).forEach((th, position) => {
th.addEventListener(`click`, evt => sortTable(position));
});
(更好的是,使用<th><button>Nummer</button></th>
并添加基于th button
的事件侦听th button
,因为它就是这样。如果您有可以单击以“做某事”的文本,那是一个按钮。使用正确的标记,然后只需使用 CSS 设置您想要的样式,例如无边框、背景:继承等)
也许使用不同的方法。 在渲染之前存储您的数据并对数组进行排序。
let tblData = [{ number: 2, land: 'Rumänien', name: 'Dan' }, { number: 1, land: 'Deutschland', name: 'Aaron' }, { number: 3, land: 'USA', name: 'Peter' } ]; const getRow = (data) => `<tr><td>${data.number}</td><td>${data.land}</td><td>${data.name}</td></tr>`; const sortNumber = (a, b) => a.number - b.number; const sortLand = (a, b) => (a.land === b.land) ? 0 : (a.land > b.land) ? 1 : -1; const sortName = (a, b) => (a.name === b.name) ? 0 : (a.name > b.name) ? 1 : -1; function buildTable(data) { document.querySelector('tbody').innerHTML = data.map(row => getRow(row)).join(''); } function sortTable(n) { let sort = sortNumber; switch (n) { case 1: sort = sortLand; break; case 2: sort = sortName; } console.log(n); buildTable(tblData.sort(sort)); } buildTable(tblData);
<table id="table"> <thead> <tr> <th onclick="sortTable(0)">Nummer</th> <th onclick="sortTable(1)">Land</th> <th onclick="sortTable(2)">Name</th> </tr> </thead> <tbody> </tbody> </table>
运行您的代码时,我得到了预期的结果。 我想知道是否仅仅因为您的数据是这样设置的,结果似乎不正确。
例如,您的数据是:
1 Deutschland Aaron
2 Rumänien Dan
3 USA Peter
对 Number 进行排序,将有 Deutschland First 和 Aaron,并且 Deutschland 和 Aaron 在其余数据之前按字母顺序排在第一位。
因此,其他列正在排序是一种错觉,而实际上它们实际上只是遵循您的数据结构。
Mike 'Pomax' Kamermans的回答效果很好,除了排序表会将<tr>
放在<tbody>
标记之外,这是不希望的。 这可以通过更改他的答案来轻松解决:
function sortTable(colnum) {
let tbody = table.querySelector(`tbody`);
let rows = Array.from(table.querySelectorAll(`tr`));
// other codes...
rows.forEach(row => tbody.appendChild(row));
table.appendChild(tbody);
}
然后生成的表应该可以正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.