jquery - not able to catch `@` (at the rate symbol) on keyup event

Viewed 487

I have in my code a keyup event and I need to catch the @ character. I'm using this code:

$(function() {
  $("#textbox").keyup(function(e) {
    var keynum = e.keyCode;
    if (keynum && e.shiftKey && keynum == 50) {
      // Made a small change.
      console.log("You pressed @ and value is: " + e.target.value);
    }
  })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<input id="textbox" />

Now, the problem is that it doesn't work whenever user types shift+2 a little faster

EDIT

You can reproduce this problem by releasing the modifier (shift key) a few milliseconds before the other (2 on my keyboard) key, i.e typing shift + 2 really fast.

@ConstantinGroß was able to address this problem and has a workaround. Please check the accepted answer below.

2 Answers

You could use KeyboardEvent.key (e.key vs e.keyCode): https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

$("#textbox").keyup(function(e) {
  if (e.key === '@') {
    console.log("You pressed @ and value is: " + e.target.value);
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<input id="textbox" />

There does indeed seem to be an issue with jQuery detecting multi-key characters when they are done too fast (e.g. releasing the modifier key just a few milliseconds before the other key). I was able to reproduce this on my Germany keyboard layout as well, where @ is AltGr+Q. Here's another solution keeping track of the number of times the @ character occurs in the input value. Not very elegant, but it does the trick reliably for me.

$("#textbox").keyup(function(e) {
  // if content is empty reset at-count
  if('' === $(this).val().trim()) {
     $(this).data('at-count', 0);
  }
  // removing all characters other than @, then counting the length
  var atCount = $(this).val().replace(/[^@]/g, "").length;
  // if the number of @ in the input value has increased:
  if (atCount > ($(this).data('at-count') || 0)) {
    console.log("You pressed @ and value is: " + e.target.value);
  }
  // store the current @ count for later comparison
  $(this).data('at-count', atCount);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<input id="textbox" />

Related