键盘事件的实现细节
在我们之前的介绍性文章 Firefox OS TV 的键盘事件 中,我们描述了由智能电视遥控器上的信息键触发的四种键盘事件场景:系统专用、系统优先、应用取消和应用优先。我们解释了这些键盘事件是如何被激活的,描述了事件的默认顺序,并探索了 Firefox OS 及其嵌入式浏览器的 iframe 结构,以便了解开发者如何实现这四种键盘事件场景。
现在我们将更深入地了解这四种场景,并为每种事件处理场景提供示例代码。
系统专用
如果键盘事件被归类为**系统专用**,则所需的响应是在mozbrowserbeforekey* 的事件处理程序中定义的。一旦按下此键,系统将在key* 事件分派到应用程序之前收到mozbrowserbeforekey* 事件。此外,一旦系统事件处理程序被调用,key* 事件的分派就会被取消。现在,我们需要找到一种方法来停止事件分派。 图 5 - Firefox OS TV 的键盘事件 显示键盘事件被分派到系统进程,然后也分派到应用程序进程。为了停止将事件分派到嵌入页面,event.preventDefault() 是一种直接的解决方案。Event.preventDefault() 用于阻止默认操作。mozbrowserbeforekey* 事件的定义默认操作是分派key* 事件。出于这个原因,通过在mozbrowserbeforekey* 的事件处理程序中调用event.preventDefault(),key* 事件将不会被分派。最终结果将与图 7 中所示相同。
系统优先
这与**系统专用**的实现非常相似。唯一的区别是 - 在mozbrowserbeforekey* 的事件处理程序中不需要调用event.preventDefault()。系统完成处理后,应用程序能够处理key* 事件。
应用取消
如果特定的键盘事件被指定为仅供应用程序使用,例如那些分配给智能电视遥控器上的四个彩色键(如图 9 所示)的事件,则event.preventDefault() 将在应用程序的key* 事件处理程序中被调用。event.preventDefault() 无法阻止mozbrowserafterkey* 事件被分派到系统,但mozbrowserafterkey* 的属性embeddedCancelled 将在嵌入式应用程序调用event.preventDefault() 后被设置为true。embeddedCancelled 的值允许系统检测该事件是否已被处理。如果该值是 true,系统将不会执行任何操作。
应用优先
**应用优先**与**应用取消**之间的区别在于,对于**应用优先**,event.preventDefault() 将不会在应用程序的事件处理程序中被调用。因此,embeddedCancelled 的值为false,系统可以接管键盘事件。
示例代码
事件处理程序
function handleEvent(event) {
dump("Receive event '" + event.type + "'.");
// Handle event here.....
};
function handleEventAndPreventDefault(event) {
dump("Receive event '" + event.type + "'.");
// Handle event here.....
// Call preventDefault() to stop the default action.
// It means that the event is already handled.
event.preventDefault();
};
function checkAttrAndHandleEvent(event) {
dump("Receive event '" + event.type +
"' with embeddedCancelled equals to '" +
event.embeddedCancelled + "'.");
if (!event.embeddedCancelled) {
// Do something if the event wasn't being handled before!
// The following code should be executed in APP-FIRST scenario only!
}
};
系统专用
- mozbrowser iframe 宿主页面
window.addEventListener('mozbrowserbeforekeydown', handleEventAndPreventDefault);
window.addEventListener('mozbrowserbeforekeyup', handleEventAndPreventDefault);
window.addEventListener('mozbrowserafterkeydown', function() { }); // no use
window.addEventListener('mozbrowserafterkeyup', function() { }); // no use
- 嵌入页面
// This function will never be triggered because the preventDefault() is called in mozbrowserbeforekeyXXX's handler.
window.addEventListener('keydown', handleEvent);
window.addEventListener('keyup', handleEvent);
- keydown 相关事件的结果
顺序 | 嵌入页面 | mozbrowser iframe 宿主页面 | 输出 |
---|---|---|---|
1 | mozbrowserbeforekeydown | 接收事件 'mozbrowserbeforekeydown'。 | |
2 | mozbrowserafterkeydown |
- keyup 相关事件的结果
顺序 | 嵌入页面 | 宿主页面 | 输出 |
---|---|---|---|
1 | mozbrowserbeforekeyup | 接收事件 'mozbrowserbeforekeyup'。 | |
2 | mozbrowserafterkeyup |
系统优先
- mozbrowser iframe 宿主页面
window.addEventListener('mozbrowserbeforekeydown', handleEvent);
window.addEventListener('mozbrowserbeforekeyup', handleEvent);
window.addEventListener('mozbrowserafterkeydown', function() { }); // no use
window.addEventListener('mozbrowserafterkeyup', function() { }); // no use
- 嵌入页面
window.addEventListener('keydown', handleEvent);
window.addEventListener('keyup', handleEvent);
- 接收到的keydown 相关事件的结果
顺序 | mozbrowser-嵌入页面 | mozbrowser iframe 宿主页面 | 输出 |
---|---|---|---|
1 | mozbrowserbeforekeydown | 接收事件 'mozbrowserbeforekeydown'。 | |
2 | keydown | 接收事件 'keydown'。 | |
3 | mozbrowserafterkeydown |
- 接收到的keyup 相关事件的结果
顺序 | 嵌入页面 | mozbrowser iframe 宿主页面 | 输出 |
---|---|---|---|
1 | mozbrowserbeforekeyup | 接收事件 'mozbrowserbeforekeyup'。 | |
2 | keyup | 接收事件 'keyup'。 | |
3 | mozbrowserafterkeyup | 接收事件 'mozbrowserafterkeyup',embeddedCancelled 等于 'true'。 |
应用取消
- mozbrowser iframe 宿主页面
window.addEventListener('mozbrowserbeforekeydown', function() { }); // no use
window.addEventListener('mozbrowserbeforekeyup', function() { }); // no use
window.addEventListener('mozbrowserafterkeydown', checkAttrAndHandleEvent);
window.addEventListener('mozbrowserafterkeyup', checkAttrAndHandleEvent);
- mozbrowser iframe 嵌入页面
window.addEventListener('keydown', handleEventAndPreventDefault);
window.addEventListener('keyup', handleEventAndPreventDefault);
- 接收到的keydown 相关事件的结果
顺序 | 嵌入页面 | mozbrowser iframe 宿主页面 | 输出 |
---|---|---|---|
1 | mozbrowserbeforekeydown | ||
2 | keydown | 接收事件 'keydown'。 | |
3 | mozbrowserafterkeydown | 接收事件 'mozbrowserafterkeydown',embeddedCancelled 等于 'true'。 |
- 接收到的 keyup 相关事件的结果
顺序 | mozbrowser-嵌入页面 | mozbrowser iframe 宿主页面 | 输出 |
---|---|---|---|
1 | mozbrowserbeforekeyup | ||
2 | keyup | 接收事件 'keyup'。 | |
3 | mozbrowserafterkeyup | 接收事件 'mozbrowserafterkeyup',embeddedCancelled 等于 'true'。 |
应用优先
- mozbrowser iframe 宿主页面
window.addEventListener('mozbrowserbeforekeydown', function() { }); // no use
window.addEventListener('mozbrowserbeforekeyup', function() { }); // no use
// This will be trigger after keydown event is
// dispatched to mozbrowser iframe embedded page
window.addEventListener('mozbrowserafterkeydown', checkAttrAndHandleEvent);
window.addEventListener('mozbrowserafterkeyup', checkAttrAndHandleEvent);
- mozbrowser iframe 嵌入页面
window.addEventListener('keydown', handleEvent);
window.addEventListener('keyup', handleEvent);
- 接收到的keydown 相关事件的结果
顺序 | mozbrowser-嵌入页面 | mozbrowser-iframe 宿主页面 | 输出 |
---|---|---|---|
1 | mozbrowserbeforekeydown | ||
2 | keydown | 接收事件 'keydown'。 | |
3 | mozbrowserafterkeydown | 接收事件 'mozbrowserafterkeydown',embeddedCancelled 等于 'false'。 |
- 接收到的keyup 相关事件的结果
顺序 | mozbrowser-嵌入页面 | mozbrowser iframe 宿主页面 | 输出 |
---|---|---|---|
1 | mozbrowserbeforekeyup | ||
2 | keyup | 接收事件 'keyup'。 | |
3 | mozbrowserafterkeyup | 接收事件 'mozbrowserafterkeyup',embeddedCancelled 等于 'false'。 |