diff --git a/web/static/js/subject-actions.v1.js b/web/static/js/subject-actions.v1.js new file mode 100644 index 0000000..641e2bc --- /dev/null +++ b/web/static/js/subject-actions.v1.js @@ -0,0 +1,185 @@ +/* subject-actions.v1.js + Popup for .subject-pill anchors with: + - WOL Search (uses current href) + - Insight Book (only if subject exists in Insight index) + - Wikipedia Search + - Google Search + - Database Search (only for 1–2 word subjects) + + Insight index: + - The script merges a small built-in seed with (optional) /static/data/insight-index.v1.json + - JSON format: { "abraham": "120000001", "babel": "1200000456", ... } +*/ + +(function(){ + // ---- Config + var WOL_LANG = 'en'; + var WOL_LP = 'e'; + + // Where to fetch your full Insight index (optional, but recommended) + var INSIGHT_INDEX_URL = '/static/data/insight-index.v1.json'; + + // ---- Helpers + function norm(s){ return String(s||'').toLowerCase().replace(/[^\p{L}\p{N}\s'-]/gu,'').replace(/\s+/g,' ').trim(); } + function isOneOrTwoWords(s){ return norm(s).split(' ').filter(Boolean).length <= 2; } + function getSearchBase(){ + var el = document.getElementById('subject-list'); + return el ? el.getAttribute('data-search-url') || '/search' : '/search'; + } + + function wolSearchURL(q){ + return "https://wol.jw.org/"+WOL_LANG+"/wol/s/r1/lp-"+WOL_LP+"?q="+encodeURIComponent(q); + } + function insightURL(id){ + // canonical article path + return "https://wol.jw.org/"+WOL_LANG+"/wol/d/r1/lp-"+WOL_LP+"/"+id; + } + function wikipediaURL(q){ + return "https://en.wikipedia.org/wiki/Special:Search?search="+encodeURIComponent(q); + } + function googleURL(q){ + return "https://www.google.com/search?q="+encodeURIComponent(q); + } + function databaseURL(q){ + // Searches your DB limiting to subject field (adjust query key as needed) + // If your search uses a different param (e.g., 'fields'), change here: + return getSearchBase()+"?q="+encodeURIComponent(q)+"&fields=subject"; + } + + // ---- Built-in tiny seed (you will extend via JSON file) + var INSIGHT_INDEX = { + "abraham": "120000001", // sample IDs; replace with real ones in your JSON + "adam": "120000002", + "babel": "120000003", + "babylon": "120000004", + "daniel": "120000005", + "david": "120000006", + "ezra": "120000007", + "faith": "120000008", + "jerusalem": "120000009", + "jesus christ": "120000010", + "love": "120000011", + "moses": "120000012", + "paul": "120000013", + "peter": "120000014", + "resurrection": "120000015", + "sabbath": "120000016", + "salvation": "120000017", + "samuel": "120000018", + "satan": "120000019", + "wisdom": "120000020" + }; + + // Try to extend from external JSON (if present). Safe to fail silently. + (function loadExternalIndex(){ + try{ + var xhr = new XMLHttpRequest(); + xhr.open('GET', INSIGHT_INDEX_URL, true); + xhr.onreadystatechange = function(){ + if (xhr.readyState !== 4) return; + if (xhr.status >= 200 && xhr.status < 300) { + try { + var data = JSON.parse(xhr.responseText || '{}'); + if (data && typeof data === 'object'){ + for (var k in data){ if (data.hasOwnProperty(k)) INSIGHT_INDEX[norm(k)] = String(data[k]); } + } + } catch(_){} + } + }; + xhr.send(); + } catch(_){} + })(); + + // ---- Popup (reuses same visual style as scripture-actions; inject if not present) + var popupEl; + function ensurePopup(){ + if (popupEl) return popupEl; + // Minimal CSS (skip if scripture-actions already injected it — harmless to duplicate) + var style = document.createElement('style'); + style.textContent = + ".subject-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:220px;display:none}" + + ".subject-actions-pop .hdr{display:flex;justify-content:space-between;align-items:center;font-weight:600;font-size:.9rem;color:#1f2937;margin-bottom:.25rem}" + + ".subject-actions-pop .close-x{cursor:pointer;padding:.1rem .4rem;border-radius:.375rem}" + + ".subject-actions-pop .close-x:hover{background:#f3f4f6}" + + ".subject-actions-pop .btn-row{display:grid;gap:.4rem;margin-top:.25rem}" + + ".subject-actions-pop a.action{display:block;text-decoration:none;padding:.45rem .55rem;border:1px solid #e5e7eb;border-radius:.45rem;color:#1f2937}" + + ".subject-actions-pop a.action:hover{background:#f9fafb}" + + ".subject-actions-pop a.action[hidden]{display:none}"; + document.head.appendChild(style); + + popupEl = document.createElement('div'); + popupEl.className = 'subject-actions-pop'; + popupEl.innerHTML = + '