Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
FogNetwork
GitHub Repository: FogNetwork/Tsunami
Path: blob/main/public/games/files/astray/keyboard.js
1036 views
1
/*!
2
* KeyboardJS
3
*
4
* Copyright 2011, Robert William Hurst
5
* Licenced under the BSD License.
6
* See https://raw.github.com/RobertWHurst/KeyboardJS/master/license.txt
7
*/
8
(function (context, factory) {
9
if (typeof define === 'function' && define.amd) {
10
// AMD. Register as an anonymous module.
11
define(factory);
12
} else {
13
// Browser globals
14
context.k = context.KeyboardJS = factory();
15
}
16
}(this, function() {
17
18
//polyfills for ms's peice o' shit browsers
19
function bind(target, type, handler) { if (target.addEventListener) { target.addEventListener(type, handler, false); } else { target.attachEvent("on" + type, function(event) { return handler.call(target, event); }); } }
20
[].indexOf||(Array.prototype.indexOf=function(a,b,c){for(c=this.length,b=(c+~~b)%c;b<c&&(!(b in this)||this[b]!==a);b++);return b^c?b:-1;});
21
22
//locals
23
var locals = {
24
'us': {
25
"backspace": 8,
26
"tab": 9,
27
"enter": 13,
28
"shift": 16,
29
"ctrl": 17,
30
"alt": 18,
31
"pause": 19, "break": 19,
32
"capslock": 20,
33
"escape": 27, "esc": 27,
34
"space": 32, "spacebar": 32,
35
"pageup": 33,
36
"pagedown": 34,
37
"end": 35,
38
"home": 36,
39
"left": 37,
40
"up": 38,
41
"right": 39,
42
"down": 40,
43
"insert": 45,
44
"delete": 46,
45
"0": 48, "1": 49, "2": 50, "3": 51, "4": 52, "5": 53, "6": 54, "7": 55, "8": 56, "9": 57,
46
"a": 65, "b": 66, "c": 67, "d": 68, "e": 69, "f": 70, "g": 71, "h": 72, "i": 73, "j": 74, "k": 75, "l": 76, "m": 77, "n": 78, "o": 79, "p": 80, "q": 81, "r": 82, "s": 83, "t": 84, "u": 85, "v": 86, "w": 87, "x": 88, "y": 89, "z": 90,
47
"meta": 91, "command": 91, "windows": 91, "win": 91,
48
"_91": 92,
49
"select": 93,
50
"num0": 96, "num1": 97, "num2": 98, "num3": 99, "num4": 100, "num5": 101, "num6": 102, "num7": 103, "num8": 104, "num9": 105,
51
"multiply": 106,
52
"add": 107,
53
"subtract": 109,
54
"decimal": 110,
55
"divide": 111,
56
"f1": 112, "f2": 113, "f3": 114, "f4": 115, "f5": 116, "f6": 117, "f7": 118, "f8": 119, "f9": 120, "f10": 121, "f11": 122, "f12": 123,
57
"numlock": 144, "num": 144,
58
"scrolllock": 145, "scroll": 145,
59
"semicolon": 186,
60
"equal": 187, "equalsign": 187,
61
"comma": 188,
62
"dash": 189,
63
"period": 190,
64
"slash": 191, "forwardslash": 191,
65
"graveaccent": 192,
66
"openbracket": 219,
67
"backslash": 220,
68
"closebracket": 221,
69
"singlequote": 222
70
}
71
72
//If you create a new local please submit it as a pull request or post it in the issue tracker at
73
// http://github.com/RobertWhurst/KeyboardJS/issues/
74
}
75
76
//keys
77
var keys = locals['us'],
78
activeKeys = [],
79
activeBindings = {},
80
keyBindingGroups = [];
81
82
//adds keys to the active keys array
83
bind(document, "keydown", function(event) {
84
85
//lookup the key pressed and save it to the active keys array
86
for (var key in keys) {
87
if(keys.hasOwnProperty(key) && event.keyCode === keys[key]) {
88
if(activeKeys.indexOf(key) < 0) {
89
activeKeys.push(key);
90
}
91
}
92
}
93
94
//execute the first callback the longest key binding that matches the active keys
95
return executeActiveKeyBindings(event);
96
97
});
98
99
//removes keys from the active array
100
bind(document, "keyup", function (event) {
101
102
//lookup the key released and prune it from the active keys array
103
for(var key in keys) {
104
if(keys.hasOwnProperty(key) && event.keyCode === keys[key]) {
105
106
var iAK = activeKeys.indexOf(key);
107
108
if(iAK > -1) {
109
activeKeys.splice(iAK, 1);
110
}
111
}
112
}
113
114
//execute the end callback on the active key binding
115
return pruneActiveKeyBindings(event);
116
117
});
118
119
//bind to the window blur event and clear all pressed keys
120
bind(window, "blur", function() {
121
activeKeys = [];
122
123
//execute the end callback on the active key binding
124
return pruneActiveKeyBindings(event);
125
});
126
127
/**
128
* Generates an array of active key bindings
129
*/
130
function queryActiveBindings() {
131
var bindingStack = [];
132
133
//loop through the key binding groups by number of keys.
134
for(var keyCount = keyBindingGroups.length; keyCount > -1; keyCount -= 1) {
135
if(keyBindingGroups[keyCount]) {
136
var KeyBindingGroup = keyBindingGroups[keyCount];
137
138
//loop through the key bindings of the same key length.
139
for(var bindingIndex = 0; bindingIndex < KeyBindingGroup.length; bindingIndex += 1) {
140
var binding = KeyBindingGroup[bindingIndex],
141
142
//assume the binding is active till a required key is found to be unsatisfied
143
keyBindingActive = true;
144
145
//loop through each key required by the binding.
146
for(var keyIndex = 0; keyIndex < binding.keys.length; keyIndex += 1) {
147
var key = binding.keys[keyIndex];
148
149
//if the current key is not in the active keys array the mark the binding as inactive
150
if(activeKeys.indexOf(key) < 0) {
151
keyBindingActive = false;
152
}
153
}
154
155
//if the key combo is still active then push it into the binding stack
156
if(keyBindingActive) {
157
bindingStack.push(binding);
158
}
159
}
160
}
161
}
162
163
return bindingStack;
164
}
165
166
/**
167
* Collects active keys, sets active binds and fires on key down callbacks
168
* @param event
169
*/
170
function executeActiveKeyBindings(event) {
171
172
if(activeKeys < 1) {
173
return true;
174
}
175
176
var bindingStack = queryActiveBindings(),
177
spentKeys = [],
178
output;
179
180
//loop through each active binding
181
for (var bindingIndex = 0; bindingIndex < bindingStack.length; bindingIndex += 1) {
182
var binding = bindingStack[bindingIndex],
183
usesSpentKey = false;
184
185
//check each of the required keys. Make sure they have not been used by another binding
186
for(var keyIndex = 0; keyIndex < binding.keys.length; keyIndex += 1) {
187
var key = binding.keys[keyIndex];
188
if(spentKeys.indexOf(key) > -1) {
189
usesSpentKey = true;
190
break;
191
}
192
}
193
194
//if the binding does not use a key that has been spent then execute it
195
if(!usesSpentKey) {
196
197
//fire the callback
198
if(typeof binding.callback === "function") {
199
if(!binding.callback(event, binding.keys, binding.keyCombo)) {
200
output = false
201
}
202
}
203
204
//add the binding's combo to the active bindings array
205
if(!activeBindings[binding.keyCombo]) {
206
activeBindings[binding.keyCombo] = binding;
207
}
208
209
//add the current key binding's keys to the spent keys array
210
for(var keyIndex = 0; keyIndex < binding.keys.length; keyIndex += 1) {
211
var key = binding.keys[keyIndex];
212
if(spentKeys.indexOf(key) < 0) {
213
spentKeys.push(key);
214
}
215
}
216
}
217
}
218
219
//if there are spent keys then we know a binding was fired
220
// and that we need to tell jQuery to prevent event bubbling.
221
if(spentKeys.length) {
222
return false;
223
}
224
225
return output;
226
}
227
228
/**
229
* Removes no longer active keys and fires the on key up callbacks for associated active bindings.
230
* @param event
231
*/
232
function pruneActiveKeyBindings(event) {
233
var bindingStack = queryActiveBindings();
234
var output;
235
236
//loop through the active combos
237
for(var bindingCombo in activeBindings) {
238
if(activeBindings.hasOwnProperty(bindingCombo)) {
239
var binding = activeBindings[bindingCombo],
240
active = false;
241
242
//loop thorugh the active bindings
243
for(var bindingIndex = 0; bindingIndex < bindingStack.length; bindingIndex += 1) {
244
var activeCombo = bindingStack[bindingIndex].keyCombo;
245
246
//check to see if the combo is still active
247
if(activeCombo === bindingCombo) {
248
active = true;
249
break;
250
}
251
}
252
253
//if the combo is no longer active then fire its end callback and remove it
254
if(!active) {
255
256
if(typeof binding.endCallback === "function") {
257
if(!binding.endCallback(event, binding.keys, binding.keyCombo)) {
258
output = false
259
}
260
}
261
262
delete activeBindings[bindingCombo];
263
}
264
}
265
}
266
267
return output;
268
}
269
270
/**
271
* Binds a on key down and on key up callback to a key or key combo. Accepts a string containing the name of each
272
* key you want to bind to comma separated. If you want to bind a combo the use the plus sign to link keys together.
273
* Example: 'ctrl + x, ctrl + c' Will fire if Control and x or y are pressed at the same time.
274
* @param keyCombo
275
* @param callback
276
* @param endCallback
277
*/
278
function bindKey(keyCombo, callback, endCallback) {
279
280
function clear() {
281
if(keys && keys.length) {
282
var keyBindingGroup = keyBindingGroups[keys.length];
283
284
if(keyBindingGroup.indexOf(keyBinding) > -1) {
285
var index = keyBindingGroups[keys.length].indexOf(keyBinding);
286
keyBindingGroups[keys.length].splice(index, 1);
287
}
288
}
289
}
290
291
//create an array of combos from the first argument
292
var bindSets = keyCombo.toLowerCase().replace(/\s/g, '').split(',');
293
294
//create a binding for each key combo
295
for(var i = 0; i < bindSets.length; i += 1) {
296
297
//split up the keys
298
var keys = bindSets[i].split('+');
299
300
//if there are keys in the current combo
301
if(keys.length) {
302
if(!keyBindingGroups[keys.length]) { keyBindingGroups[keys.length] = []; }
303
304
//define the
305
var keyBinding = {
306
"callback": callback,
307
"endCallback": endCallback,
308
"keyCombo": bindSets[i],
309
"keys": keys
310
};
311
312
//save the binding sorted by length
313
keyBindingGroups[keys.length].push(keyBinding);
314
}
315
}
316
317
return {
318
"clear": clear
319
}
320
}
321
322
/**
323
* Binds keys or key combos to an axis. The keys should be in the following order; up, down, left, right. If any
324
* of the the binded key or key combos are active the callback will fire. The callback will be passed an array
325
* containing two numbers. The first represents x and the second represents y. Both have a possible range of -1,
326
* 0, or 1 depending on the axis direction.
327
* @param up
328
* @param down
329
* @param left
330
* @param right
331
* @param callback
332
*/
333
function bindAxis(up, down, left, right, callback) {
334
335
function clear() {
336
if(typeof clearUp === 'function') { clearUp(); }
337
if(typeof clearDown === 'function') { clearDown(); }
338
if(typeof clearLeft === 'function') { clearLeft(); }
339
if(typeof clearRight === 'function') { clearRight(); }
340
if(typeof timer === 'function') { clearInterval(timer); }
341
}
342
343
var axis = [0, 0];
344
345
if(typeof callback !== 'function') {
346
return false;
347
}
348
349
//up
350
var clearUp = bindKey(up, function () {
351
if(axis[0] === 0) {
352
axis[0] = -1;
353
}
354
}, function() {
355
axis[0] = 0;
356
}).clear;
357
358
//down
359
var clearDown = bindKey(down, function () {
360
if(axis[0] === 0) {
361
axis[0] = 1;
362
}
363
}, function() {
364
axis[0] = 0;
365
}).clear;
366
367
//left
368
var clearLeft = bindKey(left, function () {
369
if(axis[1] === 0) {
370
axis[1] = -1;
371
}
372
}, function() {
373
axis[1] = 0;
374
}).clear;
375
376
//right
377
var clearRight = bindKey(right, function () {
378
if(axis[1] === 0) {
379
axis[1] = 1;
380
}
381
}, function() {
382
axis[1] = 0;
383
}).clear;
384
385
var timer = setInterval(function(){
386
387
//NO CHANGE
388
if(axis[0] === 0 && axis[1] === 0) {
389
return;
390
}
391
392
//run the callback
393
callback(axis);
394
395
}, 1);
396
397
return {
398
"clear": clear
399
}
400
}
401
402
/**
403
* Clears all key and key combo binds containing a given key or keys.
404
* @param keys
405
*/
406
function unbindKey(keys) {
407
408
if(keys === 'all') {
409
keyBindingGroups = [];
410
return;
411
}
412
413
keys = keys.replace(/\s/g, '').split(',');
414
415
//loop through the key binding groups.
416
for(var iKCL = keyBindingGroups.length; iKCL > -1; iKCL -= 1) {
417
if(keyBindingGroups[iKCL]) {
418
var KeyBindingGroup = keyBindingGroups[iKCL];
419
420
//loop through the key bindings.
421
for(var iB = 0; iB < KeyBindingGroup.length; iB += 1) {
422
var keyBinding = KeyBindingGroup[iB],
423
remove = false;
424
425
//loop through the current key binding keys.
426
for(var iKB = 0; iKB < keyBinding.keys.length; iKB += 1) {
427
var key = keyBinding.keys[iKB];
428
429
//loop through the keys to be removed
430
for(var iKR = 0; iKR < keys.length; iKR += 1) {
431
var keyToRemove = keys[iKR];
432
if(keyToRemove === key) {
433
remove = true;
434
break;
435
}
436
}
437
if(remove) { break; }
438
}
439
if(remove) {
440
keyBindingGroups[iKCL].splice(iB, 1); iB -= 1;
441
if(keyBindingGroups[iKCL].length < 1) {
442
delete keyBindingGroups[iKCL];
443
}
444
}
445
}
446
}
447
}
448
}
449
450
/**
451
* Gets an array of active keys
452
*/
453
function getActiveKeys() {
454
return activeKeys;
455
}
456
457
/**
458
* Adds a new keyboard local not supported by keyboard JS
459
* @param local
460
* @param keys
461
*/
462
function addLocale(local, keys) {
463
locals[local] = keys;
464
}
465
466
/**
467
* Changes the keyboard local
468
* @param local
469
*/
470
function setLocale(local) {
471
if(locals[local]) {
472
keys = locals[local];
473
}
474
475
}
476
477
return {
478
"bind": {
479
"key": bindKey,
480
"axis": bindAxis
481
},
482
"activeKeys": getActiveKeys,
483
"unbind": {
484
"key": unbindKey
485
},
486
"locale": {
487
"add": addLocale,
488
"set": setLocale
489
}
490
}
491
}));
492