ime - initial version

This commit is contained in:
remi 2022-05-07 00:08:08 +02:00
parent e775b7d6a2
commit c01ebee0ae
4 changed files with 355 additions and 6 deletions

28
ime.html Normal file
View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ime test</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
@font-face {
font-family: "heonian";
src: url('HeonianAlone.otf');
}
textarea {
font-family: "heonian";
font-size: 32px;
}
</style>
</head>
<body>
<p>type in ime, wow!!!!!!!!!!!</p>
<textarea type="text" class="ime">
</textarea>
<script src="./ime.js" async defer></script>
</body>
</html>

271
ime.js Normal file
View File

@ -0,0 +1,271 @@
let input = [];
let currentWord = [];
let selected = -1;
window.onload = () => {
document.querySelectorAll(".ime").forEach(input => {
input.addEventListener("keydown", (key) => {
imeDown(key, input);
});
input.addEventListener("mousedown", (e) => {
e.preventDefault();
input.focus();
imeUpdate(input);
})
});
}
function imeDown(keyEvent, inputField) {
keyEvent.preventDefault();
switch (keyEvent.key) {
case "Backspace":
if (selected == -1) {
let latest = input[input.length]
console.log(latest);
if (currentWord.join("") == "") {
currentWord = input.pop() || [];
} else {
currentWord.pop();
}
} else {
input[selected].pop();
if (input[selected].join("") == "") {
input.splice(selected,1);
imeMove("left");
}
}
break;
case "Enter":
if (selected == -1) {
if (currentWord.join() == "") { //blame js :)
let s = document.createElement("p");
s.innerText = input.join("");
document.body.appendChild(s);
input = [];
selected = -1;
} else {
input.push(currentWord);
currentWord = [];
}
} else {
if (selected+1 >= input.length) {
selected = -1;
} else {
selected += 1;
}
}
imeReset();
break;
case "Space":
//adds a '
break;
case "ArrowLeft":
imeMove("left");
break;
case "ArrowRight":
imeMove("right");
break;
case "ArrowDown":
imeMove("start");
break;
case "ArrowUp":
imeMove("end");
break;
default:
imeInput(keyEvent.key);
if (selected == -1) {
currentWord = inputFull;
} else {
input[selected] = inputFull;
}
break;
}
imeUpdate(inputField);
}
function imeUpdate(inputField) {
let renderText = "";
input.forEach((w) => {
renderText += w.join("");
})
inputField.value = renderText + currentWord.join("");
if (selected == -1) {
inputField.setSelectionRange(renderText.length, renderText.length+currentWord.join("").length);
} else {
from = 0;
for (let x = 0; x < selected; x++) {
from += input[x].join("").length;
}
to = from+input[selected].join("").length;
inputField.setSelectionRange(from, to);
}
}
function clamp(min, max, value) {
return Math.max(min, Math.min(max, value));
}
function imeMove(direction) {
let d = 1;
if (currentWord.join("") != "") {
input.push(currentWord);
currentWord = [];
d = 2;
}
switch (direction) {
case "start":
selected = 0;
break;
case "end":
selected = -1;
break;
case "left":
if (selected == -1) selected = input.length;
selected -= 1 * d;
if (selected != -1) {
selected = clamp(0,input.length,selected);
//is there even a point in clamping it here,,,,
}
break;
case "right":
selected += 1 * d;
selected = clamp(0,input.length,selected);
//tbh same here, like.
//oh well ig ???/
if (selected == input.length) {
selected = -1;
}
break;
}
imeReset();
}
let inputState = 0; //STARTING, COMPOSTING, TRAILING, Fucking Nothing, ...cleanup
let stateState = 0; //depends on the state
let inputFull = [];
let inputCurrent = "";
let hVowels = { //standalone, composing, trailing
"a": ["0", "5", "A"],
"e": ["1", "6", "B"],
"i": ["2", "7", "C"],
"o": ["3", "8", "D"],
"u": ["4", "9", "E"]
};
let hConsonants = { //0 = standalone, 1 = composing, 2-6 = vowels
"g": "01",
"s": "02",
"r": "03",
"n": "04",
"c": "05",
"m": "06",
"j": "07",
"f": "08",
"t": "09",
"k": "0A",
"w": "0B",
"l": "0C",
"p": "0D",
"b": "0E",
"d": "0F",
"h": "10",
};
function getUnicodeVowel(vowel, sot) {
if (sot == "standalone") sot = 0;
if (sot == "composing") sot = 1;
if (sot == "trailing") sot = 2;
return String.fromCharCode(parseInt("E00" + hVowels[vowel][sot], 16));
}
function getUnicodeConsonant(consonant, scv) {
if (scv == "standalone") {scv = 0;}
else if (scv == "trailing") {scv = 1;}
else {scv = Number(hVowels[scv][0])+2}
return String.fromCharCode(parseInt("E" + hConsonants[consonant] + "" + scv, 16));
}
let hVowelsK = Object.keys(hVowels)
let hConsonantsK = Object.keys(hConsonants);
function debugInput(key) {
console.log("pre "+key+": inputstate - "+inputState +", statestate - "+ stateState);
console.log("inputfull: " + inputFull.join(" ") + ", inputcurrent:" + inputCurrent);
imeInput(key);
console.log("post "+key+": inputstate - "+inputState +", statestate - "+ stateState);
console.log("inputfull: " + inputFull.join(" ") + ", inputcurrent:" + inputCurrent);
console.log("------------------------------")
}
function imeReset() {
stateState = 0;
inputState = 0;
inputFull = [];
inputCurrent = "";
}
function imeInput(key) {
key = key.toLowerCase();
if (!hConsonantsK.includes(key) && !hVowelsK.includes(key)) return;
switch (inputState) {
case 0: //starting
if (stateState == 0) {
if (hVowelsK.includes(key)) {
inputFull.push(getUnicodeVowel(key, "standalone"));
inputState = 2;
} else {
inputFull.push(getUnicodeConsonant(key, "standalone"));
stateState = 1;
inputCurrent = key;
}
break;
} else if (stateState == 1) {
if (hVowelsK.includes(key)) {
inputState = 1;
stateState = 0;
} else {
inputFull.push(getUnicodeConsonant(key, "trailing"));
inputCurrent = key;
stateState = 2;
break;
}
} else if (stateState == 2) {
if (hVowelsK.includes(key)) {
inputState = 1;
stateState = 0;
} else break;
}
case 1: //composing
if (hVowelsK.includes(key)) {
inputState = 2;
inputFull.pop();
inputFull.push(getUnicodeConsonant(inputCurrent, key));
inputCurrent = "";
}
break;
case 2: //trailing
if (hVowelsK.includes(key)) {
inputFull.push(getUnicodeVowel(key, "trailing"));
stateState += 1;
} else {
inputFull.push(getUnicodeConsonant(key, "trailing"));
stateState += 1;
}
if (stateState == 2) {
stateState = 0;
inputState = 3;
}
break;
case 3: //do nothing (i.e "waiting 4 u 2 hit enter")
break;
case 4: //cleanup (reset vars)
stateState = 0;
inputCurrent = "";
break;
}
}

