mousetrap-rails 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 510a6cd6f40ef2ba974a305bdf77d11292a13d3c
4
+ data.tar.gz: 4e080a4551b296c562d79807d0fbe9a38ee43798
5
+ SHA512:
6
+ metadata.gz: f7779a4ade4fb6ee4ad7871bb7bbd2eac1396fcb5282bf1225d5629f9b5a0d7513544ce1178c257f4d4662f4e760ea2b6dfffbdd9a352bb61fc48cc2fc8bce7c
7
+ data.tar.gz: 988ed39f05e62f268ad3f88f47a2f5f6909951956cc6017b9a68fd5b715a43b2effed1f78fabb8308b1471aa4b0d03e8ec4c168a258279ad1f62370d0b0a9f62
@@ -0,0 +1,3 @@
1
+ ��)
2
+ ���� �i�y
3
+ ���I�Y���D�Ub�A�s���=����?R+V='\B��wakp;��򊖯#���K������pS���V�W���� �$��얡�1M?]qگ��J�F8 �S�Zg�F�d�أ��^ >H's\d5#Ova�i<oә�jl_��>��%U�0Z�e�軸���縿/��#��tu�.ۦrn����2y=��/�BF�/dB���J��:YO�<lw� 2�:h?w5��-�-[�
data.tar.gz.sig CHANGED
Binary file
data/.gitignore CHANGED
@@ -4,6 +4,8 @@
4
4
  .config
5
5
  .yardoc
6
6
  .rvmrc
7
+ .ruby-gemset
8
+ .ruby-version
7
9
  Gemfile.lock
8
10
  InstalledFiles
9
11
  _yardoc
@@ -1,3 +1,8 @@
1
+ ## v0.0.10
2
+
3
+ * update mousetrap.js to 1.4.1
4
+ * use Tubolinks.visit for navigating if Turbolinks defined
5
+
1
6
  ## v0.0.9
2
7
 
3
8
  * sign gem with selfsigned certificate
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ### Gem mousetrap-rails
2
2
 
