Normalize countdown keyboard adjustments and roll seconds across minutes
Co-authored-by: Shelley <shelley@exe.dev>
This commit is contained in:
parent
9c993beda8
commit
ebfd6e4ce1
3 changed files with 48 additions and 4 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { Countdown, integer } from './timer.mjs';
|
import { Countdown, integer, adjustTime } from './timer.mjs';
|
||||||
|
|
||||||
const timer = new Countdown();
|
const timer = new Countdown();
|
||||||
const minutes = document.querySelector('#minutes');
|
const minutes = document.querySelector('#minutes');
|
||||||
|
|
@ -55,8 +55,10 @@ for (const field of fields) {
|
||||||
if (field.readOnly || !['ArrowUp', 'ArrowDown'].includes(event.key)) return;
|
if (field.readOnly || !['ArrowUp', 'ArrowDown'].includes(event.key)) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const step = event.shiftKey ? 10n : 1n;
|
const step = event.shiftKey ? 10n : 1n;
|
||||||
const value = integer(field.value) + (event.key === 'ArrowUp' ? step : -step);
|
const adjusted = adjustTime(minutes.value, seconds.value, field.id,
|
||||||
field.value = String(value < 0n ? 0n : value);
|
event.key === 'ArrowUp' ? step : -step);
|
||||||
|
minutes.value = adjusted.minutes;
|
||||||
|
seconds.value = adjusted.seconds;
|
||||||
edited();
|
edited();
|
||||||
});
|
});
|
||||||
field.addEventListener('blur', () => {
|
field.addEventListener('blur', () => {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,16 @@ export function splitSeconds(seconds) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function adjustTime(minutes, seconds, field, delta) {
|
||||||
|
const total = integer(minutes) * 60n + integer(seconds);
|
||||||
|
if (field === 'minutes') {
|
||||||
|
const adjusted = total / 60n + delta;
|
||||||
|
return splitSeconds((adjusted < 0n ? 0n : adjusted) * 60n + total % 60n);
|
||||||
|
}
|
||||||
|
const adjusted = total + delta;
|
||||||
|
return splitSeconds(adjusted < 0n ? 0n : adjusted);
|
||||||
|
}
|
||||||
|
|
||||||
export class Countdown {
|
export class Countdown {
|
||||||
constructor(now = Date.now) {
|
constructor(now = Date.now) {
|
||||||
this.now = now;
|
this.now = now;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,38 @@
|
||||||
import { test } from 'node:test';
|
import { test } from 'node:test';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import { Countdown, integer, splitSeconds } from './timer.mjs';
|
import { Countdown, integer, splitSeconds, adjustTime } from './timer.mjs';
|
||||||
|
|
||||||
|
for (const [minutes, seconds, delta, expectedMinutes, expectedSeconds] of [
|
||||||
|
['1', '59', 1n, '2', '00'],
|
||||||
|
['2', '00', -1n, '1', '59'],
|
||||||
|
['2', '05', -10n, '1', '55'],
|
||||||
|
['1', '58', 10n, '2', '08'],
|
||||||
|
['2', '00', -10n, '1', '50'],
|
||||||
|
['0', '90', 1n, '1', '31'],
|
||||||
|
['0', '90', -10n, '1', '20'],
|
||||||
|
['0', '00', -1n, '0', '00'],
|
||||||
|
['0', '05', -10n, '0', '00'],
|
||||||
|
]) {
|
||||||
|
test(`seconds adjustment ${minutes}:${seconds} ${delta} normalizes and rolls`, () => {
|
||||||
|
assert.deepEqual(adjustTime(minutes, seconds, 'seconds', delta), {
|
||||||
|
minutes: expectedMinutes,
|
||||||
|
seconds: expectedSeconds,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
test('minute adjustments normalize first and keep minutes nonnegative', () => {
|
||||||
|
assert.deepEqual(adjustTime('0', '90', 'minutes', 1n), { minutes: '2', seconds: '30' });
|
||||||
|
assert.deepEqual(adjustTime('0', '90', 'minutes', -1n), { minutes: '0', seconds: '30' });
|
||||||
|
assert.deepEqual(adjustTime('1', '90', 'minutes', 10n), { minutes: '12', seconds: '30' });
|
||||||
|
assert.deepEqual(adjustTime('1', '90', 'minutes', -10n), { minutes: '0', seconds: '30' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('keyboard adjustments preserve large integer precision', () => {
|
||||||
|
assert.deepEqual(adjustTime('12345678901234567890', '59', 'seconds', 1n), {
|
||||||
|
minutes: '12345678901234567891', seconds: '00',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function fixture() {
|
function fixture() {
|
||||||
let now = 1000;
|
let now = 1000;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue