|
// retoor <retoor@molodetz.nl>
|
|
|
|
class SnekSpeaker extends HTMLElement {
|
|
|
|
_enabled = false
|
|
|
|
constructor() {
|
|
super();
|
|
this.attachShadow({ mode: 'open' });
|
|
|
|
// Optionally show something in the DOM
|
|
this.shadowRoot.innerHTML = `<slot></slot>`;
|
|
|
|
this._utterance = new SpeechSynthesisUtterance();
|
|
this._selectVoice();
|
|
}
|
|
toggle() {
|
|
if (window.speechSynthesis.speaking) {
|
|
window.speechSynthesis.pause();
|
|
} else {
|
|
window.speechSynthesis.resume();
|
|
}
|
|
}
|
|
stop() {
|
|
window.speechSynthesis.cancel();
|
|
}
|
|
disable() {
|
|
this._enabled = false
|
|
}
|
|
enable() {
|
|
this._enabled = true
|
|
}
|
|
set enabled(val) {
|
|
if (val) {
|
|
this.enable()
|
|
} else {
|
|
this.disable()
|
|
}
|
|
}
|
|
get enabled() {
|
|
return this._enabled
|
|
}
|
|
_selectVoice() {
|
|
const updateVoice = () => {
|
|
const voices = window.speechSynthesis.getVoices();
|
|
const maleEnglishVoices = voices.filter(voice =>
|
|
voice.lang.startsWith('en') && voice.name.toLowerCase().includes('male')
|
|
);
|
|
if (maleEnglishVoices.length > 0) {
|
|
this._utterance.voice = maleEnglishVoices[0];
|
|
}
|
|
};
|
|
|
|
updateVoice();
|
|
// Some browsers load voices asynchronously
|
|
window.speechSynthesis.onvoiceschanged = updateVoice;
|
|
}
|
|
|
|
speak(text) {
|
|
if(!this._enabled) return
|
|
|
|
if (!text) return;
|
|
|
|
this._utterance.text = text;
|
|
window.speechSynthesis.speak(this._utterance);
|
|
}
|
|
}
|
|
|
|
// Define the element
|
|
customElements.define('snek-speaker', SnekSpeaker);
|