【问题标题】:HTML table sortable by ROW instead of COLUMN with JavaScript?HTML表格可以按ROW而不是使用JavaScript的COLUMN排序?
【发布时间】:2018-05-09 05:53:01
【问题描述】:

我正在使用来自 W3Schools 的 this code 通过单击列标题对所有表行进行排序。正如预期的那样,这将按该 col 值对所有行进行排序。

我确信这已经在某个地方得到了回答,但我通过单击第一列行来过滤搜索结果以找到类似的列排序方式(希望在纯 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>

NORMAL:按 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>

DESIRED:按 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>

这是我的sn-p:

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>

【问题讨论】:

  • 请注意,W3Schools 不是 W3。没有隶属关系。
  • 已编辑,谢谢。我很困惑。
  • 对 1 行进行排序意味着对所有行进行排序,因为它会更改列顺序。
  • 是的,我知道。第一列是“行标题”......所以?

标签: javascript html html-table


【解决方案1】:

我经常问自己这个问题,但似乎从来没有真正需要它,所以再也没有问过。您的答案很好,但是在将数字作为字符串进行比较时会遇到问题。它不会显示在您的代码中,因为您使用的是 1, 2, 3 值。 查看我的sn-p 混合数据类型,当然代码可以减少很多。

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);
}
  /* 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;
  }
<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>

更新:简化并删除了onClick 调用。

【讨论】:

  • 你是对的!我注意到了这个错误,就是这样。非常感谢!
【解决方案2】:

更新:请参阅@sanxofon 的回答。是我的改进。


暂时没有答案,所以我最终使用这个程序解决了这个问题:

  1. 将表格捕获到矩阵

  2. 转置矩阵(翻转轴)

  3. 按列排序矩阵(正常)

  4. 将矩阵转回(再次翻转轴)

  5. 更新矩阵到表格

我为所有可能对解决方案感兴趣的人发布此信息。

性能:我没有测试过它的性能,但是由于所有的过程都是在矩阵上完成的,它完全取决于它的长度和它的数据。效果很好,可以在任何桌子上实现。

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];
    }
  }
}
/* 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;
  }
<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>

干杯!

【讨论】:

  • 我已经通过一些改进更新了我的答案,删除了onClickcalls。
猜你喜欢
  • 2018-09-01
  • 1970-01-01
  • 2021-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
相关资源
最近更新 更多