views:

1843

answers:

2

Finding out what's selected in real browsers is as simple as:

var range = {
  start: textbox.selectionStart,
  end: textbox.selectionEnd
}

But IE, as usual, doesn't understand. What's the best cross-browser way to do this?

+4  A: 

My current solution is verbose and based on this thread, but I'm open to better solutions.

function getSelection(inputBox) {
 if ("selectionStart" in inputBox) {
  return {
   start: inputBox.selectionStart,
   end: inputBox.selectionEnd
  }
 }

 //and now, the blinkered IE way
 var bookmark = document.selection.createRange().getBookmark()
 var selection = inputBox.createTextRange()
 selection.moveToBookmark(bookmark)

 var before = inputBox.createTextRange()
 before.collapse(true)
 before.setEndPoint("EndToStart", selection)

 var beforeLength = before.text.length
 var selLength = selection.text.length

 return {
  start: beforeLength,
  end: beforeLength + selLength
 }
}
TALlama
+4  A: 

IE's Range implementation is a slithy horror. It really wants you to use the execrable execCommand interface instead of anything involving indexing into the text.

There are two approaches I know of for getting the indices and they both have problems. The first uses range.text as in your example code. Unfortunately range.text has a habit of stripping off leading and trailing newlines, which means if the caret/selection is at the start of a line other than the first one, beforeLength will be off by (number of newlines*2) characters and you'll get the wrong selected text.

The second approach is to use range.moveStart/End (on a duplicated range), as outlined in the answer to this question: http://stackoverflow.com/questions/164147/character-offset-in-an-internet-explorer-textrange (however as you are using a known textarea parent you can ignore the stuff about node-finding). This doesn't have the same problem, but it does report all indices as if newlines were simple LF characters, even though textarea.value and range.text will return them as CRLF sequences! So you can't use them directly to index into the textarea, but you can either fix them up with a bunch of newline counting or just string-replace away all the CRs from the value before you use it.

bobince