views:

92

answers:

3

I want to get back the text that I select in an element using the Range object provided by Mozilla's flavour of javascript.

So I do this:

//assume that I'm only using Firefox, and there is just one selection
var range = window.getSelection().getRangeAt(0);
var rangeText = range.toString();

This works OK when the html of the selected text doesn't have any newlines In other words, if I have the following html:

<div>One. Two. Three. Four. Five.</div>

and I select Two. Three. Four., then everything is fine.

On the other hand, if I have

<div>
One.
Two.
Three.
Four.
Five.
</div>

and I select Two. Three. Four. as before, there are newlines introduced into the result returned from Range.toString(); the newlines are after Two., Three., and Four.

Obviously, when displayed in the browser, both html fragments are identical. Is there a way I can ensure that the same text is returned without newlines?

A: 

This should do it:

range.toString().replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, '')
brianpeiris
`\s` is sufficient as it matches `[\f\n\r\t\v\u00A0\u2028\u2029]`. See http://www.javascriptkit.com/javatutors/redev2.shtml
Justin Johnson
Thanks Justin, I've edited my answer with your correction.
brianpeiris
This almost worked, but I found that there were spaces that were being inserted between the '<div>' and the 'One' that it couldn't get rid of, since it could only reduce them to a single space. In other words, it still wasn't getting me the exact text between the div tags.
Shoko
I've edited the answer to trim whitespace from the ends of the string.
brianpeiris
+1  A: 

Yes. Use the toString() method of the selection object instead:

var rangeText = window.getSelection().toString();
Tim Down
Hi Tim,Your suggestion works, but the problem is also that I am working with multiple ranges, some which are clones of the original range. I don't know how this would work with many ranges.
Shoko
A: 

OK, I used part of the answer from Tim Down in the end:

  var sel = window.getSelection();
  var range = sel.getRangeAt(0);
  var range2 = range.cloneRange();

  //do some stuff with range2...

  var rangeText, range2Text;

  sel.removeAllRanges();
  sel.addRange(range);
  rangeText = sel.toString();

  sel.removeAllRanges();
  sel.addRange(range2);
  range2Text = sel.toString();
Shoko
That will do what you want, but you should make sure you restore the selection to whatever it started as at the end so as not to confuse the user.
Tim Down