Dojo 键盘事件<11>

在这个教程里,我们将解释Dojo的事件标准化和dojo/keys以及如何使用dojo/keys来处理键盘事件。

开始

当键盘上的键被按下时会触发键盘事件。 它包括所有的键, 字母,数字,符号, 标点符号, 以及删除,功能,回车, tab和小键盘。 每键盘按键会触发一个事件, 然后捕获和处理。

浏览器本身都支持和实现对键盘事件的处理,但方法都不相同。 使用Dojo来处理键盘事件允许你写的程序可以运行在所有的浏览器。

键盘事件

在浏览器里监听键盘事件允许你实现一个用户界面,它不像看起来像本地的应用程序, 还为你提供了更大控制权的UI.

onkeypress

当任何键被按下时直到键被释放。 onkeypress可以用于大部分键盘事件的处理。
onkeydown
当任何键被按下时触发,大部分情况下, onkeypress会在onkeydown之后触发 。
onkeyup
当键被释放(弹起)时触发。

按大部分的键都会触发上面的事件, 但在浏览器之者会有不同。 接下来的demo 允许你看到键盘按下后触发的事件。 请花一些时间来试验不同的键和组合。

Dojo 标准化了键盘事件, 使你可以通过dojo/keys 常量测试非打印键的输入(可以输出命令键的键值)。 比如我们创建一个表单, 通过向上和向下或者回来键来遍历元素。 我们可以从一个简单的例子开始:

<script src="//ajax.googleapis.com/ajax/libs/dojo/1.9.2/dojo/dojo.js"
                data-dojo-config="async: true"> </script>
<body>
    <h1>Press any key</h1>
    keyCode value: <input type="text" id="keyCode" size="2">
</body>
require(["dojo/on","dojo/domReady!"],function(on) {
    on(document,"keyup",function(event) {
        document.getElementById("keyCode").value = event.keyCode;
    });
});

查看 Demo

这个例子简单的展示了如何捕获表单元素的键盘事件并且使用Dojo的标准化事件来某些事件(记录到控制台). 以下是:

但是你会发现,我们的例子没有想向的那样, 缺失了很多的功能, 如理回车, 这会在接下的例子里讲到。
!* 注间,dojo/on不像 dojo/_base/connect 的API,事件名称的前缀如"onKeyup", 会省略掉 "on"。 可以查看 Event with Dojo获得更多的信息。

KeyboardEvent对象

如下图所示, 当一个键盘事件触发时,一个KeyboardEvent 会被传递给事件处理器。 这个事件对像包括很多关于这个事件的信息。 但通常最需要的是keyCode的值。 它是按下键的unicode的值。



继续之前的例子,我们可以使用dojo使它更加简洁功能更加强大:
<body>
    <h1>Press Up or Down Arrow Keys</h1>
    <input type="text" id="input1" value="up">
    <input type="text" id="input2" value="down">
    <input type="submit" id="send" value="send">
