-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathjquery.hotkeys.js
243 lines (223 loc) · 6.77 KB
/
jquery.hotkeys.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/*
* jQuery Hotkeys Plugin
*
* 基于 Tzury Bar Yochay 编写的插件:
* https://github.com/tzuryby/jquery.hotkeys
*
* 最初的想法起源于:
* Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
*/
(function(jQuery) {
jQuery.hotkeys = {
version: "0.2.0",
specialKeys: {
8: "backspace",
9: "tab",
10: "return",
13: "return",
16: "shift",
17: "ctrl",
18: "alt",
19: "pause",
20: "capslock",
27: "esc",
32: "space",
33: "pageup",
34: "pagedown",
35: "end",
36: "home",
37: "left",
38: "up",
39: "right",
40: "down",
45: "insert",
46: "del",
59: ";",
61: "=",
96: "0",
97: "1",
98: "2",
99: "3",
100: "4",
101: "5",
102: "6",
103: "7",
104: "8",
105: "9",
106: "*",
107: "+",
109: "-",
110: ".",
111: "/",
112: "f1",
113: "f2",
114: "f3",
115: "f4",
116: "f5",
117: "f6",
118: "f7",
119: "f8",
120: "f9",
121: "f10",
122: "f11",
123: "f12",
144: "numlock",
145: "scroll",
173: "-",
186: ";",
187: "=",
188: ",",
189: "-",
190: ".",
191: "/",
192: "`",
219: "[",
220: "\\",
221: "]",
222: "'"
},
shiftNums: {
"`": "~",
"1": "!",
"2": "@",
"3": "#",
"4": "$",
"5": "%",
"6": "^",
"7": "&",
"8": "*",
"9": "(",
"0": ")",
"-": "_",
"=": "+",
";": ": ",
"'": "\"",
",": "<",
".": ">",
"/": "?",
"\\": "|"
},
// input 类型,不包括:
// button, checkbox, file, hidden, image, password, radio, reset, search, submit, url
textAcceptingInputTypes: [
"text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime",
"datetime-local", "search", "color", "tel"],
// 除非直接绑定,否则默认情况下 input 不会绑定监听
textInputTypes: /textarea|input|select/i,
options: {
filterInputAcceptingElements: true,
filterTextInputs: true,
filterContentEditable: true
}
};
/**
* special event method
* keyHandler 方法是 keydown 时会触发的方法,
* 在其中对 key 进行判断,针对响应的 key 进行 callback 回调
* @param handleObj
* handleObj: {
* type: event 名称
* data: 传递给这个事件的数据
* handler: 事件处理函数
* }
*/
function keyHandler(handleObj) {
if (typeof handleObj.data === "string") {
handleObj.data = {
keys: handleObj.data
};
}
if (!handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string") {
return;
}
// origHandler 是事件监听的回调,即用户注册监听事件时所定义的 callback
var origHandler = handleObj.handler,
// 可以一次绑定监听多种按键组合,不同组合之间使用空格分隔
keys = handleObj.data.keys.toLowerCase().split(" ");
handleObj.handler = function(event) {
// 对于 inputs,因为在默认情况下不会绑定监听,因此直接返回
if (this !== event.target &&
(jQuery.hotkeys.options.filterInputAcceptingElements &&
jQuery.hotkeys.textInputTypes.test(event.target.nodeName) ||
(jQuery.hotkeys.options.filterContentEditable && jQuery(event.target).attr('contenteditable')) ||
(jQuery.hotkeys.options.filterTextInputs &&
// 通过 jQuery.inArray 判断 target 是否在一个 Array 里
jQuery.inArray(event.target.type, jQuery.hotkeys.textAcceptingInputTypes) > -1))) {
return;
}
/*
* event.which 为按键 code,type 为 int
* 通过 jQuery.hotkeys.specialKeys[event.which] 拿到其按键名称
*/
var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[event.which],
// String.fromCharCode() 静态方法根据指定的 Unicode 编码中的序号值来返回一个字符串
character = String.fromCharCode(event.which).toLowerCase(),
modif = "",
possible = {};
/*
* 对 alt/ctrl/shift 组合键的判断
* 如果 special 不是 alt/ctrl/shift 中的任一个,且 存在 event.altKey/event.ctrlKey/event.shiftKey,
* 则可以认为 alt/ctrl/shift 键处于按下的状态
*/
jQuery.each(["alt", "ctrl", "shift"], function(index, specialKey) {
if (event[specialKey + 'Key'] && special !== specialKey) {
modif += specialKey + '+';
}
});
/*
* 对 metaKey 组合键的判断
* event.metaKey
* 在 Mac 上代表 command 键,在 Windows 上则代表 win 键
*/
if (event.metaKey && !event.ctrlKey && special !== "meta") {
modif += "meta+";
}
// 如果同时按下了 alt+ctrl+shift 和 meta 键
if (event.metaKey && special !== "meta" && modif.indexOf("alt+ctrl+shift+") > -1) {
modif = modif.replace("alt+ctrl+shift+", "hyper+");
}
// 对获取的按键码进行组合
if (special) {
possible[modif + special] = true;
}
else {
possible[modif + character] = true;
possible[modif + jQuery.hotkeys.shiftNums[character]] = true;
// 将 Shift+keyCode 转换为 keyCode
// 例如,
// "$" 可以被认为是 "Shift+4" 或者 "Shift+$" 或者 "$"
if (modif === "shift+") {
possible[jQuery.hotkeys.shiftNums[character]] = true;
}
}
// 如果绑定的按键(组合)中有任意一个被触发,则就触发回调
for (var i = 0, l = keys.length; i < l; i++) {
if (possible[keys[i]]) {
return origHandler.apply(this, arguments);
}
}
};
}
/*
* jQuery(elem).bind(type, data, callback)
* 实际上是映射到 jQuery.event.add(elem, types, handler, data)
* http://benalman.com/news/2010/03/jquery-special-events
*
* 通过
* jQuery.event.special.xxxEvent = {
* setup: func, 在事件被bind时调用,仅调用一次
* teardown: func, 在解除bind时调用,仅调用一次
* add: func,每次绑定到元素上的时候都会调用
* }
* 来创建一个新的事件
*
* 也就是说,通过调用下面的方法之后,在
* $(dom).bind('keydown', key, callback),或者 keyup/keypress 时会触发 keyHandler 方法
* keyHandler 默认接收一个参数 handleObj,事件绑定时的 callback 会赋值给 handleObj.handler
*/
jQuery.each(["keydown", "keyup", "keypress"], function() {
jQuery.event.special[this] = {
add: keyHandler
};
});
})(jQuery || this.jQuery || window.jQuery);