'; resultsEl.classList.add('open'); return; } // Collapse multiple matches from the same page to a single result. For // each page, keep the highest-ranked entry by default, BUT if the page- // level entry's title contains a query word, prefer it — Lunr's BM25 // tends to rank short section anchors above the bare page for general // terms, even when the page's own title is the obvious match. var queryWords = query.toLowerCase().split(/\s+/).filter(Boolean); function titleMatchesQuery(title) { var t = (title || '').toLowerCase(); return queryWords.some(function(w) { return t.indexOf(w) !== -1; }); } var byPage = {}; results.forEach(function(r) { var pageKey = (docsById[r.ref].location || '').split('#')[0]; (byPage[pageKey] = byPage[pageKey] || []).push(r); }); var seenPages = {}; var deduped = []; results.forEach(function(r) { var pageKey = (docsById[r.ref].location || '').split('#')[0]; if (seenPages[pageKey]) return; seenPages[pageKey] = true; var bare = byPage[pageKey].find(function(e) { return docsById[e.ref].location.indexOf('#') === -1; }); if (bare && titleMatchesQuery(docsById[bare.ref].title)) { deduped.push(bare); } else { deduped.push(r); } }); var html = deduped.slice(0, 10).map(function(r) { var d = docsById[r.ref]; var url = URL_PREFIX + d.location.replace(/^\//, ''); var snippet = (d.text || '').slice(0, 140); var hashIdx = d.location.indexOf('#'); var titleHtml = escapeHtml(d.title); // For section-anchor results, prepend the parent page title so the // same heading text on multiple pages is distinguishable. if (hashIdx !== -1) { var pageKey = d.location.slice(0, hashIdx); var parent = pageTitles[pageKey]; if (parent && parent !== d.title) { titleHtml = '' + escapeHtml(parent) + ' › ' + titleHtml; } } return ''; }).join(''); resultsEl.innerHTML = html; resultsEl.classList.add('open'); } function escapeHtml(s) { return String(s).replace(/[&"']/g, function(c) { return { '&': '&', '': '>', '"': '"', "'": ''' }[c]; }); } var debounceTimer; function onInput() { clearTimeout(debounceTimer); var rawQuery = input.value.trim(); if (!rawQuery) { resultsEl.classList.remove('open'); return; } debounceTimer = setTimeout(function() { runSearch(rawQuery).then(function(response) { // Drop stale responses if the user has typed more since if (response.requestId !== latestRequestId) return; render(response.results || [], rawQuery); }); }, 120); } input.addEventListener('input', onInput); input.addEventListener('focus', function() { if (input.value.trim()) onInput(); }); document.addEventListener('click', function(e) { if (!e.target.closest('.zotero-docs-search')) { resultsEl.classList.remove('open'); } }); function resultLinks() { return Array.prototype.slice.call(resultsEl.querySelectorAll('h3 a')); } input.addEventListener('keydown', function(e) { if (e.key === 'ArrowDown') { var links = resultLinks(); if (links.length) { e.preventDefault(); links[0].focus(); } } else if (e.key === 'Escape') { resultsEl.classList.remove('open'); } }); resultsEl.addEventListener('keydown', function(e) { var links = resultLinks(); var i = links.indexOf(document.activeElement); if (e.key === 'ArrowDown') { e.preventDefault(); if (i 0) { links[i - 1].focus(); } else { input.focus(); } } else if (e.key === 'Escape') { resultsEl.classList.remove('open'); input.focus(); } }); });

Zotero Documentation#

Using Zotero#

Small Print#