mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-06-05 23:00:16 +00:00
Add speech button to sticky breadcrumb actions
- Click 🔊 to read page content aloud - Button changes to ⏹ while speaking - Click again to stop - Strips out navigation, buttons, and other non-content elements 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,57 @@ function changeFontSize(direction) {
|
||||
}
|
||||
}
|
||||
|
||||
// Page speech toggle (for breadcrumb button)
|
||||
function togglePageSpeech() {
|
||||
var btn = document.getElementById('speech-toggle-btn');
|
||||
if (!btn || !('speechSynthesis' in window)) return;
|
||||
|
||||
// If speaking, stop
|
||||
if (speechSynthesis.speaking || speechSynthesis.pending) {
|
||||
speechSynthesis.cancel();
|
||||
btn.classList.remove('speaking');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get page content to read
|
||||
var article = document.querySelector('article');
|
||||
if (!article) return;
|
||||
|
||||
var clone = article.cloneNode(true);
|
||||
// Remove elements we don't want to read
|
||||
clone.querySelectorAll('.breadcrumb, .sidenote, .marginnote, .toc, script, style, nav, .chapter-nav, .verse-nav, button, .breadcrumb-actions').forEach(function(el) {
|
||||
el.remove();
|
||||
});
|
||||
|
||||
var text = (clone.textContent || clone.innerText || '').trim();
|
||||
if (!text) return;
|
||||
|
||||
var utterance = new SpeechSynthesisUtterance(text);
|
||||
utterance.rate = 0.9;
|
||||
|
||||
// Try to use a good English voice
|
||||
var voices = speechSynthesis.getVoices();
|
||||
var englishVoice = voices.find(function(v) {
|
||||
return v.lang && v.lang.startsWith('en') && v.name.includes('Daniel');
|
||||
}) || voices.find(function(v) {
|
||||
return v.lang && v.lang.startsWith('en-GB');
|
||||
}) || voices.find(function(v) {
|
||||
return v.lang && v.lang.startsWith('en');
|
||||
});
|
||||
if (englishVoice) utterance.voice = englishVoice;
|
||||
|
||||
btn.classList.add('speaking');
|
||||
|
||||
utterance.onend = function() {
|
||||
btn.classList.remove('speaking');
|
||||
};
|
||||
utterance.onerror = function() {
|
||||
btn.classList.remove('speaking');
|
||||
};
|
||||
|
||||
speechSynthesis.speak(utterance);
|
||||
}
|
||||
|
||||
// Red letter toggle functionality
|
||||
(function() {
|
||||
// Check for saved red letter preference or default to enabled
|
||||
|
||||
@@ -420,6 +420,15 @@
|
||||
content: '☾';
|
||||
}
|
||||
|
||||
.breadcrumb-action-btn.speech-toggle::before {
|
||||
content: '🔊';
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.breadcrumb-action-btn.speech-toggle.speaking::before {
|
||||
content: '⏹';
|
||||
}
|
||||
|
||||
/* Font size scale classes */
|
||||
[data-font-size="small"] article {
|
||||
font-size: 0.9rem;
|
||||
@@ -1446,6 +1455,7 @@
|
||||
<span class="breadcrumb-actions">
|
||||
<button class="breadcrumb-action-btn font-decrease" title="Decrease font size" onclick="changeFontSize(-1)" aria-label="Decrease font size">A</button>
|
||||
<button class="breadcrumb-action-btn font-increase" title="Increase font size" onclick="changeFontSize(1)" aria-label="Increase font size">A</button>
|
||||
<button class="breadcrumb-action-btn speech-toggle" id="speech-toggle-btn" title="Read aloud" onclick="togglePageSpeech()" aria-label="Read page aloud"></button>
|
||||
<button class="breadcrumb-action-btn dark-toggle" title="Toggle dark mode" onclick="toggleDarkMode()" aria-label="Toggle dark mode"></button>
|
||||
</span>
|
||||
{% for crumb in breadcrumbs %}
|
||||
|
||||
Reference in New Issue
Block a user