使用JavaScript和jQuery处理按键事件(F1-F12),跨浏览器

90

我希望使用JavaScript和jQuery处理F1-F12键。

我不确定需要避免哪些陷阱,并且我目前无法在除了Internet Explorer 8、Google Chrome和Mozilla FireFox 3之外的其他浏览器中测试实现。

有没有完全跨浏览器的解决方案建议?例如经过良好测试的jQuery库或仅使用基本的jQuery / JavaScript?

15个回答

54

我同意William的观点,通常劫持功能键是一个不好的想法。话虽如此,我找到了这个快捷键库,它以非常流畅的方式添加了此功能,以及其他键盘快捷键和组合。

单个按键:

shortcut.add("F1", function() {
    alert("F1 pressed");
});

按键组合:

shortcut.add("Ctrl+Shift+A", function() {
    alert("Ctrl Shift A pressed");
});

1
看起来是一个非常好的库!谢谢分享。 - Alvaro Flaño Larrondo
最近版本的Chrome完美运行,即使使用F5-F11功能也没有问题。 - Nicolas Zozol

29

我在这类问题上最好的信息来源是这个页面:http://www.quirksmode.org/js/keys.html

他们说的是,Safari上的键码是奇怪的,在其他地方都是一致的(除了IE上没有keypress事件,但我相信keydown也可以使用)。


2
我忘记在哪里找到的,但Jan Wolter写了一篇关于JavaScript键盘事件的好文章:http://unixpapa.com/js/key.html - Paul D. Waite

27

我不确定是否能拦截功能键,但我建议完全避免使用功能键。浏览器使用功能键执行各种任务,其中一些任务非常普通。例如,在Linux上的Firefox中,至少有六个或七个功能键被保留供浏览器使用:

  • F1(帮助),
  • F3(搜索),
  • F5(刷新),
  • F6(聚焦地址栏),
  • F7(插入符号浏览模式),
  • F11(全屏模式)和
  • F12(由多个附加组件使用,包括Firebug)

最糟糕的是,不同操作系统上的不同浏览器使用不同的键执行不同的任务。这是要考虑的很多差异。您应该坚持使用更安全、不太常用的键盘组合。


7
我知道有些按键已被保留。然而,我想使用其他未被保留的按键。 - cllpse
1
在我的电脑上,所有的F键都被预留了。我使用Opera浏览器,并设置了一些自定义快捷键。从不依赖于“通常未被预留的键”的约定。 - gizmo
5
“我想使用未被占用的任何键” — 问题是,程序无法自动识别哪些键是未被占用的。占用功能键对于您的应用程序可能是可以接受的,但很难确定。 - Paul D. Waite
3
我正在使用手持工业扫描仪,需要使用功能键。 - Bmo
1
@Bmo 我马上就知道这是工业相关的东西;我猜你正在尝试在网页中模仿ERP功能并需要处理F键。我也处于同样的境地! :) - KingOfAllTrades
显示剩余3条评论

26

这非常简单。

$(function(){
    //Yes! use keydown because some keys are fired only in this trigger,
    //such arrows keys
    $("body").keydown(function(e){
         //well so you need keep on mind that your browser use some keys 
         //to call some function, so we'll prevent this
         e.preventDefault();

         //now we caught the key code.
         var keyCode = e.keyCode || e.which;

         //your keyCode contains the key code, F1 to F12 
         //is among 112 and 123. Just it.
         console.log(keyCode);       
    });
});

2
我最喜欢你的方法,因为它可以让你捕捉你想要的键并传递其余的键。我注意到你的解决方案存在一个问题:例如 ctrl + shift + r 也被捕获了。如果你想取消每个事件,这很好。但我建议在逻辑本身中进行处理。如果(key == x) {e.preventDefault(); (your logic goes here)} 返回 e,以帮助解决这个问题。 - Cees

13

没有其他外部类的情况下,您可以使用简单的代码创建自己的hack代码。

event.keyCode

