homepage search improvements

#511
This commit is contained in:
Hamid Reza Mohammadi 2026-10-02 14:31:21 +03:30
parent a1c500daee
commit 675624f807
3 changed files with 125 additions and 5 deletions

View File

@ -76,7 +76,7 @@ else
</div>
<div class="spacer" id="home-found-poets" style="display:none"></div>
<p class="up-hint" id="home-search-hint" style="display:none"><small>برای جستجوی کامل در شعرها کلید اینتر را بزنید یا روی «بیاب» کلیک کنید؛ فهرست زیر فقط جستجوی نام سخنوران است.</small></p>
<p class="up-hint" id="home-search-hint" style="display:none"><small>برای جستجو در متون «بیاب» را بزنید، فهرست زیر تنها حاصل جستجو در فهرست سخنوران و کتابهاست.</small></p>
<partial name="_InlineLoginPartial" model="Model" />
@ -197,12 +197,12 @@ else
</div>
<div class="century" id="books-shelf-caption">
مرور کتابها
قفسهٔ کتابها
</div>
<div id="books-shelf-outer">
<button type="button" class="books-shelf-handle books-shelf-handle-right" aria-label="نمایش کتابهای بیشتر در سمت راست" onclick="scrollBooksShelf(220)">‹</button>
<div id="books-shelf-wrap">
<div id="books-shelf" aria-label="مرور کتابها"></div>
<div id="books-shelf" aria-label="قفسهٔ کتابها"></div>
</div>
<button type="button" class="books-shelf-handle books-shelf-handle-left" aria-label="نمایش کتابهای بیشتر در سمت چپ" onclick="scrollBooksShelf(-220)">›</button>
</div>

View File

@ -342,7 +342,94 @@ select {
color: var(--ink-black);
}
/* Home page "مرور کتابها" book shelf - see initHomeBooksShelf()/buildBookSpine() in bk.js. */
/* A book matched by the top search box's live filter (see onHomeSearchInput()/
buildHomeBookResultChip() in bk.js) - rendered alongside matching poets in #home-found-poets, so
it needs the same flex-row layout .spacer:has(.poet) gives poet results, but triggered on its own
class too since a search can match only books and no poets at all. */
.spacer:has(.home-book-result) {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: flex-start;
gap: 14px 28px;
margin: 15px auto 25px auto;
padding: 0;
clear: both;
}
/* Sized and laid out to match .spacer .poet exactly (110px column, 76x96 "portrait" area, same pill
caption below) so a book result sits proportionate to the poet results next to it instead of
looming over them as its own, differently-sized shape. */
.home-book-result {
display: flex;
flex-direction: column;
align-items: center;
width: 110px;
margin: 0 0 10px 0;
text-decoration: none;
transition: transform 0.25s ease;
}
.home-book-result:hover {
transform: translateY(-5px);
}
.home-book-result-cover {
display: flex;
align-items: center;
justify-content: center;
width: 76px;
height: 96px;
border-radius: 10px;
padding: 6px;
overflow: hidden;
text-align: center;
color: #fdf8ee;
font-family: 'IranNastaliq', serif;
font-size: 1rem;
line-height: 1.35;
box-shadow:
0 0 0 2px var(--gold),
0 0 0 5px var(--bg-page),
0 0 0 7px var(--border-gold),
0 4px 12px rgba(0, 0, 0, 0.15);
transition: box-shadow 0.25s ease;
}
.home-book-result:hover .home-book-result-cover {
box-shadow:
0 0 0 2px var(--brand),
0 0 0 5px var(--bg-page),
0 0 0 7px var(--brand),
0 6px 18px rgba(0, 0, 0, 0.22);
}
.home-book-result-caption {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
text-align: center;
margin: 5px 0 8px 0;
padding: 6px 12px;
border-radius: 12px;
background-color: var(--card-inner);
border: 1px solid var(--border-gold);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
font-size: 0.85rem;
font-weight: 600;
color: var(--lapis);
transition: all 0.2s ease;
}
.home-book-result:hover .home-book-result-caption {
background-color: var(--gold-subtle);
border-color: var(--brand);
transform: translateY(-1px);
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.12);
}
/* Home page "قفسهٔ کتابها" book shelf - see initHomeBooksShelf()/buildBookSpine() in bk.js. */
#books-shelf-outer {
position: relative;
}

View File

@ -1560,6 +1560,31 @@ function persianizeNumerals(value) {
// behavior into the top box: typing filters poets live (same underlying match as onInlineSearch,
// against every ".poet" element's data-value), while submitting the form (Enter / the "بیاب" button)
// still does the original full poem search unchanged - so nothing about submission itself changes.
// homeBooksCache is filled once by initHomeBooksShelf() further below - the same catalog backing
// the "قفسهٔ کتابها" shelf is reused here so a search also matches book names, not just poets.
var homeBooksCache = [];
function buildHomeBookResultChip(book) {
var a = document.createElement('a');
a.className = 'home-book-result';
a.href = book.fullUrl || '#';
// Same 76x96 "portrait" box a poet result uses, just filled with the book's own hashed color
// and its name instead of a photo - see .home-book-result-cover in p8.css for the sizing.
var cover = document.createElement('span');
cover.className = 'home-book-result-cover';
cover.style.background = 'hsl(' + hashBookColorHue(book.id) + ', 42%, 32%)';
cover.textContent = book.name;
var caption = document.createElement('span');
caption.className = 'home-book-result-caption';
caption.textContent = book.poetName || '';
a.appendChild(cover);
a.appendChild(caption);
return a;
}
function onHomeSearchInput(value) {
var clearBtn = document.getElementById('home-search-clear');
var popularRow = document.getElementById('home-popular-poets-row');
@ -1603,6 +1628,13 @@ function onHomeSearchInput(value) {
foundNode.appendChild(poets[i].cloneNode(true));
}
for (var k = 0; k < homeBooksCache.length; k++) {
var book = homeBooksCache[k];
if (book.name && book.name.indexOf(replaced) !== -1) {
foundNode.appendChild(buildHomeBookResultChip(book));
}
}
var hasMatches = foundNode.childElementCount > 0;
foundNode.style.display = hasMatches ? '' : 'none';
// No matching poet: there's nothing useful to show in place of the favorites row, so put the
@ -1620,7 +1652,7 @@ function clearHomeSearch() {
input.focus();
}
// Home page (Index.cshtml) only: "مرور کتابها" - a horizontally scrollable shelf of book "spines",
// Home page (Index.cshtml) only: "قفسهٔ کتابها" - a horizontally scrollable shelf of book "spines",
// Grokipedia-homepage-style. Fetched once from this page's own "?Handler=BookCatalog" (which proxies
// RMuseum's api/ganjoor/book-catalog server-side) rather than calling that API directly from browser
// JS - same convention every other client-side data fetch on this site follows. There's no cover-art
@ -1744,6 +1776,7 @@ function initHomeBooksShelf() {
url: '?Handler=BookCatalog',
success: function (books) {
if (!books || books.length === 0) return;
homeBooksCache = books;
var frag = document.createDocumentFragment();
for (var i = 0; i < books.length; i++) {
frag.appendChild(buildBookSpine(books[i]));