Widget:BcaSearch: Difference between revisions

From Bodhicitta
(Site search (preview): full text, grouped results, class filters, shareable URL)
 
(Mobile: finger-sized chapter/verse number chips)
 
(10 intermediate revisions by the same user not shown)
Line 7: Line 7:
.bcas__go:hover{background:#fff}
.bcas__go:hover{background:#fff}
.bcas__hint{font-size:.85rem;color:#666;margin:.2rem 0 1rem}
.bcas__hint{font-size:.85rem;color:#666;margin:.2rem 0 1rem}
.bcas__hint a{cursor:pointer}
.bcas__tabs{display:flex;flex-wrap:wrap;gap:.4rem;border-bottom:1px solid rgba(17,54,81,.15);margin:1rem 0 .8rem}
.bcas__tabs{display:flex;flex-wrap:wrap;gap:.4rem;border-bottom:1px solid rgba(17,54,81,.15);margin:1rem 0 .8rem}
.bcas__tab{padding:.45rem .9rem;border:1px solid transparent;border-bottom:0;border-radius:6px 6px 0 0;cursor:pointer;color:#41607D;font-size:.95rem;margin-bottom:-1px;background:none}
.bcas__tab{padding:.45rem .9rem;border:1px solid transparent;border-bottom:0;border-radius:6px 6px 0 0;cursor:pointer;color:#41607D;font-size:.95rem;margin-bottom:-1px;background:none}
Line 19: Line 18:
.bcas__hit{padding:.85rem 1.15rem;border-top:1px solid rgba(177,175,169,.35)}
.bcas__hit{padding:.85rem 1.15rem;border-top:1px solid rgba(177,175,169,.35)}
.bcas__hit:first-child{border-top:0}
.bcas__hit:first-child{border-top:0}
.bcas__hit-title{font-size:1.2rem;font-weight:600;font-family:'Cormorant Garamond',serif}
.bcas__hit-title{font-size:1.3rem;font-weight:500;font-family:'Cormorant Garamond',serif}
.bcas__hit-meta{font-size:.82rem;color:#666;margin-top:.15rem}
.bcas__hit-meta{font-size:.82rem;color:#666;margin-top:.15rem}
.bcas__hit-meta > span + span::before{content:'·';margin:0 .4rem;opacity:.45}
.bcas__hit-meta > span + span::before{content:'·';margin:0 .4rem;opacity:.45}
Line 25: Line 24:
.bcas__pills{margin:.2rem 0 .8rem}
.bcas__pills{margin:.2rem 0 .8rem}
.bcas__empty{padding:1.2rem;color:#666}
.bcas__empty{padding:1.2rem;color:#666}
.bcas__tips{font-size:.88rem;color:#555;margin:-.4rem 0 .8rem}
.bcas__tips summary{cursor:pointer;color:#41607D;display:inline-block}
.bcas__tips ul{margin:.4rem 0 0 1.2rem}
.bcas__tips li{margin:.15rem 0}
.bcas__tips a,.bcas__hint a{cursor:pointer;color:#0645AD;text-decoration:none;border-bottom:1px dotted rgba(6,69,173,.4)}
.bcas__tips a:hover,.bcas__hint a:hover{color:#001028}
/* Start panel (in the page below the widget) */
.bcas-start{max-width:1100px;margin:1.5rem auto 3rem}
.bcas-start__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(420px,100%),1fr));gap:1.2rem}
.bcas-start__card{background:#fffcf5;border-radius:8px;border-top:2px solid #BA1B1D;padding:1rem 1.2rem 1.1rem;box-shadow:0 1px 2px rgba(0,0,0,.06),0 6px 16px rgba(60,40,10,.08)}
.bcas-start__h{font-family:'Cormorant Garamond',serif;font-size:1.45rem;font-weight:500;margin:0 0 .6rem}
.bcas-start__links a{display:block;padding:.45rem .6rem;margin:0 -.6rem;border-radius:6px;color:#113651;text-decoration:none}
.bcas-start__links a:hover{background:rgba(191,150,89,.1)}
.bcas-start__links b{font-weight:600;display:block}
.bcas-start__links span{font-size:.85rem;color:#666}
.bcas-start__chips{display:flex;flex-wrap:wrap;gap:.4rem}
.bcas-start__chips a{display:inline-flex;align-items:center;gap:.4rem;padding:.3rem .8rem;border:1px solid #d6d0c2;border-radius:999px;background:#fff;color:#113651;font-size:.9rem;text-decoration:none}
.bcas-start__chips a:hover{border-color:#bf9659;background:rgba(191,150,89,.08)}
.bcas-start__chips a span{color:#888;font-size:.8rem}
.bcas-start__chips--small{margin-top:.5rem}
.bcas-start__sub{margin-bottom:.8rem}
.bcas-start__chips--small a{padding:.15rem .6rem;font-size:.82rem}
/* Phones: finger-sized number chips (they were ~29x26px). */
@media (max-width:767.98px){.bcas-start__chips--small{gap:.5rem}.bcas-start__chips--small a{min-width:2.5rem;min-height:2.5rem;justify-content:center;font-size:.95rem}}
.bcas-start__more{margin-top:.7rem;font-size:.85rem;color:#666}
.bcas-start__more--stack a{display:block;padding:.15rem 0}
.bcas-start__sub{margin:.1rem 0 .6rem .6rem;padding-left:.8rem;border-left:2px solid rgba(191,150,89,.35)}
.bcas-start__label{font-size:.78rem;color:#888;margin-right:.2rem;align-self:center}
.bcas-start__note{font-size:.82rem;color:#666;margin-top:.45rem}
/* Whole row is the link: hover tint and a gold edge, as on PLL's lists */
.bcas__list .topic-biblio-row,.bcas__hit{cursor:pointer;position:relative;transition:background-color .15s ease,box-shadow .15s ease}
.bcas__list .topic-biblio-row:hover,.bcas__hit:hover{background:rgba(191,150,89,.09);box-shadow:inset 3px 0 0 #bf9659}
.bcas__list .topic-biblio-row:focus-within,.bcas__hit:focus-within{box-shadow:inset 3px 0 0 #bf9659}
.bcas__refine{display:flex;align-items:center;gap:.8rem;margin:.2rem 0 .6rem}
.bcas__refine input{flex:0 1 22rem;padding:.45rem 1rem;border:1px solid #d6d0c2;border-radius:2em;background:#fffcf5;font-size:.92rem}
.bcas__refine input:focus{outline:none;border-color:#bf9659;box-shadow:0 0 0 3px rgba(191,150,89,.22)}
.bcas__refine .bcas__status{margin:0}
</style>
</style>
<div class="bcas noglossary" id="bcas">
<div class="bcas noglossary" id="bcas">
Line 32: Line 68:
</form>
</form>
<div class="bcas__hint" id="bcas-hint">Try <a data-q="tonglen">tonglen</a>, <a data-q="Santideva">Santideva</a> (accents optional), <a data-q="9.1">9.1</a> (a verse), <a data-q="&quot;bodhicitta of aspiration&quot;">"bodhicitta of aspiration"</a> (exact phrase) or <a data-q="བྱང་ཆུབ་སེམས">བྱང་ཆུབ་སེམས</a>.</div>
<div class="bcas__hint" id="bcas-hint">Try <a data-q="tonglen">tonglen</a>, <a data-q="Santideva">Santideva</a> (accents optional), <a data-q="9.1">9.1</a> (a verse), <a data-q="&quot;bodhicitta of aspiration&quot;">"bodhicitta of aspiration"</a> (exact phrase) or <a data-q="བྱང་ཆུབ་སེམས">བྱང་ཆུབ་སེམས</a>.</div>
<details class="bcas__tips"><summary>Search tips</summary><ul>
<li><b>"exact phrase"</b> in quotes finds the words together: <a data-q="&quot;wish-fulfilling jewel&quot;">"wish-fulfilling jewel"</a></li>
<li><b>-word</b> leaves a word out: <a data-q="compassion -dalai">compassion -dalai</a></li>
<li><b>OR</b> finds either word: <a data-q="tonglen OR lojong">tonglen OR lojong</a></li>
<li><b>word*</b> matches any ending: <a data-q="meditat*">meditat*</a></li>
<li><b>intitle:</b> searches titles only: <a data-q="intitle:bodhisattva">intitle:bodhisattva</a></li>
<li><b>incategory:</b> searches by tag. Topics, decades, people and publishers are all tags: <a data-q="incategory:&quot;Topic: Tonglen&quot;">incategory:"Topic: Tonglen"</a>, <a data-q="incategory:&quot;Decade: 1990s&quot;">incategory:"Decade: 1990s"</a>, <a data-q="incategory:&quot;Padmakara Translation Group&quot;">incategory:"Padmakara Translation Group"</a>. Combine with words: <a data-q="patience incategory:&quot;Topic: Six Perfections&quot;">patience incategory:"Topic: Six Perfections"</a></li>
<li>Accents are optional (<a data-q="santideva">santideva</a> finds Śāntideva); Tibetan script and Wylie work too.</li>
<li>A verse number such as <a data-q="8.120">8.120</a> offers that Bodhicaryāvatāra verse page.</li>
</ul></details>
<div id="bcas-shortcut"></div>
<div id="bcas-shortcut"></div>
<div class="bcas__tabs" id="bcas-tabs" role="tablist" hidden></div>
<div class="bcas__tabs" id="bcas-tabs" role="tablist" hidden></div>
<div class="bcas__pills topic-biblio-pills" id="bcas-pills" hidden></div>
<div class="bcas__pills topic-biblio-pills" id="bcas-pills" hidden></div>
<div class="bcas__status" id="bcas-status" aria-live="polite"></div>
<div class="bcas__refine" id="bcas-refine" hidden><input id="bcas-filter" type="search" placeholder="Filter these results…" aria-label="Filter the results shown"><div class="bcas__status" id="bcas-status" aria-live="polite"></div></div>
<div class="bcas__list" id="bcas-list"></div>
<div class="bcas__list" id="bcas-list"></div>
<button class="bcas__more" id="bcas-more" type="button" hidden>Show more results</button>
<button class="bcas__more" id="bcas-more" type="button" hidden>Show more results</button>
</div>
</div>
<script>
<script>
(function () {
// Inline scripts run before ResourceLoader has loaded jQuery and mediawiki.util,
if (!window.mw || !window.jQuery) return;
// so the search starts from the RLQ queue once those modules are ready.
(window.RLQ = window.RLQ || []).push([['mediawiki.util', 'jquery'], function () {
var $ = jQuery;
var $ = jQuery;
var API = mw.util.wikiScript('api');
var API = mw.util.wikiScript('api');
Line 57: Line 104:


var state = { q: '', tab: 'library', cls: '', offset: 0 };
var state = { q: '', tab: 'library', cls: '', offset: 0 };
// First page of results per class, fetched with the class counts, so a class
// button shows its rows without waiting for another search.
var firstPages = {};
var counts = {};
var counts = {};
var token = 0;
var token = 0;
Line 87: Line 137:
return (d && d.query && d.query.results) || {};
return (d && d.query && d.query.results) || {};
});
});
}
function covers(files) {
if (!files.length) return $.Deferred().resolve({}).promise();
return $.getJSON(API, { action: 'query', format: 'json', formatversion: 2, titles: files.join('|'), prop: 'imageinfo', iiprop: 'url', iiurlwidth: 120 })
.then(function (d) {
var out = {};
((d.query && d.query.pages) || []).forEach(function (p) { if (p.imageinfo && p.imageinfo[0]) out[p.title] = p.imageinfo[0].thumburl || p.imageinfo[0].url; });
((d.query && d.query.normalized) || []).forEach(function (n) { if (out[n.to]) out[n.from] = out[n.to]; });
return out;
}, function () { return {}; });
}
}
function first(po, k) { var v = po && po[k]; if (!v || !v.length) return ''; v = v[0]; return typeof v === 'object' ? (v.fulltext || v.raw || '') : v; }
function first(po, k) { var v = po && po[k]; if (!v || !v.length) return ''; v = v[0]; return typeof v === 'object' ? (v.fulltext || v.raw || '') : v; }
Line 114: Line 154:
}).join('');
}).join('');
}
}
// Where a passage sits in its bilingual layout: the same rules as the
// citations panel (Module:SscCitations bilingualLink).
var SINGLE_PAGE_BILINGUAL = { '013-Tsadra-BCA-Com-Minyak-Ch9': 1, '011-Tsadra-BCA-Com-Pawo': 1 };
var NAMED_BILINGUAL_SUBPAGE = { '020-Tsadra-BC-Root-Bhavanakrama-1': 'Bhavanakrama-1', '020-Tsadra-BC-Root-Bhavanakrama-2': 'Bhavanakrama-2', '020-Tsadra-BC-Root-Bhavanakrama-3': 'Bhavanakrama-3' };
function bilingual(po, title) {
function bilingual(po, title) {
var base = first(po, 'TranslationWikiPage'), ch = first(po, 'TranslationChapter'), ord = first(po, 'SegmentOrder');
var tm = first(po, 'TransMemID') || title.split('/')[0].replace('Translation Memory:', '');
if (!base || !ord) return '';
var base = first(po, 'TranslationWikiPage'), ch = first(po, 'TranslationChapter');
ord = String(ord).replace(/,/g, '');
var ord = String(first(po, 'SegmentOrder') || first(po, 'SourceSegmentOrder') || '').replace(/,/g, '');
return mw.util.getUrl(base + '/Bilingual' + (ch ? '/' + ch : '')) + '#seg-' + ord;
if (!base) { base = first(po, 'SourceWikiPage'); return base ? mw.util.getUrl(base) : ''; }
if (!ord) return mw.util.getUrl(base + '/Bilingual');
if (NAMED_BILINGUAL_SUBPAGE[tm]) return mw.util.getUrl(base + '/Bilingual/' + NAMED_BILINGUAL_SUBPAGE[tm]) + '#seg-' + ord;
if (SINGLE_PAGE_BILINGUAL[tm] || !ch) return mw.util.getUrl(base + '/Bilingual') + '#seg-' + ord;
return mw.util.getUrl(base + '/Bilingual/' + ch) + '#seg-' + ord;
}
}
function renderPassages(hits, data) {
function renderPassages(hits, data) {
Line 126: Line 174:
var ch = first(po, 'TranslationChapter'), href = bilingual(po, h.title);
var ch = first(po, 'TranslationChapter'), href = bilingual(po, h.title);
return '<div class="bcas__hit"><div class="bcas__hit-title">' + (href ? '<a href="' + esc(href) + '">' : '') + esc(String(work).replace(/^(Books|Articles|Dissertations)\//, '')) + (href ? '</a>' : '') + '</div>' +
return '<div class="bcas__hit"><div class="bcas__hit-title">' + (href ? '<a href="' + esc(href) + '">' : '') + esc(String(work).replace(/^(Books|Articles|Dissertations)\//, '')) + (href ? '</a>' : '') + '</div>' +
'<div class="bcas__hit-meta">' + (ch ? '<span>Chapter ' + esc(ch) + '</span>' : '') + '<span>passage ' + esc(h.title.split('/').pop()) + '</span><span>' + link(h.title, 'segment record') + '</span></div>' +
'<div class="bcas__hit-meta">' + (ch ? '<span>Chapter ' + esc(ch) + '</span>' : '') + '<span>passage ' + esc(h.title.split('/').pop()) + '</span>' + (href ? '<span>bilingual view</span>' : '') + '</div>' +
(h.snippet ? '<div class="bcas__snip">…' + h.snippet + '…</div>' : '') + '</div>';
(h.snippet ? '<div class="bcas__snip">…' + h.snippet + '…</div>' : '') + '</div>';
}).join('');
}).join('');
Line 177: Line 225:
$('#bcas-more').prop('hidden', true);
$('#bcas-more').prop('hidden', true);
$('#bcas-status').text('Searching…');
$('#bcas-status').text('Searching…');
search(g, g.id === 'library' ? state.cls : '', state.offset, PAGE).then(function (r) {
var key = state.q + '|' + state.cls;
var cached = (g.id === 'library' && state.cls && state.offset === 0 && firstPages[key]);
return (cached ? $.Deferred().resolve(cached).promise() : search(g, g.id === 'library' ? state.cls : '', state.offset, PAGE)).then(function (r) {
if (my !== token) return;
if (my !== token) return;
var hits = r.search || [];
var hits = r.search || [];
Line 185: Line 235:
var p;
var p;
if (g.id === 'library') {
if (g.id === 'library') {
// Covers load lazily from Special:Redirect, so the rows do not wait on an
// image lookup (the files live on Commons, which can be slow).
p = ask(titles, '|?Citation|?Class|?Pubdate|?Title|?FrontCoverImg').then(function (data) {
p = ask(titles, '|?Citation|?Class|?Pubdate|?Title|?FrontCoverImg').then(function (data) {
var files = []; titles.forEach(function (t) { var f = first(((data[t] || {}).printouts) || {}, 'FrontCoverImg'); if (f) files.push(f); });
var th = {};
return covers(files).then(function (th) { return renderLibrary(hits, data, th); });
titles.forEach(function (t) { var f = first(((data[t] || {}).printouts) || {}, 'FrontCoverImg'); if (f) th[f] = mw.util.getUrl('Special:Redirect/file/' + f.replace(/^File:/, ''), { width: 120 }); });
return renderLibrary(hits, data, th);
});
});
} else if (g.id === 'passages') {
} else if (g.id === 'passages') {
p = ask(titles, '|?TranslationWikiPage|?TranslationChapter|?SegmentOrder').then(function (data) { return renderPassages(hits, data); });
p = ask(titles, '|?TranslationWikiPage|?TranslationChapter|?SegmentOrder|?SourceSegmentOrder|?TransMemID|?SourceWikiPage').then(function (data) { return renderPassages(hits, data); });
} else {
} else {
p = $.Deferred().resolve(renderPlain(hits)).promise();
p = $.Deferred().resolve(renderPlain(hits)).promise();
Line 199: Line 252:
$('#bcas-list').append(html);
$('#bcas-list').append(html);
state.offset += PAGE;
state.offset += PAGE;
window.setTimeout(refine, 0);
var shown = Math.min(state.offset, total);
var shown = Math.min(state.offset, total);
$('#bcas-status').text('Showing ' + fmt(shown) + ' of ' + fmt(total) + ' in ' + g.label.toLowerCase() + (state.cls ? ' · ' + state.cls : '') + '.');
$('#bcas-status').text('Showing ' + fmt(shown) + ' of ' + fmt(total) + ' in ' + g.label.toLowerCase() + (state.cls ? ' · ' + state.cls : '') + '.');
Line 207: Line 261:
$('#bcas-status').text('The search could not run just now. Please try again in a moment.');
$('#bcas-status').text('The search could not run just now. Please try again in a moment.');
});
});
}
// Narrow the rows already shown, without a new search (accents ignored).
function fold(s) { return String(s).normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase(); }
function refine() {
var v = fold($('#bcas-filter').val().trim()), shown = 0, all = 0;
$('#bcas-list').children('.topic-biblio-row, .bcas__hit').each(function () {
var ok = !v || fold($(this).text()).indexOf(v) > -1;
$(this).toggle(ok); all++; if (ok) shown++;
});
$('#bcas-filtered').remove();
if (v) $('#bcas-status').append('<span id="bcas-filtered"> ' + fmt(shown) + ' of the ' + fmt(all) + ' shown match the filter.</span>');
}
}


Line 213: Line 279:
writeUrl();
writeUrl();
shortcut();
shortcut();
if (!state.q) { $('#bcas-tabs,#bcas-pills,#bcas-more').prop('hidden', true); $('#bcas-list,#bcas-status').empty(); $('#bcas-hint').show(); return; }
if (!state.q) { $('#bcas-tabs,#bcas-pills,#bcas-more,#bcas-refine').prop('hidden', true); $('#bcas-list,#bcas-status').empty(); $('#bcas-hint, #bcas-start').show(); return; }
$('#bcas-hint').hide();
$('#bcas-hint, #bcas-start').hide();
$('#bcas-refine').prop('hidden', false); $('#bcas-filter').val('');
counts = {};
counts = {};
renderTabs();
renderTabs();
var my = token + 1;
// The results come first; the counts follow once they are on screen, so the
// Counts for every group, then for each library class, all in parallel.
// first page is not queued behind eleven count searches (and a class button
$.when.apply($, GROUPS.map(function (g) {
// clicked early does not wait behind them either).
var listDone = loadList(false) || $.Deferred().resolve().promise();
listDone.always(function () { $.when.apply($, GROUPS.map(function (g) {
return search(g, '', 0, 1).then(function (r) { counts[g.id] = r.searchinfo.totalhits; }, function () { counts[g.id] = 0; });
return search(g, '', 0, 1).then(function (r) { counts[g.id] = r.searchinfo.totalhits; }, function () { counts[g.id] = 0; });
})).always(function () {
})).always(function () {
Line 226: Line 295:
var cc = {};
var cc = {};
$.when.apply($, CLASSES.map(function (c) {
$.when.apply($, CLASSES.map(function (c) {
return search(GROUPS[0], c, 0, 1).then(function (r) { cc[c] = r.searchinfo.totalhits; }, function () {});
return search(GROUPS[0], c, 0, PAGE).then(function (r) { cc[c] = r.searchinfo.totalhits; firstPages[state.q + '|' + c] = r; }, function () {});
})).always(function () { renderPills(cc); });
})).always(function () { renderPills(cc); });
}
}
});
}); });
loadList(false);
}
}


Line 239: Line 307:
$('#bcas-q').val(params.get('q') || '');
$('#bcas-q').val(params.get('q') || '');
$('#bcas-form').on('submit', function (e) { e.preventDefault(); state.cls = ''; run(); });
$('#bcas-form').on('submit', function (e) { e.preventDefault(); state.cls = ''; run(); });
// Clearing the box (its x, or deleting the text) returns to the browse panels.
$('#bcas-q').on('input search', function () { if (!this.value.trim() && state.q) { state.cls = ''; state.tab = 'library'; run(); } });
$('.bcas__tips').on('click', 'a[data-q]', function () { $('#bcas-q').val($(this).attr('data-q')); state.cls = ''; run(); });
$('#bcas-hint').on('click', 'a[data-q]', function () { $('#bcas-q').val($(this).attr('data-q')); state.cls = ''; run(); });
$('#bcas-hint').on('click', 'a[data-q]', function () { $('#bcas-q').val($(this).attr('data-q')); state.cls = ''; run(); });
$('#bcas-tabs').on('click', '.bcas__tab', function () { state.tab = $(this).data('tab'); state.cls = ''; writeUrl(); renderTabs(); $('#bcas-pills').prop('hidden', true); if (state.tab === 'library') run(); else loadList(false); });
$('#bcas-tabs').on('click', '.bcas__tab', function () { state.tab = $(this).data('tab'); state.cls = ''; writeUrl(); renderTabs(); $('#bcas-pills').prop('hidden', true); if (state.tab === 'library') run(); else loadList(false); });
$('#bcas-pills').on('click', '.topic-biblio-pill', function () { state.cls = $(this).attr('data-cls') || ''; $('#bcas-pills .topic-biblio-pill').removeClass('is-active'); $(this).addClass('is-active'); writeUrl(); loadList(false); });
$('#bcas-pills').on('click', '.topic-biblio-pill', function () { state.cls = $(this).attr('data-cls') || ''; $('#bcas-pills .topic-biblio-pill').removeClass('is-active'); $(this).addClass('is-active'); writeUrl(); loadList(false); });
$('#bcas-more').on('click', function () { loadList(true); });
$('#bcas-more').on('click', function () { loadList(true); });
if (state.q) run(); else $('#bcas-q').trigger('focus');
$('#bcas-filter').on('input', refine);
// Whole row opens its first link, unless a link inside it was clicked or text selected.
$('#bcas-list').on('click', '.topic-biblio-row, .bcas__hit', function (e) {
if ($(e.target).closest('a').length || String(window.getSelection())) return;
var a = $(this).find('a').get(0); if (!a) return;
if (e.metaKey || e.ctrlKey) window.open(a.href, '_blank'); else location.href = a.href;
});
// The start panel (in the page) can launch searches too.
$(document).on('click', '#bcas-start [data-q]', function (e) { e.preventDefault(); $('#bcas-q').val($(this).attr('data-q')); state.cls = $(this).attr('data-class') || ''; state.tab = $(this).attr('data-tab') || 'library'; run(); window.scrollTo({ top: $('#bcas').offset().top - 90, behavior: 'smooth' }); });
if ($('#bcas-q').val()) run(); else { $('#bcas-start').show(); $('#bcas-q').trigger('focus'); }
});
});
}());
}]);
</script></includeonly>
</script></includeonly>

Latest revision as of 17:41, 8 October 2026

Site search for the Bodhicitta wiki (preview). Used on Advanced Search/Preview. Full-text search through CirrusSearch, results grouped (library, passages in the aligned texts, essays, topics, people), class filters with counts, the library's bibliographic rows, and the search kept in the page address so it can be shared.