Some user interface improvements

Close control on popup, progress bar when recording.
This commit is contained in:
Simon Brooke 2022-09-18 18:27:53 +01:00
parent 950eec5fed
commit 353e37cff5
No known key found for this signature in database
GPG key ID: A7A4F18D1D4DF987
4 changed files with 112 additions and 14 deletions

View file

@ -16,6 +16,7 @@ src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"
<body id="body"> <body id="body">
<div id="popup" <div id="popup"
style="display: none; border: thin solid gray; width: 10%"> style="display: none; border: thin solid gray; width: 10%">
<div id="closebox" onclick="$('#popup').hide();"></div>
<p id="character" <p id="character"
style="text-align: center; margin: 0; font-size: 4em;">?</p> style="text-align: center; margin: 0; font-size: 4em;">?</p>
<table id="controls" <table id="controls"
@ -23,23 +24,26 @@ src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"
<tr> <tr>
<th>Tutor</th> <th>Tutor</th>
<td> <td>
<button id="play-tutor"></button> <span id="play-tutor"></span>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>You</th> <th>You</th>
<td> <td>
<button id="play-student"></button> <span id="play-student"></span>
</td> </td>
<td> <td>
<button id="record-stop"></button> <span id="record-stop"></span>
</td> </td>
</tr> </tr>
<tr>
<td colspan="3" id="progress"></td>
</tr>
</table> </table>
</div> </div>
<h1>Muharni table</h1> <h1>Muharni table</h1>
<button <button
onclick="var l = document.getElementById('long'); var s = document.getElementById('short'); if (l.style.display == 'none') { l.style.display = 'block'; s.style.display = 'none'; } else { l.style.display = 'none'; s.style.display = 'block'; }">Toggle onclick="var l = document.getElementById('long'); var s = document.getElementById('short'); if (l.style.display == 'none') { l.style.display = 'block'; s.style.display = 'none'; } else { l.style.display = 'none'; s.style.display = 'block'; } $('#popup').hide();">Toggle
short/long</button> short/long</button>
<div id="long" style="display: block;"> <div id="long" style="display: block;">
<h2>Long forms</h2> <h2>Long forms</h2>

View file

