add carousel to post overlay
This commit is contained in:
parent
b6c4f52df2
commit
36fc9a7dd1
|
|
@ -235,14 +235,50 @@ function applyPostDetails(modalWrap, post) {
|
||||||
const summaryEl = modalWrap.querySelector(".sw-modal-summary");
|
const summaryEl = modalWrap.querySelector(".sw-modal-summary");
|
||||||
if (summaryEl) summaryEl.textContent = summary;
|
if (summaryEl) summaryEl.textContent = summary;
|
||||||
|
|
||||||
|
const heroGallery = collectGalleryImages(post);
|
||||||
|
const heroImageSrc = heroGallery[0] || heroImageForPost(post);
|
||||||
|
const heroFullSrc = heroGallery[0] || fullImageForPost(post);
|
||||||
|
const heroHasGallery = heroGallery.length > 1;
|
||||||
const hero = modalWrap.querySelector(".sw-modal-hero");
|
const hero = modalWrap.querySelector(".sw-modal-hero");
|
||||||
const clusterHero = modalWrap.querySelector(".sw-cluster-hero-media");
|
const clusterHero = modalWrap.querySelector(".sw-cluster-hero-media");
|
||||||
if (hero || clusterHero) {
|
if (hero || clusterHero) {
|
||||||
const target = hero || clusterHero;
|
const target = hero || clusterHero;
|
||||||
target.innerHTML = img
|
const heroImageHtml = heroImageSrc
|
||||||
? `<img src="${escapeHtml(img)}" data-fullsrc="${escapeHtml(fullImg)}" alt="" loading="lazy" />`
|
? `<img src="${escapeHtml(heroImageSrc)}" data-fullsrc="${escapeHtml(heroFullSrc)}" alt="" loading="lazy" data-gallery-index="0" />`
|
||||||
: `<div class="sw-modal-hero-fallback"><div class="sw-modal-hero-fallback-inner"><i class="${categoryIconClass(post)}"></i><span>${escapeHtml(normCatLabel(post))}</span></div></div>`;
|
: `<div class="sw-modal-hero-fallback"><div class="sw-modal-hero-fallback-inner"><i class="${categoryIconClass(post)}"></i><span>${escapeHtml(normCatLabel(post))}</span></div></div>`;
|
||||||
|
const arrowHtml = heroHasGallery
|
||||||
|
? `<button class="sw-modal-hero-arrow left" type="button" aria-label="Previous image"><i class="fa-solid fa-chevron-left" /></button><button class="sw-modal-hero-arrow right" type="button" aria-label="Next image"><i class="fa-solid fa-chevron-right" /></button>`
|
||||||
|
: "";
|
||||||
|
target.innerHTML = `${heroImageHtml}${arrowHtml}`;
|
||||||
|
let galleryRow = modalWrap.querySelector(".sw-modal-gallery-row");
|
||||||
|
if (heroHasGallery) {
|
||||||
|
if (!galleryRow) {
|
||||||
|
galleryRow = document.createElement("div");
|
||||||
|
galleryRow.className = "sw-modal-gallery-row";
|
||||||
|
const heroRow = target.closest(".sw-modal-hero-row");
|
||||||
|
const parent = heroRow?.parentNode || target.parentNode || modalWrap;
|
||||||
|
if (parent) {
|
||||||
|
parent.insertBefore(galleryRow, heroRow ? heroRow.nextSibling : target.nextSibling || null);
|
||||||
|
} else {
|
||||||
|
modalWrap.appendChild(galleryRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
galleryRow.innerHTML = heroGallery
|
||||||
|
.map(
|
||||||
|
(url, idx) =>
|
||||||
|
`<button type="button" class="sw-modal-gallery-thumb${idx === 0 ? " active" : ""}" data-index="${idx}"><img src="${escapeHtml(
|
||||||
|
url
|
||||||
|
)}" alt="" loading="lazy" /></button>`
|
||||||
|
)
|
||||||
|
.join("");
|
||||||
|
} else if (galleryRow) {
|
||||||
|
galleryRow.remove();
|
||||||
|
galleryRow = null;
|
||||||
|
}
|
||||||
bindHeroLightbox(modalWrap);
|
bindHeroLightbox(modalWrap);
|
||||||
|
if (heroHasGallery) {
|
||||||
|
initModalGallery(modalWrap, heroGallery);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const badge = modalWrap.querySelector(".sw-modal-badge");
|
const badge = modalWrap.querySelector(".sw-modal-badge");
|
||||||
|
|
@ -447,6 +483,44 @@ function bindHeroLightbox(modalWrap) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initModalGallery(modalWrap, gallery) {
|
||||||
|
if (!modalWrap || !Array.isArray(gallery) || gallery.length === 0) return;
|
||||||
|
const heroImg = modalWrap.querySelector(".sw-modal-hero img, .sw-cluster-hero-media img");
|
||||||
|
if (!heroImg) return;
|
||||||
|
let activeIndex = 0;
|
||||||
|
const thumbButtons = modalWrap.querySelectorAll(".sw-modal-gallery-thumb");
|
||||||
|
const arrows = modalWrap.querySelectorAll(".sw-modal-hero-arrow");
|
||||||
|
const setActive = (idx) => {
|
||||||
|
if (!Number.isFinite(idx)) return;
|
||||||
|
const normalized = (idx + gallery.length) % gallery.length;
|
||||||
|
activeIndex = normalized;
|
||||||
|
heroImg.src = gallery[normalized];
|
||||||
|
heroImg.dataset.fullsrc = gallery[normalized];
|
||||||
|
heroImg.dataset.galleryIndex = String(normalized);
|
||||||
|
thumbButtons.forEach((btn) => {
|
||||||
|
const btnIndex = Number(btn.dataset.index);
|
||||||
|
btn.classList.toggle("active", btnIndex === normalized);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
arrows.forEach((btn) => {
|
||||||
|
btn.addEventListener("click", (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
const direction = btn.classList.contains("left") ? -1 : 1;
|
||||||
|
const nextIndex = (activeIndex + direction + gallery.length) % gallery.length;
|
||||||
|
setActive(nextIndex);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
thumbButtons.forEach((btn) => {
|
||||||
|
btn.addEventListener("click", (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
const idx = Number(btn.dataset.index);
|
||||||
|
if (Number.isNaN(idx)) return;
|
||||||
|
setActive(idx);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setActive(0);
|
||||||
|
}
|
||||||
|
|
||||||
function openImageLightbox(src) {
|
function openImageLightbox(src) {
|
||||||
if (!src) return;
|
if (!src) return;
|
||||||
const overlay = document.createElement("div");
|
const overlay = document.createElement("div");
|
||||||
|
|
@ -607,6 +681,25 @@ function fullImageForPost(post) {
|
||||||
return normalizeImageUrl(raw);
|
return normalizeImageUrl(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function collectGalleryImages(post) {
|
||||||
|
const result = [];
|
||||||
|
const seen = new Set();
|
||||||
|
const add = (value) => {
|
||||||
|
const normalized = normalizeImageUrl(value);
|
||||||
|
if (!normalized) return;
|
||||||
|
if (seen.has(normalized)) return;
|
||||||
|
seen.add(normalized);
|
||||||
|
result.push(normalized);
|
||||||
|
};
|
||||||
|
if (Array.isArray(post?.media_urls)) {
|
||||||
|
post.media_urls.forEach(add);
|
||||||
|
}
|
||||||
|
["image_large", "image_medium", "image_small", "image", "media_url"].forEach((key) => {
|
||||||
|
add(post?.[key]);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function formatRelativeTime(createdAt) {
|
function formatRelativeTime(createdAt) {
|
||||||
try {
|
try {
|
||||||
if (!createdAt) return "now";
|
if (!createdAt) return "now";
|
||||||
|
|
|
||||||
|
|
@ -886,6 +886,65 @@ body[data-theme="blue"] .sw-centered-modal .post-card.sw-expanded-shell{
|
||||||
display:block;
|
display:block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sw-modal-hero-media{
|
||||||
|
position:relative;
|
||||||
|
}
|
||||||
|
.sw-modal-hero-arrow{
|
||||||
|
position:absolute;
|
||||||
|
top:50%;
|
||||||
|
transform:translateY(-50%) scale(0.95);
|
||||||
|
width:36px;
|
||||||
|
height:36px;
|
||||||
|
border-radius:50%;
|
||||||
|
border:1px solid rgba(255,255,255,0.35);
|
||||||
|
background: rgba(0,0,0,0.55);
|
||||||
|
color:#fff;
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
justify-content:center;
|
||||||
|
cursor:pointer;
|
||||||
|
z-index:10;
|
||||||
|
transition:transform 0.2s ease;
|
||||||
|
}
|
||||||
|
.sw-modal-hero-arrow:hover{
|
||||||
|
transform:translateY(-50%) scale(1);
|
||||||
|
}
|
||||||
|
.sw-modal-hero-arrow.left{
|
||||||
|
left:10px;
|
||||||
|
}
|
||||||
|
.sw-modal-hero-arrow.right{
|
||||||
|
right:10px;
|
||||||
|
}
|
||||||
|
.sw-modal-gallery-row{
|
||||||
|
display:flex;
|
||||||
|
gap:0.35rem;
|
||||||
|
overflow-x:auto;
|
||||||
|
padding-top:0.5rem;
|
||||||
|
margin-top:0.5rem;
|
||||||
|
}
|
||||||
|
.sw-modal-gallery-thumb{
|
||||||
|
border-radius:12px;
|
||||||
|
border:1px solid transparent;
|
||||||
|
width:48px;
|
||||||
|
height:48px;
|
||||||
|
flex:0 0 auto;
|
||||||
|
overflow:hidden;
|
||||||
|
padding:0;
|
||||||
|
display:inline-flex;
|
||||||
|
align-items:center;
|
||||||
|
justify-content:center;
|
||||||
|
background:rgba(15,23,42,0.65);
|
||||||
|
}
|
||||||
|
.sw-modal-gallery-thumb.active{
|
||||||
|
border-color:rgba(56,189,248,0.95);
|
||||||
|
}
|
||||||
|
.sw-modal-gallery-thumb img{
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
object-fit:cover;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
|
||||||
.sw-modal-hero-fallback{
|
.sw-modal-hero-fallback{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:100%;
|
height:100%;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue