skip to Main Content

I am working on a to-do list browser application (written in JavaScript, HTML and CSS, no jQuery), and I wanted to add custom behaviour for tab and shift + tab, because those should be indentation rather than navigation. Since there is no way to catch a key combination directly, I created a shift_pressed variable that detects when shift is pressed:

document.addEventListener('keyup', function (event) {
    if (event.key === 'Shift') {
        shift_pressed = false;
    }
});

document.addEventListener('keydown', function (event) {
    if (event.key === 'Shift') {
        shift_pressed = true;
    } else if (event.key === "Tab") {
        event.preventDefault();
        if (shift_pressed) {
            minus_indent();
        } else {
            plus_indent();
        }
    }
});

This works great, as long as the user stays on my tab. However, when someone uses control+shift+tab to move to the previous tab in their browser, they press shift on my tab, causing the shift_pressed variable to become true. Then, they release it on another tab, causing shift_pressed to stay true, even if they return. They then need to press and release shift again to fix it.

I decided, if the issue is control+shift+tab, let’s just catch control as well. So I did this:

document.addEventListener('keyup', function (event) {
    if (event.key === "Control") {
        ctrl = false;
    }
document.addEventListener('keydown', function (event) {
    if (event.key === 'Shift') {
        if (!ctrl) {
            shift_pressed = true;
        }
    } else if (event.key === "Control") {
        ctrl = true;
    }

This works, as long as people navigate tabs only using control+tab or control+shift+tab.
When they navigate away, control must be pressed, and when they navigate back, control must be released on my tab, so this works.

The problem is, if someone tabs away using control+shift+tab, then shift_pressed may stay false, but ctrl becomes true. And if they then navigate back not with control+tab (which would set ctrl back to false) but by clicking on the tab in their browser, ctrl stays true. This then means that shift is completely blocked from usage until they press and release control again.

2

Answers


  1. You can make sure to reset your booleans when switching tabs, to do so you can use the following:

    document.addEventListener("visibilityChange", () => {
      if (document.visibilityState === "hidden") {
        shift_pressed = false;
        ctrl = false;
      }
    });
    
    Login or Signup to reply.
  2. I don’t think you need to roll your own. You can just check the existing shiftKey modifier (a ctrlKey modified also exists).

       if (event.key === "Tab") {
            event.preventDefault();
            if (event.shiftKey) {
                minus_indent();
            } else {
                plus_indent();
            }
        }
    

    https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/shiftKey
    https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/ctrlKey

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search