How to toggle tag element for selection text without execCommand?

31 Views Asked by At

So, I'm working on a text editor for my platform and I was working with execCommand but it's not working as expected and it's limited. So I'm working now with selection surroundedContent etc

The problem is, I can't figure out a function to do the next?

For example let's take bold as example. I want, when I select text and click bold button, to apply bold to the text.

  1. Check if there's no <strong> element as parent or parent of parent
  2. If isset and the selected range start like <strong>text</strong> just remove <strong> element and keep text
  3. If isset and selected range doesn't start from the beginning like <strong>te[x]t</strong> turn it to <strong>te</strong>x<strong>t</strong>

So I want to make the function work for all tagname and use it for italic underline etc. I want to work with window selection only.

I tried this so far:

function toggleFormatting(tagName) {
  const selection = window.getSelection();
  if (!selection.isCollapsed) {
    const range = selection.getRangeAt(0);
    const selectedText = range.extractContents();

    // Check if the selected text is already wrapped in the specified tag
    const elements = selectedText.querySelectorAll(tagName);

    if (elements.length > 0) {
      // Case 1: If it's wrapped, unwrap it by replacing the tag with their contents
      elements.forEach((element) => {
        const parent = element.parentNode;
        while (element.firstChild) {
          parent.insertBefore(element.firstChild, element);
        }
        parent.removeChild(element);
      });
    } else {
      // Case 2: If it's not wrapped, wrap it with the specified tag
      const newElement = document.createElement(tagName);
      newElement.appendChild(selectedText);
      range.insertNode(newElement);
    }

    // Collapse the selection to remove any highlighting
    selection.removeAllRanges();
  }
}
0

There are 0 best solutions below