56
ime.txt Normal file
View File

@ -0,0 +1,56 @@
Description of IME:
5 states:
- STARTING
- COMPOSING
- TRAILING
Nomenclature: [Whole] / [Up|Down]
At any times, enter can be pressed to finish the input process.
Pressing enter with input process already finished will send the message.
STATE 1 - STARTING
Any first letter input is displayed as non-composing non-trailing symbol.
The big standalone variant.
Consonant [K]
Vowel [A]
If CONSONANT was inputted:
- Move to COMPOSING if next a VOWEL is inputted.
- Repeat this step if not, but adding the input as a trailing letter instead (uppercase). This can only happen once.
If VOWEL was inputted, move to TRAILING.
STATE 2 - COMPOSING
Only vowels are inputted. It is transcribed to heonian as a downside letter.
Vowel -> [K|A]
Move to TRAILING.
STATE 3 - TRAILING. (UP TO 2 TIMES)
Any letter input is displayed as a trailing symbol.
Aka uppercase.
1-3 -> [A][N| ]
1-3-3 -> [A][N| ][N| ]
1-2-3 -> [K|A][N| ]
1-2-3-3 -> [K|A][N| ][N| ]
1-1-2-3 -> [K][K|A][N| ]
1-1-2-3-3 -> [K][K|A][N| ][N| ]
This process can be repeated up to two times.
https://cronut.cafe/~lustlion/myrheon/test/
0xE -> Heonian Letter
next two digits: Vowels / What Consonant
last digit: Standalone / Trailing / Composing
simplified:
1. First letter inputted is standalone except if composing.
2. There can only be one composing per syllable, if it manages to go composing it goes to trailing.
3. You can input up to two letters before either composing or ending the syllable.
4. You can have 0, 1 or 2 trailing letters.

View File

@ -1,8 +1,3 @@
//since this _entire thing_ will be generated,
//you could "theoretically" (you definitive can)
//just sorta. skip the whole "scan all words" bit,
//which is why that's in a separate function
let words = {}
let currentFont = "r";
@ -116,7 +111,6 @@ function init() {
document.querySelector("#popup-container").style.pointerEvents = "none";
}
});
// above are commented out until wordlist is added~
document.querySelector("#font-button").addEventListener("click", () => {fontButton();});
}