Show photo titles from filenames in catalog and lightbox

This commit is contained in:
Alex Assistant 2026-02-19 17:03:10 +03:00
parent 6c57f8d5a7
commit 9196452688
3 changed files with 46 additions and 3 deletions

5
app.js
View File

@ -1,8 +1,9 @@
(() => { (() => {
const lightbox = document.getElementById('lightbox'); const lightbox = document.getElementById('lightbox');
const lightboxImage = document.getElementById('lightboxImage'); const lightboxImage = document.getElementById('lightboxImage');
const lightboxTitle = document.getElementById('lightboxTitle');
if (!lightbox || !lightboxImage) { if (!lightbox || !lightboxImage || !lightboxTitle) {
return; return;
} }
@ -37,6 +38,7 @@
lightboxImage.src = full; lightboxImage.src = full;
lightboxImage.alt = title; lightboxImage.alt = title;
lightboxTitle.textContent = title;
lightbox.hidden = false; lightbox.hidden = false;
document.body.style.overflow = 'hidden'; document.body.style.overflow = 'hidden';
}); });
@ -49,6 +51,7 @@
function closeLightbox() { function closeLightbox() {
lightbox.hidden = true; lightbox.hidden = true;
lightboxImage.src = ''; lightboxImage.src = '';
lightboxTitle.textContent = '';
document.body.style.overflow = ''; document.body.style.overflow = '';
} }
})(); })();

View File

@ -49,6 +49,7 @@ foreach ($categories as $categoryName => &$images) {
$image['thumb_path'] = $thumbWebPath; $image['thumb_path'] = $thumbWebPath;
$image['full_path'] = '?action=image&category=' . rawurlencode($categoryName) . '&file=' . rawurlencode($image['filename']); $image['full_path'] = '?action=image&category=' . rawurlencode($categoryName) . '&file=' . rawurlencode($image['filename']);
$image['title'] = titleFromFilename($image['filename']);
$image['mtime'] = $sourceMtime; $image['mtime'] = $sourceMtime;
} }
@ -115,14 +116,15 @@ if ($selectedCategory !== null && $selectedCategory !== '' && !isset($categories
<button <button
class="thumb-card js-thumb" class="thumb-card js-thumb"
data-full="<?= htmlspecialchars($img['full_path'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>" data-full="<?= htmlspecialchars($img['full_path'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>"
data-title="<?= htmlspecialchars($img['filename'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>" data-title="<?= htmlspecialchars($img['title'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>"
type="button" type="button"
> >
<img <img
src="<?= htmlspecialchars($img['thumb_path'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>" src="<?= htmlspecialchars($img['thumb_path'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>"
alt="<?= htmlspecialchars($img['filename'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>" alt="<?= htmlspecialchars($img['title'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>"
loading="lazy" loading="lazy"
> >
<span class="thumb-title"><?= htmlspecialchars($img['title'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?></span>
</button> </button>
<?php endforeach; ?> <?php endforeach; ?>
</div> </div>
@ -140,6 +142,7 @@ if ($selectedCategory !== null && $selectedCategory !== '' && !isset($categories
<div class="lightbox-content"> <div class="lightbox-content">
<button class="lightbox-close js-close" type="button" aria-label="Закрыть">×</button> <button class="lightbox-close js-close" type="button" aria-label="Закрыть">×</button>
<img id="lightboxImage" src="" alt=""> <img id="lightboxImage" src="" alt="">
<div id="lightboxTitle" class="lightbox-title"></div>
</div> </div>
</div> </div>
@ -175,6 +178,24 @@ function serveImage(string $photosDir): never
exit; exit;
} }
function titleFromFilename(string $filename): string
{
$name = pathinfo($filename, PATHINFO_FILENAME);
$name = str_replace(['_', '-'], ' ', $name);
$name = preg_replace('/\s+/', ' ', $name) ?? $name;
$name = trim($name);
if ($name === '') {
return $filename;
}
if (function_exists('mb_convert_case')) {
return mb_convert_case($name, MB_CASE_TITLE, 'UTF-8');
}
return ucwords(strtolower($name));
}
function ensureDirectories(array $dirs): void function ensureDirectories(array $dirs): void
{ {
foreach ($dirs as $dir) { foreach ($dirs as $dir) {

View File

@ -124,6 +124,7 @@ h2 {
background: #fff; background: #fff;
padding: 0; padding: 0;
cursor: pointer; cursor: pointer;
text-align: left;
transition: transform .15s ease, box-shadow .15s ease; transition: transform .15s ease, box-shadow .15s ease;
} }
@ -139,6 +140,16 @@ h2 {
object-fit: cover; object-fit: cover;
} }
.thumb-title {
display: block;
padding: 10px 10px 12px;
font-size: 13px;
line-height: 1.35;
color: var(--text);
border-top: 1px solid var(--border);
background: #fff;
}
.empty { .empty {
color: var(--muted); color: var(--muted);
} }
@ -188,6 +199,14 @@ h2 {
background: #020617; background: #020617;
} }
.lightbox-title {
color: #e5e7eb;
font-size: 14px;
line-height: 1.4;
padding: 2px 4px 6px;
word-break: break-word;
}
.lightbox-link { .lightbox-link {
align-self: flex-end; align-self: flex-end;
color: #dbeafe; color: #dbeafe;