向上或向下移动 HTML Table 个单元格(不是行)

Move HTML Table Cell up or down (not row)

我正在做一个项目,其中有一个 HTML table,我需要为用户提供交换两个 HTML table 单元格内容的选项。

具体来说,用户可以单击 select 一行,然后选择将该行向上或向下移动。实际上,他们只是在移动代表信息的第 2 列的内容。第 1 列表示顺序,不会改变。

table 总共有两列。 第 1 列将代表线性顺序(即 1-10),它不会改变。 第 2 列将是数据库提供的信息(在示例代码中我提供了姓氏)。

我制作了两个按钮,向上和向下,并使用了两个 Javascript 功能,允许用户 select 一行并将其向上或向下移动。

当前代码成功将整行向上或向下移动,但是我只需要第2列的单元格内容向上或向下.

请查看提供的代码和 JSFiddle,让我知道如何解决这个问题?提前致谢!

var index; // variable to set the selected row index
function getSelectedRow() {
  var table = document.getElementById("table");
  for (var i = 1; i < table.rows.length; i++) {
    table.rows[i].onclick = function() {
      // clear the selected from the previous selected row
      // the first time index is undefined
      if (typeof index !== "undefined") {
        table.rows[index].classList.toggle("selected");
      }

      index = this.rowIndex;
      this.classList.toggle("selected");

    };
  }

}
getSelectedRow();

function upNdown(direction) {
  var rows = document.getElementById("table").rows,
    parent = rows[index].parentNode;

  if (direction === "up") {
    if (index > 1) {
      parent.insertBefore(rows[index], rows[index - 1]);
      // when the rowgo up the index will be equal to index - 1
      index--;
    }
  }

  if (direction === "down") {
    if (index < rows.length - 1) {
      parent.insertBefore(rows[index + 1], rows[index]);
      // when the row go down the index will be equal to index + 1
      index++;
    }
  }
}
tr {
  cursor: pointer
}

.selected {
  background-color: red;
  color: #fff;
  font-weight: bold
}

button {
  margin-top: 10px;
  background-color: #eee;
  border: 2px solid #00F;
  color: #17bb1c;
  font-weight: bold;
  font-size: 25px;
  cursor: pointer
}
<!DOCTYPE html>
<html lang="en">

  <head>

    <meta charset="utf-8">
    <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
    <meta content="30" http-equiv="refresh">

    <title> {{.Title}} </title>

    <style>
      .bd-placeholder-img {
        font-size: 1.125rem;
        text-anchor: middle;
        -webkit-user-select: none;
        -moz-user-select: none;
        user-select: none;
      }

      @media (min-width: 768px) {
        .bd-placeholder-img-lg {
          font-size: 3.5rem;
        }
      }

    </style>


  </head>

  <body>

    <header>

    </header>



    <main>


      <table id="table" border="1">
        <tr>
          <th>Order</th>
          <th>Last Name</th>
        </tr>
        <tr>
          <td>1</td>
          <td>Smith</td>
        </tr>
        <tr>
          <td>2</td>
          <td>Johnson</td>
        </tr>
        <tr>
          <td>3</td>
          <td>Roberts</td>
        </tr>
        <tr>
          <td>4</td>
          <td>Davis</td>
        </tr>
        <tr>
          <td>5</td>
          <td>Doe</td>
        </tr>
      </table>
      <button onclick="upNdown('up');">&ShortUpArrow;</button>
      <button onclick="upNdown('down');">&ShortDownArrow;</button>


    </main>
    <!-- Bootstrap core JavaScript -->
    <script src="/vendor/jquery/jquery.min.js"></script>
    <script src="/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
    <script src="/js/sidebar.js"></script>
  </body>

</html>

Link to JSFiddle

这完全取决于您想要什么。您提到曾尝试移动 innerHTML,因此此代码段会这样做 - 保留两个 tds 上的任何属性不变(请参阅下面的注释):

var index; // variable to set the selected row index
function getSelectedRow() {
  var table = document.getElementById("table");
  for (var i = 1; i < table.rows.length; i++) {
    table.rows[i].onclick = function() {
      // clear the selected from the previous selected row
      // the first time index is undefined
      if (typeof index !== "undefined") {
        table.rows[index].classList.toggle("selected");
      }

      index = this.rowIndex;
      this.classList.toggle("selected");

    };
  }

}
getSelectedRow();

