More languages
More actions
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
const SENTENCE_REGEX = /[^.!?()"']*[.!?()"']*/g;
$("#content p").contents().filter(function() {
return this.nodeType == Node.TEXT_NODE;
}).each(function () {
this.replaceWith(...this.textContent.match(SENTENCE_REGEX).map(sentence =>
$(`<span class="tts-sentence">${sentence}</span>`)[0]));
});
const $ttsCaret = () => {
const $existing = $("#tts-caret");
if ($existing.length) {
return $existing.detach();
}
return $('<span id="tts-caret">|</span>');
};
let programmaticPlay = false;
let programmaticPause = false;
const audio = $('<audio controls muted loop id="tts-audio" src="//upload.wikimedia.org/wikipedia/commons/4/40/Toreador_song_cleaned.ogg"></audio>').appendTo("body")[0];
const stop = () => {
window.speechSynthesis.cancel();
$(".tts-button").css("display", "");
programmaticPause = true;
audio.pause();
};
const play = ($startingElement) => {
stop();
programmaticPlay = true;
audio.play();
let $selected = $startingElement.length ? $startingElement.parents().nextAll() : $("#content");
$selected.find(".tts-play").css("display", "none");
$selected.find(".tts-pause").css("display", "inline-block");
const $caret = $selected.find("#tts-caret");
$selected = $selected.find(".tts-sentence");
if ($caret.length) {
$selected = $selected.filter($caret.nextAll());
}
$selected.each(tts);
};
audio.onplay = () => programmaticPlay ? programmaticPlay = false : play($("#tts-caret"));
audio.onpause = () => programmaticPause ? programmaticPause = false : stop();
let queue = 0;
function tts() {
const utterance = new SpeechSynthesisUtterance(this.innerText);
const utteranceFinished = () => {
queue--;
if (queue <= 0) {
stop();
$("#tts-caret").remove();
} else {
$(this).after($ttsCaret());
}
};
utterance.onerror = utteranceFinished;
utterance.onend = utteranceFinished;
window.speechSynthesis.speak(utterance);
queue++;
};
mw.loader.using(["oojs-ui-core", "oojs-ui.styles.icons-media"], () => $(() => {
// $audio.on("ended", stop);
$("#content :header").append(() => {
const ttsPlayButton = new OO.ui.ButtonWidget({
framed: false,
icon: "play",
label: "Read aloud",
invisibleLabel: true,
title: "Icon only",
classes: ["mw-editsection", "tts-play", "tts-button"]
});
ttsPlayButton.on("click", () => play(ttsPlayButton.$element));
return ttsPlayButton.$element;
}).append(() => {
const ttsPauseButton = new OO.ui.ButtonWidget({
framed: false,
icon: "pause",
label: "Pause reading aloud",
invisibleLabel: true,
title: "Icon only",
classes: ["mw-editsection", "tts-pause", "tts-button"]
});
ttsPauseButton.on("click", stop);
return ttsPauseButton.$element;
});
}));