Skip to content

Commit 88d06fa

Browse files
Fetch full game data and improve cards
For search results, fetch full game JSON for the first 60 matches (using Promise.all) and gracefully handle fetch failures by falling back to partial data. Normalize IGDB cover URLs to use a larger cover size (t_cover_big) and ensure absolute URLs, increase cover/placeholder height from 180px to 240px, and improve name layout with two-line clamping and bolder text. Also keep the same behavior when platform data can't be loaded by still fetching game details.
1 parent a6bdc51 commit 88d06fa

1 file changed

Lines changed: 175 additions & 128 deletions

File tree

gh-pages-template/assets/js/item_loader.js

Lines changed: 175 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -384,146 +384,193 @@ function run_search() {
384384
fetch(`${base_url}/platforms/all.json`)
385385
.then(r => r.json())
386386
.then(allPlatforms => {
387-
matches.slice(0, 60).forEach(([id, game]) => {
388-
const col = document.createElement("div")
389-
col.className = "col"
390-
row.appendChild(col)
391-
392-
const card = document.createElement("a")
393-
card.className = "card h-100 text-decoration-none shadow-sm border-0 rounded-0"
394-
card.href = `${base_path}/browse/games/?id=${id}`
395-
col.appendChild(card)
396-
397-
// Cover image or placeholder
398-
if (game.cover && game.cover.url) {
399-
const coverImg = document.createElement("img")
400-
coverImg.className = "card-img-top rounded-top-0"
401-
coverImg.src = game.cover.url.replace("t_thumb", "t_cover_small")
402-
coverImg.alt = game.name
403-
coverImg.loading = "lazy"
404-
coverImg.style.height = "180px"
405-
coverImg.style.objectFit = "cover"
406-
card.appendChild(coverImg)
407-
} else {
408-
const placeholder = document.createElement("div")
409-
placeholder.className = "card-img-top bg-secondary d-flex align-items-center justify-content-center"
410-
placeholder.style.height = "180px"
411-
const icon = document.createElement("span")
412-
icon.className = "material-symbols-outlined text-white"
413-
icon.style.fontSize = "3rem"
414-
icon.textContent = "sports_esports"
415-
placeholder.appendChild(icon)
416-
card.appendChild(placeholder)
417-
}
387+
// Fetch full game data for each match
388+
const gamePromises = matches.slice(0, 60).map(([id, _game]) =>
389+
fetch(`${base_url}/games/${id}.json`)
390+
.then(r => r.ok ? r.json() : null)
391+
.then(fullGame => ({ id, game: fullGame || { name: _game.name } }))
392+
.catch(() => ({ id, game: { name: _game.name } }))
393+
)
394+
395+
Promise.all(gamePromises).then(results => {
396+
results.forEach(({ id, game }) => {
397+
const col = document.createElement("div")
398+
col.className = "col"
399+
row.appendChild(col)
400+
401+
const card = document.createElement("a")
402+
card.className = "card h-100 text-decoration-none shadow-sm border-0 rounded-0"
403+
card.href = `${base_path}/browse/games/?id=${id}`
404+
col.appendChild(card)
405+
406+
// Cover image or placeholder
407+
if (game.cover && game.cover.url) {
408+
const coverImg = document.createElement("img")
409+
coverImg.className = "card-img-top rounded-top-0"
410+
// Convert IGDB URL properly
411+
let coverUrl = game.cover.url
412+
if (!coverUrl.startsWith('http')) {
413+
coverUrl = 'https://images.igdb.com/igdb/image/upload/t_cover_big/' + coverUrl.split('/').pop()
414+
} else {
415+
coverUrl = coverUrl.replace("t_thumb", "t_cover_big")
416+
}
417+
coverImg.src = coverUrl
418+
coverImg.alt = game.name
419+
coverImg.loading = "lazy"
420+
coverImg.style.width = "100%"
421+
coverImg.style.aspectRatio = "3 / 4"
422+
coverImg.style.objectFit = "cover"
423+
card.appendChild(coverImg)
424+
} else {
425+
const placeholder = document.createElement("div")
426+
placeholder.className = "card-img-top bg-secondary d-flex align-items-center justify-content-center"
427+
placeholder.style.width = "100%"
428+
placeholder.style.aspectRatio = "3 / 4"
429+
const icon = document.createElement("span")
430+
icon.className = "material-symbols-outlined text-white"
431+
icon.style.fontSize = "3rem"
432+
icon.textContent = "sports_esports"
433+
placeholder.appendChild(icon)
434+
card.appendChild(placeholder)
435+
}
418436

419-
const cardBody = document.createElement("div")
420-
cardBody.className = "card-body p-2"
421-
card.appendChild(cardBody)
422-
423-
// Game name
424-
const nameEl = document.createElement("h6")
425-
nameEl.className = "card-title small mb-2 fw-bold text-truncate"
426-
nameEl.textContent = game.name
427-
nameEl.title = game.name
428-
cardBody.appendChild(nameEl)
429-
430-
// Platforms with release years
431-
if (game.platforms && game.platforms.length > 0) {
432-
const platformsDiv = document.createElement("div")
433-
platformsDiv.className = "mb-2"
434-
435-
// Group release dates by platform
436-
const platformYears = {}
437-
if (game.release_dates && game.release_dates.length > 0) {
438-
game.release_dates.forEach(rd => {
439-
if (rd.platform && rd.y) {
440-
if (!platformYears[rd.platform] || rd.y < platformYears[rd.platform]) {
441-
platformYears[rd.platform] = rd.y
437+
const cardBody = document.createElement("div")
438+
cardBody.className = "card-body p-2"
439+
card.appendChild(cardBody)
440+
441+
// Game name
442+
const nameEl = document.createElement("h6")
443+
nameEl.className = "card-title small mb-2 fw-bold"
444+
nameEl.textContent = game.name
445+
nameEl.title = game.name
446+
nameEl.style.overflow = "hidden"
447+
nameEl.style.display = "-webkit-box"
448+
nameEl.style.webkitLineClamp = "2"
449+
nameEl.style.webkitBoxOrient = "vertical"
450+
cardBody.appendChild(nameEl)
451+
452+
// Platforms with release years
453+
if (game.platforms && game.platforms.length > 0) {
454+
const platformsDiv = document.createElement("div")
455+
platformsDiv.className = "mb-2"
456+
457+
// Group release dates by platform
458+
const platformYears = {}
459+
if (game.release_dates && game.release_dates.length > 0) {
460+
game.release_dates.forEach(rd => {
461+
if (rd.platform && rd.y) {
462+
if (!platformYears[rd.platform] || rd.y < platformYears[rd.platform]) {
463+
platformYears[rd.platform] = rd.y
464+
}
442465
}
443-
}
466+
})
467+
}
468+
469+
// Show first 3 platforms
470+
game.platforms.slice(0, 3).forEach(platformId => {
471+
const platform = allPlatforms[String(platformId)]
472+
const platformName = platform ? platform.name : `Platform ${platformId}`
473+
const year = platformYears[platformId] ? ` (${platformYears[platformId]})` : ""
474+
475+
const badge = document.createElement("span")
476+
badge.className = "badge bg-secondary me-1 mb-1 small"
477+
badge.style.fontSize = "0.7rem"
478+
badge.textContent = platformName + year
479+
platformsDiv.appendChild(badge)
444480
})
445-
}
446481

447-
// Show first 3 platforms
448-
game.platforms.slice(0, 3).forEach(platformId => {
449-
const platform = allPlatforms[String(platformId)]
450-
const platformName = platform ? platform.name : `Platform ${platformId}`
451-
const year = platformYears[platformId] ? ` (${platformYears[platformId]})` : ""
452-
453-
const badge = document.createElement("span")
454-
badge.className = "badge bg-secondary me-1 mb-1 small"
455-
badge.style.fontSize = "0.7rem"
456-
badge.textContent = platformName + year
457-
platformsDiv.appendChild(badge)
458-
})
459-
460-
if (game.platforms.length > 3) {
461-
const moreBadge = document.createElement("span")
462-
moreBadge.className = "badge bg-secondary me-1 mb-1 small"
463-
moreBadge.style.fontSize = "0.7rem"
464-
moreBadge.textContent = `+${game.platforms.length - 3} more`
465-
platformsDiv.appendChild(moreBadge)
482+
if (game.platforms.length > 3) {
483+
const moreBadge = document.createElement("span")
484+
moreBadge.className = "badge bg-secondary me-1 mb-1 small"
485+
moreBadge.style.fontSize = "0.7rem"
486+
moreBadge.textContent = `+${game.platforms.length - 3} more`
487+
platformsDiv.appendChild(moreBadge)
488+
}
489+
490+
cardBody.appendChild(platformsDiv)
466491
}
492+
})
467493

468-
cardBody.appendChild(platformsDiv)
494+
if (matches.length > 60) {
495+
const moreNote = document.createElement("p")
496+
moreNote.className = "text-muted mt-3 small"
497+
moreNote.textContent = `Showing first 60 of ${matches.length} results. Try a more specific search term.`
498+
search_container.appendChild(moreNote)
469499
}
470500
})
471-
472-
if (matches.length > 60) {
473-
const moreNote = document.createElement("p")
474-
moreNote.className = "text-muted mt-3 small"
475-
moreNote.textContent = `Showing first 60 of ${matches.length} results. Try a more specific search term.`
476-
search_container.appendChild(moreNote)
477-
}
478501
})
479502
.catch(() => {
480-
// Fallback if platforms can't be loaded
481-
matches.slice(0, 60).forEach(([id, game]) => {
482-
const col = document.createElement("div")
483-
col.className = "col"
484-
row.appendChild(col)
485-
486-
const card = document.createElement("a")
487-
card.className = "card h-100 text-decoration-none shadow-sm border-0 rounded-0"
488-
card.href = `${base_path}/browse/games/?id=${id}`
489-
col.appendChild(card)
490-
491-
if (game.cover && game.cover.url) {
492-
const coverImg = document.createElement("img")
493-
coverImg.className = "card-img-top rounded-top-0"
494-
coverImg.src = game.cover.url.replace("t_thumb", "t_cover_small")
495-
coverImg.alt = game.name
496-
coverImg.loading = "lazy"
497-
card.appendChild(coverImg)
498-
} else {
499-
const placeholder = document.createElement("div")
500-
placeholder.className = "card-img-top bg-secondary d-flex align-items-center justify-content-center"
501-
placeholder.style.height = "180px"
502-
const icon = document.createElement("span")
503-
icon.className = "material-symbols-outlined text-white"
504-
icon.style.fontSize = "3rem"
505-
icon.textContent = "sports_esports"
506-
placeholder.appendChild(icon)
507-
card.appendChild(placeholder)
508-
}
509-
510-
const cardBody = document.createElement("div")
511-
cardBody.className = "card-body p-2"
512-
card.appendChild(cardBody)
503+
// Fallback if platforms can't be loaded - still fetch game data
504+
const gamePromises = matches.slice(0, 60).map(([id, _game]) =>
505+
fetch(`${base_url}/games/${id}.json`)
506+
.then(r => r.ok ? r.json() : null)
507+
.then(fullGame => ({ id, game: fullGame || { name: _game.name } }))
508+
.catch(() => ({ id, game: { name: _game.name } }))
509+
)
510+
511+
Promise.all(gamePromises).then(results => {
512+
results.forEach(({ id, game }) => {
513+
const col = document.createElement("div")
514+
col.className = "col"
515+
row.appendChild(col)
516+
517+
const card = document.createElement("a")
518+
card.className = "card h-100 text-decoration-none shadow-sm border-0 rounded-0"
519+
card.href = `${base_path}/browse/games/?id=${id}`
520+
col.appendChild(card)
521+
522+
if (game.cover && game.cover.url) {
523+
const coverImg = document.createElement("img")
524+
coverImg.className = "card-img-top rounded-top-0"
525+
// Convert IGDB URL properly
526+
let coverUrl = game.cover.url
527+
if (!coverUrl.startsWith('http')) {
528+
coverUrl = 'https://images.igdb.com/igdb/image/upload/t_cover_big/' + coverUrl.split('/').pop()
529+
} else {
530+
coverUrl = coverUrl.replace("t_thumb", "t_cover_big")
531+
}
532+
coverImg.src = coverUrl
533+
coverImg.alt = game.name
534+
coverImg.loading = "lazy"
535+
coverImg.style.width = "100%"
536+
coverImg.style.aspectRatio = "3 / 4"
537+
coverImg.style.objectFit = "cover"
538+
card.appendChild(coverImg)
539+
} else {
540+
const placeholder = document.createElement("div")
541+
placeholder.className = "card-img-top bg-secondary d-flex align-items-center justify-content-center"
542+
placeholder.style.width = "100%"
543+
placeholder.style.aspectRatio = "3 / 4"
544+
const icon = document.createElement("span")
545+
icon.className = "material-symbols-outlined text-white"
546+
icon.style.fontSize = "3rem"
547+
icon.textContent = "sports_esports"
548+
placeholder.appendChild(icon)
549+
card.appendChild(placeholder)
550+
}
513551

514-
const nameEl = document.createElement("p")
515-
nameEl.className = "card-text small mb-0"
516-
nameEl.textContent = game.name
517-
nameEl.title = game.name
518-
cardBody.appendChild(nameEl)
552+
const cardBody = document.createElement("div")
553+
cardBody.className = "card-body p-2"
554+
card.appendChild(cardBody)
555+
556+
const nameEl = document.createElement("p")
557+
nameEl.className = "card-text small mb-0 fw-bold"
558+
nameEl.textContent = game.name
559+
nameEl.title = game.name
560+
nameEl.style.overflow = "hidden"
561+
nameEl.style.display = "-webkit-box"
562+
nameEl.style.webkitLineClamp = "2"
563+
nameEl.style.webkitBoxOrient = "vertical"
564+
cardBody.appendChild(nameEl)
565+
})
566+
567+
if (matches.length > 60) {
568+
const moreNote = document.createElement("p")
569+
moreNote.className = "text-muted mt-3 small"
570+
moreNote.textContent = `Showing first 60 of ${matches.length} results. Try a more specific search term.`
571+
search_container.appendChild(moreNote)
572+
}
519573
})
520-
521-
if (matches.length > 60) {
522-
const moreNote = document.createElement("p")
523-
moreNote.className = "text-muted mt-3 small"
524-
moreNote.textContent = `Showing first 60 of ${matches.length} results. Try a more specific search term.`
525-
search_container.appendChild(moreNote)
526-
}
527574
})
528575
})
529576
.catch(err => {

0 commit comments

Comments
 (0)