I'm writing a Firefox addon that is triggered whenever a word is highlighted. However I need a script that detects when a word is highlighted, and I'm stuck. An example would be nytimes.com (when you're reading an article and you highlight a word, the reference icon pops up). However the nytimes.com script is super complex. I'm 16 and not much of a programmer, so that is definitely way out of my league.
4 Answers
The easiest way to do this is to detect mouseup
and keyup
events on the document and check whether any text is selected. The following will work in all major browsers.
Example: http://www.jsfiddle.net/timdown/SW54T/
function getSelectedText() {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof document.selection != "undefined" && document.selection.type == "Text") {
text = document.selection.createRange().text;
}
return text;
}
function doSomethingWithSelectedText() {
var selectedText = getSelectedText();
if (selectedText) {
alert("Got selected text " + selectedText);
}
}
document.onmouseup = doSomethingWithSelectedText;
document.onkeyup = doSomethingWithSelectedText;

- 318,141
- 75
- 454
- 536
-
4But what if you want to detect if a specific word is selected? Say you have `foo` on the page multiple times and the user selects `foo` how do you know which of the words the user selected? – Jespertheend Oct 08 '16 at 19:39
-
1@Jespertheend if the data(`foo`s) is dynamically generated, then you can give some unique id to every `foo` and then you can use `window.getSelection().getRangeAt(0).startContainer.parentNode.id` to the get the specific `foo`'s id. – Raghav Garg Apr 12 '18 at 04:46
-
This is great, thanks! I wanted to implement custom maxlength functionality on a `keypress` event of an input, but if the input's already at its max, the keypress should still go through if any text is highlighted. Your function did the job perfectly – Jacob Stamm Jun 15 '18 at 20:14
Here is a script:
<script>
function getSelText()
{
var txt = '';
if (window.getSelection)
{
txt = window.getSelection();
}
else if (document.getSelection)
{
txt = document.getSelection();
}
else if (document.selection)
{
txt = document.selection.createRange().text;
}
else return;
document.aform.selectedtext.value = txt;
}
</script>
<input type="button" value="Get selection" onmousedown="getSelText()">
<form name="aform">
<textarea name="selectedtext" rows="5" cols="20"></textarea>
</form>
Courtesy of Code Toad:
http://www.codetoad.com/javascript_get_selected_text.asp
In your case, you would want to call this script when the selection is made, and then you can process it however you wish, with an AJAX request to get relevant information for example, like NYtimes probably does.

- 2,421
- 5
- 22
- 45

- 61,249
- 84
- 283
- 456
-
6I keep seeing this code on SO, and it's wrong: `window.getSelection()` returns a `Selection` object, not a string. – Tim Down Jan 17 '11 at 12:26
-
2@tim down not the entire truth. The object has a toString() method. When a string is expected a string is returned, otherwise, as you point out an object is returned. https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection – Ted Cohen Mar 04 '15 at 16:08
-
@TedCohen: It's true that a `Selection` object does have a sensible `toString()` implementation but the rest of your comment makes no sense: a `Selection` object is always returned if `window.getSelection` exists (which it does in all modern browsers). – Tim Down Mar 04 '15 at 16:27
-
Yes, the method returns an object. If it did not return an object, how could the "thing" returned have a toString() method which we both agree on. What I disagree with is your statement that the code is wrong. What u r forgetting is that the js language implicitly casts things all the time. Some people call that being a weakly typed language. All js programmers need to spot the casting & recognize it for what it is. After the browser returns the object js implicitly calls the toString() method & returns a string. That happens for any object in js, not just getSelection(). The code is NOT wrong – Ted Cohen Mar 05 '15 at 01:54
-
@tim down which is why you see it all the time on SO. Please read the reference in my original comment as it spells out what I am saying quite clearly, probably better than I ever could. – Ted Cohen Mar 05 '15 at 01:56
-
@TedCohen I understand the issues and wasn't forgetting about implicit calls to `toString`. If anything, the MDN page you linked to supports my point with its example of trying to call a string method such as `substr` on the returned value, which was precisely the point I was considering making myself. Anyway, I suppose my original assertion of "wrong" is perhaps too strong; "deeply unhelpful" may be better. – Tim Down Mar 05 '15 at 02:07
-
I think that we agree now. I tried to edit my original comment to explain that it would have been more instructional if the code had explicitly shown the call to toString(). Even though I started my edit within 5 minutes, SO would not let me post it because by the time I had finished. 5 minutes had elapsed. I was totally hung up on your use of the word "wrong" and felt it was taking away from your otherwise insightful point about the object being returned. Of those that know the method exists, I'll bet that 99% would say that it returns a string because they learned about it looking at code. – Ted Cohen Mar 05 '15 at 02:39
-
@tim down I did not say that your comment was wrong, just that it was not the entire truth. I wish that you could go back and edit your initial comment a bit and we could delete this discussion part. You had a very important point to make that as the MDN page said, is often misunderstood (I am paraphrasing from memory, not quoting) – Ted Cohen Mar 05 '15 at 02:40
In my case I wanted to be able to either highlight a text in a row of the and click in the row and send me to other route like "/entity/:id";
I created one function that detects the mouse is highlighting some text:
export const isHighlighting = () => {
// detects mouse is highlighting a text
return window.getSelection && window.getSelection().type === 'Range';
};
then I added this to the row of the
const handleClick = (id) => {
if (!isHighlighting() {
history.push(`/entity/${id}`)
}
}
{data.map((item) => (
<tr>
<td onClick={() => handleClick(item.id)}>{item.name}</>
</tr>
))}
in this way the user can hightlight then name field or click somewhere else and goes to "/entity/:id"

- 91
- 1
- 2
Using rangy.js and jQuery:
$('#elem').on('keyup mouseup', function(){
var sel = rangy.getSelection()
if (sel.rangeCount === 0 || sel.isCollapsed) return
alert(sel.toString())
})

- 1,211
- 1
- 17
- 17