Skip to content

Commit 3c8d072

Browse files
committed
Project 23 complete
1 parent bed3bdd commit 3c8d072

File tree

3 files changed

+116
-22
lines changed

3 files changed

+116
-22
lines changed
+18-22
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,37 @@
11
<!DOCTYPE html>
22
<html lang="en">
3+
34
<head>
45
<meta charset="UTF-8">
56
<title>Speech Synthesis</title>
67
<link href='https://fonts.googleapis.com/css?family=Pacifico' rel='stylesheet' type='text/css'>
78
<link rel="stylesheet" href="style.css">
89
</head>
10+
911
<body>
1012

11-
<div class="voiceinator">
13+
<div class="voiceinator">
1214

13-
<h1>The Voiceinator 5000</h1>
15+
<h1>The Voiceinator 5000</h1>
1416

15-
<select name="voice" id="voices">
16-
<option value="">Select A Voice</option>
17-
</select>
17+
<select name="voice" id="voices">
18+
<option value="">Select A Voice</option>
19+
</select>
1820

19-
<label for="rate">Rate:</label>
20-
<input name="rate" type="range" min="0" max="3" value="1" step="0.1">
21+
<label for="rate">Rate:</label>
22+
<input name="rate" type="range" min="0" max="3" value="1" step="0.1">
2123

22-
<label for="pitch">Pitch:</label>
24+
<label for="pitch">Pitch:</label>
2325

24-
<input name="pitch" type="range" min="0" max="2" step="0.1">
25-
<textarea name="text">Hello! I love JavaScript 👍</textarea>
26-
<button id="stop">Stop!</button>
27-
<button id="speak">Speak</button>
26+
<input name="pitch" type="range" min="0" max="2" step="0.1">
27+
<textarea name="text">Hello! I love JavaScript 👍</textarea>
28+
<button id="stop">Stop!</button>
29+
<button id="speak">Speak</button>
2830

29-
</div>
31+
</div>
3032

31-
<script>
32-
const msg = new SpeechSynthesisUtterance();
33-
let voices = [];
34-
const voicesDropdown = document.querySelector('[name="voice"]');
35-
const options = document.querySelectorAll('[type="range"], [name="text"]');
36-
const speakButton = document.querySelector('#speak');
37-
const stopButton = document.querySelector('#stop');
38-
</script>
33+
<script src="typescripts.js"></script>
3934

4035
</body>
41-
</html>
36+
37+
</html>

23 - Speech Synthesis/typescripts.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const msg = new SpeechSynthesisUtterance();
2+
let voices = [];
3+
const voicesDropdown = document.querySelector('[name="voice"]');
4+
const options = document.querySelectorAll('[type="range"], [name="text"]');
5+
const speakButton = document.querySelector('#speak');
6+
const stopButton = document.querySelector('#stop');
7+
msg.text = document.querySelector('[name="text"]').value;
8+
function populateVoices() {
9+
voices = this.getVoices();
10+
voicesDropdown.innerHTML = (voices
11+
.map(voice => `<option value="${voice.name}">${voice.name} (${voice.lang})</option>`)
12+
.join(''));
13+
}
14+
function setVoice() {
15+
const newVoice = voices.find(voice => voice.name === this.value);
16+
if (newVoice) {
17+
msg.voice = newVoice;
18+
toggle();
19+
return true;
20+
}
21+
else {
22+
console.error('Selected voice not found');
23+
return false;
24+
}
25+
}
26+
function toggle(e, startOver = true) {
27+
speechSynthesis.cancel();
28+
if (startOver) {
29+
speechSynthesis.speak(msg);
30+
}
31+
}
32+
function setOption() {
33+
msg[this.name] = Number(this.value);
34+
toggle();
35+
}
36+
speechSynthesis.addEventListener('voiceschanged', populateVoices);
37+
voicesDropdown.addEventListener('change', setVoice);
38+
options.forEach(option => option.addEventListener('change', setOption));
39+
speakButton.addEventListener('click', toggle);
40+
stopButton.addEventListener('click', e => toggle(e, false));

23 - Speech Synthesis/typescripts.ts

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* JavaScript30 by Wes Bos, https://javascript30.com/
3+
* TypeScript implementation by Will Wager
4+
* Project: Speech Synthesis
5+
* Concepts: Web Speech API
6+
* Key takeaways: Specifying this in a handler function signature;
7+
* Set options with element name pattern (not very TS friendly).
8+
* Sidenotes: https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API
9+
* Chrome required.
10+
* Targeted es6 to get Array.find; Allowed implicit any for msg[input.name];
11+
* Compilation command:
12+
* tsc --removeComments --strictNullChecks --target es6 typescripts.ts
13+
*/
14+
15+
const msg = new SpeechSynthesisUtterance();
16+
let voices: SpeechSynthesisVoice[] = [];
17+
const voicesDropdown = document.querySelector('[name="voice"]')! as HTMLSelectElement;
18+
const options = document.querySelectorAll('[type="range"], [name="text"]');
19+
const speakButton = document.querySelector('#speak')! as HTMLButtonElement;
20+
const stopButton = document.querySelector('#stop')! as HTMLButtonElement;
21+
msg.text = (document.querySelector('[name="text"]')! as HTMLInputElement).value;
22+
23+
function populateVoices(this: SpeechSynthesis) {
24+
voices = this.getVoices();
25+
voicesDropdown.innerHTML = (voices
26+
.map(voice => `<option value="${voice.name}">${voice.name} (${voice.lang})</option>`)
27+
.join(''));
28+
}
29+
30+
function setVoice() {
31+
const newVoice = voices.find(voice => voice.name === this.value);
32+
if (newVoice) {
33+
msg.voice = newVoice;
34+
toggle();
35+
return true;
36+
} else {
37+
console.error('Selected voice not found');
38+
return false;
39+
}
40+
}
41+
42+
function toggle(e?: Event, startOver = true) {
43+
speechSynthesis.cancel();
44+
if (startOver) {
45+
speechSynthesis.speak(msg);
46+
}
47+
}
48+
49+
function setOption() {
50+
msg[this.name] = Number(this.value);
51+
toggle();
52+
}
53+
54+
speechSynthesis.addEventListener('voiceschanged', populateVoices);
55+
voicesDropdown.addEventListener('change', setVoice);
56+
options.forEach(option => option.addEventListener('change', setOption));
57+
speakButton.addEventListener('click', toggle);
58+
stopButton.addEventListener('click', e => toggle(e, false));

0 commit comments

Comments
 (0)