JSFiddle - React, Tailwind, and code Playground

by narzantaria

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <button id="h1-trigger">Turn selection</button>
  <button id="check">Check selection status</button>
  <div id="editor">This is the text where we can select some word by double-clicking, and press the "h1-trigger button". The function wraps the selection with h1 tags. When clicked again it will unwrap the selection and return to previous text. But if we unselect the wrapped word (h1 heading), select by double-click again, and press the button, it does another result. The second button shows the selection status with console log. Why re-selection doesn't contain the created tags?</div> 
</body>
</html>

JavaScript

document.getElementById('h1-trigger').addEventListener('click', function () {
  headerFormatter();
});

document.getElementById('check').addEventListener('click', function () {
  let sel = window.getSelection();
  let range = sel.getRangeAt(0).cloneRange();
  let rangeProxy = sel.getRangeAt(0).cloneContents();
  console.log(sel);
  console.log(range);
  console.log(rangeProxy);
});

function headerFormatter() {
  let newTag = document.createElement('h1');
  if (window.getSelection) {
    let sel = window.getSelection();
    if (sel.rangeCount) {
      let range = sel.getRangeAt(0).cloneRange();
      // create an object from range for querying tags
      let rangeProxy = sel.getRangeAt(0).cloneContents();
      if (rangeProxy.querySelector('h1') || rangeProxy.querySelector('h2') || rangeProxy.querySelector('h3')) {
        let tagContent = rangeProxy.querySelector('h1').innerHTML;
        // compare selection length with queried tag length
        if (range.startOffset == 1) {
          tagContent = tagContent.replace(/(<([^>]+)>)/ig, "");
          range.deleteContents();
          range.insertNode(document.createTextNode(tagContent));
          sel.removeAllRanges();
          sel.addRange(range);
          return;
        }
        else {
          let rangeToString = range.toString().replace(/(<([^>]+)>)/ig, "");
          range.deleteContents();
          range.insertNode(document.createTextNode(rangeToString));
          sel.removeAllRanges();
          sel.addRange(range);
          return;
        }
      } else {
        range.surroundContents(newTag);
        sel.removeAllRanges();
        sel.addRange(range);
      }
    }
  }
}