atlas_assets 0.6.4 → 0.6.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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NDlkMmM2MTRhZmY5ZmI0YjIzZGEyZjQ2Yjg1NWY0MWVmODc4MmI5ZQ==
4
+ M2IwZDJhMzk4NjE2MDI2MDg5MzBkNTFhMmU4YWJhNGM2OTcwNzc1OA==
5
5
  data.tar.gz: !binary |-
6
- Mzg3ZjM1YTQxMDc2ZGMzMTcxMDRiNmRkMWQxNjE2YWI4OGE1NmI4OA==
6
+ MmEwZmZhMDlkOTcwNDZkOTBkM2ExNGQ0ZDZiYTlkOTNlZTNiMDBiZQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZDFhOGI0ZWY3MjkwYzRkNTA4MDJmN2FiODVmZGFiMDExYTVhZDk0NjkyNzdh
10
- NWU0ZjVlYWJkMGVmZTU4NjJiMmYxNGY2MWFmNGJkYjQ2ZmZkNzg4YTJjODk3
11
- NjY3NTMxNThhOWRjMjcyNDdlYjczODY4OGYwZDRmZGY0ZmRiNmU=
9
+ ZWQxMTQyMTdmYzQ2NjJhNGU0Nzk2OGRhN2E0MjdlYjdiZmRiMDc1Y2FhMWVl
10
+ ZGM2ZGQ2ODI5YjA5Y2E3ZjhhYzVjNmRiZDMyYmYxMzdiNmFhN2NhNDRmYTk2
11
+ ZmEzMjZiMjQ0OTlhYzNiNTE3NzgyMmU4YWNkMzJiYzM4MWUwZTU=
12
12
  data.tar.gz: !binary |-
13
- YzY4ZjA4Yjk1NmFiN2I2ZDM1YTZlNDYwMjJkOTEzNTdhY2U3YTFlMDdlOGNm
14
- Mjc3MTdiNzgyM2Y1NjIwNDg2ODUyZGIyMmYxMmM1NTRkMzYzMGRkNWYxOWQ5
15
- MTk5ZDA2NzY3ZDNmMjYyMTRhYzBiYjMxODlhNzE4MmY2ZDVlNDU=
13
+ MGUxNGI5ZWRkZDQ3NDE3Njk3NTU4ZTFmNjUyNjdjYjM2MTk0MzdkODJhZTFh
14
+ ZjNkMjE4MWMxMjZkYTI0Y2YxOTJlYzNlYTNmOWRiZTRmOTFkMDAxNGYwMjky
15
+ ZTk2YjQ4YmJmODdhNDM0ZTBhMWY1YmRkY2ZiODc5MjEyNTlhMWM=
@@ -9,7 +9,7 @@ GIT
9
9
  PATH
10
10
  remote: .
11
11
  specs:
12
- atlas_assets (0.6.3)
12
+ atlas_assets (0.6.5)
13
13
  handlebars_assets (~> 0.12.2)
14
14
 
15
15
  GEM
@@ -61,7 +61,7 @@ GEM
61
61
  rack-rewrite (1.3.3)
62
62
  rake (10.0.4)
63
63
  safe_yaml (0.7.1)
64
- sass (3.2.17)
64
+ sass (3.2.18)
65
65
  sprockets (2.12.0)
66
66
  hike (~> 1.2)
67
67
  multi_json (~> 1.0)
