2

I store in a variable my range that the user has selected.

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>

I have located my anchorNode and my focusNode. So i have selected my node that nodeName "B". Stand for Bold.

If I do element.nodeName my output will be "B".

if I output my element I get <b> Phasellus egestas</b> I also got a selected range, and I have selected "asellus eges"

I would like to remove <b> tags. and add tags to the select range. If I take the innerHTML of the element and replace it, than I mess up by select range.

I have seen that people suggest doing finding the parent and than selecting the childNode and removing and doing something like:

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

But that will cause an issue if my Parent has two child nodes with the same nodeName.

I already got the element to select the specific Node , how do I keep the innerConnet & HTML markup but delete the b tags?

Chris Tarasovs
  • 703
  • 2
  • 21
  • 54
  • 1
    You want to replace, for examplr, ` Phasellus egestas` with `Phasellus egestas`? – ibrahim mahrir Jan 29 '17 at 02:20
  • Yes replacing would also an option, it would give the same result. How do you replace and update the DOM? – Chris Tarasovs Jan 29 '17 at 02:22
  • Thank You ibrahim Mahrir, reprashing the question allowed me to find the answear. I cloned the the innerHTML to an attribute, than used the replaceWith(cloneInnerHTML) and was able to replace the widthout the tag names – Chris Tarasovs Jan 29 '17 at 02:30
  • Replacing the Node with innerHTML messes up my getSelection . Is there a way just to remove the node? – Chris Tarasovs Jan 29 '17 at 02:54

4 Answers4

1

Enter a tagName in the text box and click the UNWRAP button in the Snippet. All details are commented in the Snippet.

SNIPPET

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>
zer00ne
  • 41,936
  • 6
  • 41
  • 68
  • zer00ne, I get error when I try you code, and I also update my question. I forgot to also mention I got a range.selection that after is inside and I planning my tags – Chris Tarasovs Jan 29 '17 at 03:04
  • @ChrisTarasovs I got an error trying to remove the footer but it should work as long as the wrapper has a child. I'll have to add a condition to the function for empty elements. Try typing `table` with no quotes and click the button. – zer00ne Jan 29 '17 at 03:07
  • zer00ne, I have updated the question with range selection. If I do as you say than I my range is messed up and I can update my range with the tags. – Chris Tarasovs Jan 29 '17 at 03:10
  • @ChrisTarasovs Can you please show us your HTML? It's hard to grasp what your are describing without some visual reference. – zer00ne Jan 29 '17 at 04:05
0

To get the code inbetween the HTML tags, use this :

var inside = element.innerHTML;

And if you want it to update the source code, try this :

element.outerHTML = element.innerHTML;
ElDoRado1239
  • 3,938
  • 2
  • 16
  • 13
0

Replace the element with its first child (the text node in this case)

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

In the case of multiple nodes, use insertBefore for each child before removing it.

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

element.parentElement.removeChild(element);
Casper Beyer
  • 2,203
  • 2
  • 22
  • 35
0

Corrected the algorithm of @Casper Beyer, it had some weaknesses with the children. After inserting the child in the parent node, the .nextSibling deliver the parents node next sibling after insertion and not the next in the child node. So before inserting the child in the parent i store a temporary nextSibling and then add the child to the parent. Here the code:

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