event-key-debug.js revision cd9e4415b30cf09a761815cd149ec546ecc1231c
1322N/AYUI.add('event-key', function(Y) {
1322N/A
1322N/A/**
1322N/A * Functionality to listen for one or more specific key combinations.
1322N/A * @module event
1322N/A * @submodule event-key
1322N/A */
1322N/A
1322N/Avar ALT = "+alt",
1322N/A CTRL = "+ctrl",
1322N/A META = "+meta",
1322N/A SHIFT = "+shift",
1322N/A
1322N/A trim = Y.Lang.trim,
1322N/A
1322N/A eventDef = {
1322N/A KEY_MAP: {
1322N/A enter : 13,
1322N/A esc : 27,
1322N/A backspace: 8,
1322N/A tab : 9,
1322N/A pageup : 33,
1322N/A pagedown : 34
1322N/A },
4516N/A
1322N/A _typeRE: /^(up|down|press):/,
1322N/A _keysRE: /^(?:up|down|press):|\+(alt|ctrl|meta|shift)/g,
1322N/A
4552N/A processArgs: function (args) {
1322N/A var spec = args.splice(3,1)[0],
4798N/A mods = Y.Array.hash(spec.match(/\+(?:alt|ctrl|meta|shift)\b/g) || []),
1322N/A config = {
2644N/A type: this._typeRE.test(spec) ? RegExp.$1 : null,
4896N/A mods: mods,
1322N/A keys: null
4896N/A },
2644N/A // strip type and modifiers from spec, leaving only keyCodes
3853N/A bits = spec.replace(this._keysRE, ''),
2624N/A chr, uc, lc, i;
4896N/A
2624N/A if (bits) {
4896N/A bits = bits.split(',');
4896N/A
1322N/A config.keys = {};
2181N/A
1322N/A // FIXME: need to support '65,esc' => keypress, keydown
1322N/A for (i = bits.length - 1; i >= 0; --i) {
1322N/A chr = trim(bits[i]);
1322N/A
1322N/A // catch sloppy filters, trailing commas, etc 'a,,'
2624N/A if (!chr) {
1322N/A continue;
1322N/A }
1322N/A
1322N/A // non-numerics are single characters or key names
1322N/A if (+chr == chr) {
4948N/A config.keys[chr] = mods;
4948N/A } else {
4948N/A lc = chr.toLowerCase();
4948N/A
4948N/A if (this.KEY_MAP[lc]) {
4948N/A config.keys[this.KEY_MAP[lc]] = mods;
1628N/A // FIXME: '65,enter' defaults keydown for both
4516N/A if (!config.type) {
3853N/A config.type = "down"; // safest
3853N/A }
3853N/A } else {
3853N/A uc = chr.charAt(0).toUpperCase();
3853N/A lc = lc.charAt(0);
3853N/A
3853N/A // FIXME: possibly stupid assumption that
3853N/A // the keycode of the lower case == the
3853N/A // charcode of the upper case
3853N/A // a (key:65,char:97), A (key:65,char:65)
3853N/A config.keys[uc.charCodeAt(0)] =
3853N/A (lc !== uc && chr === uc) ?
1322N/A // upper case chars get +shift free
4552N/A Y.merge(mods, { "+shift": true }) :
4552N/A mods;
4552N/A }
4798N/A }
4896N/A }
4896N/A }
4896N/A
1322N/A if (!config.type) {
1322N/A config.type = "press";
3853N/A }
1322N/A
1322N/A return config;
1322N/A },
1322N/A
1322N/A on: function (node, sub, notifier, filter) {
1322N/A var spec = sub._extra,
1322N/A type = "key" + spec.type,
4516N/A keys = spec.keys,
3853N/A method = (filter) ? "delegate" : "on";
3853N/A
4552N/A // Note: without specifying any keyCodes, this becomes a
4552N/A // horribly inefficient alias for 'keydown' (et al), but I
4552N/A // can't abort this subscription for a simple
4552N/A // Y.on('keypress', ...);
4552N/A // Please use keyCodes or just subscribe directly to keydown,
4552N/A // keyup, or keypress
4552N/A sub._detach = node[method](type, function (e) {
4552N/A var key = keys ? keys[e.keyCode] : spec.mods;
4552N/A
4552N/A if (key &&
4552N/A (!key[ALT] || (key[ALT] && e.altKey)) &&
4552N/A (!key[CTRL] || (key[CTRL] && e.ctrlKey)) &&
4552N/A (!key[META] || (key[META] && e.metaKey)) &&
4552N/A (!key[SHIFT] || (key[SHIFT] && e.shiftKey)))
4552N/A {
4552N/A notifier.fire(e);
4552N/A }
4552N/A }, filter);
4552N/A },
4552N/A
4552N/A detach: function (node, sub, notifier) {
4552N/A sub._detach.detach();
4552N/A }
4552N/A };
3853N/A
3853N/AeventDef.delegate = eventDef.on;
3853N/AeventDef.detachDelegate = eventDef.detach;
3853N/A
3853N/A/**
3853N/A * <p>Add a key listener. The listener will only be notified if the
3853N/A * keystroke detected meets the supplied specification. The
3853N/A * specification is a string that is defined as:</p>
4516N/A *
3853N/A * <dl>
3853N/A * <dt>spec</dt>
3853N/A * <dd><code>[{type}:]{code}[,{code}]*</dd>
3853N/A * <dt>type</dt>
3853N/A * <dd><code>"down", "up", or "press"</code></dd>
3853N/A * <dt>code</dt>
3853N/A * <dd><code>{keyCode|character|keyName}[+{modifier}]*</code></dd>
3853N/A * <dt>modifier</dt>
3853N/A * <dd><code>"shift", "ctrl", "alt", or "meta"</code></dd>
3853N/A * <dt>keyName</dt>
3853N/A * <dd><code>"enter", "backspace", "esc", "tab", "pageup", or "pagedown"</code></dd>
3853N/A * </dl>
3853N/A *
3853N/A * <p>Examples:</p>
3853N/A * <ul>
3853N/A * <li><code>Y.on("key", callback, "press:12,65+shift+ctrl", "#my-input");</code></li>
3853N/A * <li><code>Y.delegate("key", preventSubmit, "enter", "#forms", "input[type=text]");</code></li>
3853N/A * <li><code>Y.one("doc").on("key", viNav, "j,k,l,;");</code></li>
3853N/A * </ul>
3853N/A *
3853N/A * @event key
3853N/A * @for YUI
3853N/A * @param type {string} 'key'
3853N/A * @param fn {function} the function to execute
3853N/A * @param id {string|HTMLElement|collection} the element(s) to bind
3853N/A * @param spec {string} the keyCode and modifier specification
1322N/A * @param o optional context object
1322N/A * @param args 0..n additional arguments to provide to the listener.
4516N/A * @return {Event.Handle} the detach handle
4516N/A */
4516N/AY.Event.define('key', eventDef, true);
4516N/A
4516N/A
4516N/A}, '@VERSION@' ,{requires:['event-synthetic']});
4516N/A