4
<html>
<body>
<script language="javascript">
function getSelectionHTML()
{
    var div = document.getElementById("myDiv");

    if (document.createRange) { 
        var textNode=div.firstChild;
        var rangeObj=document.createRange();
        rangeObj.setStart(textNode,0);
        rangeObj.setEnd(textNode,5);
        div .innerHTML = div .innerHTML.replace(rangeObj.toString(), '<span style="background-color: lime">'+rangeObj.toString()+'</span>')
    }
}
</script>
<div id="myDiv">
asdf as<b>dfas df asf asdf sdfjk  dvh a sjkh jhcdjkv</b> iof scjahjkv ahsjv hdjk biud fcsvjksdhf k

</div>
<form name="aform">
<input type="button" value="Get selection" onclick="getSelectionHTML()">
</body>
</html>

Ok. Let me explain -> getSelectionHTML() method is for selection of characters from 0 to 10. I am getting the values by "myDiv" id. but inner bold, italic & other tags are giving me trouble.

In simple words, I just want to make selection of first ten characters (& apply them span tag) which are in "myDiv" tag.

What exactly I am missing?

halfer
  • 19,824
  • 17
  • 99
  • 186
sagarkothari
  • 24,520
  • 50
  • 165
  • 235

2 Answers2

2

This is much easier in IE using TextRange, which is based around characters, words and sentences rather than nodes and offsets. In non-IE browsers, you'll need to do tedious manual traversal of text nodes in the DOM. However, even if you were to do this to get the first ten text characters within your <div> (which would be "asdf asdfa"), your strategy is flawed because you're using a replacement on innerHTML, which would try and fail to find "asdf asdfa" (innerHTML would start with "asdf as<b>dfa", or possibly "asdf as<B>", depending on browser).

What I would suggest is doing the DOM traversal to find all text nodes within the <div> and surrounding the parts of the text nodes you need with <span>s, thus avoiding Ranges altogether and therefore making this work in all major browsers.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
1

You're trying to select e.g. character 1 to 10 of your text. But when using Range.setStart and .endStart, the first parameter is the text node containing your text. If you browse through the DOM with Firebug (or Web Inspector), you'll notice that character 10 of your text resides in another element (the <b> element), with its own text node.

BTW, you left out several required elements/tags, which can also be a source of errors.

My corrected version reads

<!DOCTYPE html>
<html>
<head>
  <title>Title element is required</title>
<body>
<script>
function getSelectionHTML()
{
    var div = document.getElementById("myDiv");
    var bEl = document.getElementById("bEl");

    if (document.createRange) {.
        var textNode=div.firstChild;
        var rangeObj=document.createRange();
        rangeObj.setStart(textNode,0);
        rangeObj.setEnd(bEl.firstChild,2);
        alert(rangeObj.toString());
//        div.innerHTML = div.innerHTML.replace(rangeObj.toString(), '<span style="background-color: lime">'+rangeObj.toString()+'</span>');
    }
}
</script>
<div id="myDiv">
asdf as<b id="bEl">dfas df asf asdf sdfjk  dvh a sjkh jhcdjkv</b> iof scjahjkv ahsjv hdjk biud fcsvjksdhf k
</div>
<form name="aform">
  <input type="button" value="Get selection" onclick="getSelectionHTML()">
</form>
</body>
</html>

Now rangeObj contains the selected text, but you can't simply insert a <span> element the way you tried, because elements can't be nested this way:

<span>asdf as<b>dfa</span>s df asf…
rob
  • 9,933
  • 7
  • 42
  • 73
Marcel Korpel
  • 21,536
  • 6
  • 60
  • 80
  • but this is the static solution, there may be bold or may b not. there may be any other tag in it. I asked ignoring inner elements. – sagarkothari Jun 01 '10 at 13:57
  • if u r saying it can't be nasted - then how is this possible ? theSelection = document.selection.createRange().htmlText; document.selection.createRange().pasteHTML("" + theSelection + ""); – sagarkothari Jun 01 '10 at 14:07
  • @sugar: I already feared that you wanted this to work in every situation, no matter whether there are inner elements or not. Unfortunately, you can't simply ignore them. You'll have to count the number of characters in the parent element, then traversing the DOM to count the number of characters in every child, till you have the number of characters you want. – Marcel Korpel Jun 01 '10 at 14:56
  • 1
    @sugar: Regarding your second comment: you'll have to almost parse the HTML you encounter and create inner spans in every element (so nesting them properly), like `blablablabla`. – Marcel Korpel Jun 01 '10 at 14:58
  • @Marcel - watch this question. It has directly applied span tag to selected text - http://stackoverflow.com/questions/2887101 - how's that possible ? – sagarkothari Jun 02 '10 at 06:42
  • 1
    sugar: the answer to that question works by traversing the text nodes within the selected range and surrounding each with a span. – Tim Down Jun 04 '10 at 11:23
  • @sugar: Indeed (added comment to notify OP). – Marcel Korpel Jun 04 '10 at 12:35