Update web/templates/entry_view.html
This commit is contained in:
parent
cc1ac48b6f
commit
a8ce34a78c
@ -467,7 +467,7 @@ function showToast(message, duration = 3000) {
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Highlighter: wait until search data is present -->
|
||||
<!-- Highlighter with localStorage fallback + session/template support -->
|
||||
<script>
|
||||
(function(){
|
||||
const FIELD_TO_SELECTOR = {
|
||||
@ -477,52 +477,61 @@ function showToast(message, duration = 3000) {
|
||||
scripture_raw: "#scripture-text",
|
||||
source: "#source-text",
|
||||
talk_title: "#talk_title-text",
|
||||
talk_number: "#talk_title-text",
|
||||
talk_number: "#talk_title-text"
|
||||
};
|
||||
|
||||
let tried = 0;
|
||||
function tryRun() {
|
||||
tried++;
|
||||
let q = (window.__lastSearchQ || "").trim();
|
||||
let fields = Array.isArray(window.__lastSearchFields) ? window.__lastSearchFields : [];
|
||||
if ((!q || !fields.length)) {
|
||||
// Run under all scenarios (fresh load, bfcache, soft nav)
|
||||
if (document.readyState === "complete" || document.readyState === "interactive") run();
|
||||
else document.addEventListener("DOMContentLoaded", run, { once: true });
|
||||
window.addEventListener("pageshow", run);
|
||||
|
||||
let ran = false;
|
||||
async function run(){
|
||||
if (ran) return;
|
||||
|
||||
// 1) Respect per-user toggle
|
||||
let enabled = true;
|
||||
try {
|
||||
const res = await fetch("/api/get-prefs/", { cache: "no-store", credentials: "same-origin" });
|
||||
if (res.ok) {
|
||||
const prefs = await res.json();
|
||||
if (typeof prefs.highlight_search_hits !== "undefined") {
|
||||
enabled = !!prefs.highlight_search_hits;
|
||||
}
|
||||
}
|
||||
} catch(_) {}
|
||||
if (!enabled) { ran = true; return; }
|
||||
|
||||
// 2) Obtain q + fields (prefer localStorage to avoid session timing issues)
|
||||
let q = (localStorage.getItem('lastSearchQ') || '').trim();
|
||||
let fields = [];
|
||||
try { fields = JSON.parse(localStorage.getItem('lastSearchFields') || '[]'); } catch(_) {}
|
||||
|
||||
// If LS empty, fall back to template/session values
|
||||
if (!q || !fields.length) {
|
||||
q = (window.__lastSearchQ || '').trim();
|
||||
if (!fields.length && Array.isArray(window.__lastSearchFields)) fields = window.__lastSearchFields;
|
||||
}
|
||||
|
||||
// Final fallback: JSON script tag
|
||||
if (!q || !fields.length) {
|
||||
const dataEl = document.getElementById("last-search-data");
|
||||
if (dataEl) {
|
||||
try {
|
||||
const payload = JSON.parse(dataEl.textContent || "{}");
|
||||
q = (payload.q || "").trim();
|
||||
fields = Array.isArray(payload.fields) ? payload.fields : [];
|
||||
} catch (_) {}
|
||||
} catch(_) {}
|
||||
}
|
||||
}
|
||||
|
||||
if (q && fields.length) {
|
||||
highlight(q, fields);
|
||||
return true;
|
||||
}
|
||||
if (tried < 20) { // retry up to ~2s
|
||||
setTimeout(tryRun, 100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function highlight(q, fields) {
|
||||
// Respect per-user toggle
|
||||
let enabled = true;
|
||||
try {
|
||||
const res = await fetch("/api/get-prefs/", { cache:"no-store", credentials:"same-origin" });
|
||||
if (res.ok) {
|
||||
const prefs = await res.json();
|
||||
if (prefs && typeof prefs.highlight_search_hits !== "undefined") {
|
||||
enabled = !!prefs.highlight_search_hits;
|
||||
}
|
||||
}
|
||||
} catch(_) {}
|
||||
if (!enabled) return;
|
||||
if (!q || !fields.length) { ran = true; return; }
|
||||
|
||||
// 3) Tokenize like your search: keep quoted phrases; strip wildcards
|
||||
const tokens = tokenize(q).map(t => t.replaceAll("*","").replaceAll("?","")).filter(Boolean);
|
||||
if (!tokens.length) return;
|
||||
if (!tokens.length) { ran = true; return; }
|
||||
|
||||
// 4) Highlight in the exact fields that were searched
|
||||
for (const f of fields) {
|
||||
const sel = FIELD_TO_SELECTOR[f];
|
||||
if (!sel) continue;
|
||||
@ -530,9 +539,11 @@ function showToast(message, duration = 3000) {
|
||||
if (!container) continue;
|
||||
for (const tok of tokens) highlightAll(container, tok);
|
||||
}
|
||||
|
||||
ran = true;
|
||||
}
|
||||
|
||||
// helpers
|
||||
// ---- helpers ----
|
||||
function tokenize(s) {
|
||||
const out = [];
|
||||
let i = 0, buf = "", inQ = false;
|
||||
@ -542,7 +553,7 @@ function showToast(message, duration = 3000) {
|
||||
if (inQ) { if (buf.trim()) out.push(buf); buf = ""; inQ = false; }
|
||||
else { if (buf.trim()) out.push(buf); buf = ""; inQ = true; }
|
||||
} else if (!inQ && /\s/.test(c)) {
|
||||
if (buf.trim()) out.push(buf); buf = "";
|
||||
if (buf.trim()) out.push(buf), buf = "";
|
||||
} else {
|
||||
buf += c;
|
||||
}
|
||||
@ -558,6 +569,7 @@ function showToast(message, duration = 3000) {
|
||||
function highlightAll(root, needle) {
|
||||
if (!needle) return;
|
||||
const re = new RegExp(escapeRegExp(needle), "gi");
|
||||
|
||||
const nodes = [];
|
||||
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
|
||||
while (walker.nextNode()) nodes.push(walker.currentNode);
|
||||
@ -582,12 +594,10 @@ function showToast(message, duration = 3000) {
|
||||
if (textNode.parentNode) textNode.parentNode.replaceChild(frag, textNode);
|
||||
}
|
||||
}
|
||||
|
||||
// start
|
||||
tryRun();
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user