【问题标题】:Using charCodeAt() to retrieve character from KeyCode使用 charCodeAt() 从 KeyCode 中检索字符
【发布时间】:2013-01-29 20:05:59
【问题描述】:

我正在尝试编写一个 Javascript/jQuery 函数,它会自动将键盘快捷键绑定到我的网页。我想到的方法是这样的:

  1. 遍历类以“key-”开头的所有元素
  2. 对于这些元素中的每一个,从类中检索组合键,例如'key-ctrl-s' 将返回 Ctrl+S
  3. 将这些特定键组合的事件绑定到文档

相当基本的算法,或者我认为... 问题来了...

例如,我可以输入以下内容:

<a href="javascript:void(0)" class="some_other_class ctrl+s">Save</a>
<a href="javascript:void(0)" class="ctrl+shift+s">Save As</a>

上面的代码会生成如下键盘快捷键:Ctrl+SCtrl+Shift+S

并且当这些键被按下时,会为相关的html元素触发click事件...

问题

如上所述,这里的算法非常简单,但是,像往常一样,尝试编写它时会出现问题。

我不知道在自动绑定事件时如何知道要监听哪个键码 (e.which)。

例如:

使用上面的 HTML 和下面的 jQuery,我们可以走到这一步(忽略正则表达式之类的东西):

function keyboardShortcuts(){
    // Loop through all elements with a class containing 'key-'
    $("[class*='key-']").each(function(){
        // Using a regular expression here, separate the class into individual keys
        // whilst ignoring other classes and the 'key-' prefix
        var keys = $(this).attr('class').match(/REGEX HERE/);

        // THIS IS WHERE THE CODE GETS A LITTLE MESSY
        // I AM VERY UNSURE ABOUT THE FOLLOWING

        // Define all special characters and set them to false
        var ctrl = false, alt = false, shift = false;

        // First test for special characters
        // Test for ctrl key
        if(keys.indexOf('ctrl')!=-1){
            ctrl = true;
            // Remove ctrl from the keys array
            keys.splice(keys.indexOf('ctrl'),1)
        }
        // Test for alt key
        if(keys.indexOf('alt')!=-1){
            alt = true;
            // Remove alt from the keys array
            keys.splice(keys.indexOf('alt'),1)
        }
        // Test for shift key
        if(keys.indexOf('shift')!=-1){
            shift = true;
            // Remove shift from the keys array
            keys.splice(keys.indexOf('shift'),1)
        }

        // Determine special characters to test for
        if(ctrl&&alt&&shift){

            // Bind the keypress event to the document

            $(document).keypress(function(e) {
                if((e.ctrlKey||e.metaKey)&&e.altKey&&shiftKey) {

                    var continue = true;

                    // Test for other characters in keys array
                    for(var i=0;i<keys.length;i++){

                        // THIS IS WHAT I AM REALLY UNSURE ABOUT
                        if(keys.indexOf(charCodeAt(e.which))==-1){
                            // Correct key was not pressed so do not continue
                            continue = false;
                        }
                    }

                    if(continue){
                        e.preventDefault();
                        // Proceed to triggering the click event
                        // No more help needed from here...
                    }
                }
                return true;
            });
        }else if(ctrl&&alt){

        }else if(ctrl&&shift){

        }else if(shift&&alt){

        }else if(ctrl){

        }else if(alt){

        }else if(shift){

        }
    });
}

从上面可以看出,代码很冗长,但我根本看不到另一种编写方式......除了可能在各处整理一些数组,但即便如此嵌套的 if声明几乎是必需品,不是吗?

最后,我的问题

排除代码非常不整洁并且可能会写得更好/更好(如果您对此有意见,请提供),我的实际问题是参考以下行:

keys.indexOf(charCodeAt(e.which))==-1

这是从所有浏览器的字符代码中检索字符的可靠方法吗?如果没有,有更好的方法吗?

任何对代码的其余部分有任何意见的人,请发表,希望得到一些反馈。

【问题讨论】:

  • 一个有趣的问题。根据我在 Chrome 中的实验,您实际上不会收到不可打印字符(如 ctl+s)的按键事件。但是您可以接收 keyup 和 keydown 事件。

标签: javascript jquery automation keyboard-shortcuts keycode


【解决方案1】:

当我开始做这件事时,我并不打算重写整个事情。但我做到了,你可以在 this jsfiddle 看到它。

该技术是找到所有目标元素并构建一个列表,其中列出了每个元素映射到的组合键。我们将这些存储在数组keybindings 中,每次有人按下一个键时,我们都会查看整个列表以寻找匹配项。如果我们找到一个,我们会在元素上触发一个点击事件。

我使用keydown 而不是keypress,因为您实际上可以通过它获得修饰符信息。我还改进了类字符串解析,但我敢肯定它可以变得更简洁。

这是 JS 代码。

var keybindings = [];

$('[class*="key-"]').each(function (idx, val) {
    var keyspec = {
        which: 0,
        altKey: false,
        shiftKey: false,
        ctrlKey: false,
        element: val
    };

    var keystring = $(val).attr('class').toLowerCase();
    var match = /key-\S+/.exec(keystring);
    var parts = match.toString().split('-');
    keyspec.which = parts[ parts.length-1 ].toUpperCase().charCodeAt(0);
    for (var jdx in parts) {
        if (parts[jdx] == 'alt') keyspec.altKey = true;
        else if (parts[jdx] == 'shift') keyspec.shiftKey = true;
        else if (parts[jdx] == 'ctrl') keyspec.ctrlKey = true;
    }
    keybindings.push( keyspec );
});

$(document).keydown( function(evt) {
    $.each(keybindings, function(idx, oneBind) {
       if (evt.which == oneBind.which
           && evt.altKey == oneBind.altKey
           && evt.shiftKey == oneBind.shiftKey
           && evt.ctrlKey == oneBind.ctrlKey)
           $(oneBind.element).click();
    });
});

当然,我现在想到可能已经有一个 jquery 插件,我们可以使用它。

【讨论】:

  • 非常感谢您的回答,如果我有任何问题,我会仔细阅读并回来。非常感谢,再次感谢:-) +1
  • 通过一些小的调整让它出色地工作。非常感谢,比我建议的方法好多了! :-)
猜你喜欢
  • 2014-01-01
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 2012-04-22
  • 2023-04-05
  • 2022-11-12
  • 1970-01-01
  • 2021-11-05
相关资源
最近更新 更多