javascriptalgorithmwysiwyg

remove formatting of html tags by selected text


I want write a script that will remove format of selected text like document.execCommand('removeFormat') but nativly without this deprecated method. I am wondering what the algorithm behind this. For example I have html.

  <body>
    1.
    <div>
      <h1>hello world</h1>
      <span>
        <b style="background-color: green">bold text</b>
      </span>
      <p style="background-color: red">1234</p>
    </div>
  </body>

I selected text from 'hello' to '12' The expected output might be

  <body>
    1.
      hello world bold text 12
      <p style="background-color: red">34</p>
    </div>
  </body>

first step. using window.getSelection() and window.getSelection().getRangeAt(0) we can find beginning text node "hello world" and ending text node "12" (this could happen if we split text node "1234" in two text nodes "12" "34").

Using beggining text node and ending text node we can get all text nodes between but how it can help me. It seems we need to delete all tags before "hello world" until we hit not empty text node and same goes for end text node. We remove every html tag from beggining until we saw "1." but at the end we saw "34" so I got closing div tag without opening div tag.

it seems I can use

let selection = window.getSelection();
selection.deleteFromDocument();

but it leaves empty tags

<div>
  <h1></h1><p style="background-color: red">34</p>
 </div>

and then somehow add text using selection.toString()

There is a lot of edge cases and I struggle to understand the right approach.


Solution

  • this code can solve your problem but you have to select the entire section includes the section number.

     function removeFormattingFromSelection() {
                const selection = window.getSelection();
                if (!selection.rangeCount) return;
                const range = selection.getRangeAt(0);
    
                const text = range.toString();
    
                const textNode = document.createTextNode(text);
    
                range.deleteContents();
                range.insertNode(textNode);
    
                selection.removeAllRanges();
                const newRange = document.createRange();
                newRange.selectNodeContents(textNode);
                newRange.collapse(false);
                selection.addRange(newRange);
            }
     body {
                font-family: Arial, sans-serif;
                padding: 20px;
            }
    
            .content {
                border: 1px solid #ccc;
                padding: 10px;
                margin-bottom: 10px;
                background-color: #f9f9f9;
            }
    
            h1 {
                color: darkblue;
            }
    
            b {
                font-weight: bold;
                background-color: green;
                color: white;
            }
    
            p {
                color: red;
                padding: 5px;
            }
     <div class="content" id="content">
            1.
            <div>
                <h1>hello world</h1>
                <span><b style="background-color: green">bold text</b></span>
                <p>1234</p>
            </div>
            2.
            <div>
                <h1>hello world</h1>
            </div>
        </div>
        <button onclick="removeFormattingFromSelection()">Remove Formatting</button>