diff --git a/src/resources/beeping/beep.ogg b/src/resources/beeping/beep.ogg new file mode 100644 index 0000000..7ca36de Binary files /dev/null and b/src/resources/beeping/beep.ogg differ diff --git a/src/resources/beeping/index.html b/src/resources/beeping/index.html new file mode 100644 index 0000000..c5bc016 --- /dev/null +++ b/src/resources/beeping/index.html @@ -0,0 +1,47 @@ + + + + + + Beeper! + + + + + + + + +
+

0.00

+
+

Do a beep at

+
+

second intervals

+
+

+ +
+
+

Volume (100%):

+ + +
+
+ +

Custom audio file:

+ +

default audio

+
+
+
+

Default beep sound by dklon

+
+ +
+ + + \ No newline at end of file diff --git a/src/resources/beeping/main.js b/src/resources/beeping/main.js new file mode 100644 index 0000000..65dc275 --- /dev/null +++ b/src/resources/beeping/main.js @@ -0,0 +1,160 @@ +var beeperBegun = false; +var beepInterval = 0; +var beepTimeCounter = 0; +var intervalId = 0; +var timeChangedWhileBegun = false; +var lastSec = -1; + +var showBeep = 0; + +var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); + +function main() { + timeChanged(); + updateInvalidness(); + + document.getElementById("plus").onclick = () => changeSeconds(1); + document.getElementById("minus").onclick = () => changeSeconds(-1); + document.getElementById("time-input").onchange = () => { + timeChanged(); + updateInvalidness(); + }; + document.getElementById("begin").onclick = toggle; + var audio = document.getElementById("audio"); + let slider = document.getElementById("volume-slider"); + document.getElementById("volume-slider").onchange = () => { + audio.volume = (slider.value / 100); + document.getElementById("volume").innerText = slider.value; + }; + + document.getElementById("file").addEventListener('change', () => { + var file = document.getElementById("file").files[0]; + document.getElementById("audiosource").setAttribute("src", URL.createObjectURL(file)); + document.getElementById("audio").load(); + }); + document.getElementById("audio").addEventListener("loadeddata", (event) => { + document.getElementById("audiotext").innerText = "Loaded audio"; + }); + document.getElementById("audio").addEventListener("loadstart", (event) => { + document.getElementById("audiotext").innerText = "Loading/Error"; + }); + + console.log("Beeper initialized!"); +} + +function isTimeValid() { + value = document.getElementById("time-input").value; + if (value != "" && (isNaN(value) || value < 1)) { + return false; + } + return true; +} + +function getTime() { + if (!isTimeValid()) { + return 1; + } + value = document.getElementById("time-input").value; + if (value == "") { + return 5; + } + return parseFloat(value); +} + + +function updateInvalidness() { + input = document.getElementById("time-input"); + if (!isTimeValid()) { + input.classList = "invalid"; + } else { + input.classList = ""; + } +} + +function changeSeconds(diff) { + value = document.getElementById("time-input").value; + if (!isNaN(value)) { + if (value == "") { + value = 5; + } + value = parseFloat(value); + if ((value + diff) >= 1 || diff > 0) { + input.value = value + diff; + updateInvalidness(); + timeChanged(); + } + } +} + +function timeChanged() { + if (isTimeValid()) { + if (beeperBegun) { + timeChangedWhileBegun = true; + return; + } + time = getTime(); + sec = Math.floor(time); + millis = Math.floor((time - sec) * 100) / 100; + millis = Intl.NumberFormat("en-US", { minimumFractionDigits: 2 }).format(millis); + millis = ("" + millis).slice(2); + + seconds = document.getElementById("seconds").innerText = sec; + milliseconds = document.getElementById("milliseconds").innerText = millis; + + beepInterval = getTime(); + beepTimeCounter = beepInterval; + } +} + +function toggle() { + var button = document.getElementById("begin"); + if (!beeperBegun && !isTimeValid()) { + return; + } + beeperBegun = !beeperBegun; + if (beeperBegun) { + button.innerText = "Stop!"; + intervalId = setInterval(update, 10); + } else { + button.innerText = "Begin!"; + clearInterval(intervalId); + if (timeChangedWhileBegun) { + timeChangedWhileBegun = false; + timeChanged(); + } + lastSec = -1; + showBeep = 0; + document.title = "Beeper!"; + + document.getElementById("audio").pause() + } +} + +function update() { + var seconds = document.getElementById("seconds"); + var milliseconds = document.getElementById("milliseconds"); + + beepTimeCounter -= 0.01; + showBeep -= 0.1; + if (beepTimeCounter <= 0) { + beepTimeCounter = beepInterval; + showBeep = 0.5; + document.getElementById("audio").fastSeek(0) + document.getElementById("audio").play() + } + var sec = Math.floor(beepTimeCounter); + seconds.innerText = sec; + var millis = Math.floor((beepTimeCounter - sec) * 100) / 100; + millis = Intl.NumberFormat("en-US", { minimumFractionDigits: 2 }).format(millis); + millis = ("" + millis).slice(2); + milliseconds.innerText = millis; + + if (lastSec != sec) { + lastSec = sec; + if (showBeep > 0) { + document.title = "Beeeep!"; + } else { + document.title = "Beeper - " + sec; + } + } +} \ No newline at end of file diff --git a/src/resources/beeping/style.css b/src/resources/beeping/style.css new file mode 100644 index 0000000..891646c --- /dev/null +++ b/src/resources/beeping/style.css @@ -0,0 +1,154 @@ +:root { + font-family: Helvetica, sans-serif; +} + +* { + margin: 0; + padding: 0; +} + +body { + width: 100%; + height: 100%; + background-color: #44444a; + font-size: 1.1em; +} + +.padding { + margin-bottom: 2em; +} + +.content { + padding-top: 10vh; + text-align: center; + color: #eee; +} + +.timer { + font-size: 15vw; + margin: 0; +} + +.timer-milliseconds { + font-size: 25%; + font-family: Iosevka, monospace; +} + +.inline { + display: inline-block; +} + +.input-container { + display: inline-block; + height: 1.9em; +} + +button { + display: inline-block; + border: none; + margin: 0; + padding: 0.3em; + padding-left: 0.6em; + padding-right: 0.6em; + font-size: 1em; + transition: 0.2s; + font-family: helvetica, sans-serif; + background-color: #ddd; + font-size: 1em; +} + +audio { + display: none; +} + +.scroller { + height: 100%; +} + +.scroller:first-child { + border-top-left-radius: 0.3em; + border-bottom-left-radius: 0.3em; + background-color: #eb6868; +} + +.scroller:last-child { + border-top-right-radius: 0.3em; + border-bottom-right-radius: 0.3em; + background-color: #77e777; +} + +.scroller:first-child:hover { + background-color: #dd5151; +} + +.scroller:last-child:hover { + background-color: #53db53; +} + +button:hover { + background-color: #c0c0c0; +} + +#time-input { + border: none; + background: none; + position: relative; + background-color: #eee; + max-width: 5ch; + height: 100%; + text-align: center; + transition: 0.2s; + font-size: 1em; + font-family: helvetica, sans-serif; +} + +#volume-slider { + display: inline-block; +} + +#time-input:hover { + background-color: #cbcbcb; +} + +#audiocontrols { + display: inline-flex; + width: 50vw; +} + +#audiocontrols > * { + width: 50%; +} + +#file { + width: 10em; +} + +.invalid { + background-color: #dd7979 +} + +.invalid:hover { + background-color: #c56161 +} + +.footnote { + position: absolute; + width: 100%; + text-align: center; + bottom: 0; + padding-bottom: 2em; +} + +.footnote a { + color: #c7c5ee; +} + +@media (max-width: 900px) { + .content { + padding: 0; + } + + .timer { + font-size: 40vw; + } +} \ No newline at end of file