mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-06-05 23:00:16 +00:00
b9aa030a35
Updated all Listen buttons across resource pages to toggle between Listen and Stop states when audio is playing. The button changes its icon and text to indicate current state, and clicking Stop halts the text-to-speech playback. Templates updated: - biblical_prophets.html - fruits_of_spirit.html - names_of_god.html - parables.html - resource_detail.html - resource_index.html - story_kids.html - topic_detail.html - twelve_apostles.html - women_of_the_bible.html 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
364 lines
10 KiB
HTML
364 lines
10 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{{ page_title }} - KJV Study{% endblock %}
|
|
{% block description %}{{ page_description }}{% endblock %}
|
|
|
|
{% block head %}
|
|
<style>
|
|
.resource-section {
|
|
margin: 1.5rem 0;
|
|
padding-top: 1rem;
|
|
}
|
|
|
|
.resource-section:not(:first-of-type) {
|
|
border-top: 1px solid var(--border-color);
|
|
}
|
|
|
|
.resource-entry {
|
|
margin: 1.5rem 0 2rem 0;
|
|
}
|
|
|
|
.resource-name {
|
|
font-size: 1.8rem;
|
|
font-weight: 400;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.resource-name a {
|
|
color: var(--link-color);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.resource-name a:hover {
|
|
color: var(--link-hover);
|
|
border-bottom: 1px solid var(--link-hover);
|
|
}
|
|
|
|
.resource-item-title {
|
|
font-size: 1.1rem;
|
|
color: var(--text-secondary);
|
|
font-style: italic;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.resource-entry-actions {
|
|
margin: 0.75rem 0 1.25rem 0;
|
|
}
|
|
|
|
.resource-download-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.35rem;
|
|
padding: 0.35rem 0.75rem;
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
background: var(--code-bg);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 4px;
|
|
text-decoration: none;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.resource-download-btn:hover {
|
|
background: var(--bg-color);
|
|
border-color: var(--link-color);
|
|
color: var(--link-color);
|
|
}
|
|
|
|
.resource-download-btn svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
|
|
.resource-item-description {
|
|
max-width: 60%;
|
|
font-size: 1.2rem;
|
|
line-height: 1.9;
|
|
margin: 1.5rem 0;
|
|
}
|
|
|
|
.resource-index-actions {
|
|
display: flex;
|
|
gap: 0.75rem;
|
|
margin: 1rem 0 1.5rem;
|
|
}
|
|
|
|
.action-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.35rem;
|
|
padding: 0.35rem 0.75rem;
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
background: var(--code-bg);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 4px;
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.action-btn:hover {
|
|
background: var(--bg-color);
|
|
border-color: var(--link-color);
|
|
color: var(--link-color);
|
|
}
|
|
|
|
.action-btn svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
|
|
.verse-list {
|
|
margin: 1.5rem 0 0 0;
|
|
}
|
|
|
|
.verse-item {
|
|
margin: 1.2rem 0;
|
|
padding-left: 1.5rem;
|
|
border-left: 2px solid var(--border-color-darker);
|
|
}
|
|
|
|
.verse-ref {
|
|
font-weight: 600;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.verse-ref a {
|
|
color: var(--link-color);
|
|
text-decoration: none;
|
|
border-bottom: 1px solid var(--border-color-dark);
|
|
}
|
|
|
|
.verse-ref a:hover {
|
|
border-bottom-color: var(--link-hover);
|
|
}
|
|
|
|
.verse-text {
|
|
max-width: 60%;
|
|
font-style: italic;
|
|
color: var(--text-secondary);
|
|
line-height: 1.8;
|
|
}
|
|
|
|
.intro-text {
|
|
max-width: 60%;
|
|
font-size: 1.2rem;
|
|
line-height: 1.9;
|
|
margin: 1rem 0;
|
|
}
|
|
|
|
.toc {
|
|
max-width: 55%;
|
|
margin: 2rem 0;
|
|
padding: 1.5rem;
|
|
border-left: 3px solid var(--border-color-darker);
|
|
}
|
|
|
|
.toc h2 {
|
|
margin-top: 0;
|
|
font-size: 1.1rem;
|
|
font-weight: 600;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.toc ul {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
|
|
.toc li {
|
|
margin: 0.5rem 0;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.toc a {
|
|
color: var(--text-color);
|
|
text-decoration: none;
|
|
border-bottom: 1px solid transparent;
|
|
}
|
|
|
|
.toc a:hover {
|
|
color: var(--link-color);
|
|
border-bottom-color: var(--link-color);
|
|
}
|
|
|
|
.toc li.toc-h3 {
|
|
padding-left: 1.5rem;
|
|
font-size: 0.95rem;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.resource-item-description,
|
|
.verse-text,
|
|
.intro-text,
|
|
.toc {
|
|
max-width: 100%;
|
|
}
|
|
}
|
|
|
|
@media print {
|
|
.resource-index-actions,
|
|
.resource-entry-actions,
|
|
.toc {
|
|
display: none !important;
|
|
}
|
|
|
|
.resource-item-description,
|
|
.verse-text,
|
|
.intro-text {
|
|
max-width: 100% !important;
|
|
}
|
|
|
|
.resource-entry {
|
|
page-break-inside: avoid;
|
|
}
|
|
|
|
.sidenote,
|
|
.marginnote {
|
|
display: block;
|
|
float: none;
|
|
width: 100%;
|
|
margin: 0.5rem 0;
|
|
font-size: 0.9rem;
|
|
color: #666;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<script>
|
|
document.body.dataset.resourceReader = 'true';
|
|
</script>
|
|
<h1>{{ page_title }}</h1>
|
|
<p class="subtitle">{{ page_subtitle }}</p>
|
|
|
|
<div class="resource-index-actions">
|
|
<button class="action-btn" id="listen-btn" aria-label="Listen to {{ page_title }}">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
|
<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
|
|
</button>
|
|
{% if pdf_available %}
|
|
<a class="action-btn" href="{{ base_url }}/pdf" aria-label="Download all {{ page_title }} as PDF">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
|
<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" />
|
|
</svg>
|
|
Download PDF
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{% if page_description %}
|
|
<section aria-label="Introduction">
|
|
<p class="intro-text">{{ page_description | mdi | link_verses | link_names | safe }}</p>
|
|
</section>
|
|
{% endif %}
|
|
|
|
<nav class="toc" id="toc" aria-label="Table of contents">
|
|
<h2>Contents</h2>
|
|
<ul id="toc-list"></ul>
|
|
</nav>
|
|
|
|
{% if intro_sidenotes %}
|
|
<section aria-label="Additional notes">
|
|
{% for intro in intro_sidenotes %}
|
|
<p class="intro-text">{{ intro.text | mdi | link_verses | link_names | safe }}</p>
|
|
{% endfor %}
|
|
</section>
|
|
{% endif %}
|
|
|
|
{% for category, items in resource_data.items() %}
|
|
<section class="resource-section" aria-labelledby="section-{{ category|slugify }}">
|
|
<h2 id="section-{{ category|slugify }}">{{ category }}</h2>
|
|
|
|
{% for item_name, item in items.items() %}
|
|
<article class="resource-entry" aria-labelledby="resource-{{ item_name|slugify }}">
|
|
<h3 class="resource-name" id="resource-{{ item_name|slugify }}"><a href="{{ base_url }}/{{ item_name|slugify }}">{{ item_name }}</a></h3>
|
|
<p class="resource-item-title">{{ item.title }}</p>
|
|
|
|
<div class="resource-item-description">
|
|
<p>{{ item.description | mdi | link_verses | link_names | safe }}</p>
|
|
</div>
|
|
|
|
{% if item.verses %}
|
|
<div class="verse-list" role="list" aria-label="Key verses for {{ item_name }}">
|
|
{% for verse in item.verses %}
|
|
<div class="verse-item" role="listitem">
|
|
<div class="verse-ref">
|
|
{% set ref_parts = verse.reference.rsplit(' ', 1) %}
|
|
{% if ref_parts|length == 2 %}
|
|
{% set book_name = ref_parts[0] %}
|
|
{% set chapter_verse = ref_parts[1] %}
|
|
{% if ':' in chapter_verse %}
|
|
{% set ch = chapter_verse.split(':')[0] %}
|
|
{% set v = chapter_verse.split(':')[1].split('-')[0] %}
|
|
<a href="/book/{{ book_name }}/chapter/{{ ch }}/verse/{{ v }}" aria-label="{{ verse.reference }}">{{ verse.reference }}</a>
|
|
{% else %}
|
|
{{ verse.reference }}
|
|
{% endif %}
|
|
{% else %}
|
|
{{ verse.reference }}
|
|
{% endif %}
|
|
</div>
|
|
<div class="verse-text">{{ verse.text | link_names | safe }}</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
</article>
|
|
{% endfor %}
|
|
</section>
|
|
{% endfor %}
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Listen button handler
|
|
var listenBtn = document.getElementById('listen-btn');
|
|
var isListening = false;
|
|
if (listenBtn) {
|
|
listenBtn.addEventListener('click', function() {
|
|
if (isListening) {
|
|
if (window.KJVSpeech) window.KJVSpeech.stop();
|
|
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';
|
|
isListening = false;
|
|
return;
|
|
}
|
|
var paragraphs = document.querySelectorAll('.intro-text, .resource-item-description p, .verse-text');
|
|
var text = Array.from(paragraphs).map(function(p) {
|
|
return p.textContent.trim();
|
|
}).join(' ');
|
|
if (window.KJVSpeech && text) {
|
|
window.KJVSpeech.speak(text);
|
|
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';
|
|
isListening = true;
|
|
}
|
|
});
|
|
}
|
|
|
|
// Generate TOC from h2 and h3 headings
|
|
const tocList = document.getElementById('toc-list');
|
|
const headings = document.querySelectorAll('section h2, section h3, section article h3');
|
|
|
|
headings.forEach((heading) => {
|
|
if (!heading.id) {
|
|
heading.id = 'section-' + heading.textContent.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
|
}
|
|
const li = document.createElement('li');
|
|
if (heading.tagName === 'H3') li.classList.add('toc-h3');
|
|
const a = document.createElement('a');
|
|
a.href = '#' + heading.id;
|
|
a.textContent = heading.textContent;
|
|
li.appendChild(a);
|
|
tocList.appendChild(li);
|
|
});
|
|
|
|
// Simple keyboard navigation
|
|
KJVNav.initSimpleNav('.action-btn, .intro-text, .resource-name, .resource-item-description > p, .verse-item, .resource-card');
|
|
});
|
|
</script>
|
|
{% endblock %}
|