经过一些体面的研究和试验/错误,这里最好/唯一的解决方案似乎是创建自己的自定义表单控件。
以下是解决问题的失败尝试。
http://jsfiddle.net/CoryDanielson/4jBgs/10/
这基本上是它的工作原理。
首先,有一个activeInput
变量存储DOMElement
用户关注的输入。(仅当输入是可转义的)
var activeInput = false;
为了填充这个变量,我创建了一个你提到的 DOMElements 数组escaped
(带有自动完成功能的文本框,选择元素)
var escapableElements = [];
escapableElements = escapableElements.concat(
Array.prototype.slice.call(document.getElementsByTagName('select')),
Array.prototype.slice.call(document.getElementsByTagName('input'))
//add more elements here
);
然后循环遍历数组并附加到eventListeners
和focus
(blur
失去焦点)事件。(我在这篇文章的底部包含了每个函数)
forEach(escapableElements, function() {
this.addEventListener('focus', registerActiveElement);
this.addEventListener('blur', deregisterActiveElement);
});
function registerActiveElement() {
if (!activeInput)
activeInput = this;
//console.log('registered'); //testing only
}
function deregisterActiveElement() {
if (activeInput)
activeInput = false;
//console.log('deregistered'); //testing only
}
在那之后,我eventListener
为这个keydown
活动准备了一个。在其中,我检查是否有一个,activeInput
如果没有,我只是return true;
让浏览器做它想做的事情(逃避自动完成等),如果没有activeInput
,我检查是否ESC
被按下并调用hide_dialog_box(event.keyCode);
与您关于处理ESC
按键的问题中的段落的唯一区别是我检查了是否有activeInput
事先。如果有activeInput
,我什么也不做(让浏览器本地处理 ESC)如果没有activeInput
我调用event.preventDefault()
这将取消浏览器对 ESC 的本机处理,然后调用该函数hide_dialog_box(keyCode)
,然后执行return false;
这也有助于防止浏览器处理ESC
按键。
document.addEventListener('keydown', function(event) {
if (!activeInput) {
if (event.keyCode == 27) { //esc
event.preventDefault();
hide_dialog_box(event.keyCode);
return false;
}
} else {
return true; //if active input, let browser function
}
/*
if the browser prompts with an autocomplete menu for
<input type="text">, or options on a <select> drop down
pressing escape will cancel that, not cancel the dialog.
*/
});
最后 2 段代码是函数hide_dialog_box(keyCode)
和我编写的用于循环NodeList
调用的函数escapableElements
function hide_dialog_box(keyCode) {
var dialog_box = document.getElementById('dialog_box');
dialog_box.style.display = 'none';
}
function forEach(list, callback) {
for (var i = 0; i < list.length; i++)
{
//calls the callback function, but places list[i] as the 'this'
callback.call(list[i]);
}
}