@ -16,13 +16,57 @@
*/ */
const studentSounds = Array(80).fill(0).map(x => Array(13).fill(null)); 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) { function recordStudentSound(r, c) {
console.info("Entered recordStudentSound for row " + r + ", column " + c); console.info("Entered recordStudentSound for row " + r + ", column " + c);
if (Number.isInteger(r) && Number.isInteger(c)) { if (Number.isInteger(r) && Number.isInteger(c)) {
$('#record-student').css('color', 'green'); $('#record-stop').css('color', 'green');
try { try {
createProgressbar('progress', '5s');
navigator.mediaDevices.getUserMedia({ audio: true }) navigator.mediaDevices.getUserMedia({ audio: true })
.then(stream => { .then(stream => {
const mediaRecorder = new MediaRecorder(stream); const mediaRecorder = new MediaRecorder(stream);
@ -42,18 +86,19 @@ function recordStudentSound(r, c) {
if (audioChunks.length > 0) { if (audioChunks.length > 0) {
studentSounds[r][c] = new Blob(audioChunks); studentSounds[r][c] = new Blob(audioChunks);
$('#play-student').prop('disabled', false); $('#play-student').prop('disabled', false);
$('#play-student').css('color', 'black');
$("#play-student").on("click", function (e) { $("#play-student").on("click", function (e) {
console.log("Playing student sound for row " + r + ", column " + c); console.log("Playing student sound for row " + r + ", column " + c);
new Audio(URL.createObjectURL(studentSounds[r][c])).play(); new Audio(URL.createObjectURL(studentSounds[r][c])).play();
}); });
console.log("Successfully recorded student sound for row " + r + ", column " + c); console.log("Successfully recorded student sound for row " + r + ", column " + c);
} else { } else {
console.warn("Failed to record student sound for row " + r + ", column " + c); console.warn("Failed to record student sound for row " + r + ", column " + c);
window.alert("No sound detected. Check your microphone?"); window.alert("No sound detected. Check your microphone?");
} }
$('#record-student').css('color', 'red'); $('#record-stop').css('color', 'red');
}; };
setTimeout(() => { setTimeout(() => {
@ -115,7 +160,9 @@ $(document).ready(function () {
}); });
$("#play-student").off("click"); $("#play-student").off("click");
$('#play-student').css('color', 'gray');
if (studentAudio != null) { if (studentAudio != null) {
$('#play-student').css('color', 'black');
$("#play-student").on("click", function (e) { $("#play-student").on("click", function (e) {
console.log("Playing student sound for row " + row + ", column " + col); console.log("Playing student sound for row " + row + ", column " + col);
new Audio(URL.createObjectURL(studentAudio)).play(); new Audio(URL.createObjectURL(studentAudio)).play();

View file

@ -29,11 +29,49 @@ th {
font-size: 3em; 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 { #bug {
width: 1em; width: 1em;
height: 1em; height: 1em;
} }
#closebox {
color: red;
float: right;
}
#footer { #footer {
margin-top: 2em; margin-top: 2em;
border-top: thin solid gray; border-top: thin solid gray;
@ -51,4 +89,8 @@ th {
display: none; display: none;
background-color: whitesmoke; background-color: whitesmoke;
z-index: 10; z-index: 10;
} }
#record-stop {
color: red;
}

View file

@ -4,7 +4,7 @@
(:require [hiccup.core :refer [html]] (:require [hiccup.core :refer [html]]
[clojure.java.io :refer [input-stream]] [clojure.java.io :refer [input-stream]]
[clojure.string :as s]) [clojure.string :as s])
(:import [java.io StringWriter PrintWriter] (:import [java.io StringWriter]
[java.util Properties] [java.util Properties]
[org.w3c.tidy Tidy])) [org.w3c.tidy Tidy]))
@ -192,16 +192,20 @@
[:body {:id "body"} [:body {:id "body"}
[:div {:id "popup" [:div {:id "popup"
:style "display: none; border: thin solid gray; width: 10%"} :style "display: none; border: thin solid gray; width: 10%"}
[:div {:id "closebox"
:onclick "$('#popup').hide();"} "&#10006;"]
[:p {:id "character" :style "text-align: center; margin: 0; font-size: 4em;"} "?"] [:p {:id "character" :style "text-align: center; margin: 0; font-size: 4em;"} "?"]
[:table {:id "controls" :summary "Controls for audio playback and recording"} [:table {:id "controls" :summary "Controls for audio playback and recording"}
[:tr [:tr
[:th "Tutor"] [:th "Tutor"]
[:td [:button {:id "play-tutor"} [:td [:span {:id "play-tutor"}
"&#9658;"]]] "&#9658;"]]]
[:tr [:tr
[:th "You"] [:th "You"]
[:td [:button {:id "play-student"} "&#9658;"]] [:td [:span {:id "play-student"} "&#9658;"]]
[:td [:button {:id "record-stop"} "&#9210;"]]]]] [:td [:span {:id "record-stop"} "&#9210;"]]]
[:tr
[:td {:colspan 3 :id "progress"}]]]]
[:h1 (str title)] [:h1 (str title)]
[:button {:onclick "var l = document.getElementById('long'); [:button {:onclick "var l = document.getElementById('long');
var s = document.getElementById('short'); var s = document.getElementById('short');
@ -211,7 +215,8 @@
} else { } else {
l.style.display = 'none'; l.style.display = 'none';
s.style.display = 'block'; s.style.display = 'block';
}"} "Toggle short/long"] }
$('#popup').hide();"} "Toggle short/long"]
[:div {:id "long" [:div {:id "long"
:style "display: block;"} :style "display: block;"}
[:h2 "Long forms"] [:h2 "Long forms"]