src/keyboard.js
function _bindSequence(combo, keys, callback, action) {

    var that = this;

    // start off by adding a sequence level record for this combination
    // and setting the level to 0
    this._sequenceLevels[combo] = 0;

    /**
     * callback to increase the sequence level for this sequence and reset
     * all other sequences that were active
     *
     * @param {string} nextAction
     * @returns {Function}
     */
    function _increaseSequence(nextAction) {
      return function() {
        that._nextExpectedAction = nextAction;
        ++that._sequenceLevels[combo];
        _resetSequenceTimer.call(that);
      };
    }

    /**
     * wraps the specified callback inside of another function in order
     * to reset all sequence counters as soon as this sequence is done
     *
     * @param {Event} e
     * @returns void
     */
    function _callbackAndReset(e) {
      _fireCallback.call(this, callback, e, combo);

      // we should ignore the next key up if the action is key down
      // or keypress.  this is so if you finish a sequence and
      // release the key the final key will not trigger a keyup
      if (action !== 'keyup') {
        this._ignoreNextKeyup = _characterFromEvent(e);
      }

      // weird race condition if a sequence ends with the key
      // another sequence begins with
      setTimeout(_resetSequences.bind(this), 10);
    }

    // loop through keys one at a time and bind the appropriate callback
    // function.  for any key leading up to the final one it should
    // increase the sequence. after the final, it should reset all sequences
    //
    // if an action is specified in the original bind call then that will
    // be used throughout.  otherwise we will pass the action that the
    // next key in the sequence should match.  this allows a sequence
    // to mix and match keypress and keydown events depending on which
    // ones are better suited to the key provided
    for (var i = 0; i < keys.length; ++i) {
        var isFinal = i + 1 === keys.length;
        var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence.call(this, action || _getKeyInfo(keys[i + 1]).action);
        _bindSingle.call(this, keys[i], wrappedCallback, action, combo, i);
    }
  }
function _bindSequence(combo, keys, callback, action) {

    var that = this;

    // start off by adding a sequence level record for this combination
    // and setting the level to 0
    this._sequenceLevels[combo] = 0;

    /**
     * callback to increase the sequence level for this sequence and reset
     * all other sequences that were active
     *
     * @param {string} nextAction
     * @returns {Function}
     */
    function _increaseSequence(nextAction) {
      return function() {
        that._nextExpectedAction = nextAction;
        ++that._sequenceLevels[combo];
        _resetSequenceTimer.call(that);
      };
    }

    /**
     * wraps the specified callback inside of another function in order
     * to reset all sequence counters as soon as this sequence is done
     *
     * @param {Event} e
     * @returns void
     */
    function _callbackAndReset(e) {
      _fireCallback.call(this, callback, e, combo);

      // we should ignore the next key up if the action is key down
      // or keypress.  this is so if you finish a sequence and
      // release the key the final key will not trigger a keyup
      if (action !== 'keyup') {
        this._ignoreNextKeyup = _characterFromEvent(e);
      }

      // weird race condition if a sequence ends with the key
      // another sequence begins with
      setTimeout(_resetSequences.bind(this), 10);
    }

    // loop through keys one at a time and bind the appropriate callback
    // function.  for any key leading up to the final one it should
    // increase the sequence. after the final, it should reset all sequences
    //
    // if an action is specified in the original bind call then that will
    // be used throughout.  otherwise we will pass the action that the
    // next key in the sequence should match.  this allows a sequence
    // to mix and match keypress and keydown events depending on which
    // ones are better suited to the key provided
    for (var i = 0; i < keys.length; ++i) {
        var isFinal = i + 1 === keys.length;
        var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence.call(this, action || _getKeyInfo(keys[i + 1]).action);
        _bindSingle.call(this, keys[i], wrappedCallback, action, combo, i);
    }
  }
function _bindSequence ( combo , keys , callback , action ) { var that = this ; // start off by adding a sequence level record for this combination // and setting the level to 0 this . _sequenceLevels [ combo ] = 0 ; /**
     * callback to increase the sequence level for this sequence and reset
     * all other sequences that were active
     *
     * @param {string} nextAction
     * @returns {Function}
     */ function _increaseSequence ( nextAction ) { return function ( ) { that . _nextExpectedAction = nextAction ; ++ that . _sequenceLevels [ combo ] ; _resetSequenceTimer . call ( that ) ; } ; } /**
     * wraps the specified callback inside of another function in order
     * to reset all sequence counters as soon as this sequence is done
     *
     * @param {Event} e
     * @returns void
     */ function _callbackAndReset ( e ) { _fireCallback . call ( this , callback , e , combo ) ; // we should ignore the next key up if the action is key down // or keypress.  this is so if you finish a sequence and // release the key the final key will not trigger a keyup if ( action !== 'keyup' ) { this . _ignoreNextKeyup = _characterFromEvent ( e ) ; } // weird race condition if a sequence ends with the key // another sequence begins with setTimeout ( _resetSequences . bind ( this ) , 10 ) ; } // loop through keys one at a time and bind the appropriate callback // function.  for any key leading up to the final one it should // increase the sequence. after the final, it should reset all sequences // // if an action is specified in the original bind call then that will // be used throughout.  otherwise we will pass the action that the // next key in the sequence should match.  this allows a sequence // to mix and match keypress and keydown events depending on which // ones are better suited to the key provided for ( var i = 0 ; i < keys . length ; ++ i ) { var isFinal = i + 1 === keys . length ; var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence . call ( this , action || _getKeyInfo ( keys [ i + 1 ] ) . action ) ; _bindSingle . call ( this , keys [ i ] , wrappedCallback , action , combo , i ) ; } }
binds a key sequence to an event

@param {string} combo - combo specified in bind call
@param {Array} keys
@param {Function} callback
@param {string=} action
@returns void
binds a key sequence to an event