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

240 lines
9.5 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.

/* subject-actions.v1.js
Popup for .subject-pill anchors with:
- Search in Insight Book (only if subject exists in Insight index)
- Search in WOL (uses current href if present)
- Search in Database (only for 12 word subjects)
- Search on Google
- Search on Wikipedia
Insight index:
- The script merges a small built-in seed with (optional) /static/data/insight-index.v1.json
- JSON format: { "abraham": "1200000060", "babel": "1200000613", ... }
*/
(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)
return getSearchBase()+"?q="+encodeURIComponent(q)+"&fields=subject";
}
// ---- Built-in tiny seed (~20 common, verified entries). External JSON will merge/override.
var INSIGHT_INDEX = {
"abraham": "1200000060",
"adam": "1200000089",
"baptism": "1200000555",
"david": "1200001130",
"faith": "1200001484",
"forgiveness": "1200001554",
"jerusalem": "1200002436",
"jesus christ": "1200002451",
"kingdom of god": "1200002615",
"love": "1200002781",
"moses": "1200003118",
"noah": "1200003266",
"paul": "1200003406",
"peter": "1200003451",
"prayer": "1200003568",
"resurrection": "1200003709",
"satan": "1200003845",
"marriage": "1200002912",
"mercy": "1200002994",
"wisdom": "1200004618"
};
// 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 (Object.prototype.hasOwnProperty.call(data,k)) INSIGHT_INDEX[norm(k)] = String(data[k]); }
}
} catch(_){}
}
};
xhr.send();
} catch(_){}
})();
// ---- Popup (injects minimal CSS + HTML with icons)
var popupEl;
function ensurePopup(){
if (popupEl) return popupEl;
// Minimal CSS (safe if injected twice)
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:240px;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:flex;align-items:center;gap:6px;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}" +
".subject-actions-pop a.action svg{flex:0 0 auto}";
document.head.appendChild(style);
popupEl = document.createElement('div');
popupEl.className = 'subject-actions-pop';
// Order: Insight, WOL, Database, Google, Wikipedia — with inline SVG icons
popupEl.innerHTML =
'<div class="hdr"><span>Research Subject</span><span class="close-x" aria-label="Close">✕</span></div>' +
'<div class="btn-row">' +
// Insight Book (green book)
'<a class="action act-insight" target="_blank" rel="noopener">' +
'<svg width="16" height="16" viewBox="0 0 24 24" fill="green" aria-hidden="true">' +
'<path d="M18 2H8a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10v-2H8V4h10V2z"/>' +
'<path d="M20 22h-2V6h2v16z"/>' +
'</svg>' +
'<span>Search in Insight Book</span>' +
'</a>' +
// WOL (watchtower-ish emblem)
'<a class="action act-wol" target="_blank" rel="noopener">' +
'<svg width="16" height="16" viewBox="0 0 24 24" fill="#555" aria-hidden="true">' +
'<path d="M12 2l3 5h5l-4 4 2 7-6-4-6 4 2-7-4-4h5z"/>' +
'</svg>' +
'<span>Search in WOL</span>' +
'</a>' +
// Database (stacked cylinders)
'<a class="action act-db" target="_blank" rel="noopener">' +
'<svg width="16" height="16" viewBox="0 0 24 24" fill="#1f77b4" aria-hidden="true">' +
'<ellipse cx="12" cy="5" rx="9" ry="3"/>' +
'<path d="M3 5v6c0 1.7 4 3 9 3s9-1.3 9-3V5"/>' +
'<path d="M3 11v6c0 1.7 4 3 9 3s9-1.3 9-3v-6"/>' +
'</svg>' +
'<span>Search in Database</span>' +
'</a>' +
// Google (colored G)
'<a class="action act-google" target="_blank" rel="noopener">' +
'<svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true">' +
'<path fill="#4285F4" d="M21.35 11.1H12v2.9h5.35c-.25 1.3-.98 2.4-2.1 3.1v2.6h3.4c2-1.9 3.15-4.6 3.15-7.8 0-.7-.05-1.3-.15-1.9z"/>' +
'<path fill="#34A853" d="M12 22c2.7 0 5-0.9 6.65-2.4l-3.4-2.6c-.9.6-2.05 1-3.25 1-2.5 0-4.65-1.7-5.4-4H3.1v2.6C4.8 19.9 8.1 22 12 22z"/>' +
'<path fill="#FBBC05" d="M6.6 13c-.2-.6-.3-1.3-.3-2s.1-1.4.3-2V6.4H3.1C2.4 7.9 2 9.4 2 11c0 1.6.4 3.1 1.1 4.6l3.5-2.6z"/>' +
'<path fill="#EA4335" d="M12 4.8c1.5 0 2.9.5 3.95 1.5l2.95-2.9C17 1.7 14.7.8 12 .8 8.1.8 4.8 3 3.1 6.4l3.5 2.6c.75-2.3 2.9-4.2 5.4-4.2z"/>' +
'</svg>' +
'<span>Search on Google</span>' +
'</a>' +
// Wikipedia (W)
'<a class="action act-wiki" target="_blank" rel="noopener">' +
'<svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true">' +
'<text x="2" y="17" font-family="serif" font-size="16" font-weight="bold" fill="#000">W</text>' +
'</svg>' +
'<span>Search on Wikipedia</span>' +
'</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';
// Assign hrefs
var aInsight = el.querySelector('.act-insight');
var aWol = el.querySelector('.act-wol');
var aDb = el.querySelector('.act-db');
var aGoogle = el.querySelector('.act-google');
var aWiki = el.querySelector('.act-wiki');
if (aWol) aWol.href = links.wol;
if (aWiki) aWiki.href = links.wiki;
if (aGoogle) aGoogle.href = links.google;
if (aDb) aDb.href = links.db;
// Insight visibility
if (aInsight) {
if (links.insight) { aInsight.removeAttribute('hidden'); aInsight.href = links.insight; }
else { aInsight.setAttribute('hidden',''); }
}
// DB visibility for >2 words
if (aDb) {
if (options && options.enableDB) aDb.removeAttribute('hidden');
else aDb.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 12 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 - 120; // center-ish
var y = rect.top + window.scrollY + rect.height + 6;
showPopup(x, y, { wol:wol, wiki:wiki, google:goog, db:db, insight:insight }, { enableDB: dbEnabled });
});
})();