ResponsiveVoice.JS Test - JSFiddle
by MegaScience
HTML
<script src="https://code.responsivevoice.org/responsivevoice.js"></script>
<form name="TTS" onsubmit="TTSObj.processSubmit(); return false">
<fieldset>
<legend class="clickToDrag"><legend class="label"><label for="advanced">Advanced</label></legend>Responsive Voice
<br>Sound Player</legend>
<table>
<tbody>
<tr>
<td>
<select name="voice">
<option selected>UK English Female</option>
</select>
</td>
</tr>
<tr>
<td>
<textarea required name="text" type="text" placeholder="Type here.">Example text.</textarea>
</td>
</tr>
<tr>
<td class="sliders">
<div>
<output data-name="Volume" name="volumeOutName" id="volumeOutID">1</output>
<input type="range" name="volumeName" id="volumeID" value="1" min="0" max="1" step="0.001" oninput="volumeOutID.value = volumeID.value">
</div><br/>
<input name="advanced" id="advanced" type="checkbox" />
<div class="advanced">
<div>
<output data-name="Pitch" name="pitchOutName" id="pitchOutID">1</output>
<input type="range" name="pitchName" id="pitchID" value="1" min="0" max="2" step="0.01" oninput="pitchOutID.value = pitchID.value">
</div><br/>
<div>
<output data-name="Rate" name="rateOutName" id="rateOutID">1</output>
<input type="range" name="rateName" id="rateID" value="1" min="0" max="1.5" step="0.1" oninput="rateOutID.value = rateID.value">
</div>
</div>
</td>
</tr>
<tr>
<td>
<input name="submit" type="submit" value="Play Voice" />
</td>
</tr>
</tbody>
</table>
</fieldset>
</form>
<!--
<input onclick='responsiveVoice.speak("Hello World");' type='button' value='������ Play' />-->
CSS
html,
body {
height: 100%;
margin: 0;
}
body {
overflow: hidden;
}
form {
display: table;
position: relative;
margin: 0 auto;
}
fieldset {
box-sizing: border-box;
border: 1px solid black;
border-radius: 4px;
background-color: ivory;
padding: 5px;
}
legend.clickToDrag {
background-color: floralwhite;
text-align: center;
border: 1px dashed black;
border-radius: 7px;
}
select,
textarea {
margin-bottom: 5px;
}
output,
input[type="range"] {
clear: both;
}
input,
textarea {
width: 100%;
box-sizing: border-box;
}
td.sliders,
div.advanced {
/*display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: space-between;
align-items: stretch;*/
text-align: center;
}
td.sliders {
line-height: 0;
}
output {
line-height: 1em;
}
/*td.sliders > div,
td.sliders > div.advanced > div {
flex: 1 1 auto;
}*/
output[data-name]::before {
content: attr(data-name) ": ";
font-weight: bold;
}
form[name="TTS"] {
position: absolute;
z-index: 9;
}
form[name="TTS"] legend.clickToDrag {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
cursor: move;
z-index: 10;
}
input#advanced {
position: fixed;
left: -9999px;
}
legend.clickToDrag legend.label/*, label[for="advanced"]*/ {
position: absolute;
right: 0.5em;
top: 0.5em;
/*width: 1.3em;
height: 1.3em;
box-sizing: border-box;
background-color: #2980B9;
color: white;*/
border: 1px solid black;
background-color: white;
border-radius: 4px;
text-align: center;
}
input#advanced:not(:checked) + div.advanced {
display: none;
}
JavaScript
const TTSObj = {
form: document.forms.TTS,
processSubmit: function () {
if (responsiveVoice.voiceSupport()) {
if (!responsiveVoice.isPlaying()) {
if ((txt = this.form.text.value.trim()).length > 0) {
this.form.submit.disabled = true
this.form.submit.value = '...'
responsiveVoice.speak(txt, this.form.voice.value, {
pitch: this.form.pitchName.value,
rate: this.form.rateName.value,
volume: this.form.volumeName.value,
onstart: () => {
this.form.submit.value = 'Stop Voice'
this.form.submit.disabled = false
},
onend: () => this.form.submit.value = 'Play Voice'
})
} else alert('Please type a text to say.')
} else {
this.form.submit.value = 'Play Voice'
responsiveVoice.cancel()
}
} else alert('Browser does not support TTS.')
},
init: function () {
dragElement(this.form)
if (responsiveVoice.voiceSupport()) {
this.form.voice.remove(0)
for (let v of responsiveVoice.getVoices()) {
let o = document.createElement('option')
o.textContent = v.name
this.form.voice.add(o)
}
} else this.form.submit.disabled = true
}
}
// pitch, volume, rate, onstart, onend
// https://www.w3schools.com/howto/howto_js_draggable.asp
const dragElement = (elem, par) => {
let mouseDown = false
let positions = new Array(4).fill(0)
let bounds = {}
const within = (i, min, max) => Math.min(Math.max(i, min), max)
const dragMouseDown = e => {
mouseDown = true
e = eventType(e || window.event)
positions[3] = e.clientX
positions[4] = e.clientY
...