Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Highlight text range using JavaScript

I would like to highlight (apply css to) a certain text range, denoted by its start and end position. This is more diffucult than it seems, since there may be other tags within the text, that need to be ignored.

Example:

<div>abcd<em>efg</em>hij</div>

highlight(2, 6) needs to highlight "cdef" without removing the tag.

I have tried already using a TextRange object, but without success.

Thanks in advance!

like image 523
Vincent Avatar asked Jun 05 '11 00:06

Vincent


People also ask

How do you highlight text in Javascript?

Highlight Text Using the Mark Tag Method in JavaScriptIf you surround any text inside the mark tag, the browser will automatically highlight it in a striking yellow color. This will make highlighting a searched text quite a simple task then.

How do you highlight certain text in HTML?

The <mark> tag in HTML is used to define the marked text. It is used to highlight the part of the text in a paragraph.

How do you highlight text in textarea?

You can't actually highlight text in a <textarea> . Any markup you would add to do so would simply display as plain text within the <textarea> . The good news is, with some carefully crafted CSS and JavaScript, you can fake it.


2 Answers

Below is a function to set the selection to a pair of character offsets within a particular element. This is naive implementation: it does not take into account any text that may be made invisible (either by CSS or by being inside a <script> or <style> element, for example) and may have browser discrepancies (IE versus everything else) with line breaks, and takes no account of collapsed whitespace (such as 2 or more consecutive space characters collapsing to one visible space on the page). However, it does work for your example in all major browsers.

For the other part, the highlighting, I'd suggest using document.execCommand() for that. You can use my function below to set the selection and then call document.execCommand(). You'll need to make the document temporarily editable in non-IE browsers for the command to work. See my answer here for code: getSelection & surroundContents across multiple tags

Here's a jsFiddle example showing the whole thing, working in all major browsers: http://jsfiddle.net/8mdX4/1211/

And the selection setting code:

function getTextNodesIn(node) {
    var textNodes = [];
    if (node.nodeType == 3) {
        textNodes.push(node);
    } else {
        var children = node.childNodes;
        for (var i = 0, len = children.length; i < len; ++i) {
            textNodes.push.apply(textNodes, getTextNodesIn(children[i]));
        }
    }
    return textNodes;
}

function setSelectionRange(el, start, end) {
    if (document.createRange && window.getSelection) {
        var range = document.createRange();
        range.selectNodeContents(el);
        var textNodes = getTextNodesIn(el);
        var foundStart = false;
        var charCount = 0, endCharCount;

        for (var i = 0, textNode; textNode = textNodes[i++]; ) {
            endCharCount = charCount + textNode.length;
            if (!foundStart && start >= charCount
                    && (start < endCharCount ||
                    (start == endCharCount && i <= textNodes.length))) {
                range.setStart(textNode, start - charCount);
                foundStart = true;
            }
            if (foundStart && end <= endCharCount) {
                range.setEnd(textNode, end - charCount);
                break;
            }
            charCount = endCharCount;
        }

        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (document.selection && document.body.createTextRange) {
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(true);
        textRange.moveEnd("character", end);
        textRange.moveStart("character", start);
        textRange.select();
    }
}
like image 64
Tim Down Avatar answered Oct 12 '22 03:10

Tim Down


You could take a look at how works this powerful JavaScript utility which support selection over multiple DOM elements:

MASHA (short for Mark & Share) allow you to mark interesting parts of web page content and share it

http://mashajs.com/index_eng.html

It's also on GitHub https://github.com/SmartTeleMax/MaSha

Works even on Mobile Safari and IE!

like image 3
Nicola Giulia Pernice Avatar answered Oct 12 '22 04:10

Nicola Giulia Pernice