diff --git a/kjvstudy_org/templates/commentary.html b/kjvstudy_org/templates/commentary.html index ead1111..878652e 100644 --- a/kjvstudy_org/templates/commentary.html +++ b/kjvstudy_org/templates/commentary.html @@ -496,19 +496,56 @@ document.addEventListener('DOMContentLoaded', function() { target.scrollIntoView({ behavior: 'smooth', block: 'center' }); target.style.transition = 'background-color 1s'; target.style.backgroundColor = 'rgba(255, 235, 59, 0.5)'; - + // Get verse number to show in toast const verseMatch = window.location.hash.match(/verse-(\d+)/); if (verseMatch && verseMatch[1]) { showToast('Navigated to Verse ' + verseMatch[1]); } - + setTimeout(() => { target.style.backgroundColor = ''; }, 2000); } }, 100); } + + // Keyboard navigation for verse cards + const verseCards = Array.from(document.querySelectorAll('.verse-card[id^="verse-"]')); + if (verseCards.length === 0) return; + + let selectedIndex = -1; + + function selectCard(index) { + if (selectedIndex >= 0 && selectedIndex < verseCards.length) { + verseCards[selectedIndex].style.outline = ''; + verseCards[selectedIndex].style.outlineOffset = ''; + } + selectedIndex = Math.max(0, Math.min(index, verseCards.length - 1)); + verseCards[selectedIndex].style.outline = '2px solid #4a7c59'; + verseCards[selectedIndex].style.outlineOffset = '4px'; + verseCards[selectedIndex].scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + + document.addEventListener('keydown', function(e) { + if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return; + + if (e.key === 'ArrowDown' || e.key === 'j') { + e.preventDefault(); + selectCard(selectedIndex < 0 ? 0 : selectedIndex + 1); + } else if (e.key === 'ArrowUp' || e.key === 'k') { + e.preventDefault(); + if (selectedIndex <= 0) selectCard(0); + else selectCard(selectedIndex - 1); + } else if (e.key === 'ArrowLeft' || e.key === 'h') { + e.preventDefault(); + history.back(); + } else if (e.key === 'Enter' && selectedIndex >= 0) { + e.preventDefault(); + const verseLink = verseCards[selectedIndex].querySelector('.verse-action[href*="/book/"]'); + if (verseLink) window.location.href = verseLink.href; + } + }); }); {% endblock %} \ No newline at end of file diff --git a/kjvstudy_org/templates/stories_index.html b/kjvstudy_org/templates/stories_index.html index 96a365c..123d5e7 100644 --- a/kjvstudy_org/templates/stories_index.html +++ b/kjvstudy_org/templates/stories_index.html @@ -450,6 +450,68 @@ document.addEventListener('DOMContentLoaded', function() { hideDropdown(); } }); + + // Keyboard navigation for story cards (2D grid) + var visibleStories = function() { + return Array.from(document.querySelectorAll('.story-card:not(.hidden)')); + }; + var selectedCardIndex = -1; + + function getGridColumns() { + var grid = document.querySelector('.stories-grid'); + if (!grid) return 1; + var style = getComputedStyle(grid); + var cols = style.gridTemplateColumns.split(' ').length; + return cols || 1; + } + + function selectStoryCard(index) { + var cards = visibleStories(); + if (cards.length === 0) return; + + if (selectedCardIndex >= 0 && selectedCardIndex < cards.length) { + cards[selectedCardIndex].style.outline = ''; + cards[selectedCardIndex].style.outlineOffset = ''; + } + + selectedCardIndex = Math.max(0, Math.min(index, cards.length - 1)); + cards[selectedCardIndex].style.outline = '2px solid #4a7c59'; + cards[selectedCardIndex].style.outlineOffset = '4px'; + cards[selectedCardIndex].scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + + document.addEventListener('keydown', function(e) { + if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return; + + var cards = visibleStories(); + if (cards.length === 0) return; + + var cols = getGridColumns(); + + if (e.key === 'ArrowDown' || e.key === 'j') { + e.preventDefault(); + if (selectedCardIndex < 0) selectStoryCard(0); + else selectStoryCard(selectedCardIndex + cols); + } else if (e.key === 'ArrowUp' || e.key === 'k') { + e.preventDefault(); + if (selectedCardIndex < 0) selectStoryCard(0); + else if (selectedCardIndex - cols >= 0) selectStoryCard(selectedCardIndex - cols); + } else if (e.key === 'ArrowRight' || e.key === 'l') { + e.preventDefault(); + if (selectedCardIndex < 0) selectStoryCard(0); + else selectStoryCard(selectedCardIndex + 1); + } else if (e.key === 'ArrowLeft' || e.key === 'h') { + e.preventDefault(); + if (selectedCardIndex <= 0) history.back(); + else selectStoryCard(selectedCardIndex - 1); + } else if (e.key === 'Enter' && selectedCardIndex >= 0) { + e.preventDefault(); + var cards = visibleStories(); + if (cards[selectedCardIndex]) { + window.location.href = cards[selectedCardIndex].href; + } + } + }); }); {% endblock %} diff --git a/kjvstudy_org/templates/stories_kids_index.html b/kjvstudy_org/templates/stories_kids_index.html index 71c6541..a438377 100644 --- a/kjvstudy_org/templates/stories_kids_index.html +++ b/kjvstudy_org/templates/stories_kids_index.html @@ -488,6 +488,68 @@ document.addEventListener('DOMContentLoaded', function() { hideDropdown(); } }); + + // Keyboard navigation for story cards (2D grid) + var visibleStories = function() { + return Array.from(document.querySelectorAll('.kids-story-card:not(.hidden)')); + }; + var selectedCardIndex = -1; + + function getGridColumns() { + var grid = document.querySelector('.stories-grid'); + if (!grid) return 1; + var style = getComputedStyle(grid); + var cols = style.gridTemplateColumns.split(' ').length; + return cols || 1; + } + + function selectStoryCard(index) { + var cards = visibleStories(); + if (cards.length === 0) return; + + if (selectedCardIndex >= 0 && selectedCardIndex < cards.length) { + cards[selectedCardIndex].style.outline = ''; + cards[selectedCardIndex].style.outlineOffset = ''; + } + + selectedCardIndex = Math.max(0, Math.min(index, cards.length - 1)); + cards[selectedCardIndex].style.outline = '2px solid #8b5cf6'; + cards[selectedCardIndex].style.outlineOffset = '4px'; + cards[selectedCardIndex].scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + + document.addEventListener('keydown', function(e) { + if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return; + + var cards = visibleStories(); + if (cards.length === 0) return; + + var cols = getGridColumns(); + + if (e.key === 'ArrowDown' || e.key === 'j') { + e.preventDefault(); + if (selectedCardIndex < 0) selectStoryCard(0); + else selectStoryCard(selectedCardIndex + cols); + } else if (e.key === 'ArrowUp' || e.key === 'k') { + e.preventDefault(); + if (selectedCardIndex < 0) selectStoryCard(0); + else if (selectedCardIndex - cols >= 0) selectStoryCard(selectedCardIndex - cols); + } else if (e.key === 'ArrowRight' || e.key === 'l') { + e.preventDefault(); + if (selectedCardIndex < 0) selectStoryCard(0); + else selectStoryCard(selectedCardIndex + 1); + } else if (e.key === 'ArrowLeft' || e.key === 'h') { + e.preventDefault(); + if (selectedCardIndex <= 0) history.back(); + else selectStoryCard(selectedCardIndex - 1); + } else if (e.key === 'Enter' && selectedCardIndex >= 0) { + e.preventDefault(); + var cards = visibleStories(); + if (cards[selectedCardIndex]) { + window.location.href = cards[selectedCardIndex].href; + } + } + }); }); {% endblock %}