function upNdown(direction) {
  var rows = document.getElementById("table").rows,
    parent = rows[index].parentNode;

  if (direction === "up") {
    if (index > 1) {
      // get the relevant cell which is the second one as we know only tds are the children
      let td = rows[index].children[1];
      let tdAbove = rows[index - 1].children[1];
      let temp = td.innerHTML;
      td.innerHTML = tdAbove.innerHTML;
      tdAbove.innerHTML = temp;
      // when the rowgo up the index will be equal to index - 1
      index--;
    }
  }

  if (direction === "down") {
    if (index < rows.length - 1) {
      let td = rows[index].children[1];
      let tdBelow = rows[index + 1].children[1];
      let temp = td.innerHTML;
      td.innerHTML = tdBelow.innerHTML;
      tdBelow.innerHTML = temp;
      // when the row go down the index will be equal to index + 1
      index++;
    }
  }
}
.bd-placeholder-img {
  font-size: 1.125rem;
  text-anchor: middle;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
}

@media (min-width: 768px) {
  .bd-placeholder-img-lg {
    font-size: 3.5rem;
  }
}

tr {
  cursor: pointer
}

.selected {
  background-color: red;
  color: #fff;
  font-weight: bold
}

button {
  margin-top: 10px;
  background-color: #eee;
  border: 2px solid #00F;
  color: #17bb1c;
  font-weight: bold;
  font-size: 25px;
  cursor: pointer
}
<body>

  <header>

  </header>



  <main>


    <table id="table" border="1">
      <tr>
        <th>Order</th>
        <th>Last Name</th>
      </tr>
      <tr>
        <td>1</td>
        <td>Smith</td>
      </tr>
      <tr>
        <td>2</td>
        <td>Johnson</td>
      </tr>
      <tr>
        <td>3</td>
        <td>Roberts</td>
      </tr>
      <tr>
        <td>4</td>
        <td>Davis</td>
      </tr>
      <tr>
        <td>5</td>
        <td>Doe</td>
      </tr>
    </table>
    <button onclick="upNdown('up');">&ShortUpArrow;</button>
    <button onclick="upNdown('down');">&ShortDownArrow;</button>


  </main>

注意:问题中引入了移动整个元素的想法,而不仅仅是其内容。您可以这样做,而不是通过使用例如 outerHTML 来交换内容(即所有属性也将被移动)。但是,这可能不是您想要的,因为例如,如果这是排行榜,顶部元素上可能有一个内联样式,它以金色突出显示它。这完全取决于您的要求。

另请注意,该代码段假定 table 格式正确,因为在 selectable 行中没有非 td 元素作为直接子元素。

为了简单起见(至少在表面上),此答案对发布的代码进行了更改,并防止使用按钮将 header 行向下移动到 table:

  • 保留对所选行的引用而不是索引。

  • 在HTML中,header行被放置在thead元素中,数据行在tbody元素中(重要在代码中)。

  • 移动一行时,两行的顺序会颠倒,然后它们第一个单元格的 textContent 交换 - 无需将“顺序”列单元格移动到不同的行。如果这太简单了,您可以交换单元格的 innerHTML 属性。

  • 在进行更改时,再次单击一行可取消选择它:单击 table 外部将是您可以监控的另一件事,如您所愿。

"use strict";
const tbody = document.querySelector("#table tbody");
let selected = null;
tbody.addEventListener("click", function(e){
  let row = e.target.closest("tr");
  if( row === selected) {
    row.classList.toggle("selected")
    selected = null;
  }
  else {
    if(selected) {
      selected.classList.toggle("selected");
    }
    selected = row;
    row.classList.toggle("selected");
  }
});

function upNdown( direction) {
  let up, down;
  if( selected) {
    up  =  direction == "up" ? selected : selected.nextElementSibling;
    down = direction == "up" ? selected.previousElementSibling : selected;
    if( up && down) {
      tbody.insertBefore(up, down); // put up before down
      var temp = up.firstElementChild.textContent; // swap first cells' text content
      up.firstElementChild.textContent = down.firstElementChild.textContent;
      down.firstElementChild.textContent = temp;
    }
  }
}
tr {
  cursor: pointer
}

.selected {
  background-color: red;
  color: #fff;
  font-weight: bold
}
<table id="table" border="1">
  <thead>
    <tr>
      <th>Order</th>
      <th>Last Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Smith</td>
    </tr>
  
    <tr>
      <td>2</td>
      <td>Johnson</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Roberts</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Davis</td>
    </tr>
    <tr>
      <td>5</td>
      <td>Doe</td>
    </tr>
   </tbody>
</table>
<button onclick="upNdown('up');">&ShortUpArrow;</button>
<button onclick="upNdown('down');">&ShortDownArrow;</button>