getSelection & surroundContents across multiple tags
Asked Answered
S

2

12

I've got a script that changes the background colour of text that has been selected. However i'm encountering an issue when the text is selected across multiple elements/tags.

The code that i've got is:

var text = window.getSelection().getRangeAt(0);
var colour = document.createElement("hlight");
colour.style.backgroundColor = "Yellow";
text.surroundContents(colour);

And the error being output is:

Error: The boundary-points of a range does not meet specific requirements. =
NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR
Line: 7

I believe this is to do with the getRange() function though i'm not too sure how to proceed since I am a beginner at javascript.

Is there any other way I can replicate what I am trying to achieve?

Many thanks.

Subaudition answered 6/4, 2010 at 11:9 Comment(1)
Duplicate of #2583331 and #1623129Covenant
C
18

This question has been asked today: How can I highlight the text of the DOM Range object?

Here's my answer:

The following should do what you want. In non-IE browsers it turns on designMode, applies a background colour and then switches designMode off again.

UPDATE

Fixed to work in IE 9.

function makeEditableAndHighlight(colour) {
    sel = window.getSelection();
    if (sel.rangeCount && sel.getRangeAt) {
        range = sel.getRangeAt(0);
    }
    document.designMode = "on";
    if (range) {
        sel.removeAllRanges();
        sel.addRange(range);
    }
    // Use HiliteColor since some browsers apply BackColor to the whole block
    if (!document.execCommand("HiliteColor", false, colour)) {
        document.execCommand("BackColor", false, colour);
    }
    document.designMode = "off";
}

function highlight(colour) {
    var range, sel;
    if (window.getSelection) {
        // IE9 and non-IE
        try {
            if (!document.execCommand("BackColor", false, colour)) {
                makeEditableAndHighlight(colour);
            }
        } catch (ex) {
            makeEditableAndHighlight(colour)
        }
    } else if (document.selection && document.selection.createRange) {
        // IE <= 8 case
        range = document.selection.createRange();
        range.execCommand("BackColor", false, colour);
    }
}
Covenant answered 6/4, 2010 at 11:18 Comment(4)
Many thanks Tim, that worked perfectly and apologies for the duplication. The other thread didnt come up in my searches.Subaudition
but how do you call the function highlight ?Deckhouse
@LayaleMatta: Example: highlight("#ff0000") will add a red background to the currently selected text.Covenant
@TimDown can you please share a fiddle for the code above.Woosley
E
2

Well I think the use of mark.js library is great in this case. The library's intention is to highlight all instances of a certain word in the HTML document, but it can be tweaked through the filter option function, and additional span attributes can be added through the each option function.

function markFunc(node, text, color) {
  var instance = new Mark(node);
    instance.mark(text, {
    "element": "span",
      "className": color,
      "acrossElements": true,
      "separateWordSearch": false,
      "accuracy": "partially",
      "diacritics": true,
      "ignoreJoiners": true,
    "each": function(element) {
            element.setAttribute("id", "sohayb");
            element.setAttribute("title", "sohayb_title");
       },
    "done":function(totalMarks) {
            window.getSelection().empty();//This only in Chrome
            console.log("total marks: " + totalMarks);
     },
      "filter": function(node, term, totalCounter, counter) {
        var res = false;
        if (counter == 0) {
            res = selectionRange.isPointInRange(node, selectionRange.startOffset);
        } else {
        res = selectionRange.isPointInRange(node, 1);
        }
        console.log("Counter: " + counter + ", startOffset: " + selectionRange.startOffset);
        return res;
        }
  });
};

Check this JSFiddle sample for completed code that highlights user's selection, even across multiple HTML elements.

Exsect answered 8/2, 2017 at 7:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.