Highlight user selected text across multiple paragraphs

133 Views Asked by At

I'm trying to make a highlighter in JavaScript. As of now it's working when selecting text within a single paragraph. However, when I'm trying to select text across multiple paragraphs I get the following error:

Uncaught DOMException: An attempt was made to use an object that is not, or is no longer, usable

I'm wrapping the selected text with a span tag which is the problem, I suppose, since I can't wrap a single span across multiple paragraphs. Am I right? Please help me view the problem from a different angle as I don't know what should I do. I don't really get the Range interface. I suppose I should manually split the selection across two paragraphs and wrap spans around each selection in a given paragraph. If there is a better approach, please give me a hint as to how to solve the problem.

JavaScript:

document.addEventListener("DOMContentLoaded", () => {
    document.addEventListener("mouseup", function () {

        const selectedText = window.getSelection();
        const selectedRange = selectedText.getRangeAt(0);
        selectedRange.surroundContents(document.createElement("span"));

    });
});

For highlight itself, I'm using a style tag within a HTML document:

<style>
    span {
        background-color: #E8E288;
    }
</style>

I've tried using extractContents method, but it broke the functionality completely, not even allowing me to highlight the text within a single paragraph. Once again, I'm don't really get the Range interface.

1

There are 1 best solutions below

0
ali saberimovahed On

You are crossing the text range, and that's why you get an error in surroundContents method. check the following solution:

  document.addEventListener("DOMContentLoaded", () => {
    document.addEventListener("mouseup", function (e) {
      const selectedText = window.getSelection();
      const selectedRange = selectedText.getRangeAt(0);
      let span = document.createElement("span");
      span.appendChild(selectedRange.extractContents());
      selectedRange.insertNode(span)

    });
  });