How do you tell if caps lock is on using JavaScript?

How do you tell if caps lock is on using JavaScript?

One caveat though: I did google it and the best solution I could find was to attach an onkeypress event to every input, then check each time if the letter pressed was uppercase, and if it was, then check if shift was also held down. If it wasn't, therefore caps lock must be on. This feels really dirty and just... wasteful - surely there's a better way than this?


Solution 1:

In jQuery,

$('#example').keypress(function(e) { 
    var s = String.fromCharCode( e.which );
    if ( s.toUpperCase() === s && s.toLowerCase() !== s && !e.shiftKey ) {
        alert('caps is on');
    }
});

Avoid the mistake, like the backspace key, s.toLowerCase() !== s is needed.

Solution 2:

You can use a KeyboardEvent to detect numerous keys including the caps lock on most recent browsers.

The getModifierState function will provide the state for:

  • Alt
  • AltGraph
  • CapsLock
  • Control
  • Fn (Android)
  • Meta
  • NumLock
  • OS (Windows & Linux)
  • ScrollLock
  • Shift

This demo works in all major browsers including mobile (caniuse).

passwordField.addEventListener( 'keydown', function( event ) {
  var caps = event.getModifierState && event.getModifierState( 'CapsLock' );
  console.log( caps ); // true when you press the keyboard CapsLock key
});

Solution 3:

You can give it a try.. Added a working example. When focus is on input, turning on caps lock makes the led go red otherwise green. (Haven't tested on mac/linux)

NOTE: Both versions are working for me. Thanks for constructive inputs in the comments.

OLD VERSION: https://jsbin.com/mahenes/edit?js,output

Also, here is a modified version (can someone test on mac and confirm)

NEW VERSION: https://jsbin.com/xiconuv/edit?js,output

NEW VERSION:

function isCapslock(e) {
  const IS_MAC = /Mac/.test(navigator.platform);

  const charCode = e.charCode;
  const shiftKey = e.shiftKey;

  if (charCode >= 97 && charCode <= 122) {
    capsLock = shiftKey;
  } else if (charCode >= 65 && charCode <= 90
    && !(shiftKey && IS_MAC)) {
    capsLock = !shiftKey;
  }

  return capsLock;
}

OLD VERSION:

function isCapslock(e) {
  e = (e) ? e : window.event;

  var charCode = false;
  if (e.which) {
    charCode = e.which;
  } else if (e.keyCode) {
    charCode = e.keyCode;
  }

  var shifton = false;
  if (e.shiftKey) {
    shifton = e.shiftKey;
  } else if (e.modifiers) {
    shifton = !!(e.modifiers & 4);
  }

  if (charCode >= 97 && charCode <= 122 && shifton) {
    return true;
  }

  if (charCode >= 65 && charCode <= 90 && !shifton) {
    return true;
  }

  return false;
}

For international characters, additional check can be added for the following keys as needed. You have to get the keycode range for characters you are interested in, may be by using a keymapping array which will hold all the valid use case keys you are addressing...

uppercase A-Z or 'Ä', 'Ö', 'Ü', lowercase a-Z or 0-9 or 'ä', 'ö', 'ü'

The above keys are just sample representation.

Solution 4:

You can detect caps lock using "is letter uppercase and no shift pressed" using a keypress capture on the document. But then you better be sure that no other keypress handler pops the event bubble before it gets to the handler on the document.

document.onkeypress = function ( e ) {
  e = e || window.event;
  var s = String.fromCharCode( e.keyCode || e.which );
  if ( (s.toUpperCase() === s) !== e.shiftKey ) {
    // alert('caps is on')
  }
}

You could grab the event during the capturing phase in browsers that support that, but it seems somewhat pointless to as it won't work on all browsers.

I can't think of any other way of actually detecting caps lock status. The check is simple anyway and if non detectable characters were typed, well... then detecting wasn't necessary.

There was an article on 24 ways on this last year. Quite good, but lacks international character support (use toUpperCase() to get around that).

Solution 5:

Many existing answers will check for caps lock on when shift is not pressed but will not check for it if you press shift and get lowercase, or will check for that but will not also check for caps lock being off, or will check for that but will consider non-alpha keys as 'off'. Here is an adapted jQuery solution that will show a warning if an alpha key is pressed with caps (shift or no shift), will turn off the warning if an alpha key is pressed without caps, but will not turn the warning off or on when numbers or other keys are pressed.

$("#password").keypress(function(e) { 
    var s = String.fromCharCode( e.which );
    if ((s.toUpperCase() === s && s.toLowerCase() !== s && !e.shiftKey)|| //caps is on
      (s.toUpperCase() !== s && s.toLowerCase() === s && e.shiftKey)) {
        $("#CapsWarn").show();
    } else if ((s.toLowerCase() === s && s.toUpperCase() !== s && !e.shiftKey)||
      (s.toLowerCase() !== s && s.toUpperCase() === s && e.shiftKey)) { //caps is off
        $("#CapsWarn").hide();
    } //else upper and lower are both same (i.e. not alpha key - so do not hide message if already on but do not turn on if alpha keys not hit yet)
  });