How can I highlight the text of the DOM Range object?

I select some text on the html page(opened in firefox) using mouse,and using javascript functions, i create/get the rangeobject corresponding to the selected text.

 userSelection =window.getSelection(); 
 var rangeObject = getRangeObject(userSelection);

Now i want to highlight all the text which comes under the rangeobject.I am doing it like this,

  var span = document.createElement("span");
  rangeObject.surroundContents(span);
  span.style.backgroundColor = "yellow";

Well,this works fine, only when the rangeobject(startpoint and endpoint) lies in the same textnode,then it highlights the corresponding text.Ex

    <p>In this case,the text selected will be highlighted properly,
       because the selected text lies under a single textnode</p>

But if the rangeobject covers more than one textnode, then it is not working properlay, It highlights only the texts which lie in the first textnode,Ex

 <p><h3>In this case</h3>, only the text inside the header(h3) 
  will be highlighted, not any text outside the header</p> 

Any idea how can i make, all the texts which comes under rangeobject,highlighted,independent of whether range lies in a single node or multiple node? Thanks....

Answers:

Answer

Could you please elaborate the need of this functionality. If you only want to change the highlight style of the selected text you can use CSS: '::selection'

More Info: http://www.quirksmode.org/css/selection.html https://developer.mozilla.org/en/CSS/::selection

Answer

Can you try adding a class for the surrounding span and apply hierarchical CSS?

var span = document.createElement("span");
span.className="selection";
rangeObject.surroundContents(span);

In CSS definition,

span.selection, span.selection * {
   background-color : yellow;  
}

I did not try it. But just guessing that it would work.

Answer

I would suggest using document's or the TextRange's execCommand method, which is built for just such a purpose, but is usually used in editable documents. Here's the answer I gave to a similar question:

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.

UPDATE 12 September 2013

Here's a link detailing a method for removing highlights created by this method:

https://stackoverflow.com/a/8106283/96100

function makeEditableAndHighlight(colour) {
    var range, 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;
    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);
    }
}
Answer

Rangy is a cross-browser range and selection library that solves this problem perfectly with its CSS Class Applier module. I'm using it to implement highlighting across a range of desktop browsers and on iPad and it works perfectly.

Tim Down's answer is great but Rangy spares you from having to write and maintain all that feature detection code yourself.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.