46

I'm using a regular expression to strip invalid characters out of an text input area in javascript (running in IE). I run the replace function on every keyup event. However, this makes the cursor jump to the end of the text box after each keypress, which makes inline editing impossible.

Here is it in action:

http://jsbin.com/ifufuv/2

Does anyone know how to make it so the cursor does not jump to the end of the input box?

Petey B
  • 11,439
  • 25
  • 81
  • 101
  • 2
    I strongly recommend that you choose a better event to handle. `onkeyup` is poor for detecting user input. See http://whattheheadsaid.com/2010/09/effectively-detecting-user-input-in-javascript. – Andy E Nov 21 '11 at 23:15
  • Here's a fully realised example of how to maintain the selection when replacing the value of a textarea: http://stackoverflow.com/questions/3286595/update-textarea-value-but-keep-cursor-position/3288215#3288215 – Tim Down Nov 22 '11 at 00:13

3 Answers3

31

In addition to gilly3's answer, I thought someone might find it useful to see an actual code snippet.

In the example below, the selectionStart property is retrieved from the input element prior to the JavaScript string manipulation. Then selectionStart is set back to the initial position after the manipulation.

Depending on what you're trying to achieve, you could also access selectionEnd in place of selectionStart, and set a range: setSelectionRange(start, end).

document.getElementById('target').addEventListener('input', function (e) {
  var target = e.target,
      position = target.selectionStart; // Capture initial position
  
  target.value = target.value.replace(/\s/g, '');  // This triggers the cursor to move.
  
  target.selectionEnd = position;    // Set the cursor back to the initial position.
});
<p>The method <code>.replace()</code> will move the cursor's position, but you won't notice this.</p>
<input type="text" id="target" />
Community
  • 1
  • 1
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
18

You'll have to manually put the cursor back where you want it. For IE9, set .selectionStart and .selectionEnd (or use .setSelectionRange(start, end)). For IE8 and earlier, use .createTextRange() and call .moveStart() on the text range.

gilly3
  • 87,962
  • 25
  • 144
  • 176
  • 4
    W3Schools have a wonderful example on how to use onkeypress to cancel keys (in their example, it cancels numbers, and you seem sufficiently capable to modify the regex to take out the characters you don't want). http://www.w3schools.com/jsref/event_onkeypress.asp – John Nov 21 '11 at 23:07
  • 8
    @Mike: W3Schools doesn't really deserve people like you promoting their website for them. Take a look at http://w3fools.com - a lot of information at w3s is wrong or promoting bad practices for developers. There are much better resources on the web, like http://quirksmode.org or http://developer.mozilla.org. – Andy E Nov 21 '11 at 23:13
  • Fair enough point, I was unaware of the issues with that site. – John Nov 21 '11 at 23:22
  • 2
    See http://stackoverflow.com/questions/3286595/update-textarea-value-but-keep-cursor-position/3288215#3288215 for my implementation of this basic technique. – Tim Down Nov 22 '11 at 00:13
0

I was running into the same issue, I found https://www.sitepoint.com/6-jquery-cursor-functions/ had the solution. here are 6 methods that will allow you to get/set the cursor position in an input/textarea. I believe this will work for content editable fields as well!

This was very helpful as the bug only showed for IE and Windows 7 combination.

Here is my Before code

$body.on('input paste','.replace-special-chars',function () {
    let coma = /‚/g;
    let doubleQuotes = /[“”]/g;
    let singleQuotes = /[‘’]/g;
    $(this).val($(this).val().replace(doubleQuotes,'"'));
    $(this).val($(this).val().replace(coma,','));
    $(this).val($(this).val().replace(singleQuotes,"'"));
    $(this).val($(this).val().replace(/[^\x00-\xff]/g, '- '));
});

and my after code which utilizes the jquery methods that I found on the website I stated above

$body.on('input paste','.replace-special-chars',function () {
    let position = $(this).getCursorPosition();
    let coma = /‚/g;
    let doubleQuotes = /[“”]/g;
    let singleQuotes = /[‘’]/g;
    $(this).val($(this).val().replace(doubleQuotes,'"'));
    $(this).val($(this).val().replace(coma,','));
    $(this).val($(this).val().replace(singleQuotes,"'"));
    $(this).val($(this).val().replace(/[^\x00-\xff]/g, '- '));
    $(this).setCursorPosition(position);
});
Mike
  • 96
  • 5