Update web/templates/search.html
This commit is contained in:
parent
228e52b9a4
commit
fc82767666
@ -11,7 +11,8 @@
|
|||||||
<button class="btn btn-primary">Search</button>
|
<button class="btn btn-primary">Search</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="filter-row">
|
<!-- Desktop filters -->
|
||||||
|
<div class="filter-row desktop-filters">
|
||||||
{% for f in field_options %}
|
{% for f in field_options %}
|
||||||
<label class="check-pill">
|
<label class="check-pill">
|
||||||
<input type="checkbox" name="{{ f.name }}" {% if f.checked %}checked{% endif %}>
|
<input type="checkbox" name="{{ f.name }}" {% if f.checked %}checked{% endif %}>
|
||||||
@ -19,6 +20,21 @@
|
|||||||
</label>
|
</label>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Mobile dropdown filters -->
|
||||||
|
<div class="filter-row mobile-filters">
|
||||||
|
<button type="button" id="filterDropdownBtn" class="btn btn-secondary dropdown-toggle" aria-expanded="false">
|
||||||
|
Filters ▾
|
||||||
|
</button>
|
||||||
|
<div id="filterDropdownPanel" class="dropdown-panel">
|
||||||
|
{% for f in field_options %}
|
||||||
|
<label class="check-pill" style="display:block; margin:6px 0;">
|
||||||
|
<input type="checkbox" name="{{ f.name }}" {% if f.checked %}checked{% endif %}>
|
||||||
|
<span>{{ f.label }}</span>
|
||||||
|
</label>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% if ran_search and result_count == 0 %}
|
{% if ran_search and result_count == 0 %}
|
||||||
@ -109,7 +125,7 @@
|
|||||||
return url + sep + 't=' + Date.now();
|
return url + sep + 't=' + Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search history (keeps selected-fields subtitle)
|
// Search history
|
||||||
function renderHistory(items){
|
function renderHistory(items){
|
||||||
const list = document.getElementById('searchHistoryList');
|
const list = document.getElementById('searchHistoryList');
|
||||||
const empty = document.getElementById('searchHistoryEmpty');
|
const empty = document.getElementById('searchHistoryEmpty');
|
||||||
@ -197,6 +213,17 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Dropdown toggle for mobile filters
|
||||||
|
(function(){
|
||||||
|
const btn = document.getElementById('filterDropdownBtn');
|
||||||
|
const panel = document.getElementById('filterDropdownPanel');
|
||||||
|
if (!btn || !panel) return;
|
||||||
|
btn.addEventListener('click', ()=>{
|
||||||
|
const open = panel.classList.toggle('open');
|
||||||
|
btn.setAttribute('aria-expanded', open ? 'true' : 'false');
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
// ===============================
|
// ===============================
|
||||||
// No-results: show a random funny illustration
|
// No-results: show a random funny illustration
|
||||||
// ===============================
|
// ===============================
|
||||||
@ -221,99 +248,6 @@
|
|||||||
el.textContent = pick;
|
el.textContent = pick;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/* ===============================
|
|
||||||
Illustration of the Day (client-only, deterministic)
|
|
||||||
=============================== */
|
|
||||||
(function illustrationOfTheDay(){
|
|
||||||
const total = {{ total|default:0 }};
|
|
||||||
const iotdTextEl = document.getElementById('iotd-text');
|
|
||||||
const iotdOpenEl = document.getElementById('iotd-open');
|
|
||||||
if (!iotdTextEl || !iotdOpenEl) return;
|
|
||||||
|
|
||||||
if (!total || total < 1){
|
|
||||||
iotdTextEl.textContent = 'No illustrations available yet.';
|
|
||||||
iotdOpenEl.style.display = 'none';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seed from local date (YYYYMMDD) so it’s the same for everyone that day
|
|
||||||
const today = new Date();
|
|
||||||
const ymd = today.getFullYear()*10000 + (today.getMonth()+1)*100 + today.getDate();
|
|
||||||
|
|
||||||
// 32-bit xorshift PRNG for a good daily seed
|
|
||||||
function xorshift32(seed){
|
|
||||||
let x = seed | 0;
|
|
||||||
x ^= x << 13; x ^= x >>> 17; x ^= x << 5;
|
|
||||||
return (x >>> 0);
|
|
||||||
}
|
|
||||||
const seed = xorshift32(ymd ^ 0x9E3779B9);
|
|
||||||
|
|
||||||
const maxGuess = Math.max(100, Math.floor(total * 4));
|
|
||||||
const maxAttempts = Math.min(600, maxGuess);
|
|
||||||
|
|
||||||
function idAt(i){
|
|
||||||
const v = (Math.imul(i + 1, 1103515245) + 12345 + seed) >>> 0;
|
|
||||||
return 1 + (v % maxGuess);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchEntryHtml(id){
|
|
||||||
const url = entryUrlFor(id);
|
|
||||||
try{
|
|
||||||
const r = await fetch(url, { credentials: 'same-origin' });
|
|
||||||
if (r.ok) return await r.text();
|
|
||||||
}catch(_){}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensurePunct(str){
|
|
||||||
const s = (str || '').trim();
|
|
||||||
if (!s) return '';
|
|
||||||
return /[.!?…]$/.test(s) ? s : (s + '.');
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractSectionText(doc, label){
|
|
||||||
const labels = doc.querySelectorAll('.section-label, .meta-label, h3, h4, strong');
|
|
||||||
for (const el of labels){
|
|
||||||
const t = (el.textContent || '').trim().toLowerCase();
|
|
||||||
if (t === label){
|
|
||||||
const section = el.closest('.section') || el.parentElement;
|
|
||||||
if (section){
|
|
||||||
const body = section.querySelector('.lead-text') ||
|
|
||||||
section.querySelector('.section-body') ||
|
|
||||||
section.querySelector('p');
|
|
||||||
if (body) return (body.textContent || '').trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const alt = doc.querySelector('.lead-text, .section-body');
|
|
||||||
return alt ? (alt.textContent || '').trim() : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderIotd(id, html){
|
|
||||||
const dom = new DOMParser().parseFromString(html, 'text/html');
|
|
||||||
const illustration = extractSectionText(dom, 'illustration');
|
|
||||||
const application = extractSectionText(dom, 'application');
|
|
||||||
const merged = (ensurePunct(illustration) + (application ? ' ' + application : '')).trim();
|
|
||||||
|
|
||||||
iotdTextEl.textContent = merged || 'Open to view today’s illustration.';
|
|
||||||
iotdOpenEl.href = entryUrlFor(id);
|
|
||||||
iotdOpenEl.style.display = 'inline-block';
|
|
||||||
}
|
|
||||||
|
|
||||||
(async function findAndRender(){
|
|
||||||
for (let i = 0; i < maxAttempts; i++){
|
|
||||||
const id = idAt(i);
|
|
||||||
const html = await fetchEntryHtml(id);
|
|
||||||
if (html){
|
|
||||||
renderIotd(id, html);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iotdTextEl.textContent = 'Unable to load today’s illustration.';
|
|
||||||
iotdOpenEl.style.display = 'none';
|
|
||||||
})();
|
|
||||||
})();
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -342,32 +276,25 @@
|
|||||||
padding:10px 16px;
|
padding:10px 16px;
|
||||||
margin:0;
|
margin:0;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
|
||||||
<!-- Save q + selected fields exactly as submitted -->
|
/* Mobile filter dropdown styling */
|
||||||
<script>
|
.mobile-filters { display:none; margin-top:10px; }
|
||||||
(function(){
|
@media (max-width: 700px){
|
||||||
const form = document.querySelector('form.search-form') || document.querySelector('form[method="get"]');
|
.desktop-filters { display:none; }
|
||||||
if (!form) return;
|
.mobile-filters { display:block; }
|
||||||
const qInput = form.querySelector('input[name="q"]');
|
#filterDropdownPanel {
|
||||||
|
border:1px solid var(--border);
|
||||||
form.addEventListener('submit', () => {
|
background:#fff;
|
||||||
const fd = new FormData(form);
|
border-radius:10px;
|
||||||
const fields = [];
|
margin-top:6px;
|
||||||
for (const [k, v] of fd.entries()) {
|
padding:10px;
|
||||||
if (k.startsWith('sel[') && k.endsWith(']') && (v === 'on' || v === 'true' || v === '1')) {
|
|
||||||
fields.push(k.slice(4, -1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const q = (qInput && qInput.value || '').trim();
|
#filterDropdownBtn {
|
||||||
|
width:100%;
|
||||||
try {
|
text-align:left;
|
||||||
localStorage.setItem('lastSearchQ', q);
|
}
|
||||||
localStorage.setItem('lastSearchFields', JSON.stringify(fields));
|
}
|
||||||
} catch (_) {}
|
</style>
|
||||||
});
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% include "partials/announcement_modal.html" %}
|
{% include "partials/announcement_modal.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Loading…
Reference in New Issue
Block a user