setSelectionRange not behaving the same way across browsers?
Asked Answered
M

1

3

I found this on a different question:

 setCaretToPos = function(input, selectionStart, selectionEnd){
      if(input.setSelectionRange){
        input.focus();
        input.setSelectionRange(selectionStart, selectionEnd);

      }else if(input.createTextRange){
        var range = input.createTextRange();
        range.collapse(true);
        range.moveEnd('character', selectionEnd);
        range.moveStart('character', selectionStart);
        range.select();
      }
    };

 setCaretToPos(8, 12);

It should select text from a text area between the 8th character and 12th character.

It works in Firefox and Chrome, but in Opera I get the wrong selection. Offset moves two characters behind

What's wrong with it?


It seems it has something to do with new lines: \n because the selection is correct if the text doesn't contain new line character.
Motive answered 19/1, 2012 at 15:25 Comment(3)
The way I see it is that you are missing the input parameter for your function. It's in the argument list but you are not passing it to your function. Check this out : jsfiddle.net/7Tsx6 and try to remove document.getElementById part and try both cases.Ous
No, that was just a mistake in my question, forgot to add the input argument. The problem appears when the textarea has new linesMotive
Based on the above comment are you passing the jQuery object or the actual element?Bioscope
H
8

New lines are two characters (CRLF, or \r\n) in textareas in Opera and IE and one character (\n) in other browsers. You'll need to adjust for that. Here's a function to do that, treating line breaks as a single character in all browsers.

Live demo: http://jsfiddle.net/DqtVK/1/

Code:

function adjustOffset(el, offset) {
    var val = el.value, newOffset = offset;
    if (val.indexOf("\r\n") > -1) {
        var matches = val.replace(/\r\n/g, "\n").slice(0, offset).match(/\n/g);
        newOffset += matches ? matches.length : 0;
    }
    return newOffset;
}

var setCaretToPos = function(input, selectionStart, selectionEnd){
  input.focus();
  if(input.setSelectionRange){
    selectionStart = adjustOffset(input, selectionStart);
    selectionEnd = adjustOffset(input, selectionEnd);
    input.setSelectionRange(selectionStart, selectionEnd);

  }else if(input.createTextRange){
    var range = input.createTextRange();
    range.collapse(true);
    range.moveEnd('character', selectionEnd);
    range.moveStart('character', selectionStart);
    range.select();
  }
};
Hotheaded answered 19/1, 2012 at 15:44 Comment(1)
for whatever reason, I had to change the newOffset += to newOffset -=Grissom

© 2022 - 2024 — McMap. All rights reserved.