angular-hotkeys-rails 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []