为什么Javascript在Mac浏览器上按下metaKey时会丢弃keyUp事件?

时间:2012-08-05 17:45:18

标签: javascript macos events

在Mac浏览器上,当metakey关闭时,javascript不会收到大多数键的键盘事件(其他修饰键似乎是个例外)。使用这个jsfiddle来演示(聚焦结果区域并尝试类似cmd + x的东西,x将不会收到keyup事件): http://jsfiddle.net/mUEaV/

我在Chrome,FF,Safari和Opera的稳定版本中重现了这一点。 Windows 7中的控制键似乎没有发生同样的事情。

操作系统是否劫持了keyup事件?这看起来特别奇怪,因为使用metakey的命令,如save,find,cut,copy等等都在keydown上激活而不是在keyup上,并且可以被javascript劫持就好了。

4 个答案:

答案 0 :(得分:2)

按这些键时,浏览器窗口是否保持焦点?在Windows中,按下windows+RCTRL+ESC以及类似的键组合可以获得类似的结果,这些组合会使浏览器失去焦点并导致错过事件。

答案 1 :(得分:1)

尽管event.metaKey返回false,但仍然填充event.keyCode和event.key。

// onkeyup ...
if (e.metaKey || e.key == 'Meta') {
   // do something interesting.
}

答案 2 :(得分:0)

我今天了解到,使用meta时根本不可能获得onKeyUp事件。非常不幸,很难解决。您必须以其他方式模拟它们。

答案 3 :(得分:-1)

您可以通过在上一次按键事件之后等待一段时间来创建人为的按键事件。唯一需要注意的是,人们的操作系统会有不同的重复率。 https://jsfiddle.net/u7t43coz/10/

const metaKeyCodes = ["MetaLeft", "MetaRight"];
const shiftKeyCodes = ["ShiftLeft", "ShiftRight"];
const ctrlKeyCodes = ["ControlLeft", "ControlRight"];
const altKeyCodes = ["AltLeft", "AltRight"];
const modifierKeyCodes = [
  ...metaKeyCodes,
  ...shiftKeyCodes,
  ...ctrlKeyCodes,
  ...altKeyCodes
];

// record which keys are down
const downKeys = new Set()
const artificialKeyUpTimes = {}

function onKeydown(e) {
    downKeys.add(e.code);

    // do other keydown stuff here
    console.log("meta", e.metaKey, e.code, "down")

    // check if metaKey is down
    if (metaKeyCodes.some(k => downKeys.has(k))) {
      downKeys.forEach(dk => {
        // we want to exclude modifier keys has they dont repeat
        if (!modifierKeyCodes.includes(dk)) {
          // fire artificial keyup on timeout
          if (!artificialKeyUpTimes[dk])
            setTimeout(
              () => fireArtificialKeyUp(dk, e),
              500
            );
          artificialKeyUpTimes[dk] = Date.now();
        }
      });
    }
  }

 function fireArtificialKeyUp(code, e) {
    // if enough time has passed fire keyup
    if (Date.now() - artificialKeyUpTimes[code] > 100) {
      delete artificialKeyUpTimes[code];
      //if key is still down, fire keyup
      if (downKeys.has(code)) {
        const eCode = isNaN(code) ? { code: code } : { keyCode: code };
        document.dispatchEvent(
          new KeyboardEvent("keyup", { ...e, ...eCode })
        );
      }
    } else {
      setTimeout(() => fireArtificialKeyUp(code, e), 100);
    }
  }

  function onKeyup(e) {
    downKeys.delete(e.code);

    // do keyup stuff here
    console.log("meta", e.metaKey, e.code, "up")
  }

  document.addEventListener("keydown", onKeydown)
  document.addEventListener("keyup", onKeyup)