epuber 0.3.5
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.
- checksums.yaml +7 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +46 -0
- data/bin/epuber +10 -0
- data/epuber.gemspec +51 -0
- data/lib/epuber.rb +14 -0
- data/lib/epuber/book.rb +267 -0
- data/lib/epuber/book/contributor.rb +90 -0
- data/lib/epuber/book/file_request.rb +68 -0
- data/lib/epuber/book/target.rb +284 -0
- data/lib/epuber/book/toc_item.rb +130 -0
- data/lib/epuber/checker.rb +19 -0
- data/lib/epuber/checker/text_checker.rb +129 -0
- data/lib/epuber/checker_transformer_base.rb +71 -0
- data/lib/epuber/command.rb +65 -0
- data/lib/epuber/command/compile.rb +142 -0
- data/lib/epuber/command/init.rb +145 -0
- data/lib/epuber/command/server.rb +59 -0
- data/lib/epuber/compiler.rb +255 -0
- data/lib/epuber/compiler/compilation_context.rb +86 -0
- data/lib/epuber/compiler/file_finders/abstract.rb +270 -0
- data/lib/epuber/compiler/file_finders/imaginary.rb +167 -0
- data/lib/epuber/compiler/file_finders/normal.rb +22 -0
- data/lib/epuber/compiler/file_resolver.rb +316 -0
- data/lib/epuber/compiler/file_types/abstract_file.rb +119 -0
- data/lib/epuber/compiler/file_types/bade_file.rb +39 -0
- data/lib/epuber/compiler/file_types/container_xml_file.rb +26 -0
- data/lib/epuber/compiler/file_types/generated_file.rb +29 -0
- data/lib/epuber/compiler/file_types/ibooks_display_options_file.rb +31 -0
- data/lib/epuber/compiler/file_types/image_file.rb +42 -0
- data/lib/epuber/compiler/file_types/mime_type_file.rb +20 -0
- data/lib/epuber/compiler/file_types/nav_file.rb +42 -0
- data/lib/epuber/compiler/file_types/opf_file.rb +27 -0
- data/lib/epuber/compiler/file_types/source_file.rb +52 -0
- data/lib/epuber/compiler/file_types/static_file.rb +18 -0
- data/lib/epuber/compiler/file_types/stylus_file.rb +20 -0
- data/lib/epuber/compiler/file_types/xhtml_file.rb +102 -0
- data/lib/epuber/compiler/generator.rb +67 -0
- data/lib/epuber/compiler/meta_inf_generator.rb +41 -0
- data/lib/epuber/compiler/nav_generator.rb +201 -0
- data/lib/epuber/compiler/opf_generator.rb +284 -0
- data/lib/epuber/compiler/xhtml_processor.rb +254 -0
- data/lib/epuber/config.rb +133 -0
- data/lib/epuber/dsl/attribute.rb +248 -0
- data/lib/epuber/dsl/attribute_support.rb +130 -0
- data/lib/epuber/dsl/object.rb +145 -0
- data/lib/epuber/dsl/tree_object.rb +101 -0
- data/lib/epuber/helper.rb +19 -0
- data/lib/epuber/lockfile.rb +55 -0
- data/lib/epuber/plugin.rb +108 -0
- data/lib/epuber/ruby_extensions/match_data.rb +40 -0
- data/lib/epuber/ruby_extensions/thread.rb +13 -0
- data/lib/epuber/server.rb +614 -0
- data/lib/epuber/server/auto_refresh/auto_refresh.coffee +97 -0
- data/lib/epuber/server/auto_refresh/connector.coffee +125 -0
- data/lib/epuber/server/auto_refresh/protocol.coffee +41 -0
- data/lib/epuber/server/auto_refresh/reloader.coffee +261 -0
- data/lib/epuber/server/base.styl +3 -0
- data/lib/epuber/server/basic.styl +211 -0
- data/lib/epuber/server/book_content.styl +39 -0
- data/lib/epuber/server/default_cover.png +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Bold.ttf +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-BoldItalic.ttf +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Italic.ttf +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Regular.ttf +0 -0
- data/lib/epuber/server/handlers.rb +67 -0
- data/lib/epuber/server/keyboard_control.coffee +6 -0
- data/lib/epuber/server/pages/book.bade +75 -0
- data/lib/epuber/server/pages/common.bade +59 -0
- data/lib/epuber/server/pages/files.bade +17 -0
- data/lib/epuber/server/pages/toc.bade +29 -0
- data/lib/epuber/server/support.coffee +10 -0
- data/lib/epuber/templates/template.bookspec +143 -0
- data/lib/epuber/third_party/bower.rb +22 -0
- data/lib/epuber/third_party/bower/bower.json +10 -0
- data/lib/epuber/third_party/bower/bower_components/cookies-js/bower.json +10 -0
- data/lib/epuber/third_party/bower/bower_components/cookies-js/dist/cookies.d.ts +33 -0
- data/lib/epuber/third_party/bower/bower_components/cookies-js/dist/cookies.js +173 -0
- data/lib/epuber/third_party/bower/bower_components/cookies-js/dist/cookies.min.js +6 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/MIT-LICENSE.txt +21 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/bower.json +28 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/dist/jquery.js +9210 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/dist/jquery.min.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/dist/jquery.min.map +1 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax.js +786 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/jsonp.js +89 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/load.js +75 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/parseJSON.js +13 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/parseXML.js +28 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/script.js +64 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/var/nonce.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/var/rquery.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/xhr.js +136 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes.js +11 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes/attr.js +141 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes/classes.js +158 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes/prop.js +94 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes/support.js +35 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes/val.js +161 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/callbacks.js +205 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core.js +502 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core/access.js +60 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core/init.js +123 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core/parseHTML.js +39 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core/ready.js +97 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core/var/rsingleTag.js +4 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css.js +450 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/addGetHookIf.js +22 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/curCSS.js +57 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/defaultDisplay.js +70 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/hiddenVisibleSelectors.js +15 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/support.js +96 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/swap.js +28 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/var/cssExpand.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/var/getStyles.js +12 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/var/isHidden.js +13 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/var/rmargin.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/var/rnumnonpx.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/data.js +178 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/data/Data.js +181 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/data/accepts.js +20 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/data/var/data_priv.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/data/var/data_user.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/deferred.js +149 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/deprecated.js +13 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/dimensions.js +50 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/effects.js +648 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/effects/Tween.js +114 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/effects/animatedSelector.js +13 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/event.js +868 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/event/ajax.js +13 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/event/alias.js +39 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/event/support.js +9 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/exports/amd.js +24 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/exports/global.js +32 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/intro.js +44 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/jquery.js +37 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/manipulation.js +580 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/manipulation/_evalUrl.js +18 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/manipulation/support.js +32 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/manipulation/var/rcheckableType.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/offset.js +207 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/outro.js +1 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/queue.js +142 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/queue/delay.js +22 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/selector-native.js +172 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/selector-sizzle.js +14 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/selector.js +1 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/serialize.js +111 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/sizzle/dist/sizzle.js +2067 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/sizzle/dist/sizzle.min.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/sizzle/dist/sizzle.min.map +1 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/traversing.js +199 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/traversing/findFilter.js +100 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/traversing/var/rneedsContext.js +6 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/arr.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/class2type.js +4 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/concat.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/hasOwn.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/indexOf.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/pnum.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/push.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/rnotwhite.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/slice.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/strundefined.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/support.js +4 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/toString.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/wrap.js +79 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/MIT-LICENSE +20 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/Makefile +4 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/README.markdown +212 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/bower.json +27 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/keymaster.js +296 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/package.json +11 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/test.html +93 -0
- data/lib/epuber/third_party/bower/bower_components/spin.js/LICENSE.txt +21 -0
- data/lib/epuber/third_party/bower/bower_components/spin.js/README.md +21 -0
- data/lib/epuber/third_party/bower/bower_components/spin.js/bower.json +18 -0
- data/lib/epuber/third_party/bower/bower_components/spin.js/jquery.spin.js +80 -0
- data/lib/epuber/third_party/bower/bower_components/spin.js/spin.js +337 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/LICENSE.txt +21 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/README.md +534 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/bower.json +16 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/contributing.md +19 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/IPv6.js +188 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/SecondLevelDomains.js +241 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/URI.fragmentQuery.js +104 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/URI.fragmentURI.js +97 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/URI.js +2115 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/URI.min.js +86 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/URITemplate.js +499 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/jquery.URI.js +235 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/jquery.URI.min.js +7 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/punycode.js +508 -0
- data/lib/epuber/transformer.rb +19 -0
- data/lib/epuber/transformer/text_transformer.rb +60 -0
- data/lib/epuber/user_interface.rb +186 -0
- data/lib/epuber/vendor/globals_context.rb +26 -0
- data/lib/epuber/vendor/hash_binding.rb +26 -0
- data/lib/epuber/vendor/nokogiri_extensions.rb +30 -0
- data/lib/epuber/vendor/ruby_templater.rb +71 -0
- data/lib/epuber/vendor/size.rb +20 -0
- data/lib/epuber/vendor/version.rb +83 -0
- data/lib/epuber/version.rb +4 -0
- metadata +556 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011-2013 Thomas Fuchs
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,212 @@
|
|
1
|
+
# keymaster.js
|
2
|
+
|
3
|
+
Keymaster is a simple micro-library for defining and
|
4
|
+
dispatching keyboard shortcuts in web applications.
|
5
|
+
|
6
|
+
It has no dependencies.
|
7
|
+
|
8
|
+
*It’s a work in progress (e.g. beta), so spare me your nerdrage and instead
|
9
|
+
contribute! Patches are welcome, but they are not guaranteed to make
|
10
|
+
it in.*
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
Include `keymaster.js` in your web app*, by loading it as usual:
|
15
|
+
|
16
|
+
```html
|
17
|
+
<script src="keymaster.js"></script>
|
18
|
+
```
|
19
|
+
|
20
|
+
Keymaster has no dependencies and can be used completely standalone.
|
21
|
+
It should not interfere with any JavaScript libraries or frameworks.
|
22
|
+
|
23
|
+
_*Preferably use a minified version that fits your workflow. You can
|
24
|
+
run `make` to have UglifyJS (if you have it installed) create a
|
25
|
+
`keymaster.min.js` file for you._
|
26
|
+
|
27
|
+
## Defining shortcuts
|
28
|
+
|
29
|
+
One global method is exposed, `key` which defines shortcuts when
|
30
|
+
called directly.
|
31
|
+
|
32
|
+
```javascript
|
33
|
+
// define short of 'a'
|
34
|
+
key('a', function(){ alert('you pressed a!') });
|
35
|
+
|
36
|
+
// returning false stops the event and prevents default browser events
|
37
|
+
key('ctrl+r', function(){ alert('stopped reload!'); return false });
|
38
|
+
|
39
|
+
// multiple shortcuts that do the same thing
|
40
|
+
key('⌘+r, ctrl+r', function(){ });
|
41
|
+
```
|
42
|
+
|
43
|
+
The handler method is called with two arguments set, the keydown `event` fired, and
|
44
|
+
an object containing, among others, the following two properties:
|
45
|
+
|
46
|
+
`shortcut`: a string that contains the shortcut used, e.g. `ctrl+r`
|
47
|
+
`scope`: a string describing the scope (or `all`)
|
48
|
+
|
49
|
+
```javascript
|
50
|
+
key('⌘+r, ctrl+r', function(event, handler){
|
51
|
+
console.log(handler.shortcut, handler.scope);
|
52
|
+
});
|
53
|
+
|
54
|
+
// "ctrl+r", "all"
|
55
|
+
```
|
56
|
+
|
57
|
+
|
58
|
+
## Supported keys
|
59
|
+
|
60
|
+
Keymaster understands the following modifiers:
|
61
|
+
`⇧`, `shift`, `option`, `⌥`, `alt`, `ctrl`, `control`, `command`, and `⌘`.
|
62
|
+
|
63
|
+
The following special keys can be used for shortcuts:
|
64
|
+
`backspace`, `tab`, `clear`, `enter`, `return`, `esc`, `escape`, `space`,
|
65
|
+
`up`, `down`, `left`, `right`, `home`, `end`, `pageup`, `pagedown`, `del`, `delete`
|
66
|
+
and `f1` through `f19`.
|
67
|
+
|
68
|
+
|
69
|
+
## Modifier key queries
|
70
|
+
|
71
|
+
At any point in time (even in code other than key shortcut handlers),
|
72
|
+
you can query the `key` object for the state of any keys. This
|
73
|
+
allows easy implementation of things like shift+click handlers. For example,
|
74
|
+
`key.shift` is `true` if the shift key is currently pressed.
|
75
|
+
|
76
|
+
```javascript
|
77
|
+
if(key.shift) alert('shift is pressed, OMGZ!');
|
78
|
+
```
|
79
|
+
|
80
|
+
|
81
|
+
## Other key queries
|
82
|
+
|
83
|
+
At any point in time (even in code other than key shortcut handlers),
|
84
|
+
you can query the `key` object for the state of any key. This
|
85
|
+
is very helpful for game development using a game loop. For example,
|
86
|
+
`key.isPressed(77)` is `true` if the M key is currently pressed.
|
87
|
+
|
88
|
+
```javascript
|
89
|
+
if(key.isPressed("M")) alert('M key is pressed, can ya believe it!?');
|
90
|
+
if(key.isPressed(77)) alert('M key is pressed, can ya believe it!?');
|
91
|
+
```
|
92
|
+
|
93
|
+
You can also get these as an array using...
|
94
|
+
```javascript
|
95
|
+
key.getPressedKeyCodes() // returns an array of key codes currently pressed
|
96
|
+
```
|
97
|
+
|
98
|
+
|
99
|
+
## Scopes
|
100
|
+
|
101
|
+
If you want to reuse the same shortcut for separate areas in your single page app,
|
102
|
+
Keymaster supports switching between scopes. Use the `key.setScope` method to set scope.
|
103
|
+
|
104
|
+
```javascript
|
105
|
+
// define shortcuts with a scope
|
106
|
+
key('o, enter', 'issues', function(){ /* do something */ });
|
107
|
+
key('o, enter', 'files', function(){ /* do something else */ });
|
108
|
+
|
109
|
+
// set the scope (only 'all' and 'issues' shortcuts will be honored)
|
110
|
+
key.setScope('issues'); // default scope is 'all'
|
111
|
+
```
|
112
|
+
|
113
|
+
|
114
|
+
## Filter key presses
|
115
|
+
|
116
|
+
By default, when an `INPUT`, `SELECT` or `TEXTAREA` element is focused, Keymaster doesn't process any shortcuts.
|
117
|
+
|
118
|
+
You can change this by overwriting `key.filter` with a new function. This function is called before
|
119
|
+
Keymaster processes shortcuts, with the keydown event as argument.
|
120
|
+
|
121
|
+
If your function returns false, then the no shortcuts will be processed.
|
122
|
+
|
123
|
+
Here's the default implementation for reference:
|
124
|
+
|
125
|
+
```javascript
|
126
|
+
function filter(event){
|
127
|
+
var tagName = (event.target || event.srcElement).tagName;
|
128
|
+
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
|
129
|
+
}
|
130
|
+
```
|
131
|
+
|
132
|
+
If you only want _some_ shortcuts to work while in an input element, you can change the scope in the
|
133
|
+
`key.filter` function. Here's an example implementation, setting the scope to either `'input'` or `'other'`.
|
134
|
+
Don't forget to return `true` so the any shortcuts get processed.
|
135
|
+
|
136
|
+
```javascript
|
137
|
+
key.filter = function(event){
|
138
|
+
var tagName = (event.target || event.srcElement).tagName;
|
139
|
+
key.setScope(/^(INPUT|TEXTAREA|SELECT)$/.test(tagName) ? 'input' : 'other');
|
140
|
+
return true;
|
141
|
+
}
|
142
|
+
```
|
143
|
+
|
144
|
+
However a more robust way to handle this is to use proper
|
145
|
+
focus and blur event handlers on your input element, and change scopes there as you see fit.
|
146
|
+
|
147
|
+
|
148
|
+
## noConflict mode
|
149
|
+
|
150
|
+
You can call ```key.noConflict``` to remove the ```key``` function from global scope and restore whatever ```key``` was defined to before Keymaster was loaded. Calling ```key.noConflict``` will return the Keymaster ```key``` function.
|
151
|
+
|
152
|
+
```javascript
|
153
|
+
var k = key.noConflict();
|
154
|
+
k('a', function() { /* ... */ });
|
155
|
+
|
156
|
+
key()
|
157
|
+
// --> TypeError: 'undefined' is not a function
|
158
|
+
```
|
159
|
+
|
160
|
+
|
161
|
+
## Unbinding shortcuts
|
162
|
+
|
163
|
+
Similar to defining shortcuts, they can be unbound using `key.unbind`.
|
164
|
+
|
165
|
+
```javascript
|
166
|
+
// unbind 'a' handler
|
167
|
+
key.unbind('a');
|
168
|
+
|
169
|
+
// unbind a key only for a single scope
|
170
|
+
// when no scope is specified it defaults to the current scope (key.getScope())
|
171
|
+
key.unbind('o, enter', 'issues');
|
172
|
+
key.unbind('o, enter', 'files');
|
173
|
+
```
|
174
|
+
|
175
|
+
|
176
|
+
## Notes
|
177
|
+
|
178
|
+
Keymaster should work with any browser that fires `keyup` and `keydown` events,
|
179
|
+
and is tested with IE (6+), Safari, Firefox and Chrome.
|
180
|
+
|
181
|
+
See [http://madrobby.github.com/keymaster/](http://madrobby.github.com/keymaster/) for a live demo.
|
182
|
+
|
183
|
+
|
184
|
+
## CoffeeScript
|
185
|
+
|
186
|
+
If you're using CoffeeScript, configuring key shortcuts couldn't be simpler:
|
187
|
+
|
188
|
+
```coffeescript
|
189
|
+
key 'a', -> alert('you pressed a!')
|
190
|
+
|
191
|
+
key '⌘+r, ctrl+r', ->
|
192
|
+
alert 'stopped reload!'
|
193
|
+
off
|
194
|
+
|
195
|
+
key 'o, enter', 'issues', ->
|
196
|
+
whatevs()
|
197
|
+
|
198
|
+
alert 'shift is pressed, OMGZ!' if key.shift
|
199
|
+
```
|
200
|
+
|
201
|
+
|
202
|
+
## Contributing
|
203
|
+
|
204
|
+
To contribute, please fork Keymaster, add your patch and tests for it (in the `test/` folder) and
|
205
|
+
submit a pull request.
|
206
|
+
|
207
|
+
## TODOs
|
208
|
+
|
209
|
+
* Finish test suite
|
210
|
+
|
211
|
+
Keymaster is (c) 2011-2013 Thomas Fuchs and may be freely distributed under the MIT license.
|
212
|
+
See the `MIT-LICENSE` file.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
{
|
2
|
+
"name": "keymaster",
|
3
|
+
"main": "keymaster.js",
|
4
|
+
"version": "1.6.3",
|
5
|
+
"homepage": "https://github.com/madrobby/keymaster",
|
6
|
+
"authors": [
|
7
|
+
"Thomas Fuchs <thomas@slash7.com> (http://mir.aculo.us)"
|
8
|
+
],
|
9
|
+
"description": "library for defining and dispatching keyboard shortcuts",
|
10
|
+
"moduleType": [
|
11
|
+
"es6",
|
12
|
+
"globals"
|
13
|
+
],
|
14
|
+
"keywords": [
|
15
|
+
"key",
|
16
|
+
"keyboard",
|
17
|
+
"shortcuts"
|
18
|
+
],
|
19
|
+
"license": "MIT",
|
20
|
+
"ignore": [
|
21
|
+
"**/.*",
|
22
|
+
"node_modules",
|
23
|
+
"bower_components",
|
24
|
+
"test",
|
25
|
+
"tests"
|
26
|
+
]
|
27
|
+
}
|
@@ -0,0 +1,296 @@
|
|
1
|
+
// keymaster.js
|
2
|
+
// (c) 2011-2013 Thomas Fuchs
|
3
|
+
// keymaster.js may be freely distributed under the MIT license.
|
4
|
+
|
5
|
+
;(function(global){
|
6
|
+
var k,
|
7
|
+
_handlers = {},
|
8
|
+
_mods = { 16: false, 18: false, 17: false, 91: false },
|
9
|
+
_scope = 'all',
|
10
|
+
// modifier keys
|
11
|
+
_MODIFIERS = {
|
12
|
+
'⇧': 16, shift: 16,
|
13
|
+
'⌥': 18, alt: 18, option: 18,
|
14
|
+
'⌃': 17, ctrl: 17, control: 17,
|
15
|
+
'⌘': 91, command: 91
|
16
|
+
},
|
17
|
+
// special keys
|
18
|
+
_MAP = {
|
19
|
+
backspace: 8, tab: 9, clear: 12,
|
20
|
+
enter: 13, 'return': 13,
|
21
|
+
esc: 27, escape: 27, space: 32,
|
22
|
+
left: 37, up: 38,
|
23
|
+
right: 39, down: 40,
|
24
|
+
del: 46, 'delete': 46,
|
25
|
+
home: 36, end: 35,
|
26
|
+
pageup: 33, pagedown: 34,
|
27
|
+
',': 188, '.': 190, '/': 191,
|
28
|
+
'`': 192, '-': 189, '=': 187,
|
29
|
+
';': 186, '\'': 222,
|
30
|
+
'[': 219, ']': 221, '\\': 220
|
31
|
+
},
|
32
|
+
code = function(x){
|
33
|
+
return _MAP[x] || x.toUpperCase().charCodeAt(0);
|
34
|
+
},
|
35
|
+
_downKeys = [];
|
36
|
+
|
37
|
+
for(k=1;k<20;k++) _MAP['f'+k] = 111+k;
|
38
|
+
|
39
|
+
// IE doesn't support Array#indexOf, so have a simple replacement
|
40
|
+
function index(array, item){
|
41
|
+
var i = array.length;
|
42
|
+
while(i--) if(array[i]===item) return i;
|
43
|
+
return -1;
|
44
|
+
}
|
45
|
+
|
46
|
+
// for comparing mods before unassignment
|
47
|
+
function compareArray(a1, a2) {
|
48
|
+
if (a1.length != a2.length) return false;
|
49
|
+
for (var i = 0; i < a1.length; i++) {
|
50
|
+
if (a1[i] !== a2[i]) return false;
|
51
|
+
}
|
52
|
+
return true;
|
53
|
+
}
|
54
|
+
|
55
|
+
var modifierMap = {
|
56
|
+
16:'shiftKey',
|
57
|
+
18:'altKey',
|
58
|
+
17:'ctrlKey',
|
59
|
+
91:'metaKey'
|
60
|
+
};
|
61
|
+
function updateModifierKey(event) {
|
62
|
+
for(k in _mods) _mods[k] = event[modifierMap[k]];
|
63
|
+
};
|
64
|
+
|
65
|
+
// handle keydown event
|
66
|
+
function dispatch(event) {
|
67
|
+
var key, handler, k, i, modifiersMatch, scope;
|
68
|
+
key = event.keyCode;
|
69
|
+
|
70
|
+
if (index(_downKeys, key) == -1) {
|
71
|
+
_downKeys.push(key);
|
72
|
+
}
|
73
|
+
|
74
|
+
// if a modifier key, set the key.<modifierkeyname> property to true and return
|
75
|
+
if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko
|
76
|
+
if(key in _mods) {
|
77
|
+
_mods[key] = true;
|
78
|
+
// 'assignKey' from inside this closure is exported to window.key
|
79
|
+
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true;
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
updateModifierKey(event);
|
83
|
+
|
84
|
+
// see if we need to ignore the keypress (filter() can can be overridden)
|
85
|
+
// by default ignore key presses if a select, textarea, or input is focused
|
86
|
+
if(!assignKey.filter.call(this, event)) return;
|
87
|
+
|
88
|
+
// abort if no potentially matching shortcuts found
|
89
|
+
if (!(key in _handlers)) return;
|
90
|
+
|
91
|
+
scope = getScope();
|
92
|
+
|
93
|
+
// for each potential shortcut
|
94
|
+
for (i = 0; i < _handlers[key].length; i++) {
|
95
|
+
handler = _handlers[key][i];
|
96
|
+
|
97
|
+
// see if it's in the current scope
|
98
|
+
if(handler.scope == scope || handler.scope == 'all'){
|
99
|
+
// check if modifiers match if any
|
100
|
+
modifiersMatch = handler.mods.length > 0;
|
101
|
+
for(k in _mods)
|
102
|
+
if((!_mods[k] && index(handler.mods, +k) > -1) ||
|
103
|
+
(_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false;
|
104
|
+
// call the handler and stop the event if neccessary
|
105
|
+
if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){
|
106
|
+
if(handler.method(event, handler)===false){
|
107
|
+
if(event.preventDefault) event.preventDefault();
|
108
|
+
else event.returnValue = false;
|
109
|
+
if(event.stopPropagation) event.stopPropagation();
|
110
|
+
if(event.cancelBubble) event.cancelBubble = true;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
};
|
116
|
+
|
117
|
+
// unset modifier keys on keyup
|
118
|
+
function clearModifier(event){
|
119
|
+
var key = event.keyCode, k,
|
120
|
+
i = index(_downKeys, key);
|
121
|
+
|
122
|
+
// remove key from _downKeys
|
123
|
+
if (i >= 0) {
|
124
|
+
_downKeys.splice(i, 1);
|
125
|
+
}
|
126
|
+
|
127
|
+
if(key == 93 || key == 224) key = 91;
|
128
|
+
if(key in _mods) {
|
129
|
+
_mods[key] = false;
|
130
|
+
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false;
|
131
|
+
}
|
132
|
+
};
|
133
|
+
|
134
|
+
function resetModifiers() {
|
135
|
+
for(k in _mods) _mods[k] = false;
|
136
|
+
for(k in _MODIFIERS) assignKey[k] = false;
|
137
|
+
};
|
138
|
+
|
139
|
+
// parse and assign shortcut
|
140
|
+
function assignKey(key, scope, method){
|
141
|
+
var keys, mods;
|
142
|
+
keys = getKeys(key);
|
143
|
+
if (method === undefined) {
|
144
|
+
method = scope;
|
145
|
+
scope = 'all';
|
146
|
+
}
|
147
|
+
|
148
|
+
// for each shortcut
|
149
|
+
for (var i = 0; i < keys.length; i++) {
|
150
|
+
// set modifier keys if any
|
151
|
+
mods = [];
|
152
|
+
key = keys[i].split('+');
|
153
|
+
if (key.length > 1){
|
154
|
+
mods = getMods(key);
|
155
|
+
key = [key[key.length-1]];
|
156
|
+
}
|
157
|
+
// convert to keycode and...
|
158
|
+
key = key[0]
|
159
|
+
key = code(key);
|
160
|
+
// ...store handler
|
161
|
+
if (!(key in _handlers)) _handlers[key] = [];
|
162
|
+
_handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods });
|
163
|
+
}
|
164
|
+
};
|
165
|
+
|
166
|
+
// unbind all handlers for given key in current scope
|
167
|
+
function unbindKey(key, scope) {
|
168
|
+
var multipleKeys, keys,
|
169
|
+
mods = [],
|
170
|
+
i, j, obj;
|
171
|
+
|
172
|
+
multipleKeys = getKeys(key);
|
173
|
+
|
174
|
+
for (j = 0; j < multipleKeys.length; j++) {
|
175
|
+
keys = multipleKeys[j].split('+');
|
176
|
+
|
177
|
+
if (keys.length > 1) {
|
178
|
+
mods = getMods(keys);
|
179
|
+
}
|
180
|
+
|
181
|
+
key = keys[keys.length - 1];
|
182
|
+
key = code(key);
|
183
|
+
|
184
|
+
if (scope === undefined) {
|
185
|
+
scope = getScope();
|
186
|
+
}
|
187
|
+
if (!_handlers[key]) {
|
188
|
+
return;
|
189
|
+
}
|
190
|
+
for (i = 0; i < _handlers[key].length; i++) {
|
191
|
+
obj = _handlers[key][i];
|
192
|
+
// only clear handlers if correct scope and mods match
|
193
|
+
if (obj.scope === scope && compareArray(obj.mods, mods)) {
|
194
|
+
_handlers[key][i] = {};
|
195
|
+
}
|
196
|
+
}
|
197
|
+
}
|
198
|
+
};
|
199
|
+
|
200
|
+
// Returns true if the key with code 'keyCode' is currently down
|
201
|
+
// Converts strings into key codes.
|
202
|
+
function isPressed(keyCode) {
|
203
|
+
if (typeof(keyCode)=='string') {
|
204
|
+
keyCode = code(keyCode);
|
205
|
+
}
|
206
|
+
return index(_downKeys, keyCode) != -1;
|
207
|
+
}
|
208
|
+
|
209
|
+
function getPressedKeyCodes() {
|
210
|
+
return _downKeys.slice(0);
|
211
|
+
}
|
212
|
+
|
213
|
+
function filter(event){
|
214
|
+
var tagName = (event.target || event.srcElement).tagName;
|
215
|
+
// ignore keypressed in any elements that support keyboard data input
|
216
|
+
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
|
217
|
+
}
|
218
|
+
|
219
|
+
// initialize key.<modifier> to false
|
220
|
+
for(k in _MODIFIERS) assignKey[k] = false;
|
221
|
+
|
222
|
+
// set current scope (default 'all')
|
223
|
+
function setScope(scope){ _scope = scope || 'all' };
|
224
|
+
function getScope(){ return _scope || 'all' };
|
225
|
+
|
226
|
+
// delete all handlers for a given scope
|
227
|
+
function deleteScope(scope){
|
228
|
+
var key, handlers, i;
|
229
|
+
|
230
|
+
for (key in _handlers) {
|
231
|
+
handlers = _handlers[key];
|
232
|
+
for (i = 0; i < handlers.length; ) {
|
233
|
+
if (handlers[i].scope === scope) handlers.splice(i, 1);
|
234
|
+
else i++;
|
235
|
+
}
|
236
|
+
}
|
237
|
+
};
|
238
|
+
|
239
|
+
// abstract key logic for assign and unassign
|
240
|
+
function getKeys(key) {
|
241
|
+
var keys;
|
242
|
+
key = key.replace(/\s/g, '');
|
243
|
+
keys = key.split(',');
|
244
|
+
if ((keys[keys.length - 1]) == '') {
|
245
|
+
keys[keys.length - 2] += ',';
|
246
|
+
}
|
247
|
+
return keys;
|
248
|
+
}
|
249
|
+
|
250
|
+
// abstract mods logic for assign and unassign
|
251
|
+
function getMods(key) {
|
252
|
+
var mods = key.slice(0, key.length - 1);
|
253
|
+
for (var mi = 0; mi < mods.length; mi++)
|
254
|
+
mods[mi] = _MODIFIERS[mods[mi]];
|
255
|
+
return mods;
|
256
|
+
}
|
257
|
+
|
258
|
+
// cross-browser events
|
259
|
+
function addEvent(object, event, method) {
|
260
|
+
if (object.addEventListener)
|
261
|
+
object.addEventListener(event, method, false);
|
262
|
+
else if(object.attachEvent)
|
263
|
+
object.attachEvent('on'+event, function(){ method(window.event) });
|
264
|
+
};
|
265
|
+
|
266
|
+
// set the handlers globally on document
|
267
|
+
addEvent(document, 'keydown', function(event) { dispatch(event) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48
|
268
|
+
addEvent(document, 'keyup', clearModifier);
|
269
|
+
|
270
|
+
// reset modifiers to false whenever the window is (re)focused.
|
271
|
+
addEvent(window, 'focus', resetModifiers);
|
272
|
+
|
273
|
+
// store previously defined key
|
274
|
+
var previousKey = global.key;
|
275
|
+
|
276
|
+
// restore previously defined key and return reference to our key object
|
277
|
+
function noConflict() {
|
278
|
+
var k = global.key;
|
279
|
+
global.key = previousKey;
|
280
|
+
return k;
|
281
|
+
}
|
282
|
+
|
283
|
+
// set window.key and window.key.set/get/deleteScope, and the default filter
|
284
|
+
global.key = assignKey;
|
285
|
+
global.key.setScope = setScope;
|
286
|
+
global.key.getScope = getScope;
|
287
|
+
global.key.deleteScope = deleteScope;
|
288
|
+
global.key.filter = filter;
|
289
|
+
global.key.isPressed = isPressed;
|
290
|
+
global.key.getPressedKeyCodes = getPressedKeyCodes;
|
291
|
+
global.key.noConflict = noConflict;
|
292
|
+
global.key.unbind = unbindKey;
|
293
|
+
|
294
|
+
if(typeof module !== 'undefined') module.exports = assignKey;
|
295
|
+
|
296
|
+
})(this);
|