Add web/static/js/scripture-actions.v1.js
This commit is contained in:
parent
05a7be7d4f
commit
5724087f99
232
web/static/js/scripture-actions.v1.js
Normal file
232
web/static/js/scripture-actions.v1.js
Normal file
@ -0,0 +1,232 @@
|
||||
/* 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:3–5" 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);
|
||||
});
|
||||
|
||||
})();
|
||||
Loading…
Reference in New Issue
Block a user