Skip to content

Commit 12cbc15

Browse files
kennethreitzclaude
andcommitted
Add Listen button across site for text-to-speech
- Chapter pages: Listen to full chapter text - Bible stories (adult & kids): Listen button at bottom with PDF - Resource index pages (Ten Commandments, Beatitudes, etc.) - Resource detail pages (individual commandments, etc.) - Twelve Apostles, Biblical Prophets, Names of God - Parables, Women of the Bible, Fruits of the Spirit All pages use consistent .action-btn styling and KJVSpeech integration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a8b64d6 commit 12cbc15

File tree

11 files changed

+470
-143
lines changed

11 files changed

+470
-143
lines changed

kjvstudy_org/templates/biblical_prophets.html

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,12 @@
4242
}
4343

4444
.prophets-actions {
45+
display: flex;
46+
gap: 0.75rem;
4547
margin: 1rem 0 1.5rem;
4648
}
4749

48-
.prophet-download-btn {
50+
.action-btn {
4951
display: inline-flex;
5052
align-items: center;
5153
gap: 0.35rem;
@@ -56,20 +58,27 @@
5658
border: 1px solid var(--border-color, #ddd);
5759
border-radius: 4px;
5860
text-decoration: none;
61+
cursor: pointer;
5962
transition: all 0.2s;
6063
}
6164

62-
.prophet-download-btn:hover {
65+
.action-btn:hover {
6366
background: var(--bg-color, #fff);
6467
border-color: var(--link-color);
6568
color: var(--link-color);
6669
}
6770

68-
.prophet-download-btn svg {
71+
.action-btn svg {
6972
width: 14px;
7073
height: 14px;
7174
}
7275

76+
.action-btn.playing {
77+
background: var(--link-color);
78+
color: white;
79+
border-color: var(--link-color);
80+
}
81+
7382
.prophet-description {
7483
max-width: 60%;
7584
font-size: 1.2rem;
@@ -159,7 +168,6 @@
159168

160169
@media print {
161170
.prophets-actions,
162-
.prophet-download-btn,
163171
.toc {
164172
display: none !important;
165173
}
@@ -195,16 +203,22 @@
195203
<h1>Biblical Prophets</h1>
196204
<p class="subtitle">Messengers of the Most High</p>
197205

198-
{% if resource_pdf_available %}
199206
<div class="prophets-actions">
200-
<a class="prophet-download-btn" href="/biblical-prophets/pdf">
207+
<button class="action-btn" id="listen-btn">
208+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
209+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" />
210+
</svg>
211+
Listen
212+
</button>
213+
{% if resource_pdf_available %}
214+
<a class="action-btn" href="/biblical-prophets/pdf">
201215
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
202216
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
203217
</svg>
204-
Download All Prophets (PDF)
218+
Download PDF
205219
</a>
220+
{% endif %}
206221
</div>
207-
{% endif %}
208222

209223
<nav class="toc" id="toc">
210224
<h2>Contents</h2>
@@ -279,6 +293,20 @@ <h2>The Prophetic Office</h2>
279293

280294
<script>
281295
document.addEventListener('DOMContentLoaded', function() {
296+
// Listen button handler
297+
var listenBtn = document.getElementById('listen-btn');
298+
if (listenBtn) {
299+
listenBtn.addEventListener('click', function() {
300+
var paragraphs = document.querySelectorAll('.intro-text, .prophet-description p, .verse-text');
301+
var text = Array.from(paragraphs).map(function(p) {
302+
return p.textContent.trim();
303+
}).join(' ');
304+
if (window.KJVSpeech && text) {
305+
window.KJVSpeech.speak(text);
306+
}
307+
});
308+
}
309+
282310
// Generate TOC from h2 and h3 headings
283311
const tocList = document.getElementById('toc-list');
284312
const headings = document.querySelectorAll('section h2, section h3, section article h3');
@@ -297,7 +325,7 @@ <h2>The Prophetic Office</h2>
297325
});
298326

299327
// Simple keyboard navigation
300-
KJVNav.initSimpleNav('.prophet-download-btn, .intro-text, .prophet-name, .prophet-description > p, .verse-item');
328+
KJVNav.initSimpleNav('.action-btn, .intro-text, .prophet-name, .prophet-description > p, .verse-item');
301329
});
302330
</script>
303331
{% endblock %}

kjvstudy_org/templates/chapter.html

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,12 @@ <h1>{{ book }} {{ chapter }}</h1>
538538
PDF
539539
</a>
540540
{% endif %}
541+
<button class="action-btn listen-btn" id="chapter-listen-btn">
542+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
543+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" />
544+
</svg>
545+
Listen
546+
</button>
541547
</div>
542548

543549
<section{% if is_poetry %} class="poetry-chapter"{% endif %}>
@@ -619,6 +625,33 @@ <h3 class="section-heading">{{ section_headings[verse.verse] }}</h3>
619625

620626
<script>
621627
document.addEventListener('DOMContentLoaded', function() {
628+
// Listen button - read chapter aloud
629+
var listenBtn = document.getElementById('chapter-listen-btn');
630+
var isListening = false;
631+
632+
if (listenBtn) {
633+
listenBtn.addEventListener('click', function() {
634+
if (isListening) {
635+
if (window.KJVSpeech) window.KJVSpeech.stop();
636+
listenBtn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" /></svg> Listen';
637+
isListening = false;
638+
return;
639+
}
640+
641+
// Gather all verse text
642+
var verses = document.querySelectorAll('p[id^="verse-"]');
643+
var text = Array.from(verses).map(function(v) {
644+
return v.textContent.replace(/^\d+\s*/, '').trim();
645+
}).join('. ');
646+
647+
if (window.KJVSpeech && text) {
648+
window.KJVSpeech.speak(text);
649+
listenBtn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 10a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z" /></svg> Stop';
650+
isListening = true;
651+
}
652+
});
653+
}
654+
622655
// Function to link verse references
623656
function linkVerseReferences(element) {
624657
let html = element.innerHTML;

kjvstudy_org/templates/fruits_of_spirit.html

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,12 @@
8181
}
8282

8383
.fruits-actions {
84+
display: flex;
85+
gap: 0.75rem;
8486
margin: 1rem 0 1.5rem;
8587
}
8688

87-
.fruits-download-btn {
89+
.action-btn {
8890
display: inline-flex;
8991
align-items: center;
9092
gap: 0.35rem;
@@ -95,16 +97,17 @@
9597
border: 1px solid var(--border-color, #ddd);
9698
border-radius: 4px;
9799
text-decoration: none;
100+
cursor: pointer;
98101
transition: all 0.2s;
99102
}
100103

101-
.fruits-download-btn:hover {
104+
.action-btn:hover {
102105
background: var(--bg-color, #fff);
103106
border-color: var(--link-color);
104107
color: var(--link-color);
105108
}
106109

107-
.fruits-download-btn svg {
110+
.action-btn svg {
108111
width: 14px;
109112
height: 14px;
110113
}
@@ -159,7 +162,6 @@
159162

160163
@media print {
161164
.fruits-actions,
162-
.fruits-download-btn,
163165
.toc {
164166
display: none !important;
165167
}
@@ -195,16 +197,22 @@
195197
<h1>Fruits of the Spirit</h1>
196198
<p class="subtitle">The Nine Graces of Galatians 5:22-23</p>
197199

198-
{% if pdf_available %}
199200
<div class="fruits-actions">
200-
<a class="fruits-download-btn" href="/fruits-of-the-spirit/pdf">
201+
<button class="action-btn" id="listen-btn">
202+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
203+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" />
204+
</svg>
205+
Listen
206+
</button>
207+
{% if pdf_available %}
208+
<a class="action-btn" href="/fruits-of-the-spirit/pdf">
201209
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
202210
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
203211
</svg>
204-
Download All Studies (PDF)
212+
Download PDF
205213
</a>
214+
{% endif %}
206215
</div>
207-
{% endif %}
208216

209217
<nav class="toc" id="toc">
210218
<h2>Contents</h2>
@@ -285,6 +293,20 @@ <h2>The Spirit's Work in Sanctification</h2>
285293

286294
<script>
287295
document.addEventListener('DOMContentLoaded', function() {
296+
// Listen button handler
297+
var listenBtn = document.getElementById('listen-btn');
298+
if (listenBtn) {
299+
listenBtn.addEventListener('click', function() {
300+
var paragraphs = document.querySelectorAll('.intro-text, .fruit-description p, .verse-text');
301+
var text = Array.from(paragraphs).map(function(p) {
302+
return p.textContent.trim();
303+
}).join(' ');
304+
if (window.KJVSpeech && text) {
305+
window.KJVSpeech.speak(text);
306+
}
307+
});
308+
}
309+
288310
// Generate TOC from h2 and h3 headings
289311
const tocList = document.getElementById('toc-list');
290312
const headings = document.querySelectorAll('section h2, section h3, section article h3');
@@ -303,7 +325,7 @@ <h2>The Spirit's Work in Sanctification</h2>
303325
});
304326

305327
// Simple keyboard navigation
306-
KJVNav.initSimpleNav('.fruits-download-btn, .intro-text, .fruit-name, .fruit-description > p, .verse-item');
328+
KJVNav.initSimpleNav('.action-btn, .intro-text, .fruit-name, .fruit-description > p, .verse-item');
307329
});
308330
</script>
309331
{% endblock %}

kjvstudy_org/templates/names_of_god.html

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,12 @@
8181
}
8282

8383
.names-actions {
84+
display: flex;
85+
gap: 0.75rem;
8486
margin: 1rem 0 1.5rem;
8587
}
8688

87-
.names-download-btn {
89+
.action-btn {
8890
display: inline-flex;
8991
align-items: center;
9092
gap: 0.35rem;
@@ -95,20 +97,27 @@
9597
border: 1px solid var(--border-color, #ddd);
9698
border-radius: 4px;
9799
text-decoration: none;
100+
cursor: pointer;
98101
transition: all 0.2s;
99102
}
100103

101-
.names-download-btn:hover {
104+
.action-btn:hover {
102105
background: var(--bg-color, #fff);
103106
border-color: var(--link-color);
104107
color: var(--link-color);
105108
}
106109

107-
.names-download-btn svg {
110+
.action-btn svg {
108111
width: 14px;
109112
height: 14px;
110113
}
111114

115+
.action-btn.playing {
116+
background: var(--link-color);
117+
color: white;
118+
border-color: var(--link-color);
119+
}
120+
112121
.intro-text {
113122
max-width: 60%;
114123
font-size: 1.2rem;
@@ -159,7 +168,6 @@
159168

160169
@media print {
161170
.names-actions,
162-
.names-download-btn,
163171
.toc {
164172
display: none !important;
165173
}
@@ -191,16 +199,22 @@
191199
<h1>Names of God</h1>
192200
<p class="subtitle">The Divine Names Revealed in Holy Scripture</p>
193201

194-
{% if pdf_available %}
195202
<div class="names-actions">
196-
<a class="names-download-btn" href="/names-of-god/pdf">
203+
<button class="action-btn" id="listen-btn">
204+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
205+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" />
206+
</svg>
207+
Listen
208+
</button>
209+
{% if pdf_available %}
210+
<a class="action-btn" href="/names-of-god/pdf">
197211
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
198212
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
199213
</svg>
200-
Download All Names (PDF)
214+
Download PDF
201215
</a>
216+
{% endif %}
202217
</div>
203-
{% endif %}
204218

205219
<nav class="toc" id="toc">
206220
<h2>Contents</h2>
@@ -275,6 +289,20 @@ <h2>The Significance of Divine Names</h2>
275289

276290
<script>
277291
document.addEventListener('DOMContentLoaded', function() {
292+
// Listen button handler
293+
var listenBtn = document.getElementById('listen-btn');
294+
if (listenBtn) {
295+
listenBtn.addEventListener('click', function() {
296+
var paragraphs = document.querySelectorAll('.intro-text, .name-description p, .verse-text');
297+
var text = Array.from(paragraphs).map(function(p) {
298+
return p.textContent.trim();
299+
}).join(' ');
300+
if (window.KJVSpeech && text) {
301+
window.KJVSpeech.speak(text);
302+
}
303+
});
304+
}
305+
278306
// Generate TOC from h2 and h3 headings
279307
const tocList = document.getElementById('toc-list');
280308
const headings = document.querySelectorAll('section h2, section h3, section article h3');
@@ -293,7 +321,7 @@ <h2>The Significance of Divine Names</h2>
293321
});
294322

295323
// Simple keyboard navigation
296-
KJVNav.initSimpleNav('.names-download-btn, .intro-text, .name-heading, .name-description > p, .verse-item');
324+
KJVNav.initSimpleNav('.action-btn, .intro-text, .name-heading, .name-description > p, .verse-item');
297325
});
298326
</script>
299327
{% endblock %}

0 commit comments

Comments
 (0)