Illustrations/web/static/js/scripture-actions.v1.js

232 lines
9.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* scripture-actions.v1.js
Adds a small popup to .scripture-pill anchors with:
- "WOL Search" (keeps existing behavior / current href)
- "NWT Study Bible" (deep link to nwtsty/{bookNum}/{chapter}#s={verse}&study=discover)
No dependencies. Safe to include after your existing validators.
*/
(function () {
// ===== Config: set language/LP if your site is localized
var WOL_LANG = 'en'; // e.g., 'en', 'es'
var WOL_LP = 'e'; // e.g., 'e' for English, 's' for Spanish
// ----- Utility
function normSpaces(s){ return String(s||'').replace(/\s+/g,' ').trim(); }
function stripDots(s){ return String(s||'').replace(/\.+/g,''); }
function lower(s){ return String(s||'').toLowerCase(); }
// ===== WOL abbrev → numeric mapping (1..66)
var CODE_TO_NUM = {
// OT
Ge:1, Ex:2, Le:3, Nu:4, De:5, Jos:6, Jg:7, Ru:8, '1Sa':9, '2Sa':10,
'1Ki':11, '2Ki':12, '1Ch':13, '2Ch':14, Ezr:15, Ne:16, Es:17, Job:18,
Ps:19, Pr:20, Ec:21, Ca:22, Isa:23, Jer:24, La:25, Eze:26, Da:27, Ho:28,
Joe:29, Am:30, Ob:31, Jon:32, Mic:33, Na:34, Hab:35, Zep:36, Hag:37, Zec:38, Mal:39,
// NT
Mt:40, Mr:41, Lu:42, Joh:43, Ac:44, Ro:45, '1Co':46, '2Co':47, Ga:48, Eph:49,
Php:50, Col:51, '1Th':52, '2Th':53, '1Ti':54, '2Ti':55, Tit:56, Phm:57,
Heb:58, Jas:59, '1Pe':60, '2Pe':61, '1Jo':62, '2Jo':63, '3Jo':64, Jude:65, Re:66
};
// Full names → WOL codes (from your validator)
var FULL_TO_CODE = {
"genesis":"Ge","exodus":"Ex","leviticus":"Le","numbers":"Nu","deuteronomy":"De",
"joshua":"Jos","judges":"Jg","ruth":"Ru",
"1 samuel":"1Sa","2 samuel":"2Sa","1 kings":"1Ki","2 kings":"2Ki",
"1 chronicles":"1Ch","2 chronicles":"2Ch",
"ezra":"Ezr","nehemiah":"Ne","esther":"Es","job":"Job","psalms":"Ps","psalm":"Ps",
"proverbs":"Pr","ecclesiastes":"Ec","song of solomon":"Ca","song of songs":"Ca",
"isaiah":"Isa","jeremiah":"Jer","lamentations":"La","ezekiel":"Eze","daniel":"Da",
"hosea":"Ho","joel":"Joe","amos":"Am","obadiah":"Ob","jonah":"Jon","micah":"Mic",
"nahum":"Na","habakkuk":"Hab","zephaniah":"Zep","haggai":"Hag","zechariah":"Zec","malachi":"Mal",
"matthew":"Mt","mark":"Mr","luke":"Lu","john":"Joh","acts":"Ac","romans":"Ro",
"1 corinthians":"1Co","2 corinthians":"2Co",
"galatians":"Ga","ephesians":"Eph","philippians":"Php","colossians":"Col",
"1 thessalonians":"1Th","2 thessalonians":"2Th",
"1 timothy":"1Ti","2 timothy":"2Ti",
"titus":"Tit","philemon":"Phm","hebrews":"Heb","james":"Jas",
"1 peter":"1Pe","2 peter":"2Pe",
"1 john":"1Jo","2 john":"2Jo","3 john":"3Jo",
"jude":"Jude","revelation":"Re"
};
// Aliases → WOL codes (from your validator)
var ALIAS_TO_CODE = {
// OT
"gen":"Ge","exod":"Ex","lev":"Le","num":"Nu","deut":"De",
"josh":"Jos","judg":"Jg","ps":"Ps","prov":"Pr","eccl":"Ec","song":"Ca","cant":"Ca",
"isa":"Isa","jer":"Jer","lam":"La","ezek":"Eze","dan":"Da","hos":"Ho","joel":"Joe",
"amos":"Am","obad":"Ob","jon":"Jon","mic":"Mic","nah":"Na","hab":"Hab","zeph":"Zep",
"hag":"Hag","zech":"Zec","mal":"Mal",
// NT
"matt":"Mt","mark":"Mr","luke":"Lu","john":"Joh","acts":"Ac","rom":"Ro",
"gal":"Ga","eph":"Eph","phil":"Php","col":"Col","heb":"Heb","jas":"Jas",
"jude":"Jude","rev":"Re"
};
// Numbered-series families (from your validator)
var SERIES = [
{ prefixes:["sam","samu","samuel"], codes:{1:"1Sa",2:"2Sa"} },
{ prefixes:["ki","king","kings","kgs"], codes:{1:"1Ki",2:"2Ki"} },
{ prefixes:["chron","chr","ch","chronicles"], codes:{1:"1Ch",2:"2Ch"} },
{ prefixes:["cor","corin","corinth","corinthians","co","c"], codes:{1:"1Co",2:"2Co"} },
{ prefixes:["thes","thess","thessalon","thessalonians","th"], codes:{1:"1Th",2:"2Th"} },
{ prefixes:["tim","ti","timothy","t"], codes:{1:"1Ti",2:"2Ti"} },
{ prefixes:["pet","pe","peter","pt","p"], codes:{1:"1Pe",2:"2Pe"} },
{ prefixes:["jo","jn","joh","john","jno","jhn"], codes:{1:"1Jo",2:"2Jo",3:"3Jo"} }
];
// Set of valid WOL abbreviations (accept with/without a space after the leading number)
var WOL_ABBR = (function(){
var s = new Set();
Object.keys(CODE_TO_NUM).forEach(function(k){ s.add(k); });
return s;
})();
function resolveBookNumber(bookRaw){
if (!bookRaw) return null;
var b = normSpaces(stripDots(bookRaw));
// Full names
var fullCode = FULL_TO_CODE[lower(b)];
if (fullCode) return CODE_TO_NUM[fullCode];
// Aliases
var aliasCode = ALIAS_TO_CODE[lower(b)];
if (aliasCode) return CODE_TO_NUM[aliasCode];
// WOL abbr with optional space after number
var tightened = b.replace(/^([1-3])\s+([A-Za-z].*)$/, function(_,n,rest){ return n+rest; });
if (WOL_ABBR.has(tightened)) return CODE_TO_NUM[tightened];
// Numbered series prose (e.g., "2 Sam", "1 Chron", "3 Jo")
var m = lower(b).match(/^([1-3])\s*([a-z]+)$/);
if (m){
var n = parseInt(m[1],10), base = m[2];
for (var i=0;i<SERIES.length;i++){
var fam = SERIES[i];
if (fam.prefixes.some(function(p){ return base.indexOf(p) === 0; })){
var code = fam.codes[n];
if (code) return CODE_TO_NUM[code];
}
}
}
return null;
}
// Parse first scripture in a pill like "Rom. 14:13, 19" or "1 Pet. 1:35" or "John 3:16"
function parseFirstRef(refText){
var text = String(refText||'').trim();
if (!text) return null;
var m = text.match(/^(.+?)\s+(\d{1,3})(?::(.+))?$/);
if (!m) return null;
var bookRaw = m[1];
var chapter = parseInt(m[2],10);
var versePart = (m[3]||'').trim();
var bookNum = resolveBookNumber(bookRaw);
if (!bookNum || !chapter) return null;
// first verse number in the versePart; default 1 if missing (chapter-only pills)
var vm = versePart.match(/(\d{1,3})/);
var verse = vm ? parseInt(vm[1],10) : 1;
return { bookNum: bookNum, chapter: chapter, verse: verse };
}
// Build Study link using the agreed format
function buildStudyURL(bookNum, chapter, verse){
return "https://wol.jw.org/" + WOL_LANG + "/wol/b/r1/lp-" + WOL_LP + "/nwtsty/" + bookNum + "/" + chapter + "#s=" + verse + "&study=discover";
}
// Derive the WOL Search URL for the pill (keep existing behavior if present)
function getPillWOLSearchURL(pillEl){
var href = pillEl.getAttribute('href');
if (href && /wol\.jw\.org\/.+\bq=/.test(href)) return href;
var q = (pillEl.getAttribute('data-ref') || pillEl.textContent || '').trim();
return "https://wol.jw.org/" + WOL_LANG + "/wol/l/r1/lp-" + WOL_LP + "?q=" + encodeURIComponent(q);
}
// ===== Popup (singleton) — inject minimal CSS automatically
var ScripturePopup = (function(){
var el, cssInjected = false;
function injectCSS(){
if (cssInjected) return;
cssInjected = true;
var style = document.createElement('style');
style.textContent =
".scripture-actions-pop{position:absolute;z-index:9999;background:#fff;border:1px solid #e5e7eb;border-radius:.5rem;box-shadow:0 10px 20px rgba(0,0,0,.1);padding:.5rem;min-width:200px;display:none}" +
".scripture-actions-pop .hdr{display:flex;justify-content:space-between;align-items:center;font-weight:600;font-size:.9rem;color:#1f2937;margin-bottom:.25rem}" +
".scripture-actions-pop .close-x{cursor:pointer;padding:.1rem .4rem;border-radius:.375rem}" +
".scripture-actions-pop .close-x:hover{background:#f3f4f6}" +
".scripture-actions-pop .btn-row{display:grid;gap:.4rem;margin-top:.25rem}" +
".scripture-actions-pop a.action{display:block;text-decoration:none;padding:.45rem .55rem;border:1px solid #e5e7eb;border-radius:.45rem;color:#1f2937}" +
".scripture-actions-pop a.action:hover{background:#f9fafb}";
document.head.appendChild(style);
}
function ensure(){
if (el) return el;
injectCSS();
el = document.createElement('div');
el.className = 'scripture-actions-pop';
el.innerHTML =
'<div class="hdr">' +
'<span>Open scripture</span>' +
'<span class="close-x" aria-label="Close">✕</span>' +
'</div>' +
'<div class="btn-row">' +
'<a class="action act-wol" target="_blank" rel="noopener">WOL Search</a>' +
'<a class="action act-study" target="_blank" rel="noopener">NWT Study Bible</a>' +
'</div>';
document.body.appendChild(el);
el.querySelector('.close-x').addEventListener('click', hide);
document.addEventListener('click', function(e){
if (!el.contains(e.target) && !e.target.closest('.scripture-pill')) hide();
}, true);
document.addEventListener('keydown', function(e){ if (e.key === 'Escape') hide(); });
return el;
}
function show(x,y,wolURL,studyURL){
var n = ensure();
n.style.left = x + "px";
n.style.top = y + "px";
n.querySelector('.act-wol').setAttribute('href', wolURL);
n.querySelector('.act-study').setAttribute('href', studyURL);
n.style.display = 'block';
}
function hide(){ if (el) el.style.display = 'none'; }
return { show: show, hide: hide };
})();
// ===== Click handling
document.addEventListener('click', function(e){
var pill = e.target.closest('.scripture-pill');
if (!pill) return;
var refText = (pill.getAttribute('data-ref') || pill.textContent || '').trim();
var wolURL = getPillWOLSearchURL(pill);
var parsed = parseFirstRef(refText);
var studyURL = parsed ? buildStudyURL(parsed.bookNum, parsed.chapter, parsed.verse) : wolURL;
// Shortcuts: Alt = Study immediately, Shift = WOL immediately
if (e.altKey){ window.open(studyURL, '_blank', 'noopener'); e.preventDefault(); return; }
if (e.shiftKey){ window.open(wolURL, '_blank', 'noopener'); e.preventDefault(); return; }
// Otherwise, show the popup
e.preventDefault();
var r = pill.getBoundingClientRect();
var x = r.left + window.scrollX + r.width/2 - 100;
var y = r.top + window.scrollY + r.height + 6;
ScripturePopup.show(x, y, wolURL, studyURL);
});
})();