@@ -0,0 +1,34 @@
1
+ ---
2
+ layout: default
3
+ title: "Keypress"
4
+ ---
5
+
6
+ Keypress
7
+ ======
8
+
9
+
10
+ Keypress is a robust keyboard input capturing Javascript utility focused on input for games. For details and documentation, please visit [http://dmauro.github.io/Keypress/](http://dmauro.github.io/Keypress/).
11
+
12
+ ## Simple Example
13
+
14
+ <p><button class='btn btn-info' id='shift-s'>Hellooooooo, press shift+s to slideToggle me</button></p>
15
+
16
+ ~~~js
17
+ var listener = new window.keypress.Listener()
18
+ listener.simple_combo("shift s", function() {
19
+ console.log("You pressed shift and s");
20
+ $('#shift-s').slideToggle()
21
+ })
22
+ ~~~
23
+
24
+ <script>
25
+ $(function () {
26
+ var listener = new window.keypress.Listener()
27
+ listener.simple_combo("shift s", function() {
28
+ console.log("You pressed shift and s");
29
+ $('#shift-s').slideToggle()
30
+ })
31
+
32
+ })
33
+ </script>
34
+
@@ -0,0 +1,872 @@
1
+ ###
2
+ Copyright 2014 David Mauro
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ Keypress is a robust keyboard input capturing Javascript utility
17
+ focused on input for games.
18
+
19
+ version 2.0.1
20
+ ###
21
+
22
+ ###
23
+ Combo options available and their defaults:
24
+ keys : [] - An array of the keys pressed together to activate combo.
25
+ count : 0 - The number of times a counting combo has been pressed. Reset on release.
26
+ is_unordered : false - Unless this is set to true, the keys can be pressed down in any order.
27
+ is_counting : false - Makes this a counting combo (see documentation).
28
+ is_exclusive : false - This combo will replace other exclusive combos when true.
29
+ is_solitary : false - This combo will only fire if ONLY it's keys are pressed down.
30
+ is_sequence : false - Rather than a key combo, this is an ordered key sequence.
31
+ prevent_default : false - Prevent default behavior for all component key keypresses.
32
+ prevent_repeat : false - Prevent the combo from repeating when keydown is held.
33
+ on_keydown : null - A function that is called when the combo is pressed.
34
+ on_keyup : null - A function that is called when the combo is released.
35
+ on_release : null - A function that is called when all keys in the combo are released.
36
+ this : undefined - Defines the scope for your callback functions.
37
+ ###
38
+
39
+ ###########
40
+ # Constants
41
+ ###########
42
+
43
+ _factory_defaults =
44
+ is_unordered : false
45
+ is_counting : false
46
+ is_exclusive : false
47
+ is_solitary : false
48
+ prevent_default : false
49
+ prevent_repeat : false
50
+
51
+ _modifier_keys = ["meta", "alt", "option", "ctrl", "shift", "cmd"]
52
+
53
+ _metakey = "ctrl"
54
+
55
+ ###########################
56
+ # Public object and Classes
57
+ ###########################
58
+
59
+ window.keypress = {}
60
+
61
+ keypress.debug = false
62
+
63
+ class Combo
64
+ constructor: (dictionary) ->
65
+ # Copy over any non-false values
66
+ for own property, value of dictionary
67
+ @[property] = value if value != false
68
+
69
+ # Standard Defaults
70
+ @keys = @keys or []
71
+ @count = @count or 0
72
+
73
+ allows_key_repeat: ->
74
+ # Combos with keydown functions should be able to rapid fire
75
+ # when holding down the key for an extended period
76
+ return not @prevent_repeat and typeof @on_keydown is "function"
77
+
78
+ reset: ->
79
+ @count = 0
80
+ @keyup_fired = null
81
+
82
+ class keypress.Listener
83
+ constructor:(element, defaults) ->
84
+ # Public properties
85
+ @should_suppress_event_defaults = false
86
+ @should_force_event_defaults = false
87
+ @sequence_delay = 800
88
+
89
+ # Private properties
90
+ @_registered_combos = []
91
+ @_keys_down = []
92
+ @_active_combos = []
93
+ @_sequence = []
94
+ @_sequence_timer = null
95
+ @_prevent_capture = false
96
+ @_defaults = defaults or {}
97
+ for own property, value of _factory_defaults
98
+ @_defaults[property] = @_defaults[property] or value
99
+
100
+ # Attach handlers to element
101
+ element = element or document.body
102
+
103
+ attach_handler = (target, event, handler) ->
104
+ if target.addEventListener
105
+ target.addEventListener event, handler
106
+ else if target.attachEvent
107
+ target.attachEvent "on#{event}", handler
108
+
109
+ attach_handler element, "keydown", (e) =>
110
+ e = e or window.event
111
+ @_receive_input e, true
112
+ @_bug_catcher e
113
+ attach_handler element, "keyup", (e) =>
114
+ e = e or window.event
115
+ @_receive_input e, false
116
+ attach_handler window, "blur", =>
117
+ # Assume all keys are released when we can't catch key events
118
+ # This prevents alt+tab conflicts
119
+ for key in @_keys_down
120
+ @_key_up key, {}
121
+ @_keys_down = []
122
+
123
+ # Helper Methods
124
+
125
+ _bug_catcher: (e) ->
126
+ # This seems to be Mac specific weirdness, so we'll target "cmd" as metaKey
127
+ # Force a keyup for non-modifier keys when command is held because they don't fire
128
+ if _metakey is "cmd" and "cmd" in @_keys_down and _convert_key_to_readable(e.keyCode) not in ["cmd", "shift", "alt", "caps", "tab"]
129
+ @_receive_input e, false
130
+ # Note: we're currently ignoring the fact that this doesn't catch the bug that a keyup
131
+ # will not fire if you keydown a combo, then press and hold cmd, then keyup the combo.
132
+ # Perhaps we should fire keyup on all active combos when we press cmd?
133
+
134
+ _cmd_bug_check: (combo_keys) ->
135
+ # We don't want to allow combos to activate if the cmd key
136
+ # is pressed, but cmd isn't in them. This is so they don't
137
+ # accidentally rapid fire due to our hack-around for the cmd
138
+ # key bug and having to fake keyups.
139
+ if _metakey is "cmd" and "cmd" in @_keys_down and "cmd" not in combo_keys
140
+ return false
141
+ return true
142
+
143
+ _prevent_default: (e, should_prevent) ->
144
+ # If we've pressed a combo, or if we are working towards
145
+ # one, we should prevent the default keydown event.
146
+ if (should_prevent or @should_suppress_event_defaults) and not @should_force_event_defaults
147
+ if e.preventDefault then e.preventDefault() else e.returnValue = false
148
+ e.stopPropagation() if e.stopPropagation
149
+
150
+ # Tracking Combos
151
+
152
+ _get_active_combos: (key) ->
153
+ # Based on the keys_down and the key just pressed or released
154
+ # (which should not be in keys_down), we determine if any
155
+ # combo in registered_combos could be considered active.
156
+ # This will return an array of active combos
157
+
158
+ active_combos = []
159
+
160
+ # First check that every key in keys_down maps to a combo
161
+ keys_down = _filter_array @_keys_down, (down_key) ->
162
+ down_key isnt key
163
+ keys_down.push key
164
+
165
+ # Get perfect matches
166
+ @_match_combo_arrays keys_down, (match) =>
167
+ active_combos.push(match) if @_cmd_bug_check match.keys
168
+
169
+ # Get fuzzy matches
170
+ @_fuzzy_match_combo_arrays keys_down, (match) =>
171
+ return if match in active_combos
172
+ active_combos.push(match) unless match.is_solitary or not @_cmd_bug_check match.keys
173
+
174
+ return active_combos
175
+
176
+ _get_potential_combos: (key) ->
177
+ # Check if we are working towards pressing a combo.
178
+ # Used for preventing default on keys that might match
179
+ # to a combo in the future.
180
+ potentials = []
181
+ for combo in @_registered_combos
182
+ continue if combo.is_sequence
183
+ potentials.push(combo) if key in combo.keys and @_cmd_bug_check combo.keys
184
+ return potentials
185
+
186
+ _add_to_active_combos: (combo) ->
187
+ should_replace = false
188
+ should_prepend = true
189
+ already_replaced = false
190
+ # An active combo is any combo which the user has already entered.
191
+ # We use this to track when a user has released the last key of a
192
+ # combo for on_release, and to keep combos from 'overlapping'.
193
+ if combo in @_active_combos
194
+ return true
195
+ else if @_active_combos.length
196
+ # We have to check if we're replacing another active combo
197
+ # So compare the combo.keys to all active combos' keys.
198
+ for i in [0...@_active_combos.length]
199
+ active_combo = @_active_combos[i]
200
+ continue unless active_combo and active_combo.is_exclusive and combo.is_exclusive
201
+ active_keys = active_combo.keys
202
+ unless should_replace
203
+ for active_key in active_keys
204
+ should_replace = true
205
+ unless active_key in combo.keys
206
+ should_replace = false
207
+ break
208
+
209
+ if should_prepend and not should_replace
210
+ for combo_key in combo.keys
211
+ should_prepend = false
212
+ unless combo_key in active_keys
213
+ should_prepend = true
214
+ break
215
+
216
+ if should_replace
217
+ if already_replaced
218
+ active_combo = @_active_combos.splice(i, 1)[0]
219
+ active_combo.reset() if active_combo?
220
+ else
221
+ active_combo = @_active_combos.splice(i, 1, combo)[0]
222
+ active_combo.reset() if active_combo?
223
+ already_replaced = true
224
+ should_prepend = false
225
+ if should_prepend
226
+ @_active_combos.unshift combo
227
+
228
+ return should_replace or should_prepend
229
+
230
+ _remove_from_active_combos: (combo) ->
231
+ for i in [0...@_active_combos.length]
232
+ active_combo = @_active_combos[i]
233
+ if active_combo is combo
234
+ combo = @_active_combos.splice(i, 1)[0]
235
+ combo.reset()
236
+ break
237
+ return
238
+
239
+ # Sequence Methods
240
+
241
+ _get_possible_sequences: ->
242
+ # Determine what if any sequences we're working towards.
243
+ # We will consider any which any part of the end of the sequence
244
+ # matches and return all of them.
245
+ matches = []
246
+ for combo in @_registered_combos
247
+ for j in [1..@_sequence.length]
248
+ sequence = @_sequence.slice -j
249
+ continue unless combo.is_sequence
250
+ unless "shift" in combo.keys
251
+ sequence = _filter_array sequence, (key) ->
252
+ return key isnt "shift"
253
+ continue unless sequence.length
254
+ for i in [0...sequence.length]
255
+ if combo.keys[i] is sequence[i]
256
+ match = true
257
+ else
258
+ match = false
259
+ break
260
+ matches.push(combo) if match
261
+ return matches
262
+
263
+ _add_key_to_sequence: (key, e) ->
264
+ @_sequence.push key
265
+ # Now check if they're working towards a sequence
266
+ sequence_combos = @_get_possible_sequences()
267
+ if sequence_combos.length
268
+ for combo in sequence_combos
269
+ @_prevent_default e, combo.prevent_default
270
+ # If we're working towards one, give them more time to keep going
271
+ clearTimeout(@_sequence_timer) if @_sequence_timer
272
+ if @sequence_delay > -1
273
+ @_sequence_timer = setTimeout ->
274
+ @_sequence = []
275
+ , @sequence_delay
276
+ else
277
+ # If we're not working towards something, just clear it out
278
+ @_sequence = []
279
+ return
280
+
281
+ _get_sequence: (key) ->
282
+ # Compare _sequence to all combos
283
+ for combo in @_registered_combos
284
+ continue unless combo.is_sequence
285
+ for j in [1..@_sequence.length]
286
+ # As we are traversing backwards through the sequence keys,
287
+ # Take out any shift keys, unless shift is in the combo.
288
+ sequence = (_filter_array @_sequence, (seq_key) ->
289
+ return true if "shift" in combo.keys
290
+ return seq_key isnt "shift"
291
+ ).slice -j
292
+ continue unless combo.keys.length is sequence.length
293
+ for i in [0...sequence.length]
294
+ seq_key = sequence[i]
295
+ # Special case for shift. Ignore shift keys, unless the sequence explicitly uses them
296
+ continue if seq_key is "shift" unless "shift" in combo.keys
297
+ # Don't select this combo if we're pressing shift and shift isn't in it
298
+ continue if key is "shift" and "shift" not in combo.keys
299
+ if combo.keys[i] is seq_key
300
+ match = true
301
+ else
302
+ match = false
303
+ break
304
+ return combo if match
305
+ return false
306
+
307
+ # Catching Combos
308
+
309
+ _receive_input: (e, is_keydown) ->
310
+ # If we're not capturing input, we should
311
+ # clear out _keys_down for good measure
312
+ if @_prevent_capture
313
+ @_keys_down = [] if @_keys_down.length
314
+ return
315
+ key = _convert_key_to_readable e.keyCode
316
+ # Catch tabbing out of a non-capturing state
317
+ if !is_keydown and !@_keys_down.length and key in ["alt", _metakey]
318
+ return
319
+ return unless key
320
+ if is_keydown
321
+ @_key_down key, e
322
+ else
323
+ @_key_up key, e
324
+
325
+ _fire: (event, combo, key_event, is_autorepeat) ->
326
+ # Only fire this event if the function is defined
327
+ if typeof combo["on_" + event] is "function"
328
+ @_prevent_default key_event, (combo["on_" + event].call(combo.this, key_event, combo.count, is_autorepeat) isnt true)
329
+ # We need to mark that keyup has already happened
330
+ if event is "release"
331
+ combo.count = 0
332
+ if event is "keyup"
333
+ combo.keyup_fired = true
334
+
335
+ _match_combo_arrays: (potential_match, match_handler) ->
336
+ # This will return all combos that match
337
+ for source_combo in @_registered_combos
338
+ if (not source_combo.is_unordered and _compare_arrays_sorted(potential_match, source_combo.keys)) or (source_combo.is_unordered and _compare_arrays(potential_match, source_combo.keys))
339
+ match_handler source_combo
340
+ return
341
+
342
+ _fuzzy_match_combo_arrays: (potential_match, match_handler) ->
343
+ # This will return combos that match even if other keys are pressed
344
+ for source_combo in @_registered_combos
345
+ if (not source_combo.is_unordered and _is_array_in_array_sorted(source_combo.keys, potential_match)) or (source_combo.is_unordered and _is_array_in_array(source_combo.keys, potential_match))
346
+ match_handler source_combo
347
+ return
348
+
349
+ _keys_remain: (combo) ->
350
+ for key in combo.keys
351
+ if key in @_keys_down
352
+ keys_remain = true
353
+ break
354
+ return keys_remain
355
+
356
+ _key_down: (key, e) ->
357
+ # Check if we're holding shift
358
+ shifted_key = _convert_to_shifted_key key, e
359
+ key = shifted_key if shifted_key
360
+
361
+ # Add the key to sequences
362
+ @_add_key_to_sequence key, e
363
+ sequence_combo = @_get_sequence key
364
+ @_fire("keydown", sequence_combo, e) if sequence_combo
365
+
366
+ # We might have modifier keys down when coming back to
367
+ # this window and they might not be in _keys_down, so
368
+ # we're doing a check to make sure we put it back in.
369
+ # This only works for explicit modifier keys.
370
+ for mod, event_mod of _modifier_event_mapping
371
+ continue unless e[event_mod]
372
+ continue if mod is key or mod in @_keys_down
373
+ @_keys_down.push mod
374
+ # Alternatively, we might not have modifier keys down
375
+ # that we think are, so we should catch those too
376
+ for mod, event_mod of _modifier_event_mapping
377
+ continue if mod is key
378
+ if mod in @_keys_down and not e[event_mod]
379
+ # The Windows key will think it is the cmd key, but won't trigger the event mod
380
+ continue if mod is "cmd" and _metakey isnt "cmd"
381
+ for i in [0...@_keys_down.length]
382
+ @_keys_down.splice(i, 1) if @_keys_down[i] is mod
383
+
384
+ # Find which combos we have pressed or might be working towards, and prevent default
385
+ combos = @_get_active_combos key
386
+ potential_combos = @_get_potential_combos key
387
+ for combo in combos
388
+ @_handle_combo_down combo, potential_combos, key, e
389
+ if potential_combos.length
390
+ for potential in potential_combos
391
+ @_prevent_default e, potential.prevent_default
392
+
393
+ if key not in @_keys_down
394
+ @_keys_down.push key
395
+ return
396
+
397
+ _handle_combo_down: (combo, potential_combos, key, e) ->
398
+ # Make sure we're not trying to fire for a combo that already fired
399
+ return false unless key in combo.keys
400
+
401
+ @_prevent_default e, (combo and combo.prevent_default)
402
+
403
+ is_autorepeat = false
404
+ # If we've already pressed this key, check that we want to fire
405
+ # again, otherwise just add it to the keys_down list.
406
+ if key in @_keys_down
407
+ is_autorepeat = true
408
+ return false unless combo.allows_key_repeat()
409
+
410
+ # Now we add this combo or replace it in _active_combos
411
+ result = @_add_to_active_combos combo, key
412
+
413
+ # We reset the keyup_fired property because you should be
414
+ # able to fire that again, if you've pressed the key down again
415
+ combo.keyup_fired = false
416
+
417
+ # Now we fire the keydown event unless there is a larger exclusive potential combo
418
+ is_other_exclusive = false
419
+ if combo.is_exclusive
420
+ for potential_combo in potential_combos
421
+ if potential_combo.is_exclusive and potential_combo.keys.length > combo.keys.length
422
+ is_other_exclusive = true
423
+ break
424
+
425
+ unless is_other_exclusive
426
+ if combo.is_counting and typeof combo.on_keydown is "function"
427
+ combo.count += 1
428
+
429
+ # Only fire keydown if we added it
430
+ if result
431
+ @_fire "keydown", combo, e, is_autorepeat
432
+
433
+ _key_up: (key, e) ->
434
+ # Check if we're holding shift
435
+ unshifted_key = key
436
+ shifted_key = _convert_to_shifted_key key, e
437
+ key = shifted_key if shifted_key
438
+ shifted_key = _keycode_shifted_keys[unshifted_key]
439
+ # We have to make sure the key matches to what we had in _keys_down
440
+ if e.shiftKey
441
+ key = unshifted_key unless shifted_key and shifted_key in @_keys_down
442
+ else
443
+ key = shifted_key unless unshifted_key and unshifted_key in @_keys_down
444
+
445
+ # Check if we have a keyup firing
446
+ sequence_combo = @_get_sequence key
447
+ @_fire("keyup", sequence_combo, e) if sequence_combo
448
+
449
+ # Remove from the list
450
+ return false unless key in @_keys_down
451
+ for i in [0...@_keys_down.length]
452
+ if @_keys_down[i] in [key, shifted_key, unshifted_key]
453
+ @_keys_down.splice i, 1
454
+ break
455
+
456
+ # Store this for later cleanup
457
+ active_combos_length = @_active_combos.length
458
+
459
+ # When releasing we should only check if we
460
+ # match from _active_combos so that we don't
461
+ # accidentally fire for a combo that was a
462
+ # smaller part of the one we actually wanted.
463
+ combos = []
464
+ for active_combo in @_active_combos
465
+ if key in active_combo.keys
466
+ combos.push active_combo
467
+ for combo in combos
468
+ @_handle_combo_up combo, e, key
469
+
470
+ # We also need to check other combos that might still be in active_combos
471
+ # and needs to be removed from it.
472
+ if active_combos_length > 1
473
+ for active_combo in @_active_combos
474
+ continue if active_combo is undefined or active_combo in combos
475
+ unless @_keys_remain active_combo
476
+ @_remove_from_active_combos active_combo
477
+ return
478
+
479
+ _handle_combo_up: (combo, e, key) ->
480
+ @_prevent_default e, (combo and combo.prevent_default)
481
+
482
+ # Check if any keys from this combo are still being held.
483
+ keys_remaining = @_keys_remain combo
484
+
485
+ # Any unactivated combos will fire
486
+ if !combo.keyup_fired
487
+ # And we should not fire it if it is a solitary combo and something else is pressed
488
+ keys_down = @_keys_down.slice()
489
+ keys_down.push key
490
+ if not combo.is_solitary or _compare_arrays keys_down, combo.keys
491
+ @_fire "keyup", combo, e
492
+ # Dont' add to the count unless we only have a keyup callback
493
+ if combo.is_counting and typeof combo.on_keyup is "function" and typeof combo.on_keydown isnt "function"
494
+ combo.count += 1
495
+
496
+ # If this was the last key released of the combo, clean up.
497
+ unless keys_remaining
498
+ @_fire "release", combo, e
499
+ @_remove_from_active_combos combo
500
+ return
501
+
502
+ # Public Registration Methods
503
+
504
+ simple_combo: (keys, callback) ->
505
+ # Shortcut for simple combos.
506
+ @register_combo(
507
+ keys : keys
508
+ on_keydown : callback
509
+ )
510
+
511
+ counting_combo: (keys, count_callback) ->
512
+ # Shortcut for counting combos
513
+ @register_combo(
514
+ keys : keys
515
+ is_counting : true
516
+ is_unordered : false
517
+ on_keydown : count_callback
518
+ )
519
+
520
+ sequence_combo: (keys, callback) ->
521
+ @register_combo(
522
+ keys : keys
523
+ on_keydown : callback
524
+ is_sequence : true
525
+ )
526
+
527
+ register_combo: (combo_dictionary) ->
528
+ # Allow a space dilineated string instead of array
529
+ if typeof combo_dictionary["keys"] is "string"
530
+ combo_dictionary["keys"] = combo_dictionary["keys"].split " "
531
+ for own property, value of @_defaults
532
+ if combo_dictionary[property] == undefined
533
+ combo_dictionary[property] = value
534
+ combo = new Combo combo_dictionary
535
+
536
+ if _validate_combo combo
537
+ @_registered_combos.push combo
538
+ return combo
539
+
540
+ register_many: (combo_array) ->
541
+ # Will return an array of the combos actually registered
542
+ @register_combo(combo) for combo in combo_array
543
+
544
+ unregister_combo: (keys_or_combo) ->
545
+ return false unless keys_or_combo
546
+
547
+ unregister_combo = (combo) =>
548
+ for i in [0...@_registered_combos.length]
549
+ if combo is @_registered_combos[i]
550
+ @_registered_combos.splice i, 1
551
+ break
552
+
553
+ if keys_or_combo.keys
554
+ unregister_combo keys_or_combo
555
+ else
556
+ for combo in @_registered_combos
557
+ continue unless combo
558
+ if typeof keys_or_combo is "string"
559
+ keys_or_combo = keys_or_combo.split " "
560
+ if (combo.is_unordered and _compare_arrays(keys_or_combo, combo.keys)) or (not combo.is_unordered and _compare_arrays_sorted(keys_or_combo, combo.keys))
561
+ unregister_combo combo
562
+
563
+ unregister_many: (combo_array) ->
564
+ for combo in combo_array
565
+ @unregister_combo combo
566
+
567
+ # Other public methods
568
+
569
+ get_registered_combos: ->
570
+ return @_registered_combos
571
+
572
+ reset: ->
573
+ @_registered_combos = []
574
+
575
+ listen: ->
576
+ @_prevent_capture = false
577
+
578
+ stop_listening: ->
579
+ @_prevent_capture = true
580
+
581
+ get_meta_key: ->
582
+ # Helpful for debugging purposes
583
+ return _metakey
584
+
585
+ ##################
586
+ # Helper Functions
587
+ ##################
588
+
589
+ _decide_meta_key = ->
590
+ # If the useragent reports Mac OS X, assume cmd is metakey
591
+ if navigator.userAgent.indexOf("Mac OS X") != -1
592
+ _metakey = "cmd"
593
+ return
594
+
595
+ _change_keycodes_by_browser = ->
596
+ if navigator.userAgent.indexOf("Opera") != -1
597
+ # Opera does weird stuff with command and control keys, let's fix that.
598
+ # Note: Opera cannot override meta + s browser default of save page.
599
+ # Note: Opera does some really strange stuff when cmd+alt+shift
600
+ # are held and a non-modifier key is pressed.
601
+ _keycode_dictionary["17"] = "cmd"
602
+ return
603
+
604
+ _convert_key_to_readable = (k) ->
605
+ return _keycode_dictionary[k]
606
+
607
+ _filter_array = (array, callback) ->
608
+ if array.filter
609
+ return array.filter(callback)
610
+ else
611
+ # For browsers without Array.prototype.filter like IE<9:
612
+ return (element for element in array when callback(element))
613
+
614
+ _compare_arrays = (a1, a2) ->
615
+ # This will ignore the ordering of the arrays
616
+ # and simply check if they have the same contents.
617
+ return false unless a1.length is a2.length
618
+ for item in a1
619
+ continue if item in a2
620
+ return false
621
+ return true
622
+
623
+ _compare_arrays_sorted = (a1, a2) ->
624
+ return false unless a1.length is a2.length
625
+ for i in [0...a1.length]
626
+ return false unless a1[i] is a2[i]
627
+ return true
628
+
629
+ _is_array_in_array = (a1, a2) ->
630
+ # Returns true only if all of the contents of
631
+ # a1 are included in a2
632
+ for item in a1
633
+ return false unless item in a2
634
+ return true
635
+
636
+ _is_array_in_array_sorted = (a1, a2) ->
637
+ # Return true only if all of the contents of
638
+ # a1 are include in a2 and they appear in the
639
+ # same order in both.
640
+ prev = 0
641
+ for item in a1
642
+ index = a2.indexOf item
643
+ if index >= prev
644
+ prev = index
645
+ else
646
+ return false
647
+ return true
648
+
649
+ _log_error = () ->
650
+ console.log arguments... if keypress.debug
651
+
652
+ _key_is_valid = (key) ->
653
+ valid = false
654
+ for _, valid_key of _keycode_dictionary
655
+ if key is valid_key
656
+ valid = true
657
+ break
658
+ unless valid
659
+ for _, valid_key of _keycode_shifted_keys
660
+ if key is valid_key
661
+ valid = true
662
+ break
663
+ return valid
664
+
665
+ _validate_combo = (combo) ->
666
+ validated = true
667
+
668
+ # Warn for lack of keys
669
+ unless combo.keys.length
670
+ _log_error "You're trying to bind a combo with no keys:", combo
671
+
672
+ # Convert "meta" to either "ctrl" or "cmd"
673
+ # Don't explicity use the command key, it breaks
674
+ # because it is the windows key in Windows, and
675
+ # cannot be hijacked.
676
+ for i in [0...combo.keys.length]
677
+ key = combo.keys[i]
678
+ # Check the name and replace if needed
679
+ alt_name = _keycode_alternate_names[key]
680
+ key = combo.keys[i] = alt_name if alt_name
681
+ if key is "meta"
682
+ combo.keys.splice i, 1, _metakey
683
+ if key is "cmd"
684
+ _log_error "Warning: use the \"meta\" key rather than \"cmd\" for Windows compatibility"
685
+
686
+ # Check that all keys in the combo are valid
687
+ for key in combo.keys
688
+ unless _key_is_valid key
689
+ _log_error "Do not recognize the key \"#{key}\""
690
+ validated = false
691
+
692
+ # We can only allow a single non-modifier key
693
+ # in combos that include the command key (this
694
+ # includes 'meta') because of the keyup bug.
695
+ if "meta" in combo.keys or "cmd" in combo.keys
696
+ non_modifier_keys = combo.keys.slice()
697
+ for mod_key in _modifier_keys
698
+ if (i = non_modifier_keys.indexOf(mod_key)) > -1
699
+ non_modifier_keys.splice(i, 1)
700
+ if non_modifier_keys.length > 1
701
+ _log_error "META and CMD key combos cannot have more than 1 non-modifier keys", combo, non_modifier_keys
702
+ validated = false
703
+
704
+ # Tell the user if they are trying to use any
705
+ # combo properties that don't actually exist,
706
+ # but allow the combo
707
+ for property, value of combo
708
+ if _factory_defaults[property] is "undefined"
709
+ _log_error "The property #{property} is not a valid combo property. Your combo has still been registered."
710
+
711
+ return validated
712
+
713
+ _convert_to_shifted_key = (key, e) ->
714
+ return false unless e.shiftKey
715
+ k = _keycode_shifted_keys[key]
716
+ return k if k?
717
+ return false
718
+
719
+ ##########################
720
+ # Key Mapping Dictionaries
721
+ ##########################
722
+
723
+ _modifier_event_mapping =
724
+ "cmd" : "metaKey"
725
+ "ctrl" : "ctrlKey"
726
+ "shift" : "shiftKey"
727
+ "alt" : "altKey"
728
+
729
+ _keycode_alternate_names =
730
+ "escape" : "esc"
731
+ "control" : "ctrl"
732
+ "command" : "cmd"
733
+ "break" : "pause"
734
+ "windows" : "cmd"
735
+ "option" : "alt"
736
+ "caps_lock" : "caps"
737
+ "apostrophe" : "\'"
738
+ "semicolon" : ";"
739
+ "tilde" : "~"
740
+ "accent" : "`"
741
+ "scroll_lock" : "scroll"
742
+ "num_lock" : "num"
743
+
744
+ _keycode_shifted_keys =
745
+ "/" : "?"
746
+ "." : ">"
747
+ "," : "<"
748
+ "\'" : "\""
749
+ ";" : ":"
750
+ "[" : "{"
751
+ "]" : "}"
752
+ "\\" : "|"
753
+ "`" : "~"
754
+ "=" : "+"
755
+ "-" : "_"
756
+ "1" : "!"
757
+ "2" : "@"
758
+ "3" : "#"
759
+ "4" : "$"
760
+ "5" : "%"
761
+ "6" : "^"
762
+ "7" : "&"
763
+ "8" : "*"
764
+ "9" : "("
765
+ "0" : ")"
766
+
767
+ _keycode_dictionary =
768
+ 0 : "\\" # Firefox reports this keyCode when shift is held
769
+ 8 : "backspace"
770
+ 9 : "tab"
771
+ 12 : "num"
772
+ 13 : "enter"
773
+ 16 : "shift"
774
+ 17 : "ctrl"
775
+ 18 : "alt"
776
+ 19 : "pause"
777
+ 20 : "caps"
778
+ 27 : "esc"
779
+ 32 : "space"
780
+ 33 : "pageup"
781
+ 34 : "pagedown"
782
+ 35 : "end"
783
+ 36 : "home"
784
+ 37 : "left"
785
+ 38 : "up"
786
+ 39 : "right"
787
+ 40 : "down"
788
+ 44 : "print"
789
+ 45 : "insert"
790
+ 46 : "delete"
791
+ 48 : "0"
792
+ 49 : "1"
793
+ 50 : "2"
794
+ 51 : "3"
795
+ 52 : "4"
796
+ 53 : "5"
797
+ 54 : "6"
798
+ 55 : "7"
799
+ 56 : "8"
800
+ 57 : "9"
801
+ 65 : "a"
802
+ 66 : "b"
803
+ 67 : "c"
804
+ 68 : "d"
805
+ 69 : "e"
806
+ 70 : "f"
807
+ 71 : "g"
808
+ 72 : "h"
809
+ 73 : "i"
810
+ 74 : "j"
811
+ 75 : "k"
812
+ 76 : "l"
813
+ 77 : "m"
814
+ 78 : "n"
815
+ 79 : "o"
816
+ 80 : "p"
817
+ 81 : "q"
818
+ 82 : "r"
819
+ 83 : "s"
820
+ 84 : "t"
821
+ 85 : "u"
822
+ 86 : "v"
823
+ 87 : "w"
824
+ 88 : "x"
825
+ 89 : "y"
826
+ 90 : "z"
827
+ 91 : "cmd"
828
+ 92 : "cmd"
829
+ 93 : "cmd"
830
+ 96 : "num_0"
831
+ 97 : "num_1"
832
+ 98 : "num_2"
833
+ 99 : "num_3"
834
+ 100 : "num_4"
835
+ 101 : "num_5"
836
+ 102 : "num_6"
837
+ 103 : "num_7"
838
+ 104 : "num_8"
839
+ 105 : "num_9"
840
+ 106 : "num_multiply"
841
+ 107 : "num_add"
842
+ 108 : "num_enter"
843
+ 109 : "num_subtract"
844
+ 110 : "num_decimal"
845
+ 111 : "num_divide"
846
+ 124 : "print"
847
+ 144 : "num"
848
+ 145 : "scroll"
849
+ 186 : ";"
850
+ 187 : "="
851
+ 188 : ","
852
+ 189 : "-"
853
+ 190 : "."
854
+ 191 : "/"
855
+ 192 : "`"
856
+ 219 : "["
857
+ 220 : "\\"
858
+ 221 : "]"
859
+ 222 : "\'"
860
+ 223 : "`"
861
+ 224 : "cmd"
862
+ 225 : "alt"
863
+ # Opera weirdness
864
+ 57392 : "ctrl"
865
+ 63289 : "num"
866
+
867
+ ############
868
+ # Initialize
869
+ ############
870
+
871
+ _decide_meta_key()
872
+ _change_keycodes_by_browser()
@@ -1,5 +1,5 @@
1
1
  module Atlas
2
2
  module Assets
3
- VERSION = "0.6.4"
3
+ VERSION = "0.6.5"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atlas_assets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rune Skjoldborg Madsen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-21 00:00:00.000000000 Z
11
+ date: 2014-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: handlebars_assets
@@ -60,6 +60,7 @@ files:
60
60
  - docs/_posts/2013-09-12-logo.md
61
61
  - docs/_posts/2013-10-28-dropdown.md
62
62
  - docs/_posts/2014-03-12-drop.md
63
+ - docs/_posts/2014-04-03-keypress.md
63
64
  - docs/_posts/2014-2-10-colors.md
64
65
  - docs/glyphicons-license.txt
65
66
  - docs/index.html
@@ -88,7 +89,7 @@ files:
88
89
  - lib/assets/javascripts/libraries/drop.js
89
90
  - lib/assets/javascripts/libraries/jquery.js
90
91
  - lib/assets/javascripts/libraries/jquery_ujs.js
91
- - lib/assets/javascripts/libraries/keypress.js
92
+ - lib/assets/javascripts/libraries/keypress.coffee
92
93
  - lib/assets/javascripts/libraries/pusher.js
93
94
  - lib/assets/javascripts/libraries/select.coffee
94
95
  - lib/assets/javascripts/libraries/string.js
@@ -1,22 +0,0 @@
1
-
2
- /* Keypress version 1.0.8 */
3
- (function(){var w,x,j,Q,R,S,T,y,z,A,U,G,H,m,V,W,X,Y,I,Z,$,aa,ba,ca,J,da,r,s,g,K,t,ea,L,u,M,B,v,N,C,h,O,D,p,E,P,F,fa,i=[].indexOf||function(a){for(var c=0,b=this.length;c<b;c++)if(c in this&&this[c]===a)return c;return-1},ga={}.hasOwnProperty;Array.prototype.filter||(Array.prototype.filter=function(a){var c,b,d,e;e=[];b=0;for(d=this.length;b<d;b++)c=this[b],a(c)&&e.push(c);return e});h=[];p=[];E=null;g=[];j=[];B=!1;L="ctrl";M="meta alt option ctrl shift cmd".split(" ");F=[];z={keys:[],count:0};t=function(){return console.log.apply(console,
4
- arguments)};A=function(a,c){var b,d,e;if(a.length!==c.length)return false;d=0;for(e=a.length;d<e;d++){b=a[d];if(!(i.call(c,b)>=0))return false}return true};U=function(a,c){var b,d,e;if(a.length!==c.length)return false;b=d=0;for(e=a.length;0<=e?d<e:d>e;b=0<=e?++d:--d)if(a[b]!==c[b])return false;return true};aa=function(a,c){var b,d,e;d=0;for(e=a.length;d<e;d++){b=a[d];if(i.call(c,b)<0)return false}return true};ba=function(a,c){var b,d,e,f;e=d=0;for(f=a.length;e<f;e++){b=a[e];b=c.indexOf(b);if(b>=d)d=
5
- b;else return false}return true};v=function(a,c){if((c||keypress.suppress_event_defaults)&&!keypress.force_event_defaults){a.preventDefault?a.preventDefault():a.returnValue=false;if(a.stopPropagation)return a.stopPropagation()}};S=function(a){if(a.prevent_repeat)return false;if(typeof a.on_keydown==="function")return true};K=function(a){var c,b,d,e;e=a.keys;b=0;for(d=e.length;b<d;b++){a=e[b];if(i.call(g,a)>=0){c=true;break}}return c};m=function(a,c,b){typeof c["on_"+a]==="function"&&v(b,c["on_"+a].call(c["this"],
6
- b,c.count)===false);if(a==="release")c.count=0;if(a==="keyup")return c.keyup_fired=true};ea=function(a,c){var b,d,e;d=0;for(e=h.length;d<e;d++){b=h[d];(b.is_ordered&&U(a,b.keys)||!b.is_ordered&&A(a,b.keys))&&c(b)}};V=function(a,c){var b,d,e;d=0;for(e=h.length;d<e;d++){b=h[d];(b.is_ordered&&ba(b.keys,a)||!b.is_ordered&&aa(b.keys,a))&&c(b)}};y=function(a){return i.call(g,"cmd")>=0&&i.call(a,"cmd")<0?false:true};W=function(a){var c,b;c=[];b=g.filter(function(b){return b!==a});b.push(a);ea(b,function(a){if(y(a.keys))return c.push(a)});
7
- V(b,function(a){if(!(i.call(c,a)>=0)&&!a.is_solitary&&y(a.keys))return c.push(a)});return c};Y=function(a){var c,b,d,e;b=[];d=0;for(e=h.length;d<e;d++){c=h[d];c.is_sequence||i.call(c.keys,a)>=0&&y(c.keys)&&b.push(c)}return b};R=function(a){var c,b,d,e,f,q,g,h,l,k,o;q=false;f=true;d=false;if(i.call(j,a)>=0)return true;if(j.length){e=g=0;for(k=j.length;0<=k?g<k:g>k;e=0<=k?++g:--g)if((c=j[e])&&c.is_exclusive&&a.is_exclusive){c=c.keys;if(!q){h=0;for(l=c.length;h<l;h++){b=c[h];q=true;if(i.call(a.keys,
8
- b)<0){q=false;break}}}if(f&&!q){o=a.keys;h=0;for(l=o.length;h<l;h++){b=o[h];f=false;if(i.call(c,b)<0){f=true;break}}}if(q){if(d)D(j.splice(e,1));else{D(j.splice(e,1,a));d=true}f=false}}}f&&j.unshift(a);return q||f};O=function(a){var c,b,d,e;b=d=0;for(e=j.length;0<=e?d<e:d>e;b=0<=e?++d:--d){c=j[b];if(c===a){D(j.splice(b,1));break}}};D=function(a){if(a){a.count=null;return a.keyup_fired=null}};Q=function(a,c){var b,d,e,f;p.push(a);d=X();if(d.length){e=0;for(f=d.length;e<f;e++){b=d[e];v(c,b.prevent_default)}E&&
9
- clearTimeout(E);keypress.sequence_delay>-1&&(E=setTimeout(function(){return p=[]},keypress.sequence_delay))}else p=[]};X=function(){var a,c,b,d,e,f,g,n,j,l,k;d=[];f=0;for(j=h.length;f<j;f++){a=h[f];c=g=1;for(l=p.length;1<=l?g<=l:g>=l;c=1<=l?++g:--g){e=p.slice(-c);if(a.is_sequence){if(i.call(a.keys,"shift")<0){e=e.filter(function(a){return a!=="shift"});if(!e.length)continue}c=n=0;for(k=e.length;0<=k?n<k:n>k;c=0<=k?++n:--n)if(a.keys[c]===e[c])b=true;else{b=false;break}b&&d.push(a)}}}return d};I=function(a){var c,
10
- b,d,e,f,g,j,m,l,k,o;g=0;for(l=h.length;g<l;g++){c=h[g];if(c.is_sequence){b=j=1;for(k=p.length;1<=k?j<=k:j>=k;b=1<=k?++j:--j){f=p.filter(function(a){return i.call(c.keys,"shift")>=0?true:a!=="shift"}).slice(-b);if(c.keys.length===f.length){b=m=0;for(o=f.length;0<=o?m<o:m>o;b=0<=o?++m:--m){e=f[b];if(!(i.call(c.keys,"shift")<0&&e==="shift")&&!(a==="shift"&&i.call(c.keys,"shift")<0))if(c.keys[b]===e)d=true;else{d=false;break}}}}if(d)return c}}return false};H=function(a,c){var b;if(!c.shiftKey)return false;
11
- b=s[a];return b!=null?b:false};Z=function(a,c,b){if(i.call(a.keys,c)<0)return false;v(b,a&&a.prevent_default);if(i.call(g,c)>=0&&!S(a))return false;c=R(a,c);a.keyup_fired=false;if(a.is_counting&&typeof a.on_keydown==="function")a.count=a.count+1;if(c)return m("keydown",a,b)};ca=function(a,c){var b,d,e,f;(d=H(a,c))&&(a=d);Q(a,c);(d=I(a))&&m("keydown",d,c);for(b in u){d=u[b];c[d]&&(b===a||i.call(g,b)>=0||g.push(b))}for(b in u){d=u[b];if(b!==a&&i.call(g,b)>=0&&!c[d]){d=e=0;for(f=g.length;0<=f?e<f:e>
12
- f;d=0<=f?++e:--e)g[d]===b&&g.splice(d,1)}}d=W(a);e=0;for(f=d.length;e<f;e++){b=d[e];Z(b,a,c)}d=Y(a);if(d.length){e=0;for(f=d.length;e<f;e++){b=d[e];v(c,b.prevent_default)}}i.call(g,a)<0&&g.push(a)};$=function(a,c,b){var d,e;e=K(a);if(!a.keyup_fired){d=g.slice();d.push(b);if(!a.is_solitary||A(d,a.keys)){m("keyup",a,c);if(a.is_counting&&typeof a.on_keyup==="function"&&typeof a.on_keydown!=="function")a.count=a.count+1}}if(!e){m("release",a,c);O(a)}};J=function(a,c){var b,d,e,f,h,n;d=a;(e=H(a,c))&&(a=
13
- e);e=s[d];c.shiftKey?e&&i.call(g,e)>=0||(a=d):d&&i.call(g,d)>=0||(a=e);(f=I(a))&&m("keyup",f,c);if(i.call(g,a)<0)return false;f=h=0;for(n=g.length;0<=n?h<n:h>n;f=0<=n?++h:--h)if((b=g[f])===a||b===e||b===d){g.splice(f,1);break}d=j.length;e=[];f=0;for(h=j.length;f<h;f++){b=j[f];i.call(b.keys,a)>=0&&e.push(b)}f=0;for(h=e.length;f<h;f++){b=e[f];$(b,c,a)}if(d>1){d=0;for(f=j.length;d<f;d++){b=j[d];b===void 0||i.call(e,b)>=0||K(b)||O(b)}}};C=function(a,c){var b;if(B)g.length&&(g=[]);else if(c||g.length)if(b=
14
- G(a.keyCode))return c?ca(b,a):J(b,a)};P=function(a){var c,b,d,e;e=[];c=b=0;for(d=h.length;0<=d?b<d:b>d;c=0<=d?++b:--b)if(a===h[c]){h.splice(c,1);break}else e.push(void 0);return e};fa=function(a){var c,b,d,e,f;a.keys.length||t("You're trying to bind a combo with no keys.");b=e=0;for(f=a.keys.length;0<=f?e<f:e>f;b=0<=f?++e:--e){d=a.keys[b];(c=da[d])&&(d=a.keys[b]=c);d==="meta"&&a.keys.splice(b,1,L);d==="cmd"&&t('Warning: use the "meta" key rather than "cmd" for Windows compatibility')}f=a.keys;c=0;
15
- for(e=f.length;c<e;c++){d=f[c];if(i.call(F,d)<0){t('Do not recognize the key "'+d+'"');return false}}if(i.call(a.keys,"meta")>=0||i.call(a.keys,"cmd")>=0){c=a.keys.slice();e=0;for(f=M.length;e<f;e++){d=M[e];(b=c.indexOf(d))>-1&&c.splice(b,1)}c.length>1&&t("META and CMD key combos cannot have more than 1 non-modifier keys",a,c)}return true};T=function(a){var c;if(i.call(g,"cmd")>=0&&(c=G(a.keyCode))!=="cmd"&&c!=="shift"&&c!=="alt"&&c!=="caps"&&c!=="tab")return C(a,false)};window.keypress={};keypress.force_event_defaults=
16
- !1;keypress.suppress_event_defaults=!1;keypress.sequence_delay=800;keypress.get_registered_combos=function(){return h};keypress.reset=function(){h=[]};keypress.combo=function(a,c,b){b==null&&(b=false);return keypress.register_combo({keys:a,on_keydown:c,prevent_default:b})};keypress.counting_combo=function(a,c,b){b==null&&(b=false);return keypress.register_combo({keys:a,is_counting:true,is_ordered:true,on_keydown:c,prevent_default:b})};keypress.sequence_combo=function(a,c,b){b==null&&(b=false);return keypress.register_combo({keys:a,
17
- on_keydown:c,is_sequence:true,prevent_default:b})};keypress.register_combo=function(a){var c,b;if(typeof a.keys==="string")a.keys=a.keys.split(" ");for(c in z)if(ga.call(z,c)){b=z[c];a[c]==null&&(a[c]=b)}if(fa(a)){h.push(a);return true}};keypress.register_many=function(a){var c,b,d,e;e=[];b=0;for(d=a.length;b<d;b++){c=a[b];e.push(keypress.register_combo(c))}return e};keypress.unregister_combo=function(a){var c,b,d;if(!a)return false;if(a.keys)return P(a);d=[];c=0;for(b=h.length;c<b;c++)(a=h[c])&&
18
- (A(keys,a.keys)?d.push(P(a)):d.push(void 0));return d};keypress.unregister_many=function(a){var c,b,d,e;e=[];b=0;for(d=a.length;b<d;b++){c=a[b];e.push(keypress.unregister_combo(c))}return e};keypress.listen=function(){return B=false};keypress.stop_listening=function(){return B=true};G=function(a){return r[a]};u={cmd:"metaKey",ctrl:"ctrlKey",shift:"shiftKey",alt:"altKey"};da={control:"ctrl",command:"cmd","break":"pause",windows:"cmd",option:"alt",caps_lock:"caps",apostrophe:"'",semicolon:";",tilde:"~",
19
- accent:"`",scroll_lock:"scroll",num_lock:"num"};s={"/":"?",".":">",",":"<","'":'"',";":":","[":"{","]":"}","\\":"|","`":"~","=":"+","-":"_",1:"!",2:"@",3:"#",4:"$",5:"%",6:"^",7:"&",8:"*",9:"(","0":")"};r={"0":"\\",8:"backspace",9:"tab",12:"num",13:"enter",16:"shift",17:"ctrl",18:"alt",19:"pause",20:"caps",27:"escape",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",44:"print",45:"insert",46:"delete",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",
20
- 56:"8",57:"9",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",91:"cmd",92:"cmd",93:"cmd",96:"num_0",97:"num_1",98:"num_2",99:"num_3",100:"num_4",101:"num_5",102:"num_6",103:"num_7",104:"num_8",105:"num_9",106:"num_multiply",107:"num_add",108:"num_enter",109:"num_subtract",110:"num_decimal",111:"num_divide",124:"print",144:"num",145:"scroll",186:";",187:"=",188:",",
21
- 189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",223:"`",224:"cmd",57392:"ctrl",63289:"num"};for(x in r)w=r[x],F.push(w);for(x in s)w=s[x],F.push(w);-1!==navigator.userAgent.indexOf("Mac OS X")&&(L="cmd");-1!==navigator.userAgent.indexOf("Opera")&&(r["17"]="cmd");N=function(a){return(document.attachEvent?document.readyState==="complete":document.readyState!=="loading")?a():setTimeout(function(){return N(a)},9)};N(function(){var a;a=function(a,b,d){if(a.addEventListener)return a.addEventListener(b,
22
- d);if(a.attachEvent)return a.attachEvent("on"+b,d)};a(document.body,"keydown",function(a){a=a||window.event;C(a,true);return T(a)});a(document.body,"keyup",function(a){a=a||window.event;return C(a,false)});return a(window,"blur",function(){var a,b,d;b=0;for(d=g.length;b<d;b++){a=g[b];J(a,{})}g=[];return[]})})}).call(this);