6

I need my regex to accept arrow keys, letters, and numbers. I got the letters and numbers, but im stuck on arrow keys. I have this so far.

var patt = /[^a-zA-Z0-9]+/g;
var helper;
$('#name').keyup(function(e){
    helper = $('#name').val();
    helper = helper.replace(patt,' ');
    $('#name').val(helper);
});

Thanks for any help.

Mark Fox
  • 8,694
  • 9
  • 53
  • 75
Zapp
  • 232
  • 3
  • 12
  • 2
    Regular expressions match text strings, and arrow keys don't generally generate text strings. What are you trying to do? – Amber Feb 15 '16 at 02:14
  • @Amber Im trying to ignore arrow key input. I only want letters, numbers, arrow keys, and punctuation keys. When I hit the arrow keys, my pattern matches and puts me at the end of the line of text. – Zapp Feb 15 '16 at 02:17
  • @Zapp How is that code being executed? Is it inside of a `keypress`/`keydown`/`keyup` event listener or something...? – Josh Crozier Feb 15 '16 at 02:20
  • @JoshCrozier This is in a keyup event. I'll add the code – Zapp Feb 15 '16 at 02:22
  • 2
    This isn't a regex problem. Your code explicitly sets the value of the field, even if (depending on which key was pressed) the .replace() didn't do anything, and setting the value loses the cursor position. Note also that validating in a key event handler isn't enough, because the user can change the field via the Edit menu or by drag'n'drop. – nnnnnn Feb 15 '16 at 02:25
  • What you want is a list of key *codes* you're willing to accept. Every key has an associated number, but only some of these keys generate *characters*. – tadman Feb 15 '16 at 02:26
  • @tadman I tried using 'alert(e.which)' to find the arrow keys key code, but nothing happened when I hit the arrow keys. I got the codes for other keys though. – Zapp Feb 15 '16 at 02:29

3 Answers3

19

The problem is that you're replacing the element's entire value when the keyup event is fired. In doing so, the cursor will always be reset to the end.

To resolve this, you can capture the cursor's initial position by accessing the selectionStart property of the element. Then after replacing the value, you can simply set it back to where it initially was:

Here is an example in plain JS demonstrating this:

document.getElementById('name').addEventListener('input', function() {
  var position = this.selectionStart;
  
  this.value = this.value.replace(/[^a-zA-Z0-9]+/g, '');
  this.selectionEnd = position;
});
<input id="name" type="text" />

Likewise, the jQuery-version would be the same. I also changed the keyup event to an input event so that the event is only fired when the value is actually changed.

$('#name').on('input', function(e) {
  var position = this.selectionStart;

  this.value = this.value.replace(/[^a-zA-Z0-9]+/g, '');
  this.selectionEnd = position;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="name" type="text" />

As an alternative, you could also just listen to the change event and then replace the value; however, this wouldn't update the value while typing.

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
2

When you press the arrow key you're changing the value of the input, so the cursor will lose its place. This is unrelated to the regex you're using.

You should not modify user input while they're typing. Instead do it on the .change() jQuery callback listener, not .keyup()

Andy Ray
  • 30,372
  • 14
  • 101
  • 138
0

Another way is in keyup event callback, execute event.preventDefault(); , that solved my problem

Haojen
  • 686
  • 7
  • 9