mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-06-20 14:30:57 +00:00
456 lines
14 KiB
HTML
456 lines
14 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Bible Stories - KJV Study{% endblock %}
|
|
{% block description %}Explore {{ story_count }} Bible stories from Creation to the early Church, with both adult narratives and kid-friendly versions.{% endblock %}
|
|
|
|
{% block og_type %}website{% endblock %}
|
|
{% block og_title %}Bible Stories - KJV Study{% endblock %}
|
|
{% block og_description %}Explore {{ story_count }} Bible stories from Creation to the early Church, with both adult narratives and kid-friendly versions.{% endblock %}
|
|
|
|
{% block head %}
|
|
<style>
|
|
.story-toc {
|
|
margin: 1.25rem 0 2rem;
|
|
}
|
|
.story-toc ul {
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
gap: 0.75rem;
|
|
}
|
|
.story-toc-item {
|
|
display: block;
|
|
padding: 0.6rem 0.9rem;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 6px;
|
|
text-decoration: none;
|
|
color: inherit;
|
|
transition: border-color 0.15s, transform 0.15s;
|
|
}
|
|
.story-toc-item:hover,
|
|
.story-toc-item:focus-visible {
|
|
border-color: var(--link-color);
|
|
transform: translateY(-1px);
|
|
}
|
|
.story-toc-item strong {
|
|
display: block;
|
|
}
|
|
.story-toc-count {
|
|
font-size: 0.8rem;
|
|
color: var(--text-tertiary);
|
|
}
|
|
.story-search {
|
|
max-width: 400px;
|
|
margin: 1.5rem 0;
|
|
position: relative;
|
|
}
|
|
.story-search input {
|
|
width: 100%;
|
|
padding: 0.5rem 0.75rem;
|
|
font-size: 1rem;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 4px;
|
|
background: var(--bg-color);
|
|
color: var(--text-color);
|
|
}
|
|
.story-search input:focus {
|
|
outline: none;
|
|
border-color: var(--link-color);
|
|
}
|
|
.story-search-dropdown {
|
|
position: absolute;
|
|
top: 100%;
|
|
left: 0;
|
|
right: 0;
|
|
background: var(--bg-color);
|
|
border: 1px solid var(--border-color-darker);
|
|
border-top: none;
|
|
border-radius: 0 0 4px 4px;
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
z-index: 1000;
|
|
display: none;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
}
|
|
.story-search-dropdown.show {
|
|
display: block;
|
|
}
|
|
.search-result-category {
|
|
padding: 0.5rem 0.75rem 0.25rem;
|
|
font-size: 0.7rem;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
color: var(--text-tertiary);
|
|
background: var(--code-bg);
|
|
border-bottom: 1px solid var(--border-color);
|
|
}
|
|
.search-result-item {
|
|
display: block;
|
|
padding: 0.5rem 0.75rem;
|
|
text-decoration: none;
|
|
color: var(--text-color);
|
|
border-bottom: 1px solid var(--border-color);
|
|
cursor: pointer;
|
|
transition: background 0.15s;
|
|
}
|
|
.search-result-item:hover,
|
|
.search-result-item.selected {
|
|
background: var(--code-bg);
|
|
}
|
|
.search-result-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
.search-result-title {
|
|
font-weight: 500;
|
|
font-size: 0.9rem;
|
|
}
|
|
.search-result-subtitle {
|
|
font-size: 0.75rem;
|
|
color: var(--text-tertiary);
|
|
margin-top: 0.1rem;
|
|
}
|
|
|
|
/* Story cards grid */
|
|
.stories-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
gap: 1.25rem;
|
|
margin: 1.5rem 0;
|
|
}
|
|
.story-card {
|
|
display: block;
|
|
border: 1px solid var(--border-color, #ddd);
|
|
border-radius: 6px;
|
|
padding: 1.25rem;
|
|
background: #fff;
|
|
text-decoration: none;
|
|
color: inherit;
|
|
position: relative;
|
|
transition: box-shadow 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
|
|
}
|
|
.story-card:hover,
|
|
.story-card:focus-visible {
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
|
border-color: var(--link-color);
|
|
transform: translateY(-2px);
|
|
}
|
|
.story-card.hidden {
|
|
display: none;
|
|
}
|
|
.story-card h3 {
|
|
margin: 0 0 0.5rem 0;
|
|
font-size: 1.1rem;
|
|
line-height: 1.3;
|
|
}
|
|
.story-card .description {
|
|
font-size: 0.9rem;
|
|
color: #555;
|
|
margin-bottom: 0.75rem;
|
|
line-height: 1.5;
|
|
}
|
|
.story-card .scripture {
|
|
font-size: 0.8rem;
|
|
color: var(--link-color);
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
.story-card .meta {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.4rem;
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
.story-card .tag {
|
|
display: inline-block;
|
|
padding: 0.15rem 0.5rem;
|
|
background: var(--code-bg, #f5f5f5);
|
|
border-radius: 3px;
|
|
font-size: 0.75rem;
|
|
color: #666;
|
|
}
|
|
.story-card .tag.character {
|
|
background: #e8f4f8;
|
|
color: #2a6f8f;
|
|
}
|
|
.story-card .tag.theme {
|
|
background: #f0f4e8;
|
|
color: #5a7a2a;
|
|
}
|
|
.story-card .links {
|
|
display: flex;
|
|
gap: 1rem;
|
|
margin-top: 0.75rem;
|
|
padding-top: 0.75rem;
|
|
border-top: 1px solid var(--border-color-light, #eee);
|
|
font-size: 0.85rem;
|
|
}
|
|
.story-card .links a {
|
|
text-decoration: none;
|
|
}
|
|
.story-card .links .kids-link {
|
|
color: #8b5cf6;
|
|
}
|
|
|
|
.category-section.hidden {
|
|
display: none;
|
|
}
|
|
.category-section {
|
|
margin-bottom: 3rem;
|
|
}
|
|
.category-description {
|
|
font-size: 1rem;
|
|
color: #555;
|
|
margin-bottom: 1rem;
|
|
max-width: 65ch;
|
|
}
|
|
.no-results {
|
|
display: none;
|
|
padding: 1.5rem;
|
|
background: var(--code-bg);
|
|
border-radius: 4px;
|
|
color: var(--text-secondary);
|
|
text-align: center;
|
|
}
|
|
.no-results.visible {
|
|
display: block;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<h1>Bible Stories</h1>
|
|
<p class="subtitle">{{ story_count }} stories across {{ category_count }} categories</p>
|
|
|
|
<section>
|
|
<p><span class="newthought">These Bible stories</span> bring Scripture to life through engaging narratives that remain faithful to God's Word. Each story includes both an adult version with theological depth and a kid-friendly version perfect for family devotions or Sunday school.</p>
|
|
|
|
<p style="margin-top: 1rem;"><a href="/stories/kids" style="color: #8b5cf6; font-weight: 500;">View Kids Version</a> — Stories written for younger readers</p>
|
|
|
|
<h3>Categories</h3>
|
|
<nav class="story-toc" aria-label="Story categories">
|
|
<ul>
|
|
{% for category in categories %}
|
|
<li>
|
|
<a class="story-toc-item" href="#{{ category.slug }}">
|
|
<strong>{{ category.category }}</strong>
|
|
<span class="story-toc-count">{{ category.stories|length }} stories</span>
|
|
</a>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</nav>
|
|
|
|
<div class="story-search">
|
|
<input type="text" id="story-search" placeholder="Search stories by name, character, or theme..." autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
|
|
<div id="story-search-dropdown" class="story-search-dropdown"></div>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="no-results" id="no-results">
|
|
No stories found matching your search.
|
|
</div>
|
|
|
|
{% for category in categories %}
|
|
<section id="{{ category.slug }}" class="category-section">
|
|
<h2>{{ category.category }}</h2>
|
|
<p class="category-description">{{ category.description }}</p>
|
|
|
|
<div class="stories-grid">
|
|
{% for story in category.stories %}
|
|
<a class="story-card" href="/stories/{{ story.slug }}" data-title="{{ story.title|lower }}" data-description="{{ story.description|lower }}" data-characters="{{ story.characters|join(' ')|lower }}" data-themes="{{ story.themes|join(' ')|lower }}">
|
|
<h3>{{ story.title }}</h3>
|
|
<p class="description">{{ story.description }}</p>
|
|
<div class="scripture">
|
|
{% for verse in story.verses[:2] %}{{ verse }}{% if not loop.last %}, {% endif %}{% endfor %}{% if story.verses|length > 2 %} +{{ story.verses|length - 2 }} more{% endif %}
|
|
</div>
|
|
<div class="meta">
|
|
{% for character in story.characters[:3] %}
|
|
<span class="tag character">{{ character }}</span>
|
|
{% endfor %}
|
|
{% for theme in story.themes[:2] %}
|
|
<span class="tag theme">{{ theme }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
</section>
|
|
{% endfor %}
|
|
|
|
<nav>
|
|
<p><a href="/">← Home</a></p>
|
|
</nav>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
var searchInput = document.getElementById('story-search');
|
|
var dropdown = document.getElementById('story-search-dropdown');
|
|
var stories = document.querySelectorAll('.story-card');
|
|
var categorySections = document.querySelectorAll('.category-section');
|
|
var noResults = document.getElementById('no-results');
|
|
var currentResults = [];
|
|
var selectedIndex = -1;
|
|
|
|
function filterStories(query) {
|
|
if (!query) {
|
|
stories.forEach(function(s) { s.classList.remove('hidden'); });
|
|
categorySections.forEach(function(c) { c.classList.remove('hidden'); });
|
|
noResults.classList.remove('visible');
|
|
return;
|
|
}
|
|
|
|
var matchCount = 0;
|
|
stories.forEach(function(story) {
|
|
var title = story.dataset.title || '';
|
|
var description = story.dataset.description || '';
|
|
var characters = story.dataset.characters || '';
|
|
var themes = story.dataset.themes || '';
|
|
|
|
var matches = title.includes(query) ||
|
|
description.includes(query) ||
|
|
characters.includes(query) ||
|
|
themes.includes(query);
|
|
|
|
if (matches) {
|
|
story.classList.remove('hidden');
|
|
matchCount++;
|
|
} else {
|
|
story.classList.add('hidden');
|
|
}
|
|
});
|
|
|
|
categorySections.forEach(function(category) {
|
|
var visibleStories = category.querySelectorAll('.story-card:not(.hidden)');
|
|
if (visibleStories.length === 0) {
|
|
category.classList.add('hidden');
|
|
} else {
|
|
category.classList.remove('hidden');
|
|
}
|
|
});
|
|
|
|
if (matchCount === 0) {
|
|
noResults.classList.add('visible');
|
|
} else {
|
|
noResults.classList.remove('visible');
|
|
}
|
|
}
|
|
|
|
function getMatchingStories(query) {
|
|
var matches = [];
|
|
stories.forEach(function(story) {
|
|
var title = story.dataset.title || '';
|
|
var description = story.dataset.description || '';
|
|
var characters = story.dataset.characters || '';
|
|
var themes = story.dataset.themes || '';
|
|
|
|
if (title.includes(query) || description.includes(query) ||
|
|
characters.includes(query) || themes.includes(query)) {
|
|
var link = story.querySelector('h3 a');
|
|
if (link) {
|
|
matches.push({
|
|
title: link.textContent,
|
|
url: link.getAttribute('href'),
|
|
description: story.querySelector('.description')?.textContent?.substring(0, 60) + '...'
|
|
});
|
|
}
|
|
}
|
|
});
|
|
return matches.slice(0, 5);
|
|
}
|
|
|
|
function showDropdown(html) {
|
|
dropdown.innerHTML = html;
|
|
dropdown.classList.add('show');
|
|
}
|
|
|
|
function hideDropdown() {
|
|
dropdown.classList.remove('show');
|
|
currentResults = [];
|
|
selectedIndex = -1;
|
|
}
|
|
|
|
function updateSelection() {
|
|
var items = dropdown.querySelectorAll('.search-result-item');
|
|
items.forEach(function(item, i) {
|
|
if (i === selectedIndex) {
|
|
item.classList.add('selected');
|
|
} else {
|
|
item.classList.remove('selected');
|
|
}
|
|
});
|
|
}
|
|
|
|
function renderDropdown(query) {
|
|
var html = '';
|
|
currentResults = [];
|
|
|
|
// Matching stories on this page
|
|
var matchingStories = getMatchingStories(query.toLowerCase());
|
|
if (matchingStories.length > 0) {
|
|
html += '<div class="search-result-category">Stories</div>';
|
|
matchingStories.forEach(function(story) {
|
|
currentResults.push(story.url);
|
|
var isSelected = currentResults.length === 1;
|
|
html += '<a href="' + story.url + '" class="search-result-item' + (isSelected ? ' selected' : '') + '">';
|
|
html += '<div class="search-result-title">' + story.title + '</div>';
|
|
if (story.description) {
|
|
html += '<div class="search-result-subtitle">' + story.description + '</div>';
|
|
}
|
|
html += '</a>';
|
|
});
|
|
}
|
|
|
|
if (html) {
|
|
selectedIndex = currentResults.length > 0 ? 0 : -1;
|
|
showDropdown(html);
|
|
} else {
|
|
hideDropdown();
|
|
}
|
|
}
|
|
|
|
searchInput.addEventListener('input', function() {
|
|
var query = this.value.trim();
|
|
|
|
// Filter stories on page
|
|
filterStories(query.toLowerCase());
|
|
|
|
if (query.length < 2) {
|
|
hideDropdown();
|
|
return;
|
|
}
|
|
|
|
// Show matching stories in dropdown
|
|
renderDropdown(query);
|
|
});
|
|
|
|
searchInput.addEventListener('keydown', function(e) {
|
|
if (!dropdown.classList.contains('show')) return;
|
|
|
|
if (e.key === 'ArrowDown') {
|
|
e.preventDefault();
|
|
selectedIndex = Math.min(selectedIndex + 1, currentResults.length - 1);
|
|
updateSelection();
|
|
} else if (e.key === 'ArrowUp') {
|
|
e.preventDefault();
|
|
selectedIndex = Math.max(selectedIndex - 1, -1);
|
|
updateSelection();
|
|
} else if (e.key === 'Enter' && selectedIndex >= 0 && currentResults[selectedIndex]) {
|
|
e.preventDefault();
|
|
window.location.href = currentResults[selectedIndex];
|
|
} else if (e.key === 'Escape') {
|
|
hideDropdown();
|
|
}
|
|
});
|
|
|
|
// Click outside to close dropdown
|
|
document.addEventListener('click', function(e) {
|
|
if (!dropdown.contains(e.target) && e.target !== searchInput) {
|
|
hideDropdown();
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
{% endblock %}
|