4

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.

Sumit Wadhwa
  • 2,825
  • 1
  • 20
  • 34

2 Answers2

4

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" />
Constantin Groß
  • 10,719
  • 4
  • 24
  • 50
Tanner
  • 2,232
  • 13
  • 22
  • 2
    It's jQuery code, and that library normalizes the event attributes so that `keyCode` is reliable. – Pointy Oct 22 '19 at 15:09
  • @Tanner, I'm not sure why I saw someone down-vote your answer almost as soon as it appeared. Even if jQuery "normalizes the event attributes", using `key` is good practice as far as I'm concerned. – kshetline Oct 22 '19 at 15:11
  • 1
    OP is using jQuery, so where's the problem? – Constantin Groß Oct 22 '19 at 15:11
  • this should be the right answer, but believe me it still doesn't work for me – Sumit Wadhwa Oct 22 '19 at 15:16
  • I'm console logging the `e.key`, upon doing it slowly I get `@` but faster I get `Shift` even though textbox prints @ in there – Sumit Wadhwa Oct 22 '19 at 15:17
  • I was able to reproduce this on my German keyboard as well, where it's `AltGr+Q`. If you're too fast, the detection won't work. I've come up with a solution in my own answer. – Constantin Groß Oct 22 '19 at 15:27
  • @JayWadhwa you're right, looks like the issue persists. How does Constantin's answer work for you? – Tanner Oct 22 '19 at 15:35
3

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" />
Sumit Wadhwa
  • 2,825
  • 1
  • 20
  • 34
Constantin Groß
  • 10,719
  • 4
  • 24
  • 50
  • By the way, I tried the following based on the accepted answer of the [question linked as possible duplicate](https://stackoverflow.com/questions/10110073/in-keydown-event-get-charecter-in-different-language): Using `keypress` instead of `keyup` in conjunction with `if (String.fromCharCode(e.which) === "@") { ... }` - but it failed for me trying it with the Chinese Pinyin input method under Windows, while my solution keeps working even then. – Constantin Groß Oct 22 '19 at 15:43
  • but I still don't understand; if we're releasing the shift key a few milliseconds earlier than how come my system prints `@` and not `2`? – Sumit Wadhwa Oct 23 '19 at 05:28
  • 1
    I guess the OSes (or maybe even the keyboard hardware itself) implement some kind of "cooldown phase" for modifier keys exactly for that purpose, because you would quite often mistype otherwise. – Constantin Groß Oct 23 '19 at 06:27
  • I've edited your question to fix a small bug. It won't work if you remove everything from the textarea and type `@`. – Sumit Wadhwa Oct 23 '19 at 06:40
  • Strange, that should have worked without that change, because the @ count is 0 already when the value is empty. I had edited the answer yesterday to fix a similar issue, maybe you didn't have the latest version of the code. I'll check once I'm back at my work station. – Constantin Groß Oct 23 '19 at 07:46