##// END OF EJS Templates
Add mousetrap.js file from Mousetrap 1.4.5, under the Apache license....
Bradley M. Kuhn -
r4126:158ef336 rhodecode-2.2.5-gpl
parent child Browse files
Show More
This diff has been collapsed as it changes many lines, (931 lines changed) Show them Hide them
@@ -0,0 +1,931 b''
1 /*global define:false */
2 /**
3 * Copyright 2013 Craig Campbell
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Mousetrap is a simple keyboard shortcut library for Javascript with
18 * no external dependencies
19 *
20 * @version 1.4.5
21 * @url craig.is/killing/mice
22 */
23 (function(window, document, undefined) {
24
25 /**
26 * mapping of special keycodes to their corresponding keys
27 *
28 * everything in this dictionary cannot use keypress events
29 * so it has to be here to map to the correct keycodes for
30 * keyup/keydown events
31 *
32 * @type {Object}
33 */
34 var _MAP = {
35 8: 'backspace',
36 9: 'tab',
37 13: 'enter',
38 16: 'shift',
39 17: 'ctrl',
40 18: 'alt',
41 20: 'capslock',
42 27: 'esc',
43 32: 'space',
44 33: 'pageup',
45 34: 'pagedown',
46 35: 'end',
47 36: 'home',
48 37: 'left',
49 38: 'up',
50 39: 'right',
51 40: 'down',
52 45: 'ins',
53 46: 'del',
54 91: 'meta',
55 93: 'meta',
56 224: 'meta'
57 },
58
59 /**
60 * mapping for special characters so they can support
61 *
62 * this dictionary is only used incase you want to bind a
63 * keyup or keydown event to one of these keys
64 *
65 * @type {Object}
66 */
67 _KEYCODE_MAP = {
68 106: '*',
69 107: '+',
70 109: '-',
71 110: '.',
72 111 : '/',
73 186: ';',
74 187: '=',
75 188: ',',
76 189: '-',
77 190: '.',
78 191: '/',
79 192: '`',
80 219: '[',
81 220: '\\',
82 221: ']',
83 222: '\''
84 },
85
86 /**
87 * this is a mapping of keys that require shift on a US keypad
88 * back to the non shift equivelents
89 *
90 * this is so you can use keyup events with these keys
91 *
92 * note that this will only work reliably on US keyboards
93 *
94 * @type {Object}
95 */
96 _SHIFT_MAP = {
97 '~': '`',
98 '!': '1',
99 '@': '2',
100 '#': '3',
101 '$': '4',
102 '%': '5',
103 '^': '6',
104 '&': '7',
105 '*': '8',
106 '(': '9',
107 ')': '0',
108 '_': '-',
109 '+': '=',
110 ':': ';',
111 '\"': '\'',
112 '<': ',',
113 '>': '.',
114 '?': '/',
115 '|': '\\'
116 },
117
118 /**
119 * this is a list of special strings you can use to map
120 * to modifier keys when you specify your keyboard shortcuts
121 *
122 * @type {Object}
123 */
124 _SPECIAL_ALIASES = {
125 'option': 'alt',
126 'command': 'meta',
127 'return': 'enter',
128 'escape': 'esc',
129 'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'
130 },
131
132 /**
133 * variable to store the flipped version of _MAP from above
134 * needed to check if we should use keypress or not when no action
135 * is specified
136 *
137 * @type {Object|undefined}
138 */
139 _REVERSE_MAP,
140
141 /**
142 * a list of all the callbacks setup via Mousetrap.bind()
143 *
144 * @type {Object}
145 */
146 _callbacks = {},
147
148 /**
149 * direct map of string combinations to callbacks used for trigger()
150 *
151 * @type {Object}
152 */
153 _directMap = {},
154
155 /**
156 * keeps track of what level each sequence is at since multiple
157 * sequences can start out with the same sequence
158 *
159 * @type {Object}
160 */
161 _sequenceLevels = {},
162
163 /**
164 * variable to store the setTimeout call
165 *
166 * @type {null|number}
167 */
168 _resetTimer,
169
170 /**
171 * temporary state where we will ignore the next keyup
172 *
173 * @type {boolean|string}
174 */
175 _ignoreNextKeyup = false,
176
177 /**
178 * temporary state where we will ignore the next keypress
179 *
180 * @type {boolean}
181 */
182 _ignoreNextKeypress = false,
183
184 /**
185 * are we currently inside of a sequence?
186 * type of action ("keyup" or "keydown" or "keypress") or false
187 *
188 * @type {boolean|string}
189 */
190 _nextExpectedAction = false;
191
192 /**
193 * loop through the f keys, f1 to f19 and add them to the map
194 * programatically
195 */
196 for (var i = 1; i < 20; ++i) {
197 _MAP[111 + i] = 'f' + i;
198 }
199
200 /**
201 * loop through to map numbers on the numeric keypad
202 */
203 for (i = 0; i <= 9; ++i) {
204 _MAP[i + 96] = i;
205 }
206
207 /**
208 * cross browser add event method
209 *
210 * @param {Element|HTMLDocument} object
211 * @param {string} type
212 * @param {Function} callback
213 * @returns void
214 */
215 function _addEvent(object, type, callback) {
216 if (object.addEventListener) {
217 object.addEventListener(type, callback, false);
218 return;
219 }
220
221 object.attachEvent('on' + type, callback);
222 }
223
224 /**
225 * takes the event and returns the key character
226 *
227 * @param {Event} e
228 * @return {string}
229 */
230 function _characterFromEvent(e) {
231
232 // for keypress events we should return the character as is
233 if (e.type == 'keypress') {
234 var character = String.fromCharCode(e.which);
235
236 // if the shift key is not pressed then it is safe to assume
237 // that we want the character to be lowercase. this means if
238 // you accidentally have caps lock on then your key bindings
239 // will continue to work
240 //
241 // the only side effect that might not be desired is if you
242 // bind something like 'A' cause you want to trigger an
243 // event when capital A is pressed caps lock will no longer
244 // trigger the event. shift+a will though.
245 if (!e.shiftKey) {
246 character = character.toLowerCase();
247 }
248
249 return character;
250 }
251
252 // for non keypress events the special maps are needed
253 if (_MAP[e.which]) {
254 return _MAP[e.which];
255 }
256
257 if (_KEYCODE_MAP[e.which]) {
258 return _KEYCODE_MAP[e.which];
259 }
260
261 // if it is not in the special map
262
263 // with keydown and keyup events the character seems to always
264 // come in as an uppercase character whether you are pressing shift
265 // or not. we should make sure it is always lowercase for comparisons
266 return String.fromCharCode(e.which).toLowerCase();
267 }
268
269 /**
270 * checks if two arrays are equal
271 *
272 * @param {Array} modifiers1
273 * @param {Array} modifiers2
274 * @returns {boolean}
275 */
276 function _modifiersMatch(modifiers1, modifiers2) {
277 return modifiers1.sort().join(',') === modifiers2.sort().join(',');
278 }
279
280 /**
281 * resets all sequence counters except for the ones passed in
282 *
283 * @param {Object} doNotReset
284 * @returns void
285 */
286 function _resetSequences(doNotReset) {
287 doNotReset = doNotReset || {};
288
289 var activeSequences = false,
290 key;
291
292 for (key in _sequenceLevels) {
293 if (doNotReset[key]) {
294 activeSequences = true;
295 continue;
296 }
297 _sequenceLevels[key] = 0;
298 }
299
300 if (!activeSequences) {
301 _nextExpectedAction = false;
302 }
303 }
304
305 /**
306 * finds all callbacks that match based on the keycode, modifiers,
307 * and action
308 *
309 * @param {string} character
310 * @param {Array} modifiers
311 * @param {Event|Object} e
312 * @param {string=} sequenceName - name of the sequence we are looking for
313 * @param {string=} combination
314 * @param {number=} level
315 * @returns {Array}
316 */
317 function _getMatches(character, modifiers, e, sequenceName, combination, level) {
318 var i,
319 callback,
320 matches = [],
321 action = e.type;
322
323 // if there are no events related to this keycode
324 if (!_callbacks[character]) {
325 return [];
326 }
327
328 // if a modifier key is coming up on its own we should allow it
329 if (action == 'keyup' && _isModifier(character)) {
330 modifiers = [character];
331 }
332
333 // loop through all callbacks for the key that was pressed
334 // and see if any of them match
335 for (i = 0; i < _callbacks[character].length; ++i) {
336 callback = _callbacks[character][i];
337
338 // if a sequence name is not specified, but this is a sequence at
339 // the wrong level then move onto the next match
340 if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {
341 continue;
342 }
343
344 // if the action we are looking for doesn't match the action we got
345 // then we should keep going
346 if (action != callback.action) {
347 continue;
348 }
349
350 // if this is a keypress event and the meta key and control key
351 // are not pressed that means that we need to only look at the
352 // character, otherwise check the modifiers as well
353 //
354 // chrome will not fire a keypress if meta or control is down
355 // safari will fire a keypress if meta or meta+shift is down
356 // firefox will fire a keypress if meta or control is down
357 if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {
358
359 // when you bind a combination or sequence a second time it
360 // should overwrite the first one. if a sequenceName or
361 // combination is specified in this call it does just that
362 //
363 // @todo make deleting its own method?
364 var deleteCombo = !sequenceName && callback.combo == combination;
365 var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;
366 if (deleteCombo || deleteSequence) {
367 _callbacks[character].splice(i, 1);
368 }
369
370 matches.push(callback);
371 }
372 }
373
374 return matches;
375 }
376
377 /**
378 * takes a key event and figures out what the modifiers are
379 *
380 * @param {Event} e
381 * @returns {Array}
382 */
383 function _eventModifiers(e) {
384 var modifiers = [];
385
386 if (e.shiftKey) {
387 modifiers.push('shift');
388 }
389
390 if (e.altKey) {
391 modifiers.push('alt');
392 }
393
394 if (e.ctrlKey) {
395 modifiers.push('ctrl');
396 }
397
398 if (e.metaKey) {
399 modifiers.push('meta');
400 }
401
402 return modifiers;
403 }
404
405 /**
406 * actually calls the callback function
407 *
408 * if your callback function returns false this will use the jquery
409 * convention - prevent default and stop propogation on the event
410 *
411 * @param {Function} callback
412 * @param {Event} e
413 * @returns void
414 */
415 function _fireCallback(callback, e, combo) {
416
417 // if this event should not happen stop here
418 if (Mousetrap.stopCallback(e, e.target || e.srcElement, combo)) {
419 return;
420 }
421
422 if (callback(e, combo) === false) {
423 if (e.preventDefault) {
424 e.preventDefault();
425 }
426
427 if (e.stopPropagation) {
428 e.stopPropagation();
429 }
430
431 e.returnValue = false;
432 e.cancelBubble = true;
433 }
434 }
435
436 /**
437 * handles a character key event
438 *
439 * @param {string} character
440 * @param {Array} modifiers
441 * @param {Event} e
442 * @returns void
443 */
444 function _handleKey(character, modifiers, e) {
445 var callbacks = _getMatches(character, modifiers, e),
446 i,
447 doNotReset = {},
448 maxLevel = 0,
449 processedSequenceCallback = false;
450
451 // Calculate the maxLevel for sequences so we can only execute the longest callback sequence
452 for (i = 0; i < callbacks.length; ++i) {
453 if (callbacks[i].seq) {
454 maxLevel = Math.max(maxLevel, callbacks[i].level);
455 }
456 }
457
458 // loop through matching callbacks for this key event
459 for (i = 0; i < callbacks.length; ++i) {
460
461 // fire for all sequence callbacks
462 // this is because if for example you have multiple sequences
463 // bound such as "g i" and "g t" they both need to fire the
464 // callback for matching g cause otherwise you can only ever
465 // match the first one
466 if (callbacks[i].seq) {
467
468 // only fire callbacks for the maxLevel to prevent
469 // subsequences from also firing
470 //
471 // for example 'a option b' should not cause 'option b' to fire
472 // even though 'option b' is part of the other sequence
473 //
474 // any sequences that do not match here will be discarded
475 // below by the _resetSequences call
476 if (callbacks[i].level != maxLevel) {
477 continue;
478 }
479
480 processedSequenceCallback = true;
481
482 // keep a list of which sequences were matches for later
483 doNotReset[callbacks[i].seq] = 1;
484 _fireCallback(callbacks[i].callback, e, callbacks[i].combo);
485 continue;
486 }
487
488 // if there were no sequence matches but we are still here
489 // that means this is a regular match so we should fire that
490 if (!processedSequenceCallback) {
491 _fireCallback(callbacks[i].callback, e, callbacks[i].combo);
492 }
493 }
494
495 // if the key you pressed matches the type of sequence without
496 // being a modifier (ie "keyup" or "keypress") then we should
497 // reset all sequences that were not matched by this event
498 //
499 // this is so, for example, if you have the sequence "h a t" and you
500 // type "h e a r t" it does not match. in this case the "e" will
501 // cause the sequence to reset
502 //
503 // modifier keys are ignored because you can have a sequence
504 // that contains modifiers such as "enter ctrl+space" and in most
505 // cases the modifier key will be pressed before the next key
506 //
507 // also if you have a sequence such as "ctrl+b a" then pressing the
508 // "b" key will trigger a "keypress" and a "keydown"
509 //
510 // the "keydown" is expected when there is a modifier, but the
511 // "keypress" ends up matching the _nextExpectedAction since it occurs
512 // after and that causes the sequence to reset
513 //
514 // we ignore keypresses in a sequence that directly follow a keydown
515 // for the same character
516 var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;
517 if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) {
518 _resetSequences(doNotReset);
519 }
520
521 _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';
522 }
523
524 /**
525 * handles a keydown event
526 *
527 * @param {Event} e
528 * @returns void
529 */
530 function _handleKeyEvent(e) {
531
532 // normalize e.which for key events
533 // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion
534 if (typeof e.which !== 'number') {
535 e.which = e.keyCode;
536 }
537
538 var character = _characterFromEvent(e);
539
540 // no character found then stop
541 if (!character) {
542 return;
543 }
544
545 // need to use === for the character check because the character can be 0
546 if (e.type == 'keyup' && _ignoreNextKeyup === character) {
547 _ignoreNextKeyup = false;
548 return;
549 }
550
551 Mousetrap.handleKey(character, _eventModifiers(e), e);
552 }
553
554 /**
555 * determines if the keycode specified is a modifier key or not
556 *
557 * @param {string} key
558 * @returns {boolean}
559 */
560 function _isModifier(key) {
561 return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';
562 }
563
564 /**
565 * called to set a 1 second timeout on the specified sequence
566 *
567 * this is so after each key press in the sequence you have 1 second
568 * to press the next key before you have to start over
569 *
570 * @returns void
571 */
572 function _resetSequenceTimer() {
573 clearTimeout(_resetTimer);
574 _resetTimer = setTimeout(_resetSequences, 1000);
575 }
576
577 /**
578 * reverses the map lookup so that we can look for specific keys
579 * to see what can and can't use keypress
580 *
581 * @return {Object}
582 */
583 function _getReverseMap() {
584 if (!_REVERSE_MAP) {
585 _REVERSE_MAP = {};
586 for (var key in _MAP) {
587
588 // pull out the numeric keypad from here cause keypress should
589 // be able to detect the keys from the character
590 if (key > 95 && key < 112) {
591 continue;
592 }
593
594 if (_MAP.hasOwnProperty(key)) {
595 _REVERSE_MAP[_MAP[key]] = key;
596 }
597 }
598 }
599 return _REVERSE_MAP;
600 }
601
602 /**
603 * picks the best action based on the key combination
604 *
605 * @param {string} key - character for key
606 * @param {Array} modifiers
607 * @param {string=} action passed in
608 */
609 function _pickBestAction(key, modifiers, action) {
610
611 // if no action was picked in we should try to pick the one
612 // that we think would work best for this key
613 if (!action) {
614 action = _getReverseMap()[key] ? 'keydown' : 'keypress';
615 }
616
617 // modifier keys don't work as expected with keypress,
618 // switch to keydown
619 if (action == 'keypress' && modifiers.length) {
620 action = 'keydown';
621 }
622
623 return action;
624 }
625
626 /**
627 * binds a key sequence to an event
628 *
629 * @param {string} combo - combo specified in bind call
630 * @param {Array} keys
631 * @param {Function} callback
632 * @param {string=} action
633 * @returns void
634 */
635 function _bindSequence(combo, keys, callback, action) {
636
637 // start off by adding a sequence level record for this combination
638 // and setting the level to 0
639 _sequenceLevels[combo] = 0;
640
641 /**
642 * callback to increase the sequence level for this sequence and reset
643 * all other sequences that were active
644 *
645 * @param {string} nextAction
646 * @returns {Function}
647 */
648 function _increaseSequence(nextAction) {
649 return function() {
650 _nextExpectedAction = nextAction;
651 ++_sequenceLevels[combo];
652 _resetSequenceTimer();
653 };
654 }
655
656 /**
657 * wraps the specified callback inside of another function in order
658 * to reset all sequence counters as soon as this sequence is done
659 *
660 * @param {Event} e
661 * @returns void
662 */
663 function _callbackAndReset(e) {
664 _fireCallback(callback, e, combo);
665
666 // we should ignore the next key up if the action is key down
667 // or keypress. this is so if you finish a sequence and
668 // release the key the final key will not trigger a keyup
669 if (action !== 'keyup') {
670 _ignoreNextKeyup = _characterFromEvent(e);
671 }
672
673 // weird race condition if a sequence ends with the key
674 // another sequence begins with
675 setTimeout(_resetSequences, 10);
676 }
677
678 // loop through keys one at a time and bind the appropriate callback
679 // function. for any key leading up to the final one it should
680 // increase the sequence. after the final, it should reset all sequences
681 //
682 // if an action is specified in the original bind call then that will
683 // be used throughout. otherwise we will pass the action that the
684 // next key in the sequence should match. this allows a sequence
685 // to mix and match keypress and keydown events depending on which
686 // ones are better suited to the key provided
687 for (var i = 0; i < keys.length; ++i) {
688 var isFinal = i + 1 === keys.length;
689 var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);
690 _bindSingle(keys[i], wrappedCallback, action, combo, i);
691 }
692 }
693
694 /**
695 * Converts from a string key combination to an array
696 *
697 * @param {string} combination like "command+shift+l"
698 * @return {Array}
699 */
700 function _keysFromString(combination) {
701 if (combination === '+') {
702 return ['+'];
703 }
704
705 return combination.split('+');
706 }
707
708 /**
709 * Gets info for a specific key combination
710 *
711 * @param {string} combination key combination ("command+s" or "a" or "*")
712 * @param {string=} action
713 * @returns {Object}
714 */
715 function _getKeyInfo(combination, action) {
716 var keys,
717 key,
718 i,
719 modifiers = [];
720
721 // take the keys from this pattern and figure out what the actual
722 // pattern is all about
723 keys = _keysFromString(combination);
724
725 for (i = 0; i < keys.length; ++i) {
726 key = keys[i];
727
728 // normalize key names
729 if (_SPECIAL_ALIASES[key]) {
730 key = _SPECIAL_ALIASES[key];
731 }
732
733 // if this is not a keypress event then we should
734 // be smart about using shift keys
735 // this will only work for US keyboards however
736 if (action && action != 'keypress' && _SHIFT_MAP[key]) {
737 key = _SHIFT_MAP[key];
738 modifiers.push('shift');
739 }
740
741 // if this key is a modifier then add it to the list of modifiers
742 if (_isModifier(key)) {
743 modifiers.push(key);
744 }
745 }
746
747 // depending on what the key combination is
748 // we will try to pick the best event for it
749 action = _pickBestAction(key, modifiers, action);
750
751 return {
752 key: key,
753 modifiers: modifiers,
754 action: action
755 };
756 }
757
758 /**
759 * binds a single keyboard combination
760 *
761 * @param {string} combination
762 * @param {Function} callback
763 * @param {string=} action
764 * @param {string=} sequenceName - name of sequence if part of sequence
765 * @param {number=} level - what part of the sequence the command is
766 * @returns void
767 */
768 function _bindSingle(combination, callback, action, sequenceName, level) {
769
770 // store a direct mapped reference for use with Mousetrap.trigger
771 _directMap[combination + ':' + action] = callback;
772
773 // make sure multiple spaces in a row become a single space
774 combination = combination.replace(/\s+/g, ' ');
775
776 var sequence = combination.split(' '),
777 info;
778
779 // if this pattern is a sequence of keys then run through this method
780 // to reprocess each pattern one key at a time
781 if (sequence.length > 1) {
782 _bindSequence(combination, sequence, callback, action);
783 return;
784 }
785
786 info = _getKeyInfo(combination, action);
787
788 // make sure to initialize array if this is the first time
789 // a callback is added for this key
790 _callbacks[info.key] = _callbacks[info.key] || [];
791
792 // remove an existing match if there is one
793 _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);
794
795 // add this call back to the array
796 // if it is a sequence put it at the beginning
797 // if not put it at the end
798 //
799 // this is important because the way these are processed expects
800 // the sequence ones to come first
801 _callbacks[info.key][sequenceName ? 'unshift' : 'push']({
802 callback: callback,
803 modifiers: info.modifiers,
804 action: info.action,
805 seq: sequenceName,
806 level: level,
807 combo: combination
808 });
809 }
810
811 /**
812 * binds multiple combinations to the same callback
813 *
814 * @param {Array} combinations
815 * @param {Function} callback
816 * @param {string|undefined} action
817 * @returns void
818 */
819 function _bindMultiple(combinations, callback, action) {
820 for (var i = 0; i < combinations.length; ++i) {
821 _bindSingle(combinations[i], callback, action);
822 }
823 }
824
825 // start!
826 _addEvent(document, 'keypress', _handleKeyEvent);
827 _addEvent(document, 'keydown', _handleKeyEvent);
828 _addEvent(document, 'keyup', _handleKeyEvent);
829
830 var Mousetrap = {
831
832 /**
833 * binds an event to mousetrap
834 *
835 * can be a single key, a combination of keys separated with +,
836 * an array of keys, or a sequence of keys separated by spaces
837 *
838 * be sure to list the modifier keys first to make sure that the
839 * correct key ends up getting bound (the last key in the pattern)
840 *
841 * @param {string|Array} keys
842 * @param {Function} callback
843 * @param {string=} action - 'keypress', 'keydown', or 'keyup'
844 * @returns void
845 */
846 bind: function(keys, callback, action) {
847 keys = keys instanceof Array ? keys : [keys];
848 _bindMultiple(keys, callback, action);
849 return this;
850 },
851
852 /**
853 * unbinds an event to mousetrap
854 *
855 * the unbinding sets the callback function of the specified key combo
856 * to an empty function and deletes the corresponding key in the
857 * _directMap dict.
858 *
859 * TODO: actually remove this from the _callbacks dictionary instead
860 * of binding an empty function
861 *
862 * the keycombo+action has to be exactly the same as
863 * it was defined in the bind method
864 *
865 * @param {string|Array} keys
866 * @param {string} action
867 * @returns void
868 */
869 unbind: function(keys, action) {
870 return Mousetrap.bind(keys, function() {}, action);
871 },
872
873 /**
874 * triggers an event that has already been bound
875 *
876 * @param {string} keys
877 * @param {string=} action
878 * @returns void
879 */
880 trigger: function(keys, action) {
881 if (_directMap[keys + ':' + action]) {
882 _directMap[keys + ':' + action]({}, keys);
883 }
884 return this;
885 },
886
887 /**
888 * resets the library back to its initial state. this is useful
889 * if you want to clear out the current keyboard shortcuts and bind
890 * new ones - for example if you switch to another page
891 *
892 * @returns void
893 */
894 reset: function() {
895 _callbacks = {};
896 _directMap = {};
897 return this;
898 },
899
900 /**
901 * should we stop this event before firing off callbacks
902 *
903 * @param {Event} e
904 * @param {Element} element
905 * @return {boolean}
906 */
907 stopCallback: function(e, element) {
908
909 // if the element has the class "mousetrap" then no need to stop
910 if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {
911 return false;
912 }
913
914 // stop for input, select, and textarea
915 return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;
916 },
917
918 /**
919 * exposes _handleKey publicly so it can be overwritten by extensions
920 */
921 handleKey: _handleKey
922 };
923
924 // expose mousetrap to the global object
925 window.Mousetrap = Mousetrap;
926
927 // expose mousetrap as an AMD module
928 if (typeof define === 'function' && define.amd) {
929 define(Mousetrap);
930 }
931 }) (window, document);
General Comments 0
You need to be logged in to leave comments. Login now