Javascript - 如何删除 nodeName 或 HTML 标签但单独保留内部标记?

Javascript - How to remove nodeName or the HTML tag but leave the inside markup alone?

我将用户select编辑的范围存储在变量中。

var sel, range, off, tags; 
sel = window.getSelection();
 if (sel.rangeCount) {
            range = sel.getRangeAt(0);
            var off = sel.anchorOffset;

         }
         else if (document.selection && document.selection.createRange) {
            range = document.selection.createRange();
            var off = document.selection.anchorOffset;

        }
return range;

html

    <div ng-mouseup="mouseUpEvent(e)" ng-keyup="keyUpEvent()" contenteditable data-element="textBlock" id="markdown-body">

        Chicken ipsum dolor sit amet, consectetur adipiscing elivolutpat volutpat. Nunc imperdiet urna et orci mattis, 
pellentesque posuere enim pellentesque. Aenean id orci et nunc venenatis vestibulum et et ligula. Morbi mollis ornare purus
 non blandit.<b> Phasellus egestas</b>, ipsum <i>sit amet finibus </i>pellentesque, <span style="color: red;">tellus urna
 lobortis tellus, id tincidunt </span>Piza house byys nget lectus. Proin pulvinar enim non mi vestibulum interdum. 

            Sed nisl enim, sagittis non vestibulum eget, congue pellentesque ipsum. Nullam nec interdum elit

    </div>

我找到了我的anchorNode 和我的focusNode。 所以我 select 编辑了我的节点 nodeName "B"。代表粗体。

如果我这样做 element.nodeName,我的输出将是 "B"。

如果我输出我的元素,我会得到 <b> Phasellus egestas</b> 我还有一个 selected 范围,我有 selected "asellus eges"

我想删除 <b> 标签。并将标签添加到 select 范围。 如果我取出元素的内部 HTML 并替换它,那么我会弄乱 select 范围。

我看到人们建议找到父节点而不是 selecting 子节点并删除并执行类似的操作:

element[index].parentNode.removeChild(element[index]);

但是如果我的父节点有两个具有相同节点名称的子节点,那将导致问题。

我已经得到 select 特定节点的元素,如何保留 innerConnet & HTML 标记但删除 b 标记?

要获取 HTML 标签之间的代码,请使用:

var inside = element.innerHTML;

如果你想让它更新源代码,试试这个:

element.outerHTML = element.innerHTML;

用第一个子元素(本例中的文本节点)替换元素

if (element.tagName == 'B') {
  element.parentNode.replaceChild(element.firstChild, element);
}

在多个节点的情况下,在删除每个子节点之前使用 insertBefore

var child = element.firstChild;
while (child) {
  element.parentElement.insertBefore(child, element);
  child = child.nextSibling;
}

element.parentElement.removeChild(element);

在文本框中输入一个 tagName,然后单击代码段中的 UNWRAP 按钮。所有详细信息都在代码段中进行了评论。

片段

function unWrap(wrap) {

  if (!wrap) {
    console.log('Enter a valid selector without quotes');
  }

  // Reference the node to unwrap
  var removeThis = document.querySelector(wrap);

  if (removeThis == "undefined" || removeThis == false) {
    console.log('Selector doesn\'t exist in DOM.');
  }

  // Reference the wrapper's parent
  var parent = removeThis.parentNode;

  // Move all of wrapper's descendants...
  while (removeThis.firstChild) {

    /* ...by taking the wrapper's first child...
    || ...and placing it in front of the wrapper.
    || ...Eventually, all of wrapper's children...
    || ...are it's siblings now.
    */
    parent.insertBefore(removeThis.firstChild, removeThis);

  }

  // Once the wrapper is empty, remove it
  parent.removeChild(removeThis);

}
body {
  color: white;
}
header,
footer {
  background: cyan;
  color: black;
}
table {
  border: 3px solid gold;
  width: 300px;
}
td {
  border: 1px solid tomato;
}
section {
  border: 8px dashed blue;
}
main {
  background: #444;
}
b {
  background: yellow;
  color: #444;
}
input {
  float: right;
  width: 12ch;
}
.as-console {
  color: blue;
}
<main>
  MAIN
  <section>
    SECTION
    <header>HEADER</header>
    <p>TEXT TEXT <b>TEXT</b> TEXT TEXT</p>
    <p>TEXT TEXT <b>TEXT</b> TEXT TEXT</p>
    <p>TEXT TEXT <b>TEXT</b> TEXT TEXT</p>
    <p>TEXT TEXT <b>TEXT</b> TEXT TEXT</p>
    <p>TEXT TEXT <b>TEXT</b> TEXT TEXT</p>
    <table>

      <form id='f1' name='f1'>
        <input type='button' value='UNWRAP' onclick='unWrap(document.forms[0].txt.value)'>
        <input name='txt'>
      </form>

      <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
    </table>
    <footer>FOOTER</footer>
  </section>
</main>

修正了@Casper Beyer 的算法,它与 children 有一些弱点。在 parent 节点中插入 child 后,.nextSibling 在插入后传递 parents 节点的下一个兄弟节点,而不是 child 节点中的下一个节点。因此,在将 child 插入 parent 之前,我存储了一个临时的 nextSibling,然后将 child 添加到 parent。这里的代码:

    removeSurroundingTagOnNode(node: Node, tagName: string): void {
        if (node.nodeName == 'DIV') {
            return; // root reached
        }
        if (node.nodeName === tagName) {
            // remove the surrounding tag
            let child: Node = node.firstChild;
            while (child) {
                let nextChild: Node = child.nextSibling;
                node.parentNode.insertBefore(child, node);
                child = nextChild;
            }
            node.parentNode.removeChild(node);
        } else {
            // havn't found the tagName yet, look in the parent node
            this.removeSurroundingTagOnNode(node.parentNode, tagName);
        }
    }