angular-hotkeys-rails 0.0.1

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: 00d0bb733f8c9b0d5b90e2a30f01240339be635d
4
+ data.tar.gz: 0a7c9916b1e0636494dabea7cb482aedfcd74809
5
+ SHA512:
6
+ metadata.gz: ff74e2fa1a3da3f9dadcc2169cb9448714ba22385e38cc62cbe99a556cc445806424617dcd52e28b5b595e1cb3c9d46046feaf110040969d52681ab7a71cc722
7
+ data.tar.gz: 86be4b2c282823ec9447aa7897da3afffb285a9dc60a9b2ddd9cc190c2c416ffa2de313184f57e094b7cbdb1c39def6846bea34c1113143e5b9bd5d6b252c4f2
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Anton Shemerey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,64 @@
1
+ # Angular::Hotkeys::Rails
2
+ ================
3
+
4
+ Configuration-centric keyboard shortcuts for your Rails + Angular apps, with
5
+ powerful [Mousetrap](https://github.com/ccampbell/mousetrap) under the hood.
6
+
7
+ This gem is just a simple wrapper around this two awesome libraries
8
+
9
+ * [Mousetrap](https://github.com/ccampbell/mousetrap)
10
+ * [angular-hotkeys](https://github.com/chieffancypants/angular-hotkeys)
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ gem 'angular-hotkeys-rails'
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Now you are able to add this awesome feature into your product by adding following lines:
23
+
24
+ ```coffeescript
25
+ //= require angular/hotkeys # ---> application.js
26
+ ```
27
+
28
+ ```css
29
+ *= require angular/hotkeys # ---> application.css
30
+ ```
31
+
32
+ ### Usage:
33
+
34
+ You can either define hotkeys in your Controller, or in your Route
35
+ configuration (or both). To start, though, require the lib as a dependency for
36
+ your angular app:
37
+
38
+ ```js
39
+ angular.module('myApp', ['ngRoute', 'cfp.hotkeys']);
40
+ ```
41
+
42
+ Now you could easily check it out by pressing `Cmd` + `?`
43
+
44
+ Behind the scenes, there is [Mousetrap](https://github.com/ccampbell/mousetrap) library to manage the key
45
+ bindings. Check out the docs there for more information on what kind of key
46
+ combinations can be used.
47
+
48
+ You could find more examples on the following link [Examples](https://github.com/chieffancypants/angular-hotkeys#usage)
49
+
50
+ ## Dependency
51
+
52
+ Please take into account this library take care only about
53
+ [Mousetrap](https://github.com/ccampbell/mousetrap) dependency, under the hood it depends on
54
+ [mousetrap-rails](https://github.com/kugaevsky/mousetrap-rails). That basically means you still have to add `Angular JS` manually.
55
+
56
+ You could consider to add [angularjs-rails](https://github.com/hiravgandhi/angularjs-rails) it works perfectly fine.
57
+
58
+ ## Contributing
59
+
60
+ 1. Fork it ( https://github.com/shemerey/angular-hotkeys-rails/fork )
61
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
62
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
63
+ 4. Push to the branch (`git push origin my-new-feature`)
64
+ 5. Create a new Pull Request
@@ -0,0 +1,11 @@
1
+ require "angular/hotkeys/rails/version"
2
+ require "mousetrap-rails"
3
+
4
+ module Angular
5
+ module Hotkeys
6
+ module Rails
7
+ class Engine < ::Rails::Engine
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module Angular
2
+ module Hotkeys
3
+ module Rails
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,552 @@
1
+ /*
2
+ * angular-hotkeys
3
+ *
4
+ * Automatic keyboard shortcuts for your angular apps
5
+ *
6
+ * (c) 2014 Wes Cruver
7
+ * License: MIT
8
+ */
9
+ //= require mousetrap
10
+
11
+ (function() {
12
+
13
+ 'use strict';
14
+
15
+ angular.module('cfp.hotkeys', []).provider('hotkeys', function() {
16
+
17
+ /**
18
+ * Configurable setting to disable the cheatsheet entirely
19
+ * @type {Boolean}
20
+ */
21
+ this.includeCheatSheet = true;
22
+
23
+ /**
24
+ * Cheat sheet template in the event you want to totally customize it.
25
+ * @type {String}
26
+ */
27
+ this.template = '<div class="cfp-hotkeys-container fade" ng-class="{in: helpVisible}" style="display: none;"><div class="cfp-hotkeys">' +
28
+ '<h4 class="cfp-hotkeys-title">{{ title }}</h4>' +
29
+ '<table><tbody>' +
30
+ '<tr ng-repeat="hotkey in hotkeys | filter:{ description: \'!$$undefined$$\' }">' +
31
+ '<td class="cfp-hotkeys-keys">' +
32
+ '<span ng-repeat="key in hotkey.format() track by $index" class="cfp-hotkeys-key">{{ key }}</span>' +
33
+ '</td>' +
34
+ '<td class="cfp-hotkeys-text">{{ hotkey.description }}</td>' +
35
+ '</tr>' +
36
+ '</tbody></table>' +
37
+ '<div class="cfp-hotkeys-close" ng-click="toggleCheatSheet()">×</div>' +
38
+ '</div></div>';
39
+
40
+ /**
41
+ * Configurable setting for the cheat sheet hotkey
42
+ * @type {String}
43
+ */
44
+ this.cheatSheetHotkey = '?';
45
+
46
+ /**
47
+ * Configurable setting for the cheat sheet description
48
+ * @type {String}
49
+ */
50
+ this.cheatSheetDescription = 'Show / hide this help menu';
51
+
52
+ this.$get = ['$rootElement', '$rootScope', '$compile', '$window', '$document', function ($rootElement, $rootScope, $compile, $window, $document) {
53
+
54
+ // monkeypatch Mousetrap's stopCallback() function
55
+ // this version doesn't return true when the element is an INPUT, SELECT, or TEXTAREA
56
+ // (instead we will perform this check per-key in the _add() method)
57
+ Mousetrap.stopCallback = function(event, element) {
58
+ // if the element has the class "mousetrap" then no need to stop
59
+ if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {
60
+ return false;
61
+ }
62
+
63
+ return (element.contentEditable && element.contentEditable == 'true');
64
+ };
65
+
66
+ /**
67
+ * Convert strings like cmd into symbols like ⌘
68
+ * @param {String} combo Key combination, e.g. 'mod+f'
69
+ * @return {String} The key combination with symbols
70
+ */
71
+ function symbolize (combo) {
72
+ var map = {
73
+ command : '⌘',
74
+ shift : '⇧',
75
+ left : '←',
76
+ right : '→',
77
+ up : '↑',
78
+ down : '↓',
79
+ 'return' : '↩',
80
+ backspace : '⌫'
81
+ };
82
+ combo = combo.split('+');
83
+
84
+ for (var i = 0; i < combo.length; i++) {
85
+ // try to resolve command / ctrl based on OS:
86
+ if (combo[i] === 'mod') {
87
+ if ($window.navigator && $window.navigator.platform.indexOf('Mac') >=0 ) {
88
+ combo[i] = 'command';
89
+ } else {
90
+ combo[i] = 'ctrl';
91
+ }
92
+ }
93
+
94
+ combo[i] = map[combo[i]] || combo[i];
95
+ }
96
+
97
+ return combo.join(' + ');
98
+ }
99
+
100
+ /**
101
+ * Hotkey object used internally for consistency
102
+ *
103
+ * @param {array} combo The keycombo. it's an array to support multiple combos
104
+ * @param {String} description Description for the keycombo
105
+ * @param {Function} callback function to execute when keycombo pressed
106
+ * @param {string} action the type of event to listen for (for mousetrap)
107
+ * @param {array} allowIn an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')
108
+ * @param {Boolean} persistent Whether the hotkey persists navigation events
109
+ */
110
+ function Hotkey (combo, description, callback, action, allowIn, persistent) {
111
+ // TODO: Check that the values are sane because we could
112
+ // be trying to instantiate a new Hotkey with outside dev's
113
+ // supplied values
114
+
115
+ this.combo = combo instanceof Array ? combo : [combo];
116
+ this.description = description;
117
+ this.callback = callback;
118
+ this.action = action;
119
+ this.allowIn = allowIn;
120
+ this.persistent = persistent;
121
+ }
122
+
123
+ /**
124
+ * Helper method to format (symbolize) the key combo for display
125
+ *
126
+ * @return {[Array]} An array of the key combination sequence
127
+ * for example: "command+g c i" becomes ["⌘ + g", "c", "i"]
128
+ *
129
+ * TODO: this gets called a lot. We should cache the result
130
+ */
131
+ Hotkey.prototype.format = function() {
132
+
133
+ // Don't show all the possible key combos, just the first one. Not sure
134
+ // of usecase here, so open a ticket if my assumptions are wrong
135
+ var combo = this.combo[0];
136
+
137
+ var sequence = combo.split(/[\s]/);
138
+ for (var i = 0; i < sequence.length; i++) {
139
+ sequence[i] = symbolize(sequence[i]);
140
+ }
141
+
142
+ return sequence;
143
+ };
144
+
145
+ /**
146
+ * A new scope used internally for the cheatsheet
147
+ * @type {$rootScope.Scope}
148
+ */
149
+ var scope = $rootScope.$new();
150
+
151
+ /**
152
+ * Holds an array of Hotkey objects currently bound
153
+ * @type {Array}
154
+ */
155
+ scope.hotkeys = [];
156
+
157
+ /**
158
+ * Contains the state of the help's visibility
159
+ * @type {Boolean}
160
+ */
161
+ scope.helpVisible = false;
162
+
163
+ /**
164
+ * Holds the title string for the help menu
165
+ * @type {String}
166
+ */
167
+ scope.title = 'Keyboard Shortcuts:';
168
+
169
+ /**
170
+ * Expose toggleCheatSheet to hotkeys scope so we can call it using
171
+ * ng-click from the template
172
+ * @type {function}
173
+ */
174
+ scope.toggleCheatSheet = toggleCheatSheet;
175
+
176
+
177
+ /**
178
+ * Holds references to the different scopes that have bound hotkeys
179
+ * attached. This is useful to catch when the scopes are `$destroy`d and
180
+ * then automatically unbind the hotkey.
181
+ *
182
+ * @type {Array}
183
+ */
184
+ var boundScopes = [];
185
+
186
+
187
+ $rootScope.$on('$routeChangeSuccess', function (event, route) {
188
+ purgeHotkeys();
189
+
190
+ if (route.hotkeys) {
191
+ angular.forEach(route.hotkeys, function (hotkey) {
192
+ // a string was given, which implies this is a function that is to be
193
+ // $eval()'d within that controller's scope
194
+ // TODO: hotkey here is super confusing. sometimes a function (that gets turned into an array), sometimes a string
195
+ var callback = hotkey[2];
196
+ if (typeof(callback) === 'string' || callback instanceof String) {
197
+ hotkey[2] = [callback, route];
198
+ }
199
+
200
+ // todo: perform check to make sure not already defined:
201
+ // this came from a route, so it's likely not meant to be persistent
202
+ hotkey[5] = false;
203
+ _add.apply(this, hotkey);
204
+ });
205
+ }
206
+ });
207
+
208
+
209
+ // Auto-create a help menu:
210
+ if (this.includeCheatSheet) {
211
+ var document = $document[0];
212
+ var element = $rootElement[0];
213
+ var helpMenu = angular.element(this.template);
214
+ _add(this.cheatSheetHotkey, this.cheatSheetDescription, toggleCheatSheet);
215
+
216
+ // If $rootElement is document or documentElement, then body must be used
217
+ if (element === document || element === document.documentElement) {
218
+ element = document.body;
219
+ }
220
+
221
+ angular.element(element).append($compile(helpMenu)(scope));
222
+ }
223
+
224
+
225
+ /**
226
+ * Purges all non-persistent hotkeys (such as those defined in routes)
227
+ *
228
+ * Without this, the same hotkey would get recreated everytime
229
+ * the route is accessed.
230
+ */
231
+ function purgeHotkeys() {
232
+ var i = scope.hotkeys.length;
233
+ while (i--) {
234
+ var hotkey = scope.hotkeys[i];
235
+ if (hotkey && !hotkey.persistent) {
236
+ _del(hotkey);
237
+ }
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Toggles the help menu element's visiblity
243
+ */
244
+ var previousEsc = false;
245
+
246
+ function toggleCheatSheet() {
247
+ scope.helpVisible = !scope.helpVisible;
248
+
249
+ // Bind to esc to remove the cheat sheet. Ideally, this would be done
250
+ // as a directive in the template, but that would create a nasty
251
+ // circular dependency issue that I don't feel like sorting out.
252
+ if (scope.helpVisible) {
253
+ previousEsc = _get('esc');
254
+ _del('esc');
255
+
256
+ // Here's an odd way to do this: we're going to use the original
257
+ // description of the hotkey on the cheat sheet so that it shows up.
258
+ // without it, no entry for esc will ever show up (#22)
259
+ _add('esc', previousEsc.description, toggleCheatSheet);
260
+ } else {
261
+ _del('esc');
262
+
263
+ // restore the previously bound ESC key
264
+ if (previousEsc !== false) {
265
+ _add(previousEsc);
266
+ }
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Creates a new Hotkey and creates the Mousetrap binding
272
+ *
273
+ * @param {string} combo mousetrap key binding
274
+ * @param {string} description description for the help menu
275
+ * @param {Function} callback method to call when key is pressed
276
+ * @param {string} action the type of event to listen for (for mousetrap)
277
+ * @param {array} allowIn an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')
278
+ * @param {boolean} persistent if true, the binding is preserved upon route changes
279
+ */
280
+ function _add (combo, description, callback, action, allowIn, persistent) {
281
+
282
+ // used to save original callback for "allowIn" wrapping:
283
+ var _callback;
284
+
285
+ // these elements are prevented by the default Mousetrap.stopCallback():
286
+ var preventIn = ['INPUT', 'SELECT', 'TEXTAREA'];
287
+
288
+ // Determine if object format was given:
289
+ var objType = Object.prototype.toString.call(combo);
290
+
291
+ if (objType === '[object Object]') {
292
+ description = combo.description;
293
+ callback = combo.callback;
294
+ action = combo.action;
295
+ persistent = combo.persistent;
296
+ allowIn = combo.allowIn;
297
+ combo = combo.combo;
298
+ }
299
+
300
+ // description is optional:
301
+ if (description instanceof Function) {
302
+ action = callback;
303
+ callback = description;
304
+ description = '$$undefined$$';
305
+ } else if (angular.isUndefined(description)) {
306
+ description = '$$undefined$$';
307
+ }
308
+
309
+ // any items added through the public API are for controllers
310
+ // that persist through navigation, and thus undefined should mean
311
+ // true in this case.
312
+ if (persistent === undefined) {
313
+ persistent = true;
314
+ }
315
+
316
+ // if callback is defined, then wrap it in a function
317
+ // that checks if the event originated from a form element.
318
+ // the function blocks the callback from executing unless the element is specified
319
+ // in allowIn (emulates Mousetrap.stopCallback() on a per-key level)
320
+ if (typeof callback === 'function') {
321
+
322
+ // save the original callback
323
+ _callback = callback;
324
+
325
+ // make sure allowIn is an array
326
+ if (!(allowIn instanceof Array)) {
327
+ allowIn = [];
328
+ }
329
+
330
+ // remove anything from preventIn that's present in allowIn
331
+ var index;
332
+ for (var i=0; i < allowIn.length; i++) {
333
+ allowIn[i] = allowIn[i].toUpperCase();
334
+ index = preventIn.indexOf(allowIn[i]);
335
+ if (index !== -1) {
336
+ preventIn.splice(index, 1);
337
+ }
338
+ }
339
+
340
+ // create the new wrapper callback
341
+ callback = function(event) {
342
+ var shouldExecute = true;
343
+ var target = event.target || event.srcElement; // srcElement is IE only
344
+ var nodeName = target.nodeName.toUpperCase();
345
+
346
+ // check if the input has a mousetrap class, and skip checking preventIn if so
347
+ if ((' ' + target.className + ' ').indexOf(' mousetrap ') > -1) {
348
+ shouldExecute = true;
349
+ } else {
350
+ // don't execute callback if the event was fired from inside an element listed in preventIn
351
+ for (var i=0; i<preventIn.length; i++) {
352
+ if (preventIn[i] === nodeName) {
353
+ shouldExecute = false;
354
+ break;
355
+ }
356
+ }
357
+ }
358
+
359
+ if (shouldExecute) {
360
+ wrapApply(_callback.apply(this, arguments));
361
+ }
362
+ };
363
+ }
364
+
365
+ if (typeof(action) === 'string') {
366
+ Mousetrap.bind(combo, wrapApply(callback), action);
367
+ } else {
368
+ Mousetrap.bind(combo, wrapApply(callback));
369
+ }
370
+
371
+ var hotkey = new Hotkey(combo, description, callback, action, allowIn, persistent);
372
+ scope.hotkeys.push(hotkey);
373
+ return hotkey;
374
+ }
375
+
376
+ /**
377
+ * delete and unbind a Hotkey
378
+ *
379
+ * @param {mixed} hotkey Either the bound key or an instance of Hotkey
380
+ * @return {boolean} true if successful
381
+ */
382
+ function _del (hotkey) {
383
+ var combo = (hotkey instanceof Hotkey) ? hotkey.combo : hotkey;
384
+
385
+ Mousetrap.unbind(combo);
386
+
387
+ if (combo instanceof Array) {
388
+ var retStatus = true;
389
+ for (var i = 0; i < combo.length; i++) {
390
+ retStatus = _del(combo[i]) && retStatus;
391
+ }
392
+ return retStatus;
393
+ } else {
394
+ var index = scope.hotkeys.indexOf(_get(combo));
395
+
396
+ if (index > -1) {
397
+ // if the combo has other combos bound, don't unbind the whole thing, just the one combo:
398
+ if (scope.hotkeys[index].combo.length > 1) {
399
+ scope.hotkeys[index].combo.splice(scope.hotkeys[index].combo.indexOf(combo), 1);
400
+ } else {
401
+ scope.hotkeys.splice(index, 1);
402
+ }
403
+ return true;
404
+ }
405
+ }
406
+
407
+ return false;
408
+
409
+ }
410
+
411
+ /**
412
+ * Get a Hotkey object by key binding
413
+ *
414
+ * @param {[string]} combo the key the Hotkey is bound to
415
+ * @return {Hotkey} The Hotkey object
416
+ */
417
+ function _get (combo) {
418
+
419
+ var hotkey;
420
+
421
+ for (var i = 0; i < scope.hotkeys.length; i++) {
422
+ hotkey = scope.hotkeys[i];
423
+
424
+ if (hotkey.combo.indexOf(combo) > -1) {
425
+ return hotkey;
426
+ }
427
+ }
428
+
429
+ return false;
430
+ }
431
+
432
+ /**
433
+ * Binds the hotkey to a particular scope. Useful if the scope is
434
+ * destroyed, we can automatically destroy the hotkey binding.
435
+ *
436
+ * @param {Object} scope The scope to bind to
437
+ */
438
+ function bindTo (scope) {
439
+ // Add the scope to the list of bound scopes
440
+ boundScopes[scope.$id] = [];
441
+
442
+ scope.$on('$destroy', function () {
443
+ var i = boundScopes[scope.$id].length;
444
+ while (i--) {
445
+ _del(boundScopes[scope.$id][i]);
446
+ delete boundScopes[scope.$id][i];
447
+ }
448
+ });
449
+
450
+ // return an object with an add function so we can keep track of the
451
+ // hotkeys and their scope that we added via this chaining method
452
+ return {
453
+ add: function (args) {
454
+ var hotkey;
455
+
456
+ if (arguments.length > 1) {
457
+ hotkey = _add.apply(this, arguments);
458
+ } else {
459
+ hotkey = _add(args);
460
+ }
461
+
462
+ boundScopes[scope.$id].push(hotkey);
463
+ return this;
464
+ }
465
+ };
466
+ }
467
+
468
+ /**
469
+ * All callbacks sent to Mousetrap are wrapped using this function
470
+ * so that we can force a $scope.$apply()
471
+ *
472
+ * @param {Function} callback [description]
473
+ * @return {[type]} [description]
474
+ */
475
+ function wrapApply (callback) {
476
+ // return mousetrap a function to call
477
+ return function (event, combo) {
478
+
479
+ // if this is an array, it means we provided a route object
480
+ // because the scope wasn't available yet, so rewrap the callback
481
+ // now that the scope is available:
482
+ if (callback instanceof Array) {
483
+ var funcString = callback[0];
484
+ var route = callback[1];
485
+ callback = function (event) {
486
+ route.scope.$eval(funcString);
487
+ };
488
+ }
489
+
490
+ // this takes place outside angular, so we'll have to call
491
+ // $apply() to make sure angular's digest happens
492
+ $rootScope.$apply(function() {
493
+ // call the original hotkey callback with the keyboard event
494
+ callback(event, _get(combo));
495
+ });
496
+ };
497
+ }
498
+
499
+
500
+ var publicApi = {
501
+ add : _add,
502
+ del : _del,
503
+ get : _get,
504
+ bindTo : bindTo,
505
+ template : this.template,
506
+ toggleCheatSheet : toggleCheatSheet,
507
+ includeCheatSheat : this.includeCheatSheat,
508
+ cheatSheetHotkey : this.cheatSheetHotkey,
509
+ cheatSheetDescription : this.cheatSheetDescription,
510
+ purgeHotkeys : purgeHotkeys
511
+ };
512
+
513
+ return publicApi;
514
+
515
+ }];
516
+ })
517
+
518
+ .directive('hotkey', function (hotkeys) {
519
+ return {
520
+ restrict: 'A',
521
+ link: function (scope, el, attrs) {
522
+ var key, allowIn;
523
+
524
+ angular.forEach(scope.$eval(attrs.hotkey), function (func, hotkey) {
525
+ // split and trim the hotkeys string into array
526
+ allowIn = attrs.hotkeyAllowIn.split(/[\s,]+/);
527
+
528
+ key = hotkey;
529
+
530
+ hotkeys.add({
531
+ combo: hotkey,
532
+ description: attrs.hotkeyDescription,
533
+ callback: func,
534
+ action: attrs.hotkeyAction,
535
+ allowIn: allowIn
536
+ });
537
+ });
538
+
539
+ // remove the hotkey if the directive is destroyed:
540
+ el.bind('$destroy', function() {
541
+ hotkeys.del(key);
542
+ });
543
+ }
544
+ };
545
+ })
546
+
547
+ .run(function(hotkeys) {
548
+ // force hotkeys to run by injecting it. Without this, hotkeys only runs
549
+ // when a controller or something else asks for it via DI.
550
+ });
551
+
552
+ })();
@@ -0,0 +1,104 @@
1
+ .cfp-hotkeys-container {
2
+ display: table !important;
3
+ position: fixed;
4
+ width: 100%;
5
+ height: 100%;
6
+ top: 0;
7
+ left: 0;
8
+ color: #333;
9
+ font-size: 1em;
10
+ background-color: rgba(255,255,255,0.9);
11
+ }
12
+
13
+ .cfp-hotkeys-container.fade {
14
+ z-index: -1024;
15
+ visibility: hidden;
16
+ opacity: 0;
17
+ -webkit-transition: opacity 0.15s linear;
18
+ -moz-transition: opacity 0.15s linear;
19
+ -o-transition: opacity 0.15s linear;
20
+ transition: opacity 0.15s linear;
21
+ }
22
+
23
+ .cfp-hotkeys-container.fade.in {
24
+ z-index: 10002;
25
+ visibility: visible;
26
+ opacity: 1;
27
+ }
28
+
29
+ .cfp-hotkeys-title {
30
+ font-weight: bold;
31
+ text-align: center;
32
+ font-size: 1.2em;
33
+ }
34
+
35
+ .cfp-hotkeys {
36
+ width: 100%;
37
+ height: 100%;
38
+ display: table-cell;
39
+ vertical-align: middle;
40
+ }
41
+
42
+ .cfp-hotkeys table {
43
+ margin: auto;
44
+ color: #333;
45
+ }
46
+
47
+ .cfp-content {
48
+ display: table-cell;
49
+ vertical-align: middle;
50
+ }
51
+
52
+ .cfp-hotkeys-keys {
53
+ padding: 5px;
54
+ text-align: right;
55
+ }
56
+
57
+ .cfp-hotkeys-key {
58
+ display: inline-block;
59
+ color: #fff;
60
+ background-color: #333;
61
+ border: 1px solid #333;
62
+ border-radius: 5px;
63
+ text-align: center;
64
+ margin-right: 5px;
65
+ box-shadow: inset 0 1px 0 #666, 0 1px 0 #bbb;
66
+ padding: 5px 9px;
67
+ font-size: 1em;
68
+ }
69
+
70
+ .cfp-hotkeys-text {
71
+ padding-left: 10px;
72
+ font-size: 1em;
73
+ }
74
+
75
+ .cfp-hotkeys-close {
76
+ position: fixed;
77
+ top: 20px;
78
+ right: 20px;
79
+ font-size: 2em;
80
+ font-weight: bold;
81
+ padding: 10px;
82
+ border: 1px solid #ddd;
83
+ border-radius: 5px;
84
+ min-height: 45px;
85
+ min-width: 45px;
86
+ text-align: center;
87
+ }
88
+
89
+ .cfp-hotkeys-close:hover {
90
+ background-color: #fff;
91
+ cursor: pointer;
92
+ }
93
+
94
+ @media all and (max-width: 500px) {
95
+ .cfp-hotkeys {
96
+ font-size: 0.8em;
97
+ }
98
+ }
99
+
100
+ @media all and (min-width: 750px) {
101
+ .cfp-hotkeys {
102
+ font-size: 1.2em;
103
+ }
104
+ }
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: angular-hotkeys-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Anton Shemerey
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mousetrap-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Asset Pipline wrapper around "keyboard shortcuts for your Angular apps."
70
+ angular-hotkeys
71
+ email:
72
+ - shemerey@gmail.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - LICENSE
78
+ - README.md
79
+ - lib/angular/hotkeys/rails.rb
80
+ - lib/angular/hotkeys/rails/version.rb
81
+ - vendor/assets/javascripts/angular/hotkeys.js
82
+ - vendor/assets/stylesheets/angular/hotkeys.css
83
+ homepage: https://github.com/shemerey/angular-hotkeys-rails
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.2.2
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: angular-hotkeys Asset Pipline wrapper
107
+ test_files: []