Implement custom input handling for duration entry
This commit is contained in:
parent
d7254da5a6
commit
2b33fd18f5
2 changed files with 160 additions and 114 deletions
|
@ -1,6 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="css/styles.css">
|
||||
|
@ -26,8 +27,9 @@
|
|||
<meta name="msapplication-TileImage" content="/img/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="/img/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffeb3b">
|
||||
</head>
|
||||
<body onload="loadTimers()">
|
||||
</head>
|
||||
|
||||
<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,17 +63,19 @@
|
|||
</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>
|
||||
<div class="new-timer">
|
||||
<div class="top-menu">
|
||||
<button class="menu-button" onclick="cancelEdit()" >✕</a>
|
||||
<button class="menu-button" onclick="saveTimer()" >✓</a>
|
||||
<button class="menu-button" onclick="cancelEdit()">✕</a>
|
||||
<button class="menu-button" onclick="saveTimer()">✓</a>
|
||||
</div>
|
||||
<form id="timer-setup" name="timer-setup">
|
||||
<div class="input-wrapper">
|
||||
|
@ -83,41 +88,52 @@
|
|||
</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>
|
||||
<button class="add-timer" onclick="editTimer()">+</button>
|
||||
<script async>
|
||||
if('serviceWorker' in navigator) {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker
|
||||
.register('/sw.js')
|
||||
.then(function() { console.log("Service Worker Registered"); });
|
||||
.then(function () { console.log("Service Worker Registered"); });
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue