* 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
(combo, keys, callback, action)
| 655 | * @returns void |
| 656 | */ |
| 657 | function _bindSequence(combo, keys, callback, action) { |
| 658 | |
| 659 | // start off by adding a sequence level record for this combination |
| 660 | // and setting the level to 0 |
| 661 | _sequenceLevels[combo] = 0; |
| 662 | |
| 663 | /** |
| 664 | * callback to increase the sequence level for this sequence and reset |
| 665 | * all other sequences that were active |
| 666 | * |
| 667 | * @param {string} nextAction |
| 668 | * @returns {Function} |
| 669 | */ |
| 670 | function _increaseSequence(nextAction) { |
| 671 | return function() { |
| 672 | _nextExpectedAction = nextAction; |
| 673 | ++_sequenceLevels[combo]; |
| 674 | _resetSequenceTimer(); |
| 675 | }; |
| 676 | } |
| 677 | |
| 678 | /** |
| 679 | * wraps the specified callback inside of another function in order |
| 680 | * to reset all sequence counters as soon as this sequence is done |
| 681 | * |
| 682 | * @param {Event} e |
| 683 | * @returns void |
| 684 | */ |
| 685 | function _callbackAndReset(e) { |
| 686 | _fireCallback(callback, e, combo); |
| 687 | |
| 688 | // we should ignore the next key up if the action is key down |
| 689 | // or keypress. this is so if you finish a sequence and |
| 690 | // release the key the final key will not trigger a keyup |
| 691 | if (action !== 'keyup') { |
| 692 | _ignoreNextKeyup = _characterFromEvent(e); |
| 693 | } |
| 694 | |
| 695 | // weird race condition if a sequence ends with the key |
| 696 | // another sequence begins with |
| 697 | setTimeout(_resetSequences, 10); |
| 698 | } |
| 699 | |
| 700 | // loop through keys one at a time and bind the appropriate callback |
| 701 | // function. for any key leading up to the final one it should |
| 702 | // increase the sequence. after the final, it should reset all sequences |
| 703 | // |
| 704 | // if an action is specified in the original bind call then that will |
| 705 | // be used throughout. otherwise we will pass the action that the |
| 706 | // next key in the sequence should match. this allows a sequence |
| 707 | // to mix and match keypress and keydown events depending on which |
| 708 | // ones are better suited to the key provided |
| 709 | for (var i = 0; i < keys.length; ++i) { |
| 710 | var isFinal = i + 1 === keys.length; |
| 711 | var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action); |
| 712 | _bindSingle(keys[i], wrappedCallback, action, combo, i); |
| 713 | } |
| 714 | } |
no test coverage detected