Files
TV/js/search.js
2026-10-04 20:01:41 -07:00

71 lines
4.5 KiB
JavaScript

let sqv = '', bgT, stab = 0, SD = { q: '', all: [], mv: [], tv: [] };
const SVS = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>';
const sdraw = () => { const t = $('#stext'); t.textContent = sqv || 'Search'; t.classList.toggle('q', !!sqv) };
function setQ(v) { sqv = v; sdraw(); clearTimeout(st); st = setTimeout(() => fillSearch(sqv.trim()), 300) }
function sbgf(it) { clearTimeout(bgT); bgT = setTimeout(() => xf(bgb, I + 'w780' + (it.backdrop_path || it.poster_path)), 120) }
async function fillSearch(q) {
const my = ++sgen; skelSearch();
let all, mv, tv;
const ok = x => x.poster_path && (x.media_type === 'movie' || x.media_type === 'tv');
if (q) {
const d = await api('/search/multi', `&query=${encodeURIComponent(q)}&include_adult=false`);
if (my !== sgen) return;
all = (d.results || []).filter(ok); mv = all.filter(x => x.media_type === 'movie'); tv = all.filter(x => x.media_type === 'tv')
}
else {
const [a, b] = await Promise.all([api('/trending/movie/week'), api('/trending/tv/week')]);
if (my !== sgen) return;
mv = (a.results || []).filter(x => x.poster_path).map(x => ({ ...x, media_type: 'movie' }));
tv = (b.results || []).filter(x => x.poster_path).map(x => ({ ...x, media_type: 'tv' })); all = []
}
SD = { q, all, mv, tv }; drawSearch()
}
function tile(x) {
x._t = x.media_type;
const e = mkf('sc', `<div class="po"><img src="${I}w342${x.poster_path}" alt=""></div><b>${esc(x.title || x.name || '')}</b><small><span>&#9733; ${(x.vote_average || 0).toFixed(1)}</span><span>${yr(x)}</span><span>${x.media_type === 'tv' ? 'Show' : 'Movie'}</span></small>`, () => openDetail(x));
e._bg = x; return e
}
function drawSearch() {
const { q, all, mv, tv } = SD;
chips.innerHTML = '';
const names = [...new Set((q ? all : [...mv, ...tv]).map(x => x.title || x.name))].slice(0, 9);
if (q) chips.appendChild(mkf('chip', SVS + `"${esc(q)}"`, () => { }));
names.forEach(n => chips.appendChild(mkf('chip', esc(n), () => setQ(n))));
sres.innerHTML = '';
const L = stab === 1 ? [['Movies', mv]] : stab === 2 ? [['TV Shows', tv]] : q ? [['Top Matches', all.slice(0, 10)], ['Movies', mv], ['TV Shows', tv]] : [['Trending Movies', mv], ['Trending TV Shows', tv]];
let n = 0;
L.forEach(([h, a]) => { if (!a.length) return; n++; const sec = document.createElement('section'); sec.className = 'ss'; sec.innerHTML = `<h3>${h}</h3><div class="row ch"></div>`; sec.lastChild.append(...a.map(tile)); sres.appendChild(sec) });
if (!n) sres.innerHTML = `<p class="none">No results${q ? ` for \u201c${esc(q)}\u201d` : ''}</p>`;
[...tabs.children].forEach((t, i) => t.classList.toggle('act', i === stab));
if (cur && !document.body.contains(cur)) setFocus(chips.children[1] || chips.firstChild || kb.children[2])
}
['Top Results', 'Movies', 'TV Shows'].forEach((t, i) => tabs.appendChild(mkf('tab', t, () => { stab = i; drawSearch() })));
const KL = 'abcdefghijklmnopqrstuvwxyz'.split(''), KN = "1234567890.-'&:".split('');
let num = false;
function buildKb() {
kb.innerHTML = '';
const mk = (label, cls, fn) => kb.appendChild(mkf('k ' + cls, label, () => { fn(); sr.scrollTo({ top: 0, behavior: 'smooth' }) }));
mk(num ? 'ABC' : '123', 'w', () => { num = !num; buildKb(); setFocus(kb.firstChild) });
mk('SPACE', 'w', () => { if (sqv && !sqv.endsWith(' ')) setQ(sqv + ' ') });
(num ? KN : KL).forEach(c => mk(c, '', () => setQ(sqv + c)));
mk('<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5h11a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H9l-6-7z"/><path d="m12 9 5 5m0-5-5 5"/></svg>', 'd', () => setQ(sqv.slice(0, -1)))
}
buildKb();
function openSearch() {
setAct('search'); document.body.classList.add('srch'); sr.classList.add('show'); side.classList.remove('open'); sr.scrollTop = 0;
if (!sres.children.length) fillSearch('');
setFocus(kb.children[2])
}
function closeSearch(silent) {
if (!sr.classList.contains('show')) return;
sr.classList.remove('show'); document.body.classList.remove('srch');
heroIt = null; bgb._u = null;
if (!silent) { setAct(mode); setFocus(document.querySelector('#rows .card')) }
}
function skelSearch() {
chips.innerHTML = SK.chips(7);
sres.innerHTML = [0, 1].map(() => `<section class="ss"><i class="sb h3s"></i><div class="row ch">${SK.tiles(9)}</div></section>`).join('')
}