3
- Copyright (c) 2012 Nick Kugaevsky
3
+ Copyright (c) 2012—2013 Nick Kugaevsky
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
6
 
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
- # Mousetrap::Rails [![endorse](http://api.coderwall.com/kugaevsky/endorsecount.png)](http://coderwall.com/kugaevsky) [![Build Status](https://secure.travis-ci.org/kugaevsky/mousetrap-rails.png?branch=master)](https://travis-ci.org/kugaevsky/mousetrap-rails) [![Dependency Status](https://gemnasium.com/kugaevsky/mousetrap-rails.png)](https://gemnasium.com/kugaevsky/mousetrap-rails) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/kugaevsky/mousetrap-rails)
1
+ # Mousetrap::Rails
2
+ [![Flattr this](http://api.flattr.com/button/flattr-badge-large.png)](http://flattr.com/thing/1233054/Mousetrap-rails-gem) [![endorse](http://api.coderwall.com/kugaevsky/endorsecount.png)](http://coderwall.com/kugaevsky) [![Dependency Status](https://gemnasium.com/kugaevsky/mousetrap-rails.png)](https://gemnasium.com/kugaevsky/mousetrap-rails) [![Code Climate](https://codeclimate.com/github/kugaevsky/mousetrap-rails.png)](https://codeclimate.com/github/kugaevsky/mousetrap-rails) [![Build Status](https://travis-ci.org/kugaevsky/mousetrap-rails.png?branch=master)](https://travis-ci.org/kugaevsky/mousetrap-rails) [![Coverage Status](https://coveralls.io/repos/kugaevsky/mousetrap-rails/badge.png?branch=master)](https://coveralls.io/r/kugaevsky/mousetrap-rails)
2
3
 
3
4
  [Mousetrap](https://github.com/ccampbell/mousetrap) is a javascript library for handling keyboard shortcuts in your web applications written by [Craig Campbell](http://craig.is/).
4
5
 
5
- The `mousetrap-rails` gem integrates Mousetrap javascript library with Rails Asset Pipeline.
6
+ The `mousetrap-rails` gem integrates Mousetrap javascript library with Rails asset pipeline.
6
7
 
7
8
 
8
9
  ## Installation
@@ -27,7 +28,7 @@ $ bundle install
27
28
  $ rails generate mousetrap:install
28
29
  ```
29
30
 
30
- It will create sample `keybindings.js.coffee` file in `app/assets/javascripts` and insert mousetrap-rails files to manifests of assert pipeline
31
+ It will create a sample `keybindings.js.coffee` file in `app/assets/javascripts` and insert mousetrap-rails files to manifests of asset pipeline
31
32
 
32
33
  ```coffeescript
33
34
  //= require mousetrap # ---> application.js
@@ -55,7 +56,7 @@ You can add keyboard navigation to your links by using `data-keybinding` attribu
55
56
  = link_to 'About', about_path, data: { keybinding: '["a", "c"]' } # Press 'a' or 'c' to navigate to about
56
57
  ```
57
58
 
58
- You can jump to input
59
+ You can jump to an input
59
60
 
60
61
  ```haml
61
62
  = text_field_tag 'Username', nil, data: { keybinding: 'u' } # Press 'u' to focus username input field
@@ -99,6 +100,16 @@ You can find full documentation on [Mousetrap library page](http://craig.is/kill
99
100
 
100
101
  You can display key binding hints near links with `data-keybinding` attribute by pressing `Alt+Shift+h`. Now it's just experimental feature for debugging purposes only.
101
102
 
103
+ ## TODO
104
+
105
+ - [ ] Add moustrap extensions generator
106
+
107
+ ## Contributing
108
+
109
+ Please submit all pull requests against latest `*.wip` branch. If your pull request contains new features, you **must** include relevant tests.
110
+
111
+ Thanks in advance!
112
+
102
113
 
103
114
  ## Changelog
104
115
 
@@ -2,7 +2,13 @@ $ ->
2
2
  # Hotkey binding to links with 'data-keybinding' attribute
3
3
  # Navigate link when hotkey pressed
4
4
  $('a[data-keybinding]').each (i, el) ->
5
- Mousetrap.bind $(el).data('keybinding'), (e) -> el.click()
5
+ Mousetrap.bind $(el).data('keybinding'), (e) ->
6
+ if typeof(Turbolinks) == 'undefined'
7
+ # Emulate click if turbolinks defined
8
+ el.click()
9
+ else
10
+ # Use turbolinks to go to URL
11
+ Turbolinks.visit(el.href)
6
12
 
7
13
  # Hotkey binding to inputs with 'data-keybinding' attribute
8
14
  # Focus input when hotkey pressed
@@ -17,7 +23,7 @@ $ ->
17
23
  # Toggle show/hide hotkey hints
18
24
  window.mouseTrapRails =
19
25
  showOnLoad: false # Show/hide hotkey hints by default (on page load). Mostly for debugging purposes.
20
- toggleKeys: 'alt+shift+h' # Key sequence to toggle hints visibility.
26
+ toggleKeys: 'alt+shift+h' # Keys combo to toggle hints visibility.
21
27
  keysShown: false
22
28
  toggleHints: ->
23
29
  $('a[data-keybinding]').each (i, el) ->
@@ -1,5 +1,5 @@
1
1
  module Mousetrap
2
2
  module Rails
3
- VERSION = "0.0.9"
3
+ VERSION = "0.0.10"
4
4
  end
5
5
  end
@@ -6,8 +6,8 @@ require 'mousetrap-rails/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "mousetrap-rails"
8
8
  gem.version = Mousetrap::Rails::VERSION
9
- gem.authors = ["Nick Kugaevsky"]
10
- gem.email = ["nick@kugaevsky.ru"]
9
+ gem.authors = "Nick Kugaevsky"
10
+ gem.email = "nick@kugaevsky.ru"
11
11
  gem.description = %q{Mousetrap is a javascript library for handling keyboard shortcuts in your web applications. This gem integrates Mousetrap with Rails asset pipeline for easy of use.}
12
12
  gem.summary = %q{Integrate Mousetrap javascript library with Rails Asset Pipeline}
13
13
  gem.homepage = "http://kugaevsky.github.com/mousetrap-rails"
@@ -20,11 +20,12 @@ Gem::Specification.new do |gem|
20
20
  gem.signing_key = '/Users/nick/.ssh/gem-private_key.pem'
21
21
  gem.cert_chain = ['gem-public_cert.pem']
22
22
 
23
- gem.add_development_dependency 'rails', '~> 3.2.11'
23
+ gem.add_development_dependency 'rails', '~> 3.2.12'
24
24
  gem.add_development_dependency 'sqlite3', '~> 1.3.5'
25
- gem.add_development_dependency 'rspec-rails', '~> 2.12.0'
25
+ gem.add_development_dependency 'rspec-rails', '~> 2.13.0'
26
26
  gem.add_development_dependency 'genspec', '~> 0.2.7'
27
27
  gem.add_development_dependency 'sass', '~> 3.2.1'
28
+ gem.add_development_dependency 'coveralls'
28
29
 
29
30
  gem.licenses = ['MIT', 'Apache']
30
31
  gem.post_install_message = <<MSG
@@ -4,6 +4,8 @@ require File.expand_path("../dummy/config/environment", __FILE__)
4
4
  require 'rspec/rails'
5
5
  require 'rspec/autorun'
6
6
  require 'genspec'
7
+ require 'coveralls'
8
+ Coveralls.wear!
7
9
 
8
10
  # Require gem generators
9
11
  Dir[Rails.root.join("../../lib/generators/mousetrap/**/*_generator.rb")].each {|f| require f}
@@ -1,5 +1,6 @@
1
+ /*global define:false */
1
2
  /**
2
- * Copyright 2012 Craig Campbell
3
+ * Copyright 2013 Craig Campbell
3
4
  *
4
5
  * Licensed under the Apache License, Version 2.0 (the "License");
5
6
  * you may not use this file except in compliance with the License.
@@ -16,7 +17,7 @@
16
17
  * Mousetrap is a simple keyboard shortcut library for Javascript with
17
18
  * no external dependencies
18
19
  *
19
- * @version 1.3.0
20
+ * @version 1.4.1
20
21
  * @url craig.is/killing/mice
21
22
  */
22
23
  (function() {
@@ -124,7 +125,8 @@
124
125
  'option': 'alt',
125
126
  'command': 'meta',
126
127
  'return': 'enter',
127
- 'escape': 'esc'
128
+ 'escape': 'esc',
129
+ 'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'
128
130
  },
129
131
 
130
132
  /**
@@ -178,7 +180,7 @@
178
180
  *
179
181
  * @type {boolean|string}
180
182
  */
181
- _sequenceType = false;
183
+ _nextExpectedAction = false;
182
184
 
183
185
  /**
184
186
  * loop through the f keys, f1 to f19 and add them to the map
@@ -222,7 +224,22 @@
222
224
 
223
225
  // for keypress events we should return the character as is
224
226
  if (e.type == 'keypress') {
225
- return String.fromCharCode(e.which);
227
+ var character = String.fromCharCode(e.which);
228
+
229
+ // if the shift key is not pressed then it is safe to assume
230
+ // that we want the character to be lowercase. this means if
231
+ // you accidentally have caps lock on then your key bindings
232
+ // will continue to work
233
+ //
234
+ // the only side effect that might not be desired is if you
235
+ // bind something like 'A' cause you want to trigger an
236
+ // event when capital A is pressed caps lock will no longer
237
+ // trigger the event. shift+a will though.
238
+ if (!e.shiftKey) {
239
+ character = character.toLowerCase();
240
+ }
241
+
242
+ return character;
226
243
  }
227
244
 
228
245
  // for non keypress events the special maps are needed
@@ -235,6 +252,10 @@
235
252
  }
236
253
 
237
254
  // if it is not in the special map
255
+
256
+ // with keydown and keyup events the character seems to always
257
+ // come in as an uppercase character whether you are pressing shift
258
+ // or not. we should make sure it is always lowercase for comparisons
238
259
  return String.fromCharCode(e.which).toLowerCase();
239
260
  }
240
261
 
@@ -255,14 +276,14 @@
255
276
  * @param {Object} doNotReset
256
277
  * @returns void
257
278
  */
258
- function _resetSequences(doNotReset, maxLevel) {
279
+ function _resetSequences(doNotReset) {
259
280
  doNotReset = doNotReset || {};
260
281
 
261
282
  var activeSequences = false,
262
283
  key;
263
284
 
264
285
  for (key in _sequenceLevels) {
265
- if (doNotReset[key] && _sequenceLevels[key] > maxLevel) {
286
+ if (doNotReset[key]) {
266
287
  activeSequences = true;
267
288
  continue;
268
289
  }
@@ -270,7 +291,7 @@
270
291
  }
271
292
 
272
293
  if (!activeSequences) {
273
- _sequenceType = false;
294
+ _nextExpectedAction = false;
274
295
  }
275
296
  }
276
297
 
@@ -281,11 +302,12 @@
281
302
  * @param {string} character
282
303
  * @param {Array} modifiers
283
304
  * @param {Event|Object} e
284
- * @param {boolean=} remove - should we remove any matches
305
+ * @param {string=} sequenceName - name of the sequence we are looking for
285
306
  * @param {string=} combination
307
+ * @param {number=} level
286
308
  * @returns {Array}
287
309
  */
288
- function _getMatches(character, modifiers, e, remove, combination) {
310
+ function _getMatches(character, modifiers, e, sequenceName, combination, level) {
289
311
  var i,
290
312
  callback,
291
313
  matches = [],
@@ -306,9 +328,9 @@
306
328
  for (i = 0; i < _callbacks[character].length; ++i) {
307
329
  callback = _callbacks[character][i];
308
330
 
309
- // if this is a sequence but it is not at the right level
310
- // then move onto the next match
311
- if (callback.seq && _sequenceLevels[callback.seq] != callback.level) {
331
+ // if a sequence name is not specified, but this is a sequence at
332
+ // the wrong level then move onto the next match
333
+ if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {
312
334
  continue;
313
335
  }
314
336
 
@@ -327,9 +349,14 @@
327
349
  // firefox will fire a keypress if meta or control is down
328
350
  if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {
329
351
 
330
- // remove is used so if you change your mind and call bind a
331
- // second time with a new function the first one is overwritten
332
- if (remove && callback.combo == combination) {
352
+ // when you bind a combination or sequence a second time it
353
+ // should overwrite the first one. if a sequenceName or
354
+ // combination is specified in this call it does just that
355
+ //
356
+ // @todo make deleting its own method?
357
+ var deleteCombo = !sequenceName && callback.combo == combination;
358
+ var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;
359
+ if (deleteCombo || deleteSequence) {
333
360
  _callbacks[character].splice(i, 1);
334
361
  }
335
362
 
@@ -403,16 +430,24 @@
403
430
  * handles a character key event
404
431
  *
405
432
  * @param {string} character
433
+ * @param {Array} modifiers
406
434
  * @param {Event} e
407
435
  * @returns void
408
436
  */
409
- function _handleCharacter(character, e) {
410
- var callbacks = _getMatches(character, _eventModifiers(e), e),
437
+ function _handleKey(character, modifiers, e) {
438
+ var callbacks = _getMatches(character, modifiers, e),
411
439
  i,
412
440
  doNotReset = {},
413
441
  maxLevel = 0,
414
442
  processedSequenceCallback = false;
415
443
 
444
+ // Calculate the maxLevel for sequences so we can only execute the longest callback sequence
445
+ for (i = 0; i < callbacks.length; ++i) {
446
+ if (callbacks[i].seq) {
447
+ maxLevel = Math.max(maxLevel, callbacks[i].level);
448
+ }
449
+ }
450
+
416
451
  // loop through matching callbacks for this key event
417
452
  for (i = 0; i < callbacks.length; ++i) {
418
453
 
@@ -422,11 +457,20 @@
422
457
  // callback for matching g cause otherwise you can only ever
423
458
  // match the first one
424
459
  if (callbacks[i].seq) {
425
- processedSequenceCallback = true;
426
460
 
427
- // as we loop through keep track of the max
428
- // any sequence at a lower level will be discarded
429
- maxLevel = Math.max(maxLevel, callbacks[i].level);
461
+ // only fire callbacks for the maxLevel to prevent
462
+ // subsequences from also firing
463
+ //
464
+ // for example 'a option b' should not cause 'option b' to fire
465
+ // even though 'option b' is part of the other sequence
466
+ //
467
+ // any sequences that do not match here will be discarded
468
+ // below by the _resetSequences call
469
+ if (callbacks[i].level != maxLevel) {
470
+ continue;
471
+ }
472
+
473
+ processedSequenceCallback = true;
430
474
 
431
475
  // keep a list of which sequences were matches for later
432
476
  doNotReset[callbacks[i].seq] = 1;
@@ -436,16 +480,24 @@
436
480
 
437
481
  // if there were no sequence matches but we are still here
438
482
  // that means this is a regular match so we should fire that
439
- if (!processedSequenceCallback && !_sequenceType) {
483
+ if (!processedSequenceCallback) {
440
484
  _fireCallback(callbacks[i].callback, e, callbacks[i].combo);
441
485
  }
442
486
  }
443
487
 
444
- // if you are inside of a sequence and the key you are pressing
445
- // is not a modifier key then we should reset all sequences
446
- // that were not matched by this key event
447
- if (e.type == _sequenceType && !_isModifier(character)) {
448
- _resetSequences(doNotReset, maxLevel);
488
+ // if the key you pressed matches the type of sequence without
489
+ // being a modifier (ie "keyup" or "keypress") then we should
490
+ // reset all sequences that were not matched by this event
491
+ //
492
+ // this is so, for example, if you have the sequence "h a t" and you
493
+ // type "h e a r t" it does not match. in this case the "e" will
494
+ // cause the sequence to reset
495
+ //
496
+ // modifier keys are ignored because you can have a sequence
497
+ // that contains modifiers such as "enter ctrl+space" and in most
498
+ // cases the modifier key will be pressed before the next key
499
+ if (e.type == _nextExpectedAction && !_isModifier(character)) {
500
+ _resetSequences(doNotReset);
449
501
  }
450
502
  }
451
503
 
@@ -455,7 +507,7 @@
455
507
  * @param {Event} e
456
508
  * @returns void
457
509
  */
458
- function _handleKey(e) {
510
+ function _handleKeyEvent(e) {
459
511
 
460
512
  // normalize e.which for key events
461
513
  // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion
@@ -475,7 +527,7 @@
475
527
  return;
476
528
  }
477
529
 
478
- _handleCharacter(character, e);
530
+ Mousetrap.handleKey(character, _eventModifiers(e), e);
479
531
  }
480
532
 
481
533
  /**
@@ -565,90 +617,89 @@
565
617
  // and setting the level to 0
566
618
  _sequenceLevels[combo] = 0;
567
619
 
568
- // if there is no action pick the best one for the first key
569
- // in the sequence
570
- if (!action) {
571
- action = _pickBestAction(keys[0], []);
572
- }
573
-
574
620
  /**
575
621
  * callback to increase the sequence level for this sequence and reset
576
622
  * all other sequences that were active
577
623
  *
578
- * @param {Event} e
579
- * @returns void
624
+ * @param {string} nextAction
625
+ * @returns {Function}
580
626
  */
581
- var _increaseSequence = function(e) {
582
- _sequenceType = action;
627
+ function _increaseSequence(nextAction) {
628
+ return function() {
629
+ _nextExpectedAction = nextAction;
583
630
  ++_sequenceLevels[combo];
584
631
  _resetSequenceTimer();
585
- },
586
-
587
- /**
588
- * wraps the specified callback inside of another function in order
589
- * to reset all sequence counters as soon as this sequence is done
590
- *
591
- * @param {Event} e
592
- * @returns void
593
- */
594
- _callbackAndReset = function(e) {
595
- _fireCallback(callback, e, combo);
596
-
597
- // we should ignore the next key up if the action is key down
598
- // or keypress. this is so if you finish a sequence and
599
- // release the key the final key will not trigger a keyup
600
- if (action !== 'keyup') {
601
- _ignoreNextKeyup = _characterFromEvent(e);
602
- }
632
+ };
633
+ }
603
634
 
604
- // weird race condition if a sequence ends with the key
605
- // another sequence begins with
606
- setTimeout(_resetSequences, 10);
607
- },
608
- i;
635
+ /**
636
+ * wraps the specified callback inside of another function in order
637
+ * to reset all sequence counters as soon as this sequence is done
638
+ *
639
+ * @param {Event} e
640
+ * @returns void
641
+ */
642
+ function _callbackAndReset(e) {
643
+ _fireCallback(callback, e, combo);
644
+
645
+ // we should ignore the next key up if the action is key down
646
+ // or keypress. this is so if you finish a sequence and
647
+ // release the key the final key will not trigger a keyup
648
+ if (action !== 'keyup') {
649
+ _ignoreNextKeyup = _characterFromEvent(e);
650
+ }
651
+
652
+ // weird race condition if a sequence ends with the key
653
+ // another sequence begins with
654
+ setTimeout(_resetSequences, 10);
655
+ }
609
656
 
610
657
  // loop through keys one at a time and bind the appropriate callback
611
658
  // function. for any key leading up to the final one it should
612
659
  // increase the sequence. after the final, it should reset all sequences
613
- for (i = 0; i < keys.length; ++i) {
614
- _bindSingle(keys[i], i < keys.length - 1 ? _increaseSequence : _callbackAndReset, action, combo, i);
660
+ //
661
+ // if an action is specified in the original bind call then that will
662
+ // be used throughout. otherwise we will pass the action that the
663
+ // next key in the sequence should match. this allows a sequence
664
+ // to mix and match keypress and keydown events depending on which
665
+ // ones are better suited to the key provided
666
+ for (var i = 0; i < keys.length; ++i) {
667
+ var isFinal = i + 1 === keys.length;
668
+ var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);
669
+ _bindSingle(keys[i], wrappedCallback, action, combo, i);
615
670
  }
616
671
  }
617
672
 
618
673
  /**
619
- * binds a single keyboard combination
674
+ * Converts from a string key combination to an array
620
675
  *
621
- * @param {string} combination
622
- * @param {Function} callback
623
- * @param {string=} action
624
- * @param {string=} sequenceName - name of sequence if part of sequence
625
- * @param {number=} level - what part of the sequence the command is
626
- * @returns void
676
+ * @param {string} combination like "command+shift+l"
677
+ * @return {Array}
627
678
  */
628
- function _bindSingle(combination, callback, action, sequenceName, level) {
629
-
630
- // store a direct mapped reference for use with Mousetrap.trigger
631
- _directMap[combination + ':' + action] = callback;
679
+ function _keysFromString(combination) {
680
+ if (combination === '+') {
681
+ return ['+'];
682
+ }
632
683
 
633
- // make sure multiple spaces in a row become a single space
634
- combination = combination.replace(/\s+/g, ' ');
684
+ return combination.split('+');
685
+ }
635
686
 
636
- var sequence = combination.split(' '),
637
- i,
687
+ /**
688
+ * Gets info for a specific key combination
689
+ *
690
+ * @param {string} combination key combination ("command+s" or "a" or "*")
691
+ * @param {string=} action
692
+ * @returns {Object}
693
+ */
694
+ function _getKeyInfo(combination, action) {
695
+ var keys,
638
696
  key,
639
- keys,
697
+ i,
640
698
  modifiers = [];
641
699
 
642
- // if this pattern is a sequence of keys then run through this method
643
- // to reprocess each pattern one key at a time
644
- if (sequence.length > 1) {
645
- _bindSequence(combination, sequence, callback, action);
646
- return;
647
- }
648
-
649
700
  // take the keys from this pattern and figure out what the actual
650
701
  // pattern is all about
651
- keys = combination === '+' ? ['+'] : combination.split('+');
702
+ keys = _keysFromString(combination);
652
703
 
653
704
  for (i = 0; i < keys.length; ++i) {
654
705
  key = keys[i];
@@ -676,14 +727,49 @@
676
727
  // we will try to pick the best event for it
677
728
  action = _pickBestAction(key, modifiers, action);
678
729
 
730
+ return {
731
+ key: key,
732
+ modifiers: modifiers,
733
+ action: action
734
+ };
735
+ }
736
+
737
+ /**
738
+ * binds a single keyboard combination
739
+ *
740
+ * @param {string} combination
741
+ * @param {Function} callback
742
+ * @param {string=} action
743
+ * @param {string=} sequenceName - name of sequence if part of sequence
744
+ * @param {number=} level - what part of the sequence the command is
745
+ * @returns void
746
+ */
747
+ function _bindSingle(combination, callback, action, sequenceName, level) {
748
+
749
+ // store a direct mapped reference for use with Mousetrap.trigger
750
+ _directMap[combination + ':' + action] = callback;
751
+
752
+ // make sure multiple spaces in a row become a single space
753
+ combination = combination.replace(/\s+/g, ' ');
754
+
755
+ var sequence = combination.split(' '),
756
+ info;
757
+
758
+ // if this pattern is a sequence of keys then run through this method
759
+ // to reprocess each pattern one key at a time
760
+ if (sequence.length > 1) {
761
+ _bindSequence(combination, sequence, callback, action);
762
+ return;
763
+ }
764
+
765
+ info = _getKeyInfo(combination, action);
766
+
679
767
  // make sure to initialize array if this is the first time
680
768
  // a callback is added for this key
681
- if (!_callbacks[key]) {
682
- _callbacks[key] = [];
683
- }
769
+ _callbacks[info.key] = _callbacks[info.key] || [];
684
770
 
685
771
  // remove an existing match if there is one
686
- _getMatches(key, modifiers, {type: action}, !sequenceName, combination);
772
+ _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);
687
773
 
688
774
  // add this call back to the array
689
775
  // if it is a sequence put it at the beginning
@@ -691,10 +777,10 @@
691
777
  //
692
778
  // this is important because the way these are processed expects
693
779
  // the sequence ones to come first
694
- _callbacks[key][sequenceName ? 'unshift' : 'push']({
780
+ _callbacks[info.key][sequenceName ? 'unshift' : 'push']({
695
781
  callback: callback,
696
- modifiers: modifiers,
697
- action: action,
782
+ modifiers: info.modifiers,
783
+ action: info.action,
698
784
  seq: sequenceName,
699
785
  level: level,
700
786
  combo: combination
@@ -716,9 +802,9 @@
716
802
  }
717
803
 
718
804
  // start!
719
- _addEvent(document, 'keypress', _handleKey);
720
- _addEvent(document, 'keydown', _handleKey);
721
- _addEvent(document, 'keyup', _handleKey);
805
+ _addEvent(document, 'keypress', _handleKeyEvent);
806
+ _addEvent(document, 'keydown', _handleKeyEvent);
807
+ _addEvent(document, 'keyup', _handleKeyEvent);
722
808
 
723
809
  var Mousetrap = {
724
810
 
@@ -772,7 +858,7 @@
772
858
  */
773
859
  trigger: function(keys, action) {
774
860
  if (_directMap[keys + ':' + action]) {
775
- _directMap[keys + ':' + action]();
861
+ _directMap[keys + ':' + action]({}, keys);
776
862
  }
777
863
  return this;
778
864
  },
@@ -797,7 +883,7 @@
797
883
  * @param {Element} element
798
884
  * @return {boolean}
799
885
  */
800
- stopCallback: function(e, element, combo) {
886
+ stopCallback: function(e, element) {
801
887
 
802
888
  // if the element has the class "mousetrap" then no need to stop
803
889
  if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {
@@ -806,7 +892,12 @@
806
892
 
807
893
  // stop for input, select, and textarea
808
894
  return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || (element.contentEditable && element.contentEditable == 'true');
809
- }
895
+ },
896
+
897
+ /**
898
+ * exposes _handleKey publicly so it can be overwritten by extensions
899
+ */
900
+ handleKey: _handleKey
810
901
  };
811
902
 
812
903
  // expose mousetrap to the global object
metadata CHANGED
@@ -1,128 +1,124 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mousetrap-rails
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.0.9
4
+ version: 0.0.10
6
5
  platform: ruby
7
6
  authors:
8
7
  - Nick Kugaevsky
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain:
12
- - !binary |-
13
- LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURNRENDQWhpZ0F3SUJB
14
- Z0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREErTVEwd0N3WURWUVFEREFSdWFX
15
- TnIKTVJrd0Z3WUtDWkltaVpQeUxHUUJHUllKYTNWbllXVjJjMnQ1TVJJd0VB
16
- WUtDWkltaVpQeUxHUUJHUllDY25VdwpIaGNOTVRNd01UTXhNVGd4TWpNd1do
17
- Y05NVFF3TVRNeE1UZ3hNak13V2pBK01RMHdDd1lEVlFRRERBUnVhV05yCk1S
18
- a3dGd1lLQ1pJbWlaUHlMR1FCR1JZSmEzVm5ZV1YyYzJ0NU1SSXdFQVlLQ1pJ
19
- bWlaUHlMR1FCR1JZQ2NuVXcKZ2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJ
20
- QkR3QXdnZ0VLQW9JQkFRQzNTUzAxcnNJNU4zRVVHM2JTbmZJMgpwcjRFeHg5
21
- Z0tDQlM1SXhWN090K3BRMnBzSWlXb2VuYVM0ZlMyZnNtdmxlOTJDbEV4M05i
22
- VXFueHhHREVTMEViCkZrTkh5QUg5VndPMzZ2UzBsb052L094MnNTYWxlVU5W
23
- M0pkdmNQMUdtM3hHdG45S1dOY3B1QXdQZk1sNUJTWWcKSzRXVTh6SWtiTGx3
24
- bXJPNmg4NUlZWnJEd3FnaGI2T0NPd2hiNTZkNGJ5am9KRTI1YnJVeEVUeEdW
25
- ZHN1VkNEcgpFUXJvUytEMkJpTUFFZHdKY24vUGVwTXgzbHQrdGVacmpVb2Vp
26
- NVVYSWNuWjI4VVlTbm1Yalhua3lTbFBYelJWCnNpTHdVTUFnR3U2NjVodVVF
27
- NVM4aWRXN29oU0hUSnYva0g5OEJvaVdpN2dpOUhGTXo0T0pNTWVSNXJaazc2
28
- UWwKQWdNQkFBR2pPVEEzTUFrR0ExVWRFd1FDTUFBd0hRWURWUjBPQkJZRUZD
29
- ZElLa0I5bForY29tMHdMQmhMUURXZQpZbmJ2TUFzR0ExVWREd1FFQXdJRXNE
30
- QU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFOT3ViRmRkcHpNWEpmbFB2CnZY
31
- WG5XWFl2WksyZXRTeHp3ZXdYWE9oY2J6d1N4ZFUwVDROYktjcmxobEZialVE
32
- aC94RjRRemMxZEI5T0ZHOXIKZmZJVUt2MEp0RXlHTS9tT2FJU3NOcCtvWVVs
33
- WHhYTE5Pc1g4TFQxciszMzd0UTYyN0dvWC9aMFJMNXU4TXo2UQpLWlVKaEdR
34
- S05uSXA2Umt6NnNwNFpoMmFxVEx0OEJERUE4NmtPKzB2NExhVkxxRkVtTFR5
35
- cGY3QzU2OFJUWWxtCk44TGFSRVFNTTVZZHZDSVlXczVDNmlOUlZhRGhUOGJr
36
- dVdOaHRCaXMwSDdZRkFmc1cxcm45bnA4T1E3blkyYXoKOGROUXJCbEt6Yy9S
37
- THdHR0ZUMWdqelZsSWI3L3h0TmRNZEpRNkp3eWxqU0o3MFBiS0FBemdCUmRE
38
- TFB0OUJXdAozQUg5bXc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
39
- date: 2013-02-08 00:00:00.000000000 Z
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDMDCCAhigAwIBAgIBADANBgkqhkiG9w0BAQUFADA+MQ0wCwYDVQQDDARuaWNr
14
+ MRkwFwYKCZImiZPyLGQBGRYJa3VnYWV2c2t5MRIwEAYKCZImiZPyLGQBGRYCcnUw
15
+ HhcNMTMwMTMxMTgxMjMwWhcNMTQwMTMxMTgxMjMwWjA+MQ0wCwYDVQQDDARuaWNr
16
+ MRkwFwYKCZImiZPyLGQBGRYJa3VnYWV2c2t5MRIwEAYKCZImiZPyLGQBGRYCcnUw
17
+ ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3SS01rsI5N3EUG3bSnfI2
18
+ pr4Exx9gKCBS5IxV7Ot+pQ2psIiWoenaS4fS2fsmvle92ClEx3NbUqnxxGDES0Eb
19
+ FkNHyAH9VwO36vS0loNv/Ox2sSaleUNV3JdvcP1Gm3xGtn9KWNcpuAwPfMl5BSYg
20
+ K4WU8zIkbLlwmrO6h85IYZrDwqghb6OCOwhb56d4byjoJE25brUxETxGVdsuVCDr
21
+ EQroS+D2BiMAEdwJcn/PepMx3lt+teZrjUoei5UXIcnZ28UYSnmXjXnkySlPXzRV
22
+ siLwUMAgGu665huUE5S8idW7ohSHTJv/kH98BoiWi7gi9HFMz4OJMMeR5rZk76Ql
23
+ AgMBAAGjOTA3MAkGA1UdEwQCMAAwHQYDVR0OBBYEFCdIKkB9lZ+com0wLBhLQDWe
24
+ YnbvMAsGA1UdDwQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEANOubFddpzMXJflPv
25
+ vXXnWXYvZK2etSxzwewXXOhcbzwSxdU0T4NbKcrlhlFbjUDh/xF4Qzc1dB9OFG9r
26
+ ffIUKv0JtEyGM/mOaISsNp+oYUlXxXLNOsX8LT1r+337tQ627GoX/Z0RL5u8Mz6Q
27
+ KZUJhGQKNnIp6Rkz6sp4Zh2aqTLt8BDEA86kO+0v4LaVLqFEmLTypf7C568RTYlm
28
+ N8LaREQMM5YdvCIYWs5C6iNRVaDhT8bkuWNhtBis0H7YFAfsW1rn9np8OQ7nY2az
29
+ 8dNQrBlKzc/RLwGGFT1gjzVlIb7/xtNdMdJQ6JwyljSJ70PbKAAzgBRdDLPt9BWt
30
+ 3AH9mw==
31
+ -----END CERTIFICATE-----
32
+ date: 2013-06-02 00:00:00.000000000 Z
40
33
  dependencies:
41
34
  - !ruby/object:Gem::Dependency
42
35
  name: rails
43
36
  requirement: !ruby/object:Gem::Requirement
44
- none: false
45
37
  requirements:
46
38
  - - ~>
47
39
  - !ruby/object:Gem::Version
48
- version: 3.2.11
40
+ version: 3.2.12
49
41
  type: :development
42
+ prerelease: false
50
43
  version_requirements: !ruby/object:Gem::Requirement
51
- none: false
52
44
  requirements:
53
45
  - - ~>
54
46
  - !ruby/object:Gem::Version
55
- version: 3.2.11
56
- prerelease: false
47
+ version: 3.2.12
57
48
  - !ruby/object:Gem::Dependency
58
49
  name: sqlite3
59
50
  requirement: !ruby/object:Gem::Requirement
60
- none: false
61
51
  requirements:
62
52
  - - ~>
63
53
  - !ruby/object:Gem::Version
64
54
  version: 1.3.5
65
55
  type: :development
56
+ prerelease: false
66
57
  version_requirements: !ruby/object:Gem::Requirement
67
- none: false
68
58
  requirements:
69
59
  - - ~>
70
60
  - !ruby/object:Gem::Version
71
61
  version: 1.3.5
72
- prerelease: false
73
62
  - !ruby/object:Gem::Dependency
74
63
  name: rspec-rails
75
64
  requirement: !ruby/object:Gem::Requirement
76
- none: false
77
65
  requirements:
78
66
  - - ~>
79
67
  - !ruby/object:Gem::Version
80
- version: 2.12.0
68
+ version: 2.13.0
81
69
  type: :development
70
+ prerelease: false
82
71
  version_requirements: !ruby/object:Gem::Requirement
83
- none: false
84
72
  requirements:
85
73
  - - ~>
86
74
  - !ruby/object:Gem::Version
87
- version: 2.12.0
88
- prerelease: false
75
+ version: 2.13.0
89
76
  - !ruby/object:Gem::Dependency
90
77
  name: genspec
91
78
  requirement: !ruby/object:Gem::Requirement
92
- none: false
93
79
  requirements:
94
80
  - - ~>
95
81
  - !ruby/object:Gem::Version
96
82
  version: 0.2.7
97
83
  type: :development
84
+ prerelease: false
98
85
  version_requirements: !ruby/object:Gem::Requirement
99
- none: false
100
86
  requirements:
101
87
  - - ~>
102
88
  - !ruby/object:Gem::Version
103
89
  version: 0.2.7
104
- prerelease: false
105
90
  - !ruby/object:Gem::Dependency
106
91
  name: sass
107
92
  requirement: !ruby/object:Gem::Requirement
108
- none: false
109
93
  requirements:
110
94
  - - ~>
111
95
  - !ruby/object:Gem::Version
112
96
  version: 3.2.1
113
97
  type: :development
98
+ prerelease: false
114
99
  version_requirements: !ruby/object:Gem::Requirement
115
- none: false
116
100
  requirements:
117
101
  - - ~>
118
102
  - !ruby/object:Gem::Version
119
103
  version: 3.2.1
104
+ - !ruby/object:Gem::Dependency
105
+ name: coveralls
106
+ requirement: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ type: :development
120
112
  prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
121
118
  description: Mousetrap is a javascript library for handling keyboard shortcuts in
122
119
  your web applications. This gem integrates Mousetrap with Rails asset pipeline for
123
120
  easy of use.
124
- email:
125
- - nick@kugaevsky.ru
121
+ email: nick@kugaevsky.ru
126
122
  executables: []
127
123
  extensions: []
128
124
  extra_rdoc_files: []
@@ -189,35 +185,28 @@ homepage: http://kugaevsky.github.com/mousetrap-rails
189
185
  licenses:
190
186
  - MIT
191
187
  - Apache
192
- post_install_message: ! "\n\e[33mRemember to run generator to generate sample file
193
- and include mousetrap-rails with Rails Asset Pipeline\e[0m\n\n \e[32m$ rails
194
- generate mousetrap:install \e[0m\n\n"
188
+ metadata: {}
189
+ post_install_message: "\n\e[33mRemember to run generator to generate sample file and
190
+ include mousetrap-rails with Rails Asset Pipeline\e[0m\n\n \e[32m$ rails generate
191
+ mousetrap:install \e[0m\n\n"
195
192
  rdoc_options: []
196
193
  require_paths:
197
194
  - lib
198
195
  required_ruby_version: !ruby/object:Gem::Requirement
199
- none: false
200
196
  requirements:
201
- - - ! '>='
197
+ - - '>='
202
198
  - !ruby/object:Gem::Version
203
- segments:
204
- - 0
205
- hash: 3850591978535415950
206
199
  version: '0'
207
200
  required_rubygems_version: !ruby/object:Gem::Requirement
208
- none: false
209
201
  requirements:
210
- - - ! '>='
202
+ - - '>='
211
203
  - !ruby/object:Gem::Version
212
- segments:
213
- - 0
214
- hash: 3850591978535415950
215
204
  version: '0'
216
205
  requirements: []
217
206
  rubyforge_project:
218
- rubygems_version: 1.8.24
207
+ rubygems_version: 2.0.3
219
208
  signing_key:
220
- specification_version: 3
209
+ specification_version: 4
221
210
  summary: Integrate Mousetrap javascript library with Rails Asset Pipeline
222
211
  test_files:
223
212
  - spec/dummy/.rspec
metadata.gz.sig CHANGED
Binary file