Merge pull request #30 from seijihariki/keyboard_ìnput

Keyboard Input Support

Former-commit-id: 7559fa453face2012b0f0cd8d2b34fcf9aa31c1c
This commit is contained in:
tim h 2022-11-21 20:30:19 -06:00 committed by GitHub
commit fcc61c5710
4 changed files with 160 additions and 20 deletions

View file

@ -193,6 +193,7 @@
<script src="js/commands.js" type="text/javascript"></script> <script src="js/commands.js" type="text/javascript"></script>
<script src="js/index.js" type="text/javascript"></script> <script src="js/index.js" type="text/javascript"></script>
<script src="js/settingsbar.js" type="text/javascript"></script> <script src="js/settingsbar.js" type="text/javascript"></script>
<script src="js/shortcuts.js" type="text/javascript"></script>
</body> </body>
</html> </html>

View file

@ -2,6 +2,8 @@ const inputConfig = {
clickRadius: 10, // Radius to be considered a click (pixels). If farther, turns into a drag clickRadius: 10, // Radius to be considered a click (pixels). If farther, turns into a drag
clickTiming: 500, // Timing window to be considered a click (ms). If longer, turns into a drag clickTiming: 500, // Timing window to be considered a click (ms). If longer, turns into a drag
dClickTiming: 500, // Timing window to be considered a double click (ms). dClickTiming: 500, // Timing window to be considered a double click (ms).
keyboardHoldTiming: 100, // Timing window after which to consider holding a key (ms)
}; };
/** /**
@ -299,5 +301,118 @@ mouse.listen.window.right.onpaintend.on(() =>
*/ */
/** /**
* Mouse input processing * Keyboard input processing
*/ */
// Base object generator functions
const keyboard = {
keys: {},
isPressed(code) {
return this.keys[key].pressed;
},
isHeld(code) {
return !!this;
},
shortcuts: {},
onShortcut(shortcut, callback) {
/**
* Adds a shortcut handler (shorcut must be in format: {ctrl?: bool, alt?: bool, shift?: bool, key: string (code)})
* key must be the "code" parameter from keydown event; A key is "KeyA" for example
*/
if (this.shortcuts[shortcut.key] === undefined)
this.shortcuts[shortcut.key] = [];
this.shortcuts[shortcut.key].push({
ctrl: shortcut.ctrl,
alt: shortcut.alt,
shift: shortcut.shift,
id: guid(),
callback,
});
},
deleteShortcut(id) {
this.shortcuts.keys().forEach((key) => {
this.shortcuts[key] = this.shortcuts[key].filter((v) => v.id !== id);
});
},
listen: {
onkeydown: new Observer(),
onkeyup: new Observer(),
onkeyholdstart: new Observer(),
onkeyholdend: new Observer(),
onkeyclick: new Observer(),
onshortcut: new Observer(),
},
};
window.onkeydown = (evn) => {
keyboard.listen.onkeydown.emit({
code: evn.code,
key: evn.key,
evn,
});
keyboard.keys[evn.code] = {
pressed: true,
held: false,
_hold_to: setTimeout(() => {
keyboard.keys[evn.code].held = true;
delete keyboard.keys[evn.code]._hold_to;
keyboard.listen.onkeyholdstart.emit({
code: evn.code,
key: evn.key,
evn,
});
}, inputConfig.keyboardHoldTiming),
};
// Process shortcuts
const callbacks = keyboard.shortcuts[evn.code];
if (callbacks)
callbacks.forEach((callback) => {
if (
!!callback.ctrl === evn.ctrlKey &&
!!callback.alt === evn.altKey &&
!!callback.shift === evn.shiftKey
) {
keyboard.listen.onshortcut.emit({
code: evn.code,
key: evn.key,
id: callback.id,
evn,
});
callback.callback(evn);
}
});
};
window.onkeyup = (evn) => {
keyboard.listen.onkeyup.emit({
code: evn.code,
key: evn.key,
evn,
});
if (keyboard.keys[evn.code] && keyboard.keys[evn.code].held) {
keyboard.listen.onkeyholdend.emit({
code: evn.code,
key: evn.key,
evn,
});
} else {
keyboard.listen.onkeyclick.emit({
code: evn.code,
key: evn.key,
evn,
});
}
keyboard.keys[evn.code] = {
pressed: false,
held: false,
};
};

8
js/shortcuts.js Normal file
View file

@ -0,0 +1,8 @@
// Listen for shortcuts
keyboard.onShortcut({ctrl: true, key: "KeyZ"}, () => {
commands.undo();
});
keyboard.onShortcut({ctrl: true, key: "KeyY"}, () => {
commands.redo();
});

View file

@ -19,9 +19,25 @@ Observer.prototype = {
try { try {
await handler(msg); await handler(msg);
} catch (e) { } catch (e) {
console.warn('Observer failed to run handler'); console.warn("Observer failed to run handler");
console.warn(handler); console.warn(handler);
} }
}); });
}, },
}; };
/**
* Generates unique id
*/
const guid = (size = 3) => {
const s4 = () => {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
};
// returns id of format 'aaaaaaaa'-'aaaa'-'aaaa'-'aaaa'-'aaaaaaaaaaaa'
let id = "";
for (var i = 0; i < size - 1; i++) id += s4() + "-";
id += s4();
return id;
};