我正在编写一个Javascript类来处理击键和击键组合。例如,以下内容将为 SHIFT 键添加回调。
MYAPP.Keyboard.instance().observe(
MYAPP.Keyboard.type.KEYDOWN,
MYAPP.Keyboard.key.SHIFT,
function() {
$$('body').first().addClassName('keyboardHintShow');
}
);
SHIFT + F 的示例如下:
MYAPP.Keyboard.instance().observe(
MYAPP.Keyboard.type.KEYUP,
[MYAPP.Keyboard.key.F, MYAPP.Keyboard.key.SHIFT],
function() {
MYAPP.Broadcast.instance().signal('file');
}
);
到目前为止,这在Firefox中运行得很好,但是当我尝试使用 ALT 作为修饰符时却没有。出现两个问题。 1)事件传播不会停止,因此会弹出Firefox的“文件”菜单。 2)释放 ALT 和 F 后,只有 F 的onKeyUp会触发,因此 ALT 的状态是错误的。是什么让 ALT 与 SHIFT 如此不同?
这是完整的代码:
MYAPP.Keyboard = Class.create({
/*******************************************************************************
PUBLIC PUBLIC PUBLIC PUBLIC PUBLIC PUBLIC PUBLIC PUBLIC PUBLIC PUBLIC PUBLIC PUB
*******************************************************************************/
/**
* @return pointer
*/
initialize: function() {
this.downKeys = new Hash();
this.observers = new Hash();
document.observe(
'keydown',
this.onKeyDown.bind(this)
);
document.observe(
'keyup',
this.onKeyUp.bind(this)
);
},
/**
* @param MYAPP.Keyboard.type type
* @param MYAPP.Keyboard.key | array of MYAPP.Keyboard.key keys
* @param void function() callback
* @return void
*/
observe: function(type, keys, callback) {
var main;
var modifiers;
if (typeof(keys) === 'number') {
main = keys;
modifiers = [];
} else {
main = keys.first();
modifiers = keys.slice(1);
}
if (this.observers.get(type) === undefined) {
this.observers.set(type, new Hash());
}
this.observers.get(type).set(
main, {
modifiers: modifiers,
callback: callback
}
);
},
/**
* @param MYAPP.Keyboard.type type
* @param MYAPP.Keyboard.key
* @return void
*/
stopObserving: function(type, key) {
this.observers.get(type).unset(key);
},
/*******************************************************************************
PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE
*******************************************************************************/
/**
* @param Event event
* @return void
*/
onKeyDown: function(event) {
if (this.downKeys.get(event.keyCode) === true) {
return;
}
this.downKeys.set(event.keyCode, true);
var downObservers = this.observers.get(MYAPP.Keyboard.type.KEYDOWN);
if (downObservers !== undefined) {
this.runCallback(downObservers, event);
}
return false;
},
/**
* @param Event event
* @return void
*/
onKeyUp: function(event) {
this.downKeys.set(event.keyCode, false);
var downObservers = this.observers.get(MYAPP.Keyboard.type.KEYUP);
if (downObservers !== undefined) {
this.runCallback(downObservers, event);
}
return false;
},
/**
* @param Hash observers
* @param Event event
* @return void
*/
runCallback: function(observers, event) {
var overrideBrowser = false;
var order = observers.get(event.keyCode);
if (order !== undefined) {
if (order.modifiers.size() === 0) {
order.callback();
Event.stop(event);
} else {
for (var i = 0; i < order.modifiers.size(); i++) {
var modifierStatus = this.downKeys.get(order.modifiers[i]);
if (modifierStatus === undefined || modifierStatus === false) {
return;
}
order.callback();
Event.stop(event);
}
}
}
}
});
/*******************************************************************************
STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STA
*******************************************************************************/
/**
* @return Keyboard instance
*/
MYAPP.Keyboard.instance = function() {
if (typeof(MYAPP.keyboard) === 'undefined') {
MYAPP.keyboard = new MYAPP.Keyboard();
}
return MYAPP.keyboard;
};
/**
* Event type
*/
MYAPP.Keyboard.type = {
KEYUP: 0,
KEYDOWN: 1
};
/**
* Keycodes for various keys.
*/
MYAPP.Keyboard.key = {
SHIFT: 16,
CTRL: 17,
ALT: 18,
A: 65,
B: 66,
C: 67,
D: 68,
E: 69,
F: 70,
G: 71,
H: 72,
I: 73,
J: 74,
K: 75,
L: 76,
M: 77,
N: 78,
O: 79,
P: 80,
Q: 81,
R: 82,
S: 83,
T: 84,
U: 85,
V: 86,
W: 87,
X: 88,
Y: 89,
Z: 90
};