Javascript 剪切 table 以插入标签 <div>

Javascript cut table to insert a tag <div>

我想在 tr 之后剪切 table 以插入一个 div 并重新打开 table :

之前:

<table>
    <tr onClick="cutAfter(this);">
        <td>bla</td><td> 123 </td><td>Yes </td>
    </tr>
    <tr onClick="cutAfter(this);">
        <td>bli</td><td> 456 </td><td>no</td>
    </tr>
    <tr onClick="cutAfter(this);">
        <td>blu</td><td> 789 </td><td>hum</td>
    </tr>
</table>

之后:

<table>
    <tr onClick="cutAfter(this);">
        <td>bla</td><td> 123 </td><td>Yes </td>
    </tr>
    <tr onClick="cutAfter(this);">
        <td>bli</td><td> 456 </td><td>no</td>
    </tr>
</table>
<div onClick="fuse(this)">It works</div>
<table>
    <tr onClick="cutAfter(this);">
        <td>blu</td><td> 789 </td><td>hum</td>
    </tr>
</table>

和 return 点击时的第一个状态。 任何想法(没有 jQuery)。

一个简单的方法是使用 DOM 操作方法的组合,如 insertAdjacentHTML to create new table and appendChild 将行移动到新的 table:

function cutAfter(row) {
    var table = row.parentNode.parentNode;
  
    if (row.nextElementSibling) {
        table.insertAdjacentHTML('afterend', '<table><tbody></tbody></table>');
        var newTable = table.nextElementSibling.tBodies[0];

        while (row.nextElementSibling) {
            newTable.appendChild(row.nextElementSibling);
        }
    }

}
table {
    margin-bottom: 10px;
}
table td {
    border: 1px #AAA solid;
}
<table>
    <tr onClick="cutAfter(this);">
        <td>bla</td><td> 123 </td><td>Yes </td>
    </tr>
    <tr onClick="cutAfter(this);">
        <td>bli</td><td> 456 </td><td>no</td>
    </tr>
    <tr onClick="cutAfter(this);">
        <td>blu</td><td> 789 </td><td>hum</td>
    </tr>
</table>

这是一个简单的例子,由一个 HTML 文件(结构)和一个 Javascript 文件(行为)组成。该脚本使用节点操作,以保留现有的处理程序(例如,由其他脚本添加)。它还使用 element.onxxx 直接附加事件处理程序,以保持简单,但您应该将其替换为您最喜欢的事件管理器。

var makeSplittable = function(table, joinText) {

  init();

  function init() {
    var tBodies = table.tBodies;
    for (var ii = 0; ii < tBodies.length; ii++) {
      var rows = tBodies[ii].rows;
      for (var j = 0; j < rows.length; j++) {
        rows[j].onclick = split; // Replace with your favorite event manager
      }
    }
  }

  function split(evt) {
    var rowIndex = this.rowIndex;
    var tbody = findParent(this, "tbody");
    var numRows = tbody.rows.length;
    if (rowIndex < numRows - 1) {
      var rows = [];
      for (var ii = rowIndex + 1; ii < numRows; ii++) {
        rows.push(tbody.rows[ii]);
      }
      var existingTable = findParent(this, "table");
      var newTable = createTable(rows);
      var joiner = createJoiner();
      existingTable.parentNode.insertBefore(newTable, existingTable.nextSibling);
      existingTable.parentNode.insertBefore(joiner, existingTable.nextSibling);
    }
  }

  function createTable(rows) {
    var table = document.createElement("table");
    var tbody = document.createElement("tbody");
    for (var ii = 0; ii < rows.length; ii++) {
      tbody.appendChild(rows[ii]);
    }
    table.appendChild(tbody);
    return table;
  }

  function createJoiner() {
    var div = document.createElement("div");
    var content = document.createTextNode(joinText);
    div.appendChild(content);
    div.onclick = join; // same
    return div;
  }

  function join(evt) {
    var previousTable = this.previousSibling;
    var nextTable = this.nextSibling;
    var tbody = previousTable.tBodies[previousTable.tBodies.length - 1];
    var rows = nextTable.rows;
    while (rows.length) {
      tbody.appendChild(rows[0]);
    }
    nextTable.parentNode.removeChild(nextTable);
    this.parentNode.removeChild(this);
  }

  function findParent(element, type) {
    if (!element || !type) {
      return null;
    }
    if (element.nodeName.toLowerCase() == type.toLowerCase()) {
      return element;
    }
    return findParent(element.parentNode, type);
  }

};

makeSplittable(document.getElementById("target"), "Merge adjacent tables");
table,
div {
  margin: 5px 0;
}
tr:hover td {
  background-color: orange;
}
td {
  background-color: yellow;
  cursor: pointer;
  padding: 10px;
}
div {
  color: #0c0;
  cursor: pointer;
}
<table id="target">
  <tr>
    <td>bla</td>
    <td>123</td>
    <td>Yes</td>
  </tr>
  <tr>
    <td>bli</td>
    <td>456</td>
    <td>no</td>
  </tr>
  <tr>
    <td>blu</td>
    <td>789</td>
    <td>hum</td>
  </tr>
</table>

一种可能性,假设如果没有剪切,则不应在最后一个 TR 之后插入 DIV,但很高兴看到您的努力。还假设没有 <thead><tfoot>.

function isTagName(element, tagName) {
  return element.tagName.toUpperCase() === tagName.toUpperCase();
}

function getClosest(element, tagName) {
  var closest = null;

  while (element !== document && !isTagName(element, tagName)) {
    element = element.parentNode;
  }

  if (element !== document && isTagName(element, tagName)) {
    closest = element;
  }

  return closest;
}

function insertAfter(newNode, referenceNode) {
  return referenceNode.parentNode
          .insertBefore(newNode, referenceNode.nextSibling);
}

function moveAppend(list, dest, from) {
  var index = list.length - 1,
    last;

  for (last = from || 0; index >= last; index -= 1) {
    dest.appendChild(list[index]);
  }

  return dest;
}

document.body.addEventListener('click', function(e) {
  var target = e.target,
    tr = getClosest(target, 'tr'),
    newDiv,
    newTable,
    newBody,
    next,
    parent;

  if (tr) {
    if (tr.rowIndex < tr.parentNode.rows.length - 1) {
      newDiv = document.createElement('div');
      newDiv.appendChild(document.createTextNode('It works!'));
      insertAfter(newDiv, getClosest(tr, 'table'));
      newTable = document.createElement('table');
      newBody = document.createElement('tbody');
      moveAppend(tr.parentNode.rows, newBody, tr.rowIndex + 1);
      newTable.appendChild(newBody);
      insertAfter(newTable, newDiv);
    }
  } else if (isTagName(target, 'div') &&
              isTagName(target.previousElementSibling, 'table') &&
              isTagName(target.nextElementSibling, 'table')) {

    next = target.nextElementSibling;
    moveAppend(next.tBodies[0].rows, target.previousElementSibling.tBodies[0]);
    parent = target.parentNode;
    parent.removeChild(next);
    parent.removeChild(target);
  }
}, false);
table,
td {
  border-style: solid;
  border-width: 1px;
}
div {
  background-color: yellow;
}
<table>
  <tr>
    <td>bla</td>
    <td>123</td>
    <td>Yes</td>
  </tr>
  <tr>
    <td>bli</td>
    <td>456</td>
    <td>no</td>
  </tr>
  <tr>
    <td>blu</td>
    <td>789</td>
    <td>hum</td>
  </tr>
</table>