Want to contribute? Fork me on Codeberg.org!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

223 lines
5.8 KiB

2 years ago
// modified from https://stackoverflow.com/a/14051331
// Issue is keycode conversion for non-alphanumeric keys (e.g. period)
// is not accurate
function convertKeyCode(evt) {
var chara = "";
var keyCode = (evt.which) ? evt.which : evt.keyCode;
var shift = evt.shiftKey;
if (keyCode == 19)
chara = "pause/break";
if (keyCode == 48)
chara = (shift) ? ")" : "0";
if (keyCode == 49)
chara = (shift) ? "!" : "1";
if (keyCode == 50)
chara = (shift) ? "@" : "2";
if (keyCode == 51)
chara = (shift) ? "#" : "3";
if (keyCode == 52)
chara = (shift) ? "$" : "4";
if (keyCode == 53)
chara = (shift) ? "%" : "5";
if (keyCode == 54)
chara = (shift) ? "^" : "6";
if (keyCode == 55)
chara = (shift) ? "&" : "7";
if (keyCode == 56)
chara = (shift) ? "*" : "8";
if (keyCode == 57)
chara = (shift) ? "(" : "9";
if (keyCode == 65)
chara = (shift) ? "A" : "a";
if (keyCode == 66)
chara = (shift) ? "B" : "b";
if (keyCode == 67)
chara = (shift) ? "C" : "c";
if (keyCode == 68)
chara = (shift) ? "D" : "d";
if (keyCode == 69)
chara = (shift) ? "E" : "e";
if (keyCode == 70)
chara = (shift) ? "F" : "f";
if (keyCode == 71)
chara = (shift) ? "G" : "g";
if (keyCode == 72)
chara = (shift) ? "H" : "h";
if (keyCode == 73)
chara = (shift) ? "I" : "i";
if (keyCode == 74)
chara = (shift) ? "J" : "j";
if (keyCode == 75)
chara = (shift) ? "K" : "k";
if (keyCode == 76)
chara = (shift) ? "L" : "l";
if (keyCode == 77)
chara = (shift) ? "M" : "m";
if (keyCode == 78)
chara = (shift) ? "N" : "n";
if (keyCode == 79)
chara = (shift) ? "O" : "o";
if (keyCode == 80)
chara = (shift) ? "P" : "p";
if (keyCode == 81)
chara = (shift) ? "Q" : "q";
if (keyCode == 82)
chara = (shift) ? "R" : "r";
if (keyCode == 83)
chara = (shift) ? "S" : "s";
if (keyCode == 84)
chara = (shift) ? "T" : "t";
if (keyCode == 85)
chara = (shift) ? "U" : "u";
if (keyCode == 86)
chara = (shift) ? "V" : "v";
if (keyCode == 87)
chara = (shift) ? "W" : "w";
if (keyCode == 88)
chara = (shift) ? "X" : "x";
if (keyCode == 89)
chara = (shift) ? "Y" : "y";
if (keyCode == 90)
chara = (shift) ? "Z" : "z";
if (keyCode == 93)
chara = "select key";
if (keyCode == 186 || keyCode == 59)
chara = ";";
if (keyCode == 187 || keyCode == 61)
chara = "=";
if (keyCode == 188)
chara = ",";
if (keyCode == 189 || keyCode == 173)
chara = "-";
if (keyCode == 190)
chara = ".";
if (keyCode == 191)
chara = "/";
if (keyCode == 192)
chara = "`";
if (keyCode == 219)
chara = (shift) ? "{" : "[";
if (keyCode == 220)
chara = "\\";
if (keyCode == 221)
chara = (shift) ? "}" : "]";
if (keyCode == 222)
chara = "'";
return chara;
}
const wordDisplay = document.getElementById("word");
const input = document.getElementById("input");
const timer = document.getElementById("timer");
const hintDisplay = document.getElementById("hint");
const leftShiftCode = 32; // space
const rightShiftCode = 16; // shift key
let leftShift = false;
let rightShift = false;
let inComposition = false;
addEventListener("keydown", event => {
switch(event.keyCode) {
case leftShiftCode:
leftShift = true;
event.preventDefault();
break;
case rightShiftCode:
rightShift = true;
event.preventDefault();
break;
}
});
addEventListener("keyup", event => {
switch(event.keyCode) {
case leftShiftCode:
leftShift = false;
break;
case rightShiftCode:
rightShift = false;
break;
}
});
addEventListener("compositionstart", event => inComposition = true);
addEventListener("compositionend", event => inComposition = false);
input.addEventListener("keydown", e => {
if (inComposition) {
return;
}
const pressed = convertKeyCode(e).toLowerCase(); // String.fromCharCode(e.keyCode).toLowerCase();
if (keymap[pressed] !== undefined) {
let valueIndex = 0;
if (leftShift && keymap[pressed][1]) {
valueIndex = 1;
} else if (rightShift && keymap[pressed][2]) {
valueIndex = 2;
}
input.value += keymap[pressed][valueIndex];
if (input.value == word) {
clearTimeout(timeout);
wordDisplay.style.color = "green";
wordDisplay.innerHTML += " ✅";
setTimeout(() => {
wordDisplay.style.color = "";
reset();
}, 1000);
}
e.preventDefault();
} else if (pressed == " ") {
e.preventDefault();
}
});
// window.requestAnimationFrame() might be better suited
// https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
let typeTimePerKana = 2; // in seconds
const typeTimePerKanaInput = document.getElementById("timePerKana");
typeTimePerKanaInput.value = typeTimePerKana;
typeTimePerKanaInput.addEventListener("change", (e) => {
typeTimePerKana = typeTimePerKanaInput.value;
});
const timerFPS = 60;
let timerTimeout = null;
let timeout = null;
let word = null;
const reset = () => {
input.value = "";
hint.innerHTML = "";
timer.value = 1;
word = words[Math.round(Math.random() * words.length)];
timeout = wordDisplay.innerHTML = word;
const typeTime = typeTimePerKana * word.length;
setTimeout(() => {
for (let i = 0; i < word.length; i++) {
const letter = word[i];
let key = null;
let index = null;
for (let otherKey in keymap) {
for (let i = 0; i < keymap[otherKey].length && !key; i++) {
if (keymap[otherKey][i] == letter) {
key = otherKey;
index = i;
}
}
}
let t = `<h3>${letter.toUpperCase()}`;
if (index > 0) {
t += "<kbd>";
if (index == 1) {
t += "&larr;";
} else if (index == 2) {
t += "&rarr;";
} else if (index == 3) {
t += "&uarr;";
}
t += "</kbd> + ";
}
t += `<kbd>${key}</kbd></h3>`;
hint.innerHTML += t;
}
}, typeTime * 1000);
clearInterval(timerTimeout);
timerTimeout = setInterval(() => {
timer.value -= (1 / timerFPS) / typeTime;
}, 1000 / timerFPS);
};
reset();