From 68cba1f8a45e08def29c22f454ff402dcc7a183a Mon Sep 17 00:00:00 2001 From: j Date: Tue, 25 Mar 2025 22:34:22 +0000 Subject: [PATCH] new gallery --- camp/static/css/site.scss | 124 +++++++++++++++++++++++++++++++ camp/static/js/gallery.js | 130 +++++++++++++++++++++++++++++++++ content/templates/base.html | 1 + content/templates/gallery.html | 4 +- photologue/models.py | 7 ++ 5 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 camp/static/css/site.scss create mode 100644 camp/static/js/gallery.js diff --git a/camp/static/css/site.scss b/camp/static/css/site.scss new file mode 100644 index 0000000..6453d83 --- /dev/null +++ b/camp/static/css/site.scss @@ -0,0 +1,124 @@ +.gallery-dialog { + &:open { + background: #282828; + width: 100%; + height: 100%; + overflow: hidden; + } + &:open::backdrop { + background: black; + opacity: 0.8; + } + + .photo-container { + position: relative; + max-height: 100%; + max-width: 100%; + margin: auto; + } + .photo-container .image { + max-height: 100%; + max-width: 100%; + height: calc(100vh - 180px); + } + @media screen and (max-width: 39.9375em) { + .photo-container .image { + height: auto; + width: 100%; + } + + } + .main-image { + width: 100%; + height: 100%; + object-fit: contain; + } + .caption { + margin: 10px 0; + font-size: 18px; + color: lightgray; + text-align: center; + } + .thumbnails { + display: flex; + justify-content: center; + flex-wrap: wrap; + margin-top: 10px; + } + .thumbnail { + width: 80px; + height: 60px; + margin: 5px; + cursor: pointer; + border: 2px solid transparent; + } + .thumbnail.active { + border-color: blue; + } + .nav-btn { + cursor: pointer; + font-size: 20px; + padding: 10px; + background: #007BFF; + color: white; + border: none; + margin: 10px; + + position: absolute; + top: 50%; + margin-top: -16px; + outline: 0; + width: 32px; + height: 32px; + text-indent: -9999px; + z-index: 9999; + } + .close { + color: lightgray !important; + cursor: pointer; + position: absolute; + top: 2px; + right: 3px; + font-size: 20px; + } + .close:hover { + color: white !important; + } + .download.disabled { + display: none; + } + .download { + color: lightgray !important; + cursor: pointer; + position: absolute; + top: 4px; + right: 24px + + } + .download:hover { + color: white !important; + } + @media screen and (max-width: 39.9375em) { + .close { + bottom: 6px; + top: initial; + } + .download { + bottom: 2px; + top: initial; + } + } + .nav-btn.next { + right: 0px; + background: url('/static/css/controls.png') no-repeat -43px -32px; + } + .nav-btn.prev { + left: 0px; + background: url('/static/css/controls.png') no-repeat 0 -32px; + } + .nav-btn:disabled { + display: none; + cursor: not-allowed; + } +} + diff --git a/camp/static/js/gallery.js b/camp/static/js/gallery.js new file mode 100644 index 0000000..93aee75 --- /dev/null +++ b/camp/static/js/gallery.js @@ -0,0 +1,130 @@ +function loadGalleries() { + document.querySelectorAll('.gallery').forEach(gallery => { + var photos = [], dialog + gallery.querySelectorAll(".photo").forEach(img => { + const src = img.src.replace('_thumbnail', '_display') + let photo = { + src: src, + caption: img.dataset.caption, + orig: img.dataset.orig + } + photos.push(photo) + img.parentElement.addEventListener("click", event => { + event.preventDefault() + event.stopPropagation() + dialog.open(src) + }) + }) + dialog = loadGallery(photos) + gallery.appendChild(dialog.element) + }) +} + +function loadGallery(images) { + var gallery = document.createElement("dialog") + gallery.classList.add("gallery-dialog") + gallery.innerHTML = ` +
+
+ +
+ + +
+ + + + +
+
+ ` + + gallery.addEventListener("click", event => { + if (event.target.className == "close") { + gallery.close(); + return + } + var rect = gallery.getBoundingClientRect(); + var isInDialog = (rect.top <= event.clientY && event.clientY <= rect.top + rect.height && + rect.left <= event.clientX && event.clientX <= rect.left + rect.width); + if (!isInDialog) { + gallery.close(); + } + }) + let currentIndex = 0; + + const mainImage = gallery.querySelector(".main-image"); + const caption = gallery.querySelector(".caption"); + const prevBtn = gallery.querySelector(".prev.nav-btn"); + const nextBtn = gallery.querySelector(".next.nav-btn"); + const thumbnailsContainer = gallery.querySelector(".thumbnails"); + const download = gallery.querySelector(".download"); + + function updateSlideshow(index) { + mainImage.src = images[index].src.replace('_display', '_thumbnail'); + setTimeout(() => { + mainImage.src = images[index].src; + }, 0) + caption.innerHTML = images[index].caption; + gallery.querySelectorAll(".thumbnail").forEach((thumb, i) => { + thumb.classList.toggle("active", i === index); + }); + if (images[index].orig) { + download.href = images[index].orig + download.classList.remove('disabled') + } else { + download.href = "" + download.classList.add('disabled') + } + prevBtn.disabled = index === 0; + nextBtn.disabled = index === images.length - 1; + } + + function createThumbnails() { + images.forEach((img, index) => { + const thumb = document.createElement("img"); + thumb.src = img.src.replace('_display', '_thumbnail'); + thumb.classList.add("thumbnail"); + thumb.onclick = () => { + currentIndex = index; + updateSlideshow(index); + }; + thumbnailsContainer.appendChild(thumb); + }); + } + + function showSlideshow() { + window.dialog = gallery + gallery.showModal() + } + + prevBtn.onclick = () => { + if (currentIndex > 0) { + currentIndex--; + updateSlideshow(currentIndex); + } + }; + + nextBtn.onclick = () => { + if (currentIndex < images.length - 1) { + currentIndex++; + updateSlideshow(currentIndex); + } + }; + + createThumbnails(); + updateSlideshow(currentIndex); + + const imagesIndex = images.map(img => img.src); + return { + element: gallery, + open: function(src) { + currentIndex = imagesIndex.indexOf(src) + updateSlideshow(currentIndex) + showSlideshow() + } + } +} +window.addEventListener("load", loadGalleries) + + diff --git a/content/templates/base.html b/content/templates/base.html index 0408f53..e3e3a48 100644 --- a/content/templates/base.html +++ b/content/templates/base.html @@ -55,6 +55,7 @@ + {% endcompress %} {% block end %} diff --git a/content/templates/gallery.html b/content/templates/gallery.html index 96e09fa..b374220 100644 --- a/content/templates/gallery.html +++ b/content/templates/gallery.html @@ -1,8 +1,8 @@ {% if gallery %}
{{gallery.title}}
-