Implement custom input handling for duration entry

This commit is contained in:
William Brawner 2021-04-18 21:22:58 -07:00
parent d7254da5a6
commit 2b33fd18f5
2 changed files with 160 additions and 114 deletions

View file

@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
@ -27,7 +28,8 @@
<meta name="msapplication-config" content="/img/browserconfig.xml">
<meta name="theme-color" content="#ffeb3b">
</head>
<body onload="loadTimers()">
<body onload="initApp()">
<header>
<h1>Interval Timer</h1>
</header>
@ -36,7 +38,8 @@
<div class="loader-overlay"></div>
</div>
<div class="no-timers">
<p style="max-width: 600px;">It looks like you haven't configured any timers yet. Click on the orange "+" icon below to get started!</p>
<p style="max-width: 600px;">It looks like you haven't configured any timers yet. Click on the orange "+" icon
below to get started!</p>
</div>
<div class="timers">
<div class="timer animate-repeat">
@ -60,10 +63,12 @@
</div>
</div>
<div class="timer-bottom">
<a id="back" class="menu-button" href="#"><img class="timer-control play" src="./img/skip-back.svg" /></a>
<a id="back" class="menu-button" href="#"><img class="timer-control play"
src="./img/skip-back.svg" /></a>
<a id="play" class="menu-button" href="#"><img class="timer-control play" src="./img/play.svg" /></a>
<a id="pause" class="menu-button" href="#"><img class="timer-control pause" src="./img/pause.svg" /></a>
<a id="next" class="menu-button" href="#"><img class="timer-control play" src="./img/skip-forward.svg" /></a>
<a id="next" class="menu-button" href="#"><img class="timer-control play"
src="./img/skip-forward.svg" /></a>
</div>
</div>
</div>
@ -83,31 +88,41 @@
</div>
<div class="input-wrapper">
<label for="warmUp">Warm-up:</label>
<input type="number" name="warmUp" />
<input class="duration" type="text" name="warmUp" onmouseup="handleDurationCaret(event)"
oninput="maskDuration(event)" onkeyup="handleDurationCaret(event)" regex="\d{2}h \d{2}m \d{2}s"
value="00h 00m 00s" />
</div>
<div class="input-wrapper">
<label for="low">Low-intensity:</label>
<input type="number" name="low" />
<input class="duration" type="text" name="low" onmouseup="handleDurationCaret(event)"
oninput="maskDuration(event)" onkeyup="handleDurationCaret(event)" regex="\d{2}h \d{2}m \d{2}s"
value="00h 00m 00s" />
</div>
<div class="input-wrapper">
<label for="high">High-intensity:</label>
<input type="number" name="high" />
<input class="duration" type="text" name="high" onmouseup="handleDurationCaret(event)"
oninput="maskDuration(event)" onkeyup="handleDurationCaret(event)" regex="\d{2}h \d{2}m \d{2}s"
value="00h 00m 00s" />
</div>
<div class="input-wrapper">
<label for="rest">Rest:</label>
<input type="number" name="rest" />
<input class="duration" type="text" name="rest" onmouseup="handleDurationCaret(event)"
oninput="maskDuration(event)" onkeyup="handleDurationCaret(event)" regex="\d{2}h \d{2}m \d{2}s"
value="00h 00m 00s" />
</div>
<div class="input-wrapper">
<label for="cool">Cooldown:</label>
<input type="number" name="cool" />
<input class="duration" type="text" name="cool" onmouseup="handleDurationCaret(event)"
oninput="maskDuration(event)" onkeyup="handleDurationCaret(event)" regex="\d{2}h \d{2}m \d{2}s"
value="00h 00m 00s" />
</div>
<div class="input-wrapper">
<label for="sets">Sets:</label>
<input type="number" name="sets">
<input type="number" name="sets" value="1">
</div>
<div class="input-wrapper">
<label for="rounds">Rounds:</label>
<input type="number" name="rounds">
<input type="number" name="rounds" value="1">
</div>
</form>
</div>
@ -120,4 +135,5 @@
}
</script>
</body>
</html>

View file

@ -54,6 +54,14 @@ let _state = {
let db = null;
let timerStore = null;
function initApp() {
Array.from(document.getElementsByClassName('duration')).forEach(input => {
console.log(input)
// input.addEventListener('beforeinput', maskDuration);
});
loadTimers();
}
function loadTimers() {
let state = copyState();
const dbRequest = window.indexedDB.open('interval-timer', 1);
@ -122,6 +130,28 @@ function cancelEdit() {
})
}
function maskDuration(event) {
const input = event.target;
let formatted = input.value.replace(/[^\d]/g, '');
if (event.inputType === "deleteContentBackward") {
formatted = formatted.slice(0, formatted.length - 1)
formatted = ("000000" + formatted).slice(-6)
} else if (event.inputType === 'insertText' && event.data.match(/\d/)) {
formatted = ("000000" + formatted).slice(-6)
}
input.value = `${formatted.slice(0, 2)}h ${formatted.slice(2, 4)}m ${formatted.slice(4, 6)}s`;
}
function isBeforeInputEventAvailable() {
return window.InputEvent && typeof InputEvent.prototype.getTargetRanges === "function";
}
function handleDurationCaret(event) {
const input = event.target;
const position = Math.min(11, input.value.length);
input.setSelectionRange(position, position);
}
function toggleTimer() {
let state = copyState();
if (state.timerJob != null) {