Add filtering buttons
This commit is contained in:
parent
fc1ff1b47b
commit
8c1a337e08
|
@ -9,6 +9,12 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<canvas id='canvas'></canvas>
|
<canvas id='canvas'></canvas>
|
||||||
|
<div id="toggleButtons">
|
||||||
|
<button id="toggleKanji">Kanji</button>
|
||||||
|
<button id="toggleHiragana">Hiragana</button>
|
||||||
|
<button id="toggleKatakana">Katakana</button>
|
||||||
|
<button id="toggleAll">All</button>
|
||||||
|
</div>
|
||||||
<div id='response'>None</div>
|
<div id='response'>None</div>
|
||||||
<button id="clear">Clear</button>
|
<button id="clear">Clear</button>
|
||||||
</body>
|
</body>
|
||||||
|
|
102
script.js
102
script.js
|
@ -1,6 +1,7 @@
|
||||||
const responseDiv = document.getElementById("response");
|
const responseDiv = document.getElementById("response");
|
||||||
const clearButton = document.getElementById("clear");
|
const clearButton = document.getElementById("clear");
|
||||||
const canvas = document.getElementById("canvas");
|
const canvas = document.getElementById("canvas");
|
||||||
|
const toggleButtons = Array.from(document.getElementById('toggleButtons').children);
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -40,8 +41,13 @@ const sendKanjiRequest = async (strokes) => fetch(API, {
|
||||||
.then(data => data.json())
|
.then(data => data.json())
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res[0] != "SUCCESS") throw Error(res[0]);
|
if (res[0] != "SUCCESS") throw Error(res[0]);
|
||||||
responseDiv.innerText = res[1][0][1].join(', ');
|
return res;
|
||||||
})
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const updateResponses = async (strokes) =>
|
||||||
|
sendKanjiRequest(strokes)
|
||||||
|
.then(res => responseDiv.innerText = postProcess(res[1][0][1]).join(', '))
|
||||||
.catch(err => console.error(err));
|
.catch(err => console.error(err));
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -67,8 +73,7 @@ let timerStart = 0;
|
||||||
let x = 0;
|
let x = 0;
|
||||||
let y = 0;
|
let y = 0;
|
||||||
|
|
||||||
/** Clear/initialize the newStroke variable after adding the current to globalStrokes */
|
const resetNewStroke = () => {
|
||||||
genNewStroke = () => {
|
|
||||||
newStroke = {
|
newStroke = {
|
||||||
'xs': [],
|
'xs': [],
|
||||||
'ys': [],
|
'ys': [],
|
||||||
|
@ -76,7 +81,7 @@ genNewStroke = () => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
genNewStroke();
|
resetNewStroke();
|
||||||
|
|
||||||
const addPointToNewStroke = (x, y) => {
|
const addPointToNewStroke = (x, y) => {
|
||||||
newStroke.xs.push(x);
|
newStroke.xs.push(x);
|
||||||
|
@ -90,7 +95,7 @@ const drawLine = (dx, dy) => {
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStroke = (newX, newY) => {
|
const updateStroke = (newX, newY) => {
|
||||||
drawLine(newX, newY);
|
drawLine(newX, newY);
|
||||||
addPointToNewStroke(newX, newY);
|
addPointToNewStroke(newX, newY);
|
||||||
x = newX;
|
x = newX;
|
||||||
|
@ -99,7 +104,7 @@ updateStroke = (newX, newY) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const initStroke = (initX, initY) => {
|
const initStroke = (initX, initY) => {
|
||||||
genNewStroke();
|
resetNewStroke();
|
||||||
timerStart = Date.now();
|
timerStart = Date.now();
|
||||||
x = initX;
|
x = initX;
|
||||||
y = initY;
|
y = initY;
|
||||||
|
@ -123,7 +128,7 @@ const endStroke = () => {
|
||||||
mouseDown = false;
|
mouseDown = false;
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
strokes.push([newStroke.xs, newStroke.ys, newStroke.times]);
|
strokes.push([newStroke.xs, newStroke.ys, newStroke.times]);
|
||||||
sendKanjiRequest(strokes);
|
updateResponses(strokes);
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearBoard = () => {
|
const clearBoard = () => {
|
||||||
|
@ -132,11 +137,78 @@ const clearBoard = () => {
|
||||||
responseDiv.innerHTML = 'None';
|
responseDiv.innerHTML = 'None';
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.onmousedown = event => initStroke(event.offsetX, event.offsetY);
|
/* -------------------------------------------------------------------------- */
|
||||||
canvas.onmousemove = event => updateStrokeIfPrevLineIsDone(event.offsetX, event.offsetY);
|
/* POST-PROCESSING AND FILTERING */
|
||||||
canvas.onmouseup = () => endStroke();
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
const getOffset = (x, y) => {
|
const ON_COLOR = '#4d9e2a';
|
||||||
|
const OFF_COLOR = '#fa2b2b';
|
||||||
|
|
||||||
|
const regexState = {
|
||||||
|
state: {
|
||||||
|
kanji: true,
|
||||||
|
hiragana: true,
|
||||||
|
katakana: true,
|
||||||
|
all: false
|
||||||
|
},
|
||||||
|
regex: {
|
||||||
|
kanji: RegExp(/\p{Script_Extensions=Han}/u),
|
||||||
|
hiragana: RegExp(/\p{Script_Extensions=Hiragana}/u),
|
||||||
|
katakana: RegExp(/\p{Script_Extensions=Katakana}/u),
|
||||||
|
all: RegExp(/./)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const genCharSet = id => id.slice(6).toLowerCase();
|
||||||
|
|
||||||
|
const colorButton = id => {
|
||||||
|
const button = document.getElementById(id);
|
||||||
|
button.style.backgroundColor =
|
||||||
|
regexState.state[genCharSet(id)] ? ON_COLOR : OFF_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleRegexState = event => {
|
||||||
|
const characterSet = genCharSet(event.target.id);
|
||||||
|
|
||||||
|
regexState.state[characterSet] = !regexState.state[characterSet];
|
||||||
|
colorButton(event.target.id);
|
||||||
|
if (strokes.length !== 0) updateResponses(strokes);
|
||||||
|
}
|
||||||
|
|
||||||
|
const genCombinedRegexString = () => '^[' +
|
||||||
|
Object.keys(regexState.regex)
|
||||||
|
.filter(key => regexState.state[key])
|
||||||
|
.map(key => regexState.regex[key].source)
|
||||||
|
.join('') + ']*$';
|
||||||
|
|
||||||
|
const postProcess = results => {
|
||||||
|
const regexString = regexState.state.all
|
||||||
|
? '.*'
|
||||||
|
: genCombinedRegexString();
|
||||||
|
|
||||||
|
const combinedRegex = RegExp(`${regexString}`, 'u');
|
||||||
|
return results.filter(result => combinedRegex.test(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* EVENT LISTENERS AND SETUP */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// Add eventlisteners and colors to all toggle-buttons
|
||||||
|
toggleButtons
|
||||||
|
.map(button => {
|
||||||
|
button.addEventListener('click', toggleRegexState);
|
||||||
|
colorButton(button.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.onmousedown = event => initStroke(event.offsetX, event.offsetY);
|
||||||
|
canvas.onmousemove = event => updateStrokeIfPrevLineIsDone(event.offsetX, event.offsetY);
|
||||||
|
canvas.onmouseup = () => endStroke();
|
||||||
|
clearButton.onclick = () => clearBoard();
|
||||||
|
|
||||||
|
// Touch support
|
||||||
|
|
||||||
|
const correctTouchOffset = (x, y) => {
|
||||||
const canvasRect = canvas.getBoundingClientRect();
|
const canvasRect = canvas.getBoundingClientRect();
|
||||||
return [x - canvasRect.left, y - canvasRect.top];
|
return [x - canvasRect.left, y - canvasRect.top];
|
||||||
}
|
}
|
||||||
|
@ -144,17 +216,15 @@ return [x - canvasRect.left, y - canvasRect.top];
|
||||||
canvas.ontouchstart = event => {
|
canvas.ontouchstart = event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
({clientX, clientY} = event.changedTouches[0]);
|
({clientX, clientY} = event.changedTouches[0]);
|
||||||
[x, y] = getOffset(clientX, clientY);
|
[x, y] = correctTouchOffset(clientX, clientY);
|
||||||
initStroke(x, y);
|
initStroke(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.ontouchmove = event => {
|
canvas.ontouchmove = event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
({clientX, clientY} = event.changedTouches[0]);
|
({clientX, clientY} = event.changedTouches[0]);
|
||||||
[x, y] = getOffset(clientX, clientY);
|
[x, y] = correctTouchOffset(clientX, clientY);
|
||||||
updateStrokeIfPrevLineIsDone(x, y);
|
updateStrokeIfPrevLineIsDone(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.ontouchend = () => endStroke();
|
canvas.ontouchend = () => endStroke();
|
||||||
|
|
||||||
clearButton.onclick = () => clearBoard();
|
|
17
style.css
17
style.css
|
@ -4,11 +4,23 @@ body {
|
||||||
|
|
||||||
#canvas {
|
#canvas {
|
||||||
border: solid black 2px;
|
border: solid black 2px;
|
||||||
border-radius: 5px;
|
border-radius: 10px;
|
||||||
background-color: wheat;
|
background-color: wheat;
|
||||||
margin: 2em;
|
margin: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#toggleButtons {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toggleButtons * {
|
||||||
|
padding: 0.2em 0.4em;
|
||||||
|
margin: 0em 0.2em;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: white;
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
#response {
|
#response {
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
@ -17,4 +29,7 @@ body {
|
||||||
#clear {
|
#clear {
|
||||||
font-size: 1.4em;
|
font-size: 1.4em;
|
||||||
padding: 0.5em 1em;
|
padding: 0.5em 1em;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: white;
|
||||||
|
background-color: #222222;
|
||||||
}
|
}
|
Reference in New Issue