atlas_assets 0.6.4 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
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);