我正在使用W3Schools的this code通过点击列标题对所有表行进行排序。正如预期的那样,它按照该col值对所有行进行排序。
我很害羞这已经得到了回答,但是我很难过滤serarch结果,找到一种类似的方法(希望在纯javascript中)通过点击第一列的行来排序列。
这应按所点击的行值排序所有列。
我希望某些组合方法可以按列和行排序,具体取决于用户点击,但只需按行排序方法就可以了。
先谢谢!
预期行为
未排序的表格:
<table id="myTable">
<tbody>
<tr>
<th onclick="sortTableRows(0)">Name</th>
<th onclick="sortTableRows(1)">Col 1</th>
<th onclick="sortTableRows(2)">Col 2</th>
<th onclick="sortTableRows(3)">Col 3</th>
</tr>
<tr>
<td onclick="sortTableCols(1)">Alan Brado</td>
<td>2</td>
<td>3</td>
<td>1</td>
</tr>
<tr>
<td onclick="sortTableCols(2)">Kevin Chuca</td>
<td>1</td>
<td>3</td>
<td>2</td>
</tr>
<tr>
<td onclick="sortTableCols(3)">Pamela Chu</td>
<td>3</td>
<td>2</td>
<td>1</td>
</tr>
</tbody>
</table>
正常:按COLUMN(第1列)对表格进行排序:
<table id="myTable">
<tbody>
<tr>
<th onclick="sortTableRows(0)">Name</th>
<th onclick="sortTableRows(1)">*Col 1*</th>
<th onclick="sortTableRows(2)">Col 2</th>
<th onclick="sortTableRows(3)">Col 3</th>
</tr>
<tr>
<td onclick="sortTableCols(1)">Kevin Chuca</td>
<td>1</td>
<td>3</td>
<td>2</td>
</tr>
<tr>
<td onclick="sortTableCols(1)">Alan Brado</td>
<td>2</td>
<td>3</td>
<td>1</td>
</tr>
<tr>
<td onclick="sortTableCols(3)">Pamela Chu</td>
<td>3</td>
<td>2</td>
<td>1</td>
</tr>
</tbody>
</table>
渴望:ROW排序表(Alan Brado):
<table id="myTable">
<tbody>
<tr>
<th onclick="sortTableRows(0)">Name</th>
<th onclick="sortTableRows(1)">Col 3</th>
<th onclick="sortTableRows(2)">Col 1</th>
<th onclick="sortTableRows(3)">Col 2</th>
</tr>
<tr>
<td onclick="sortTableCols(1)">*Alan Brado*</td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td onclick="sortTableCols(2)">Kevin Chuca</td>
<td>2</td>
<td>1</td>
<td>3</td>
</tr>
<tr>
<td onclick="sortTableCols(3)">Pamela Chu</td>
<td>1</td>
<td>3</td>
<td>2</td>
</tr>
</tbody>
</table>
这是我的片段:
function sortTableRows(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("myTable");
switching = true;
dir = "asc";
while (switching) {
switching = false;
rows = table.getElementsByTagName("TR");
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;
}
}
}
}
function sortTableCols(n) {
alert("This should sort cols by row #"+n+" values");
}
/* Just for beauty */
#myTable {
border: none;
}
#myTable th {
cursor: pointer;
width: 5%;
border: none;
background-color: #e0e0e0;
}
#myTable tr td {
border: none;
border-bottom: 1px solid #aaa;
text-align: center;
}
#myTable tr td:first-child {
cursor: pointer;
background-color: #e0e0e0;
border-bottom: 1px solid #aaa;
text-align: center;
}
#myTable tr:last-child td {
border: none;
}
<table id="myTable">
<tbody>
<tr>
<th onclick="sortTableRows(0)">Name</th>
<th onclick="sortTableRows(1)">Col 1</th>
<th onclick="sortTableRows(2)">Col 2</th>
<th onclick="sortTableRows(3)">Col 3</th>
</tr>
<tr>
<td onclick="sortTableCols(1)">Alan Brado</td>
<td>2</td>
<td>3</td>
<td>1</td>
</tr>
<tr>
<td onclick="sortTableCols(2)">Kevin Chuca</td>
<td>1</td>
<td>3</td>
<td>2</td>
</tr>
<tr>
<td onclick="sortTableCols(3)">Pamela Chu</td>
<td>3</td>
<td>2</td>
<td>1</td>
</tr>
</tbody>
</table>
答案 0 :(得分:1)
更新:请参阅@ sanxofon的回答。是我的改进。
暂时没有答案所以我最终使用此程序解决了问题:
将表格捕获到矩阵
转置矩阵(翻转轴)
按列排序(正常情况下)
向后移调矩阵(再次翻转轴)
将矩阵更新为表格
我发布此帖给任何可能对解决方案感兴趣的人。
性能我还没有对其性能进行测试,但由于所有过程都是在矩阵上完成的,因此完全取决于它的长度和数据。效果很好,可以在任何桌子上实现。
ToDo:可以通过添加行标题和列标题的侦听器以及从表中删除onClick="sortTable(x,y)"
来改进。
就是这样:
var dirc = 0, dirr = 0, cc = 0, rr = 0;
function colSlice(arr,ini=0,fin=0) {
if (ini<0) ini = arr.length+ini;
if (fin==0) fin = arr.length;
else if (fin<0) fin = arr.length+fin;
else fin = ini+fin
var sliced = [];
for (var i = 0; i < arr.length; i++) {
sliced.push([]);
for (var j = 0; j < arr[i].length; j++) {
if (j>=ini && j<fin)
sliced[i].push(arr[i][j]);
}
}
return sliced;
}
function colJoin(a,b) {
var joined = [];
for (var i = 0; i < a.length; i++) {
joined.push([]);
for (var j = 0; j < a[i].length; j++) {
joined[i].push(a[i][j]);
}
for (var j = 0; j < b[i].length; j++) {
joined[i].push(b[i][j]);
}
}
return joined;
}
function sortTable(r,c) {
var table = document.getElementById("myTable");
var rows = table.getElementsByTagName("TR");
var matriz = [];
var m = null;
// Get matrix from table
for (i = 0; i < rows.length; i++) {
if (i==0) cols = rows[i].getElementsByTagName("TH");
else cols = rows[i].getElementsByTagName("TD");
m = [];
for (j = 0; j < cols.length; j++) {
m.push(cols[j].innerHTML);
}
matriz.push(m);
}
if (r==0) { // sort rows by col
if (c==cc) dirc = Math.abs(1-dirc);
else dirc = 0;
m = matriz[0];
matriz = matriz.slice(1);
matriz.sort(function(a, b){
if (dirc<=0) {
if (a[c].toLowerCase() > b[c].toLowerCase()) return 1;
else if (a[c].toLowerCase() < b[c].toLowerCase()) return -1;
} else {
if (a[c].toLowerCase() > b[c].toLowerCase()) return -1;
else if (a[c].toLowerCase() < b[c].toLowerCase()) return 1;
}
return 0;
});
matriz.unshift(m);
cc = c;
}
if (c==0) { // sort cols by row
if (r==rr) dirr = Math.abs(1-dirr);
else dirr = 0;
m = colSlice(matriz,0,1);
matriz = colSlice(matriz,1);
// Transpose matriz
var newArray = matriz[0].map(function(col, i){
return matriz.map(function(row){
return row[i];
});
});
// Sort
newArray.sort(function(a, b){
if (dirr<=0) {
if (a[r].toLowerCase() > b[r].toLowerCase()) return 1;
else if (a[r].toLowerCase() < b[r].toLowerCase()) return -1;
} else {
if (a[r].toLowerCase() > b[r].toLowerCase()) return -1;
else if (a[r].toLowerCase() < b[r].toLowerCase()) return 1;
}
return 0;
});
// Transpose back
matriz = newArray[0].map(function(col, i){
return newArray.map(function(row){
return row[i];
});
});
matriz = colJoin(m,matriz);
rr = r;
}
// Update values
for (i = 0; i < rows.length; i++) {
if (i==0) cols = rows[i].getElementsByTagName("TH");
else cols = rows[i].getElementsByTagName("TD");
for (j = 0; j < cols.length; j++) {
cols[j].innerHTML = matriz[i][j];
}
}
}
&#13;
/* Just for beauty */
#myTable {
border: none;
}
#myTable th {
cursor: n-resize;
border: none;
background-color: #e0e0e0;
}
#myTable th:first-child {
cursor: move;
}
th, td {
width: 5%;
}
#myTable tr td {
border: none;
border-bottom: 1px solid #aaa;
text-align: center;
}
#myTable tr td:first-child {
cursor: e-resize;
background-color: #e0e0e0;
border-bottom: 1px solid #aaa;
text-align: center;
}
#myTable tr:last-child td {
border: none;
}
&#13;
<table id="myTable">
<tbody>
<tr>
<th onclick="sortTable(0,0)">Both</th>
<th onclick="sortTable(0,1)">Col A</th>
<th onclick="sortTable(0,2)">Col B</th>
<th onclick="sortTable(0,3)">Col C</th>
</tr>
<tr>
<td onclick="sortTable(1,0)">Row A</td>
<td>2</td>
<td>3</td>
<td>1</td>
</tr>
<tr>
<td onclick="sortTable(2,0)">Row B</td>
<td>1</td>
<td>3</td>
<td>2</td>
</tr>
<tr>
<td onclick="sortTable(3,0)">Row C</td>
<td>3</td>
<td>2</td>
<td>1</td>
</tr>
</tbody>
</table>
&#13;
干杯!
答案 1 :(得分:1)
我经常问自己这个问题,但似乎从来没有真正需要它,所以再也没有了。您的答案很棒,但在将数字作为字符串进行比较时,您会遇到问题。它不会显示在您的代码中,因为您使用的是1, 2, 3
值。
使用混合数据类型检查我的代码段,当然代码可以减少很多。
var dirc = 0, dirr = 0, cc = 0, rr = 0;
function colSlice(arr,ini=0,fin=0) {
if (ini<0) ini = arr.length+ini;
if (fin==0) fin = (arr.length+1)-ini;
else fin = ini+fin
var sliced = [];
for (var i = 0; i < arr.length; i++) {
sliced.push([]);
for (var j = 0; j < arr[i].length; j++) {
if (j>=ini && j<fin)
if (parseFloat(arr[i][j])>0 || arr[i][j]=="0")
sliced[i].push(parseFloat(arr[i][j]));
else
sliced[i].push(arr[i][j]);
}
}
return sliced;
}
function colJoin(a,b) {
var joined = [];
for (var i = 0; i < a.length; i++) {
joined.push([]);
for (var j = 0; j < a[i].length; j++) {
joined[i].push(a[i][j]);
}
for (var j = 0; j < b[i].length; j++) {
joined[i].push(b[i][j]);
}
}
return joined;
}
function sortMatrix(a,b,x,d) {
if (d<=0) var ret = [1,-1];
else var ret = [-1,1];
if (isNaN(a[x]) && isNaN(b[x])) {
var ax = a[x].toLowerCase();
var bx = b[x].toLowerCase();
} else if (isNaN(a[x])) {
return ret[0];
} else if (isNaN(b[x])) {
return ret[1];
} else {
var ax = parseFloat(a[x]);
var bx = parseFloat(b[x]);
}
if (ax > bx) return ret[0];
else if (ax < bx) return ret[1];
else return 0;
}
function sortTable(r,c) {
var table = document.getElementById("myTable");
var rows = table.getElementsByTagName("TR");
var matriz = [];
var m = null;
// Get matrix from table
for (i = 0; i < rows.length; i++) {
if (i==0) cols = rows[i].getElementsByTagName("TH");
else cols = rows[i].getElementsByTagName("TD");
m = [];
for (j = 0; j < cols.length; j++) {
m.push(cols[j].innerHTML);
}
matriz.push(m);
}
if (r==0) { // sort rows by col
if (c==cc) dirc = Math.abs(1-dirc);
else dirc = 0;
m = matriz[0];
matriz = matriz.slice(1);
matriz.sort(function(a, b){
return sortMatrix(a,b,c,dirc);
});
matriz.unshift(m);
cc = c;
}
if (c==0) { // sort cols by row
if (r==rr) dirr = Math.abs(1-dirr);
else dirr = 0;
m = colSlice(matriz,0,1);
matriz = colSlice(matriz,1);
// Transpose matriz
var newArray = matriz[0].map(function(co, i){
return matriz.map(function(ro){
return ro[i];
});
});
// Sort
newArray.sort(function(a, b){
return sortMatrix(a,b,r,dirr);
});
// Transpose back
matriz = newArray[0].map(function(co, i){
return newArray.map(function(ro){
return ro[i];
});
});
matriz = colJoin(m,matriz);
rr = r;
}
// Update values
for (i = 0; i < rows.length; i++) {
if (i==0) cols = rows[i].getElementsByTagName("TH");
else cols = rows[i].getElementsByTagName("TD");
for (j = 0; j < cols.length; j++) {
cols[j].innerHTML = matriz[i][j];
}
}
}
function clicRow(e) {
sortTable(0,parseInt(e.target.attributes.col.value));
}
var tds=document.querySelectorAll("#myTable tr td:first-child,#myTable tr th:first-child");
var len = tds.length;
for(var i=0; i< len; i++){
tds[i].addEventListener('click', clicRow);
}
function clicCol(e) {
sortTable(parseInt(e.target.attributes.row.value),0);
}
var tds=document.querySelectorAll("#myTable tr:first-child th");
var len = tds.length;
for(var i=1; i< len; i++){
tds[i].addEventListener('click', clicCol);
}
&#13;
/* Just for beauty */
#myTable {
border: none;
}
#myTable th {
cursor: n-resize;
border: none;
background-color: #e0e0e0;
}
#myTable th:first-child {
cursor: move;
}
th, td {
width: 5%;
}
#myTable tr td {
border: none;
border-bottom: 1px solid #aaa;
text-align: center;
}
#myTable tr td:first-child {
cursor: e-resize;
background-color: #e0e0e0;
border-bottom: 1px solid #aaa;
text-align: center;
}
#myTable tr:last-child td {
border: none;
}
&#13;
<table id="myTable">
<tbody>
<tr>
<th row="0" col="0">Both</th>
<th row="1">Col A</th>
<th row="2">Col B</th>
<th row="3">Col C</th>
<th row="4">Col 4</th>
</tr>
<tr>
<td col="1">Row A</td>
<td>221</td>
<td>2</td>
<td>22</td>
<td>22.2</td>
</tr>
<tr>
<td col="2">Row B</td>
<td>123</td>
<td>1234</td>
<td>ABA</td>
<td>aba</td>
</tr>
<tr>
<td col="3">Row C</td>
<td>1</td>
<td>12.04</td>
<td>12.4</td>
<td>ab</td>
</tr>
<tr>
<td col="4">Row 4</td>
<td>123.2</td>
<td>123.1</td>
<td>acar</td>
<td>acar</td>
</tr>
</tbody>
</table>
&#13;
更新:简化和删除onClick
来电。