<!DOCTYPE html>
<html>
<head>
<style>
html,
body {
font: 400 16px/1.5 Consolas;
}
fieldset {
max-width: fit-content;
}
button {
font-size: 18px;
vertical-align: middle;
}
#time {
display: inline-block;
width: 6ch;
font: inherit;
vertical-align: middle;
text-align: center;
}
#morse {
display: inline-block;
width: 30ch;
margin-top: 0px;
font: inherit;
text-align: center;
}
[name=response] {
position: relative;
left: 9999px;
}
</style>
</head>
<body>
<form id='main' action='' method='post' target='response'>
<fieldset>
<legend>Morse Code</legend>
<label>Rate:
<input id='time' type='number' min='300' max='1000' pattern='[3-9][0-9]{2,3}' required value='350'>ms
</label>
<button type='submit'>
🔘➖
</button>
<br>
<label><small>0-Pause, 1-Dot, 2-Dash (no delimiters)</small></label>
<br>
<input id='morse' type='number' min='0' pattern='[012]+' required value='111000222000111'>
</fieldset>
</form>
<iframe name='response'></iframe>
<script>
const dot = new Audio(`https://od.lk/s/NzlfOTYzMDgzN18/dot.mp3`);
const dash = new Audio(`https://od.lk/s/NzlfOTYzMDgzNl8/dash.mp3`);
const sequencer = async(array, FW = 350) => {
const pause = () => {
return new Promise(resolve => {
setTimeout(() => resolve(dot.pause(), dash.pause()), FW);
});
}
const playDot = () => {
return new Promise(resolve => {
setTimeout(() => resolve(dot.play()), FW);
});
}
const playDash = () => {
return new Promise(resolve => {
setTimeout(() => resolve(dash.play()), FW + 100);
});
}
for (let seq of array) {
if (seq === 0) {
await pause();
}
if (seq === 1) {
await playDot();
}
if (seq === 2) {
await playDash();
}
}
}
const main = document.forms[0];
const ui = main.elements;
main.addEventListener('submit', function(e) {
let t = ui.time.valueAsNumber;
let m = ui.morse.value;
let seq = m.split('').map(num => Number(num));
sequencer(seq, t);
});
</script>
</body>
</html>