JAVASCRIPT   61

event-key.js

Guest on 4th October 2021 06:47:20 PM

  1. /*
  2. YUI 3.4.1 (build 4118)
  3. Copyright Yahoo! Inc. All rights reserved.
  4. Licensed under the BSD License.
  5. http://yuilibrary.com/license/
  6. */
  7. YUI.add('event-key', function(Y) {
  8.  
  9. /**
  10.  * Functionality to listen for one or more specific key combinations.
  11.  * @module event
  12.  * @submodule event-key
  13.  */
  14.  
  15. var ALT      = "+alt",
  16.     CTRL     = "+ctrl",
  17.     META     = "+meta",
  18.     SHIFT    = "+shift",
  19.  
  20.     trim     = Y.Lang.trim,
  21.  
  22.     eventDef = {
  23.         KEY_MAP: {
  24.             enter    : 13,
  25.             esc      : 27,
  26.             backspace: 8,
  27.             tab      : 9,
  28.             pageup   : 33,
  29.             pagedown : 34
  30.         },
  31.  
  32.         _typeRE: /^(up|down|press):/,
  33.         _keysRE: /^(?:up|down|press):|\+(alt|ctrl|meta|shift)/g,
  34.  
  35.         processArgs: function (args) {
  36.             var spec = args.splice(3,1)[0],
  37.                 mods = Y.Array.hash(spec.match(/\+(?:alt|ctrl|meta|shift)\b/g) || []),
  38.                 config = {
  39.                     type: this._typeRE.test(spec) ? RegExp.$1 : null,
  40.                     mods: mods,
  41.                     keys: null
  42.                 },
  43.                 // strip type and modifiers from spec, leaving only keyCodes
  44.                 bits = spec.replace(this._keysRE, ''),
  45.                 chr, uc, lc, i;
  46.  
  47.             if (bits) {
  48.                 bits = bits.split(',');
  49.  
  50.                 config.keys = {};
  51.  
  52.                 // FIXME: need to support '65,esc' => keypress, keydown
  53.                 for (i = bits.length - 1; i >= 0; --i) {
  54.                     chr = trim(bits[i]);
  55.  
  56.                     // catch sloppy filters, trailing commas, etc 'a,,'
  57.                     if (!chr) {
  58.                         continue;
  59.                     }
  60.  
  61.                     // non-numerics are single characters or key names
  62.                     if (+chr == chr) {
  63.                         config.keys[chr] = mods;
  64.                     } else {
  65.                         lc = chr.toLowerCase();
  66.  
  67.                         if (this.KEY_MAP[lc]) {
  68.                             config.keys[this.KEY_MAP[lc]] = mods;
  69.                             // FIXME: '65,enter' defaults keydown for both
  70.                             if (!config.type) {
  71.                                 config.type = "down"; // safest
  72.                             }
  73.                         } else {
  74.                             uc = chr.charAt(0).toUpperCase();
  75.                             lc = lc.charAt(0);
  76.  
  77.                             // FIXME: possibly stupid assumption that
  78.                             // the keycode of the lower case == the
  79.                             // charcode of the upper case
  80.                             // a (key:65,char:97), A (key:65,char:65)
  81.                             config.keys[uc.charCodeAt(0)] =
  82.                                 (lc !== uc && chr === uc) ?
  83.                                     // upper case chars get +shift free
  84.                                     Y.merge(mods, { "+shift": true }) :
  85.                                     mods;
  86.                         }
  87.                     }
  88.                 }
  89.             }
  90.  
  91.             if (!config.type) {
  92.                 config.type = "press";
  93.             }
  94.  
  95.             return config;
  96.         },
  97.  
  98.         on: function (node, sub, notifier, filter) {
  99.             var spec   = sub._extra,
  100.                 type   = "key" + spec.type,
  101.                 keys   = spec.keys,
  102.                 method = (filter) ? "delegate" : "on";
  103.  
  104.             // Note: without specifying any keyCodes, this becomes a
  105.             // horribly inefficient alias for 'keydown' (et al), but I
  106.             // can't abort this subscription for a simple
  107.             // Y.on('keypress', ...);
  108.             // Please use keyCodes or just subscribe directly to keydown,
  109.             // keyup, or keypress
  110.             sub._detach = node[method](type, function (e) {
  111.                 var key = keys ? keys[e.keyCode] : spec.mods;
  112.  
  113.                 if (key &&
  114.                     (!key[ALT]   || (key[ALT]   && e.altKey)) &&
  115.                     (!key[CTRL]  || (key[CTRL]  && e.ctrlKey)) &&
  116.                     (!key[META]  || (key[META]  && e.metaKey)) &&
  117.                     (!key[SHIFT] || (key[SHIFT] && e.shiftKey)))
  118.                 {
  119.                     notifier.fire(e);
  120.                 }
  121.             }, filter);
  122.         },
  123.  
  124.         detach: function (node, sub, notifier) {
  125.             sub._detach.detach();
  126.         }
  127.     };
  128.  
  129. eventDef.delegate = eventDef.on;
  130. eventDef.detachDelegate = eventDef.detach;
  131.  
  132. /**
  133.  * <p>Add a key listener.  The listener will only be notified if the
  134.  * keystroke detected meets the supplied specification.  The
  135.  * specification is a string that is defined as:</p>
  136.  *
  137.  * <dl>
  138.  *   <dt>spec</dt>
  139.  *   <dd><code>[{type}:]{code}[,{code}]*</code></dd>
  140.  *   <dt>type</dt>
  141.  *   <dd><code>"down", "up", or "press"</code></dd>
  142.  *   <dt>code</dt>
  143.  *   <dd><code>{keyCode|character|keyName}[+{modifier}]*</code></dd>
  144.  *   <dt>modifier</dt>
  145.  *   <dd><code>"shift", "ctrl", "alt", or "meta"</code></dd>
  146.  *   <dt>keyName</dt>
  147.  *   <dd><code>"enter", "backspace", "esc", "tab", "pageup", or "pagedown"</code></dd>
  148.  * </dl>
  149.  *
  150.  * <p>Examples:</p>
  151.  * <ul>
  152.  *   <li><code>Y.on("key", callback, "press:12,65+shift+ctrl", "#my-input");</code></li>
  153.  *   <li><code>Y.delegate("key", preventSubmit, "enter", "#forms", "input[type=text]");</code></li>
  154.  *   <li><code>Y.one("doc").on("key", viNav, "j,k,l,;");</code></li>
  155.  * </ul>
  156.  *  
  157.  * @event key
  158.  * @for YUI
  159.  * @param type {string} 'key'
  160.  * @param fn {function} the function to execute
  161.  * @param id {string|HTMLElement|collection} the element(s) to bind
  162.  * @param spec {string} the keyCode and modifier specification
  163.  * @param o optional context object
  164.  * @param args 0..n additional arguments to provide to the listener.
  165.  * @return {Event.Handle} the detach handle
  166.  */
  167. Y.Event.define('key', eventDef, true);
  168.  
  169.  
  170. }, '3.4.1' ,{requires:['event-synthetic']});

Raw Paste


Login or Register to edit or fork this paste. It's free.