Cuckoo: single click gives one call, double-click strikes the hour
Nine cuckoos on an idle click is a lot. There's no singleclick event and click always fires before dblclick, so the single call is deferred by one double-click interval (260ms) and cancelled if a second click lands.
This commit is contained in:
parent
63902f095a
commit
6b6d80ded3
@ -25,8 +25,8 @@
|
|||||||
class="cuckoo__btn"
|
class="cuckoo__btn"
|
||||||
id="cuckoo-clock"
|
id="cuckoo-clock"
|
||||||
type="button"
|
type="button"
|
||||||
aria-label="Cuckoo clock — click to strike the hour"
|
aria-label="Cuckoo clock. Click for one call; double-click to strike the hour."
|
||||||
title="Strike the hour"
|
title="Click for one call · double-click strikes the hour"
|
||||||
>
|
>
|
||||||
<svg viewBox="0 0 200 272" class="cuckoo__svg" aria-hidden="true">
|
<svg viewBox="0 0 200 272" class="cuckoo__svg" aria-hidden="true">
|
||||||
<defs>
|
<defs>
|
||||||
@ -120,7 +120,9 @@
|
|||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<span class="cuckoo__hint">Strike the hour</span>
|
<span class="cuckoo__hint">
|
||||||
|
Click <span class="cuckoo__hint-sep">·</span> double-click strikes the hour
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<p class="cuckoo__live" role="status" aria-live="polite" id="cuckoo-live"></p>
|
<p class="cuckoo__live" role="status" aria-live="polite" id="cuckoo-live"></p>
|
||||||
@ -196,7 +198,7 @@
|
|||||||
return 0.78; // seconds until the next call may begin
|
return 0.78; // seconds until the next call may begin
|
||||||
};
|
};
|
||||||
|
|
||||||
clock.addEventListener("click", async () => {
|
const strike = async (calls) => {
|
||||||
if (striking) return;
|
if (striking) return;
|
||||||
striking = true;
|
striking = true;
|
||||||
|
|
||||||
@ -204,18 +206,42 @@
|
|||||||
ctx = ctx ?? new (window.AudioContext || window.webkitAudioContext)();
|
ctx = ctx ?? new (window.AudioContext || window.webkitAudioContext)();
|
||||||
if (ctx.state === "suspended") await ctx.resume();
|
if (ctx.state === "suspended") await ctx.resume();
|
||||||
|
|
||||||
const hour = new Date().getHours() % 12 || 12;
|
|
||||||
let t = ctx.currentTime + 0.05;
|
let t = ctx.currentTime + 0.05;
|
||||||
for (let i = 0; i < hour; i++) t += call(t);
|
for (let i = 0; i < calls; i++) t += call(t);
|
||||||
|
|
||||||
clock.classList.add("is-striking");
|
clock.classList.add("is-striking");
|
||||||
if (live) live.textContent = `Cuckoo ×${hour}`;
|
if (live) live.textContent = `Cuckoo ×${calls}`;
|
||||||
|
|
||||||
const total = (t - ctx.currentTime) * 1000;
|
const total = (t - ctx.currentTime) * 1000;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
clock.classList.remove("is-striking");
|
clock.classList.remove("is-striking");
|
||||||
striking = false;
|
striking = false;
|
||||||
}, total);
|
}, total);
|
||||||
|
};
|
||||||
|
|
||||||
|
// A single click is a greeting: one call. Double-click and it strikes the
|
||||||
|
// hour properly — which at eleven o'clock is a commitment.
|
||||||
|
//
|
||||||
|
// There is no `singleclick` event, and `click` always fires BEFORE `dblclick`.
|
||||||
|
// So hold the single call for one double-click interval and cancel it if a
|
||||||
|
// second click lands. 260 ms is comfortably under the platform's threshold
|
||||||
|
// but longer than a deliberate double-tap.
|
||||||
|
let pending = null;
|
||||||
|
|
||||||
|
clock.addEventListener("click", () => {
|
||||||
|
if (pending) return; // this is the 2nd of a pair — let dblclick take it
|
||||||
|
pending = setTimeout(() => {
|
||||||
|
pending = null;
|
||||||
|
strike(1);
|
||||||
|
}, 260);
|
||||||
|
});
|
||||||
|
|
||||||
|
clock.addEventListener("dblclick", () => {
|
||||||
|
if (pending) {
|
||||||
|
clearTimeout(pending);
|
||||||
|
pending = null;
|
||||||
|
}
|
||||||
|
strike(new Date().getHours() % 12 || 12);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -260,6 +286,7 @@
|
|||||||
transition: color 0.2s;
|
transition: color 0.2s;
|
||||||
}
|
}
|
||||||
.cuckoo__btn:hover .cuckoo__hint { color: var(--sl-color-accent); }
|
.cuckoo__btn:hover .cuckoo__hint { color: var(--sl-color-accent); }
|
||||||
|
.cuckoo__hint-sep { opacity: 0.5; margin: 0 0.15em; }
|
||||||
|
|
||||||
.cuckoo__live {
|
.cuckoo__live {
|
||||||
min-height: 1.2em;
|
min-height: 1.2em;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user