1

Given any block of text, using the following as an example:

Baseball is a sport. 
A pitcher throws the baseball and the batter hits the baseball.

I need to determine, using JavaScript (use of jQuery is fine), which of the three instances of "baseball" as been selected by the user. I have code in place that will wrap the selected text in a span, which may help in figuring this problem out.

Assuming that the user selects the second occurrence of baseball, the HTML will look similar to this:

Baseball is a sport. 
A pitcher throws the <span class="selection">baseball</span> and the batter hits the baseball.

Essentially I'm looking for a solution on how to determine that the selected 'baseball' is occurrence #2 (or 1 in the case of zero-indexing).

Any help is greatly appreciated.

David Link
  • 536
  • 3
  • 9
  • How do you mean "the user selects"? Do you mean that they click the word, or that they actually select the text by highlighting it with the mouse? – Christofer Eliasson Feb 16 '12 at 15:42
  • By selecting, you mean text selection? – sgowd Feb 16 '12 at 15:42
  • Doesn't really matter since he already has a class for the selected element. – ThiefMaster Feb 16 '12 at 15:43
  • The user will highlight the text with the mouse, and there is code in place to wrap a `span` around the selected text. So it doesn't matter if the determination is made before or after the span is created. – David Link Feb 16 '12 at 16:03

3 Answers3

2

The Selection object will tell you exactly what is selected:

var sel = window.getSelection();
if (sel.rangeCount) {
    var range = sel.getRangeAt(0);
    alert("Selection goes from offset " + range.startOffset + " in "
        + range.startContainer.nodeValue + " to offset " + range.endOffset
        + " in " + range.endContainer.nodeValue);
}

For your example, assuming you have a single text node containing all your text, you could do something like:

if (range.startContainer.nodeType == 3) {
    var textPriorToSelection = range.startContainer.data.slice(0, range.startOffset);
    var priorOccurrences = textPriorToSelection.split(sel.toString()).length - 1;
    alert("Occurrence " + (priorOccurrences + 1) + " of text '" + sel + "'");
}

Live demo: http://jsfiddle.net/kGE7e/

Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Tim, what a coincidence that you were the first to answer, as I'm using Rangy to help me out in this project. :) The problem is that I need to find which of the multiple substring occurrences has been selected. So in the example provided above, I need a response of "2" because the second instance of "baseball" was selected. – David Link Feb 16 '12 at 15:58
  • @DavidLink: Right. My point is that the selection tells you unambiguously which portion of the document is selected. I've updated my answer with an example. – Tim Down Feb 16 '12 at 16:15
0

After wrapping the words with span you can do it this way, using JQuery

<div id="parent">
<span>Baseball</span> is a sport. 
A pitcher throws the <span>baseball</span> and the batter hits the <span>baseball</span>.
</div>
<script>
     $("#parent span").click(function() {
        var index = $("#parent span").index(this);
        alert(index);
        //add class?
        $(this).addClass("selection");
    });
</script>
User
  • 31,811
  • 40
  • 131
  • 232
0

I'll probably get downvoted for this since I am using regexes to parse html, but I think it does what you want

var matches = "Baseball is a sport. A pitcher throws the <span class='selection'>baseball</span> and the batter hits the baseball.".match(/<span.*?>baseball<\/span>|baseball/gi);
for(i=0;i<matches.length;i++)
    if(matches[i].indexOf('selection')!=-1)
        console.log(i+'th index of baseball is selected');
Danny
  • 7,368
  • 8
  • 46
  • 70