1
/* YUI 3.9.1 (build 5852) Copyright 2013 Yahoo! Inc. http://yuilibrary.com/license/ */
2
YUI.add('event-key', function (Y, NAME) {
5
* Functionality to listen for one or more specific key combinations.
27
_typeRE: /^(up|down|press):/,
28
_keysRE: /^(?:up|down|press):|\+(alt|ctrl|meta|shift)/g,
30
processArgs: function (args) {
31
var spec = args.splice(3,1)[0],
32
mods = Y.Array.hash(spec.match(/\+(?:alt|ctrl|meta|shift)\b/g) || []),
34
type: this._typeRE.test(spec) ? RegExp.$1 : null,
38
// strip type and modifiers from spec, leaving only keyCodes
39
bits = spec.replace(this._keysRE, ''),
43
bits = bits.split(',');
47
// FIXME: need to support '65,esc' => keypress, keydown
48
for (i = bits.length - 1; i >= 0; --i) {
51
// catch sloppy filters, trailing commas, etc 'a,,'
56
// non-numerics are single characters or key names
58
config.keys[chr] = mods;
60
lc = chr.toLowerCase();
62
if (this.KEY_MAP[lc]) {
63
config.keys[this.KEY_MAP[lc]] = mods;
64
// FIXME: '65,enter' defaults keydown for both
66
config.type = "down"; // safest
69
// FIXME: Character mapping only works for keypress
70
// events. Otherwise, it uses String.fromCharCode()
71
// from the keyCode, which is wrong.
73
uc = chr.toUpperCase();
79
// FIXME: stupid assumption that
80
// the keycode of the lower case == the
81
// charCode of the upper case
82
// a (key:65,char:97), A (key:65,char:65)
83
config.keys[chr.charCodeAt(0)] =
85
// upper case chars get +shift free
86
Y.merge(mods, { "+shift": true }) :
94
config.type = "press";
100
on: function (node, sub, notifier, filter) {
101
var spec = sub._extra,
102
type = "key" + spec.type,
104
method = (filter) ? "delegate" : "on";
106
// Note: without specifying any keyCodes, this becomes a
107
// horribly inefficient alias for 'keydown' (et al), but I
108
// can't abort this subscription for a simple
109
// Y.on('keypress', ...);
110
// Please use keyCodes or just subscribe directly to keydown,
111
// keyup, or keypress
112
sub._detach = node[method](type, function (e) {
113
var key = keys ? keys[e.which] : spec.mods;
116
(!key[ALT] || (key[ALT] && e.altKey)) &&
117
(!key[CTRL] || (key[CTRL] && e.ctrlKey)) &&
118
(!key[META] || (key[META] && e.metaKey)) &&
119
(!key[SHIFT] || (key[SHIFT] && e.shiftKey)))
126
detach: function (node, sub, notifier) {
127
sub._detach.detach();
131
eventDef.delegate = eventDef.on;
132
eventDef.detachDelegate = eventDef.detach;
135
* <p>Add a key listener. The listener will only be notified if the
136
* keystroke detected meets the supplied specification. The
137
* specification is a string that is defined as:</p>
141
* <dd><code>[{type}:]{code}[,{code}]*</code></dd>
143
* <dd><code>"down", "up", or "press"</code></dd>
145
* <dd><code>{keyCode|character|keyName}[+{modifier}]*</code></dd>
147
* <dd><code>"shift", "ctrl", "alt", or "meta"</code></dd>
149
* <dd><code>"enter", "backspace", "esc", "tab", "pageup", or "pagedown"</code></dd>
154
* <li><code>Y.on("key", callback, "press:12,65+shift+ctrl", "#my-input");</code></li>
155
* <li><code>Y.delegate("key", preventSubmit, "#forms", "enter", "input[type=text]");</code></li>
156
* <li><code>Y.one("doc").on("key", viNav, "j,k,l,;");</code></li>
161
* @param type {string} 'key'
162
* @param fn {function} the function to execute
163
* @param id {string|HTMLElement|collection} the element(s) to bind
164
* @param spec {string} the keyCode and modifier specification
165
* @param o optional context object
166
* @param args 0..n additional arguments to provide to the listener.
167
* @return {Event.Handle} the detach handle
169
Y.Event.define('key', eventDef, true);
172
}, '3.9.1', {"requires": ["event-synthetic"]});