Add web/static/js/subject-actions.v1.js
This commit is contained in:
parent
c9cae678df
commit
eb096ef5ca
185
web/static/js/subject-actions.v1.js
Normal file
185
web/static/js/subject-actions.v1.js
Normal file
@ -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 =
|
||||||
|
'<div class="hdr"><span>Open subject</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-insight" target="_blank" rel="noopener">Insight Book</a>' +
|
||||||
|
'<a class="action act-wiki" target="_blank" rel="noopener">Wikipedia</a>' +
|
||||||
|
'<a class="action act-google" target="_blank" rel="noopener">Google</a>' +
|
||||||
|
'<a class="action act-db" target="_blank" rel="noopener">Database Search</a>' +
|
||||||
|
'</div>';
|
||||||
|
document.body.appendChild(popupEl);
|
||||||
|
|
||||||
|
popupEl.querySelector('.close-x').addEventListener('click', hidePopup);
|
||||||
|
document.addEventListener('click', function(e){
|
||||||
|
if (!popupEl.contains(e.target) && !e.target.closest('.subject-pill')) hidePopup();
|
||||||
|
}, true);
|
||||||
|
document.addEventListener('keydown', function(e){ if (e.key === 'Escape') hidePopup(); });
|
||||||
|
|
||||||
|
return popupEl;
|
||||||
|
}
|
||||||
|
function showPopup(x,y,links,options){
|
||||||
|
var el = ensurePopup();
|
||||||
|
el.style.left = x + 'px';
|
||||||
|
el.style.top = y + 'px';
|
||||||
|
|
||||||
|
el.querySelector('.act-wol').href = links.wol;
|
||||||
|
el.querySelector('.act-wiki').href = links.wiki;
|
||||||
|
el.querySelector('.act-google').href = links.google;
|
||||||
|
el.querySelector('.act-db').href = links.db;
|
||||||
|
|
||||||
|
// Insight visibility
|
||||||
|
var ins = el.querySelector('.act-insight');
|
||||||
|
if (links.insight) { ins.removeAttribute('hidden'); ins.href = links.insight; }
|
||||||
|
else { ins.setAttribute('hidden',''); }
|
||||||
|
|
||||||
|
// DB visibility for >2 words
|
||||||
|
var db = el.querySelector('.act-db');
|
||||||
|
if (options && options.enableDB) db.removeAttribute('hidden');
|
||||||
|
else db.setAttribute('hidden','');
|
||||||
|
|
||||||
|
el.style.display = 'block';
|
||||||
|
}
|
||||||
|
function hidePopup(){ if (popupEl) popupEl.style.display = 'none'; }
|
||||||
|
|
||||||
|
// ---- Click handler
|
||||||
|
document.addEventListener('click', function(e){
|
||||||
|
var pill = e.target.closest('.subject-pill');
|
||||||
|
if (!pill) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var text = (pill.getAttribute('data-ref') || pill.textContent || '').trim();
|
||||||
|
var n = norm(text);
|
||||||
|
|
||||||
|
// Build links
|
||||||
|
var wol = pill.getAttribute('href') || wolSearchURL(text);
|
||||||
|
var wiki = wikipediaURL(text);
|
||||||
|
var goog = googleURL(text);
|
||||||
|
|
||||||
|
// DB link only for 1–2 words
|
||||||
|
var dbEnabled = isOneOrTwoWords(text);
|
||||||
|
var db = dbEnabled ? databaseURL(text) : '#';
|
||||||
|
|
||||||
|
// Insight visible only if we have an exact match
|
||||||
|
var insightId = INSIGHT_INDEX[n];
|
||||||
|
var insight = insightId ? insightURL(insightId) : null;
|
||||||
|
|
||||||
|
var rect = pill.getBoundingClientRect();
|
||||||
|
var x = rect.left + window.scrollX + rect.width/2 - 110;
|
||||||
|
var y = rect.top + window.scrollY + rect.height + 6;
|
||||||
|
|
||||||
|
showPopup(x, y, { wol:wol, wiki:wiki, google:goog, db:db, insight:insight }, { enableDB: dbEnabled });
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
||||||
Loading…
Reference in New Issue
Block a user