我认为对所有人有帮助的另一个东西是这个测试页面,它可以拦截keyCode(只需将其复制粘贴到新的file.html中以测试您的事件)。

 <html>
 <head>
 <title>Untitled</title>
 <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
 <style type="text/css">
 td,th{border:2px solid #aaa;}
 </style>
 <script type="text/javascript">
 var t_cel,tc_ln;
 if(document.addEventListener){ //code for Moz
   document.addEventListener("keydown",keyCapt,false); 
   document.addEventListener("keyup",keyCapt,false);
   document.addEventListener("keypress",keyCapt,false);
 }else{
   document.attachEvent("onkeydown",keyCapt); //code for IE
   document.attachEvent("onkeyup",keyCapt); 
   document.attachEvent("onkeypress",keyCapt); 
 }
 function keyCapt(e){
   if(typeof window.event!="undefined"){
    e=window.event;//code for IE
   }
   if(e.type=="keydown"){
    t_cel[0].innerHTML=e.keyCode;
    t_cel[3].innerHTML=e.charCode;
   }else if(e.type=="keyup"){
    t_cel[1].innerHTML=e.keyCode;
    t_cel[4].innerHTML=e.charCode;
   }else if(e.type=="keypress"){
    t_cel[2].innerHTML=e.keyCode;
    t_cel[5].innerHTML=e.charCode;
   }
 }
 window.onload=function(){
   t_cel=document.getElementById("tblOne").getElementsByTagName("td");
   tc_ln=t_cel.length;
 }
 </script>
 </head>
 <body>
 <table id="tblOne">
 <tr>
 <th style="border:none;"></th><th>onkeydown</th><th>onkeyup</th><th>onkeypress</td>
 </tr>
 <tr>
 <th>keyCode</th><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
 </tr>
 <tr>
 <th>charCode</th><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
 </tr>
 </table>
 <button onclick="for(i=0;i<tc_ln;i++){t_cel[i].innerHTML='&nbsp;'};">CLEAR</button>
 </body>
 </html>

这里有一个可视化演示,您可以在此处尝试:

var t_cel, tc_ln;
if (document.addEventListener) { //code for Moz
  document.addEventListener("keydown", keyCapt, false);
  document.addEventListener("keyup", keyCapt, false);
  document.addEventListener("keypress", keyCapt, false);
} else {
  document.attachEvent("onkeydown", keyCapt); //code for IE
  document.attachEvent("onkeyup", keyCapt);
  document.attachEvent("onkeypress", keyCapt);
}

function keyCapt(e) {
  if (typeof window.event != "undefined") {
    e = window.event; //code for IE
  }
  if (e.type == "keydown") {
    t_cel[0].innerHTML = e.keyCode;
    t_cel[3].innerHTML = e.charCode;
  } else if (e.type == "keyup") {
    t_cel[1].innerHTML = e.keyCode;
    t_cel[4].innerHTML = e.charCode;
  } else if (e.type == "keypress") {
    t_cel[2].innerHTML = e.keyCode;
    t_cel[5].innerHTML = e.charCode;
  }
}
window.onload = function() {
  t_cel = document.getElementById("tblOne").getElementsByTagName("td");
  tc_ln = t_cel.length;
}
td,
th {
  border: 2px solid #aaa;
}
<html>

<head>
  <title>Untitled</title>
  <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
</head>

<body>
  <table id="tblOne">
    <tr>
      <th style="border:none;"></th>
      <th>onkeydown</th>
      <th>onkeyup</th>
      <th>onkeypress</td>
    </tr>
    <tr>
      <th>keyCode</th>
      <td>&nbsp;</td>
      <td>&nbsp;</td>
      <td>&nbsp;</td>
    </tr>
    <tr>
      <th>charCode</th>
      <td>&nbsp;</td>
      <td>&nbsp;</td>
      <td>&nbsp;</td>
    </tr>
  </table>
  <button onclick="for(i=0;i<tc_ln;i++){t_cel[i].innerHTML='&nbsp;'};">CLEAR</button>
</body>

</html>


1
谢谢@paladinux,你的代码对我很有效。我正在定制它以在按键时调用自定义函数。但是我遇到了一个问题。每当我输入字符'q,r,s,t,u'时,页面会自动执行自定义函数,因为这些键具有与功能键F2...F7(113..118)相同的键码。 - raj

7

适用于现代浏览器和IE11的ES6解决方案(经过转码为ES5):

//Disable default IE help popup
window.onhelp = function() {
    return false;
};
window.onkeydown = evt => {
    switch (evt.keyCode) {
        //ESC
        case 27:
            this.onEsc();
            break;
        //F1
        case 112:
            this.onF1();
            break;
        //Fallback to default browser behaviour
        default:
            return true;
    }
    //Returning false overrides default browser event
    return false;
};

1
也许修复 this.onX 事件,以使示例更具可移植性? - mix3d

2

这对我有效。

if(code ==112) { alert("按下了 F1 键!!"); return false; }

F2 - 113, F3 - 114, F4 - 115, 以此类推。


2
你可以使用原生JavaScript和键盘事件keydownkeypresskeyup
最好使用event.key或event.code,并将它们与键名进行比较,例如event.key === "F1"
在处理功能键时,可能需要禁止默认行为(在Windows上,许多功能键由浏览器使用)。 可以通过在keydown事件上调用preventDefault()来实现这一点。 即使您想监听keyup事件,您还需要在keydown事件上调用preventDefault(),因为浏览器快捷键绑定到该事件上。 请注意,调用preventDefault()keydown也会阻止keypress事件
document
  .addEventListener("keydown", e => {
    if(e.key === "F1") {
      // Suppress default behaviour 
      // e.g. F1 in Microsoft Edge on Windows usually opens Windows help
      e.preventDefault()
    }
  })

document
  .addEventListener("keyup", e => {
    if(e.key === "F1") {
      // Handle the keyup event
      doSomething()
    }
  })

1

只需添加此事件侦听器:

function keyDown(e)
{
    let charStr, key = e.which || e.keyCode;
    if (key >= 112 && key <= 123)
    {
        e.preventDefault();
        e.stopPropagation();
        charStr = "F" + (key - 111);
        switch (charStr)
        {
            case "F1":
                alert("F1");
                break;
            case "F2":
                alert("F2");
                break;
            default:
                alert("Other F key");
                break;
        }
    }
}

document.addEventListener('keydown', keyDown);

这个在浏览器兼容性方面非常好。虽然我不知道Internet Explorer 8或Mozilla FireFox 3,但它们在2022年几乎已经不再相关了。


1
在捕获F1-F12键的过程中,一个问题是必须覆盖默认功能。以下是F1“帮助”键的实现示例,其覆盖了默认的帮助弹出窗口。这个解决方案可以扩展到F2-F12键。此外,这个示例故意不捕获组合键,但也可以进行修改。
<html>
<head>
<!-- Note:  reference your JQuery library here -->
<script type="text/javascript" src="jquery-1.6.2.min.js"></script>
</head>
<body>
    <h1>F-key trap example</h1>
    <div><h2>Example:  Press the 'F1' key to open help</h2></div>
    <script type="text/javascript">
        //uncomment to prevent on startup
        //removeDefaultFunction();          
        /** Prevents the default function such as the help pop-up **/
        function removeDefaultFunction()
        {
            window.onhelp = function () { return false; }
        }
        /** use keydown event and trap only the F-key, 
            but not combinations with SHIFT/CTRL/ALT **/
        $(window).bind('keydown', function(e) {
            //This is the F1 key code, but NOT with SHIFT/CTRL/ALT
            var keyCode = e.keyCode || e.which;
            if((keyCode == 112 || e.key == 'F1') && 
                    !(event.altKey ||event.ctrlKey || event.shiftKey || event.metaKey))
             {
                // prevent code starts here:
                removeDefaultFunction();
                e.cancelable = true;
                e.stopPropagation();
                e.preventDefault();
                e.returnValue = false;
                // Open help window here instead of alert
                alert('F1 Help key opened, ' + keyCode);
                }
            // Add other F-keys here:
            else if((keyCode == 113 || e.key == 'F2') && 
                    !(event.altKey ||event.ctrlKey || event.shiftKey || event.metaKey))
             {
                // prevent code starts here:
                removeDefaultFunction();
                e.cancelable = true;
                e.stopPropagation();
                e.preventDefault();
                e.returnValue = false;
                // Do something else for F2
                alert('F2 key opened, ' + keyCode);
                }
        });
    </script>
</body>
</html>

在开发过程中,我从相关的SO文章中借鉴了一个类似的解决方案。如果这个方法对你也有用,请告诉我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接