</body>
require(["dojo/dom-construct","dojo/on","dojo/query","dojo/keys",function(domConstruct,on,query,keys) {
    query("input[type='text']").on("keydown",function(event) {
        //query returns a nodelist,which has an on() function available that will listen
        //to all keydown events for each node in the list
        switch(event.keyCode) {
            case keys.UP_ARROW:
                event.preventDefault();
                //preventing the default behavior in case your browser
                // uses autosuggest when you hit the down or up arrow.
                log("up arrow has been pressed");
                break;
            case keys.DOWN_ARROW:
                event.preventDefault();
                //preventing the default behavior in case your browser
                // uses autosuggest when you hit the down or up arrow.
                log("down arrow has been pressed");
                break;
            case keys.ENTER:
                log("enter has been pressed");
                break;
            default:
                log("some other key: " + event.keyCode);
        }
    });
});

查看 Demo

只需几个改变, 我们消除了许多冗余的代码, 并且使我们的角本更加强大 - 允许我们在单个事件处理函数里,处理多种类型的按键(向上,向下,回车,普通字符)。 以及处理多个元素。 通过使用dojo/query,获得一个NodeList对象,通过NodeList的on方法给每个元素注册监听器。 它跟dojo/on模块的on()函数是完全一样的,除了第一个参数省略之外。

这面这个例子使用了Dojo部分强大的功能, 但为了充分完成我们通过键盘事件来遍历表单元素, 我们需要还需要更多的代码到我们的例子中, 以下是功能完全的一个例子:

<body>
    <h1>Press Up/Down Arrow Or Enter Keys to traverse form.</h1>
    <h2>Home/End will go to the beginning or end.</h2>
    <form id="traverseForm">
        First Name: <input type="text" id="firstName">
        Last Name: <input type="text" id="lastName">
        Email Address: <input type="text" id="email">
        Phone Number: <input type="text" id="phone">
        <input type="submit" id="send" value="send">
    </form>
</body>

require(["dojo/dom","dojo/dom-construct","dojo/NodeList-traverse",function(dom,domConstruct,keys) {
    var inputs = query("input");
 
    on(dom.byId("traverseForm"),"keydown",function(event) {
        var node = query.NodeList([event.target]);
        var nextNode;
 
        //on listens for the keydown events inside of the div node,on all form elements
        switch(event.keyCode) {
            case keys.UP_ARROW:
                nextNode = node.prev("input");
                if(nextNode[0]){
                    //if not first element
                    nextNode[0].focus();
                    //moving the focus from the current element to the previous
                }
                break;
            case keys.DOWN_ARROW:
                nextNode = node.next("input");
                if(nextNode[0]){
                    //if not last element
                    nextNode[0].focus();
                    //moving the focus from the current element to the next
                }
                break;
            case keys.HOME:
                inputs[0].focus();
                break;
            case keys.END:
                inputs[inputs.length - 2].focus();
                break;
            case keys.ENTER:
                event.preventDefault();
                //prevent default keeps the form from submitting when the enter button is pressed
                //on the submit button
                if(event.target.type !== "submit"){
                    nextNode = node.next("input");
                    if(nextNode[0]){
                        //if not last element
                        nextNode[0].focus();
                        //moving the focus from the current element to the next
                    }
                }else {
                    // submit the form
                    log("form submitted!");
                }
                break;
            default:
                log("some other key: " + event.keyCode);
        }
    });
});

查看 Demo

我们在表单遍历中使用了dojo/on的事件委托, 我们在form上注册了单个的事件监听器。 这个监听器也可以监听 form子元素的所有键盘事件。

事件委托显然很有用, 我们只需对做很小的修改就可以处理文本框的输入以及提交按纽。 这种解决方案还可以向上扩展; 如果有更多的表单元素被添加到我们的页面, 我们的代码依然可以工作。 - 并且在dojo/on模块对事件标准化和dojo/keys 常量模块的帮助下。 它可以在跨浏览器和平台工作。

digit/_keyNavMixin中的键盘导航

最后,如果你的首要目标是处理导航上的键盘事件, 你可以使用digit/_KeyNavMixin. 它需要在你的窗口部件中定义一些导航事件处理函数, 一旦你满足了它的要求, 它会监听和响应导航相关的键盘事件。 我们不会在这个教程里详细讲,但你可以查看相关 教程,以下是一个简单的 demo.


总结

Dojo使用dojo/on来使事件标准化。 用它可以非常简单的处理不同浏览器下的键盘事件。 使用 dojo/on和 dojo/keys,我们创建了一个表单, 扩展了up/down和回车键。

更多资源

关于dojo/on的更多细节和和其它的在这个教程中使用到的工具:

相关文章

我有一个网格,可以根据更大的树结构编辑小块数据.为了更容易...
我即将开始开发一款教育性的视频游戏.我已经决定以一种我可以...
我正在使用带有Grails2.3.9的Dojo1.9.DojoNumberTextBox小部...
1.引言鉴于个人需求的转变,本系列将记录自学arcgisapiforja...
我正在阅读使用dojo’sdeclare进行类创建的语法.描述令人困惑...
我的团队由更多的java人员和JavaScript经验丰富组成.我知道这...