-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathtime.html
More file actions
90 lines (88 loc) · 3.06 KB
/
time.html
File metadata and controls
90 lines (88 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<!DOCTYPE html>
<html>
<head>
<title>TIME</title>
<style>
div {
font-family: Consolas, monospace;
font-weight: Bold;
font-size: 220px;
text-align: center;
}
</style>
</head>
<body>
<div id='time'></div>
<audio id="C4" preload="auto"><source src="tones/C4.mp3" type="audio/mpeg"><source src="tones/C4.ogg" type="audio/ogg"></audio>
<audio id="E4" preload="auto"><source src="tones/E4.mp3" type="audio/mpeg"><source src="tones/E4.ogg" type="audio/ogg"></audio>
<audio id="G4" preload="auto"><source src="tones/G4.mp3" type="audio/mpeg"><source src="tones/G4.ogg" type="audio/ogg"></audio>
<audio id="C5" preload="auto"><source src="tones/C5.mp3" type="audio/mpeg"><source src="tones/C5.ogg" type="audio/ogg"></audio>
<audio id="E5" preload="auto"><source src="tones/E5.mp3" type="audio/mpeg"><source src="tones/E5.ogg" type="audio/ogg"></audio>
<audio id="G5" preload="auto"><source src="tones/G5.mp3" type="audio/mpeg"><source src="tones/G5.ogg" type="audio/ogg"></audio>
<audio id="C6" preload="auto"><source src="tones/C6.mp3" type="audio/mpeg"><source src="tones/C6.ogg" type="audio/ogg"></audio>
<script>
let ids
if (navigator.maxTouchPoints) {
ids = [['C5', 'E5'], ['G5', 'C6']]
document.onclick = toggle
}
else {
ids = [['C4', 'E4'], ['G4', 'C5']]
document.getElementById('time').onclick = toggle
}
let w = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']
let speaking = false
let busy = false
let delay = 5
function sleep(ms) {
// a sleep function. usage:
// async func() { await sleep(1000) }
return new Promise(resolve => setTimeout(resolve, ms));
}
function getDate() {
// produces an array of useful date data for other functions
let d = new Date();
return [d.getHours(), d.getMinutes(), d.getSeconds(), `${d.getFullYear()}`.slice(2),
`${d.getMonth()+1}`.padStart(2, '0'),
`${d.getDate()}`.padStart(2, '0'), `${w[d.getDay()]}`,
' ', `${d}`.split(' ')[4]]
}
function update() {
// updates the display, and speaks the time if that's on
let [h,m,s, ...e] = getDate()
document.getElementById('time').innerHTML = e.join('');
if (speaking && !(m%delay) && !s) {
speak([h,m])
}
}
async function speak(t) {
// speaks array of two numbers "t" in binary.
if (busy) return
busy = true
for ([idx,v] of t.entries()) {
for (digit of v.toString().padStart(2, '0')) {
for (c of parseInt(digit).toString(2).split('')) {
document.getElementById(ids[idx][c]).play()
await sleep(700)
}
await sleep(500)
}
await sleep(500)
}
busy = false
}
function toggle() {
// toggle speech. prompt on activation. invalid interval cancels.
if (!speaking) {
let t = parseInt(prompt('Announce time now and on n-minute multiples (click/tap time again to disable):', '5'))
if (t>0) delay = t
else return
speak(getDate().slice(0,2))
}
speaking = !speaking
}
update();
setTimeout(function() {setInterval(update, 1000)}, 1000 - (new Date().getMilliseconds()));
</script>
</body>
</html>