# Yahoo! UI Library

### event 3.0.0

Yahoo! UI Library > event > key.js (source view)
Search:
Filters
Show Private Show Protected Show Deprecated

    /**
     * Functionality to listen for one or more specific key combinations.
     * @module event
     * @submodule event-key
     */

    /**
     * Add a key listener.  The listener will only be notified if the
     * keystroke detected meets the supplied specification.  The
     * spec consists of the key event type, followed by a colon,
     * followed by zero or more comma separated key codes, followed
     * by zero or more modifiers delimited by a plus sign.  Ex:
     * press:12,65+shift+ctrl
     * @event key
     * @for YUI
     * @param type {string} 'key'
     * @param fn {function} the function to execute
     * @param id {string|HTMLElement|collection} the element(s) to bind
     * @param spec {string} the keyCode and modifier specification
     * @param o optional context object
     * @param args 0..n additional arguments to provide to the listener.
     * @return {Event.Handle} the detach handle
     */
    Y.Env.evt.plugins.key = {

        on: function(type, fn, id, spec, o) {
            var a = Y.Array(arguments, 0, true), parsed, etype, criteria, ename;

            parsed = spec && spec.split(':');

            if (!spec || spec.indexOf(':') == -1 || !parsed[1]) {
    Y.log('Illegal key spec, creating a regular keypress listener instead.', 'info', 'event');
                a[0] = 'key' + ((parsed && parsed[0]) || 'press');
                return Y.on.apply(Y, a);
            }

            // key event type: 'down', 'up', or 'press'
            etype = parsed[0];

            // list of key codes optionally followed by modifiers
            criteria = (parsed[1]) ? parsed[1].split(/,|\+/) : null;

            // the name of the custom event that will be created for the spec
            ename = (Y.Lang.isString(id) ? id : Y.stamp(id)) + spec;

            ename = ename.replace(/,/g, '_');

            if (!Y.getEvent(ename)) {

                // subscribe spec validator to the DOM event
                Y.on(type + etype, function(e) {

                    // Y.log('keylistener: ' + e.keyCode);

                    var passed = false, failed = false, i, crit, critInt;

                    for (i=0; i<criteria.length; i=i+1) {
                        crit = criteria[i];
                        critInt = parseInt(crit, 10);

                        // pass this section if any supplied keyCode
                        // is found
                        if (Y.Lang.isNumber(critInt)) {

                            if (e.charCode === critInt) {
                                // Y.log('passed: ' + crit);
                                passed = true;
                            } else {
                                failed = true;
                                // Y.log('failed: ' + crit);
                            }

                        // only check modifier if no keyCode was specified
                        // or the keyCode check was successful.  pass only
                        // if every modifier passes
                        } else if (passed || !failed) {
                            passed = (e[crit + 'Key']);
                            failed = !passed;
                            // Y.log(crit + ": " + passed);
                        }
                    }

                    // fire spec custom event if spec if met
                    if (passed) {
                        Y.fire(ename, e);
                    }

                }, id);

            }

            // subscribe supplied listener to custom event for spec validator
            // remove element and spec.
            a.splice(2, 2);
            a[0] = ename;

            return Y.on.apply(Y, a);
        }
    };

Copyright © 2009 Yahoo! Inc. All rights reserved.