diff --git a/resources/public/index.html b/resources/public/index.html index a4cafe9..446375c 100644 --- a/resources/public/index.html +++ b/resources/public/index.html @@ -16,6 +16,7 @@ src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"

Muharni table

Long forms

diff --git a/resources/public/scripts/muharni.js b/resources/public/scripts/muharni.js index d83502e..be6c5b4 100644 --- a/resources/public/scripts/muharni.js +++ b/resources/public/scripts/muharni.js @@ -16,13 +16,57 @@ */ const studentSounds = Array(80).fill(0).map(x => Array(13).fill(null)); +/** + * Creates a progressbar. Adapted from + * https://stackoverflow.com/questions/31109581/javascript-timer-progress-bar + * + * @param id the id of the div we want to transform in a progressbar + * @param duration the duration of the timer example: '10s' + * @param callback, optional function which is called when the progressbar reaches 0. + */ +function createProgressbar(id, duration) { + // We select the div that we want to turn into a progressbar + try { + const progressbar = document.getElementById(id); + progressbar.className = 'progressbar'; + + // We create the div that changes width to show progress + let progressbarinner = progressbar.querySelector('.inner'); + + if (progressbarinner == null) { + progressbarinner = document.createElement('div'); + progressbarinner.className = 'inner'; + + // Now we set the animation parameters + progressbarinner.style.animationDuration = duration; + + // Append the progressbar to the main progressbardiv + progressbar.appendChild(progressbarinner); + } + progressbarinner.addEventListener('animationend', () => { + while (progressbar.hasChildNodes()) { + progressbar.removeChild(progressbar.lastChild); + } + }); + + // When everything is set up we start the animation + progressbarinner.style.animationPlayState = 'running'; + } catch (e) { + console.warn("Failed to create progress bar because " + + e.message + + ". This does not, cosmically speaking, matter."); + } +} + function recordStudentSound(r, c) { console.info("Entered recordStudentSound for row " + r + ", column " + c); if (Number.isInteger(r) && Number.isInteger(c)) { - $('#record-student').css('color', 'green'); + $('#record-stop').css('color', 'green'); try { + createProgressbar('progress', '5s'); + navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { const mediaRecorder = new MediaRecorder(stream); @@ -42,18 +86,19 @@ function recordStudentSound(r, c) { if (audioChunks.length > 0) { studentSounds[r][c] = new Blob(audioChunks); - + $('#play-student').prop('disabled', false); + $('#play-student').css('color', 'black'); $("#play-student").on("click", function (e) { console.log("Playing student sound for row " + r + ", column " + c); new Audio(URL.createObjectURL(studentSounds[r][c])).play(); - }); + }); console.log("Successfully recorded student sound for row " + r + ", column " + c); } else { console.warn("Failed to record student sound for row " + r + ", column " + c); window.alert("No sound detected. Check your microphone?"); } - $('#record-student').css('color', 'red'); + $('#record-stop').css('color', 'red'); }; setTimeout(() => { @@ -115,7 +160,9 @@ $(document).ready(function () { }); $("#play-student").off("click"); + $('#play-student').css('color', 'gray'); if (studentAudio != null) { + $('#play-student').css('color', 'black'); $("#play-student").on("click", function (e) { console.log("Playing student sound for row " + row + ", column " + col); new Audio(URL.createObjectURL(studentAudio)).play(); diff --git a/resources/public/style.css b/resources/public/style.css index 33c7a14..2d83e6a 100644 --- a/resources/public/style.css +++ b/resources/public/style.css @@ -29,11 +29,49 @@ th { font-size: 3em; } +.progressbar { + width: 80%; + margin: 25px auto; + border: solid 1px #000; +} + +.progressbar .inner { + height: 15px; + animation: progressbar-countdown; + /* Placeholder, this will be updated using javascript */ + animation-duration: 40s; + /* We stop in the end */ + animation-iteration-count: 1; + /* Stay on pause when the animation is finished finished */ + animation-fill-mode: forwards; + /* We start paused, we start the animation using javascript */ + animation-play-state: paused; + /* We want a linear animation, ease-out is standard */ + animation-timing-function: linear; +} + +@keyframes progressbar-countdown { + 0% { + width: 100%; + background: #0F0; + } + + 100% { + width: 0%; + background: #F00; + } +} + #bug { width: 1em; height: 1em; } +#closebox { + color: red; + float: right; +} + #footer { margin-top: 2em; border-top: thin solid gray; @@ -51,4 +89,8 @@ th { display: none; background-color: whitesmoke; z-index: 10; -} \ No newline at end of file +} + +#record-stop { + color: red; +} diff --git a/src/muharni/construct.clj b/src/muharni/construct.clj index 59b7784..2b4f533 100644 --- a/src/muharni/construct.clj +++ b/src/muharni/construct.clj @@ -4,7 +4,7 @@ (:require [hiccup.core :refer [html]] [clojure.java.io :refer [input-stream]] [clojure.string :as s]) - (:import [java.io StringWriter PrintWriter] + (:import [java.io StringWriter] [java.util Properties] [org.w3c.tidy Tidy])) @@ -192,16 +192,20 @@ [:body {:id "body"} [:div {:id "popup" :style "display: none; border: thin solid gray; width: 10%"} + [:div {:id "closebox" + :onclick "$('#popup').hide();"} "✖"] [:p {:id "character" :style "text-align: center; margin: 0; font-size: 4em;"} "?"] [:table {:id "controls" :summary "Controls for audio playback and recording"} [:tr [:th "Tutor"] - [:td [:button {:id "play-tutor"} + [:td [:span {:id "play-tutor"} "►"]]] [:tr [:th "You"] - [:td [:button {:id "play-student"} "►"]] - [:td [:button {:id "record-stop"} "⏺"]]]]] + [:td [:span {:id "play-student"} "►"]] + [:td [:span {:id "record-stop"} "⏺"]]] + [:tr + [:td {:colspan 3 :id "progress"}]]]] [:h1 (str title)] [:button {:onclick "var l = document.getElementById('long'); var s = document.getElementById('short'); @@ -211,7 +215,8 @@ } else { l.style.display = 'none'; s.style.display = 'block'; - }"} "Toggle short/long"] + } + $('#popup').hide();"} "Toggle short/long"] [:div {:id "long" :style "display: block;"} [:h2 "Long forms"]