Javascript cut table to insert a tag

2019-09-19 12:17发布

I want to cut table after tr to insert a div and re-open the table :

Before :

<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>

After :

<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>

And return to first state on click. Any idea (no jQuery).

3条回答
干净又极端
2楼-- · 2019-09-19 13:00

A simple whay to do it is to use combination of DOM manipulation methods like insertAdjacentHTML to create new table and appendChild to move rows into new 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>

查看更多
Emotional °昔
3楼-- · 2019-09-19 13:11

A possibility, assuming that a DIV should not be inserted after the last TR if there has not been a cut, but it would have been nice to see your effort. Also assuming no <thead> or <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>

查看更多
Luminary・发光体
4楼-- · 2019-09-19 13:19

Here's a simple example, made of an HTML file (the structure) and a Javascript file (the behavior). The script uses node manipulation, so as to preserve existing handlers (e.g. added by other scripts). It also attaches event handlers directly, using element.onxxx, to keep things simple, but you should replace that by your favorite event manager.

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>

查看更多
登录 后发表回答