Complete rewrite (#1)

A complete rewrite of the gallery plugin:

* Using flexbox
* Using lightweight JS for lightbox to avoid anchor links, and allow full rotation
* Add slideshow as an additional field
* Make many more things configurable
* Better support for dirs, allow mixed paths
* Translatable captions for many files using metadata files
* SCSS instead of CSS

Reviewed-on: #1
Co-authored-by: Max Mehl <mail@mehl.mx>
Co-committed-by: Max Mehl <mail@mehl.mx>
This commit was merged in pull request #1.
This commit is contained in:
2024-02-07 22:17:49 +01:00
committed by mxmehl
parent 0e16b03230
commit 437b0202ba
11 changed files with 588 additions and 211 deletions

View File

@@ -1,282 +0,0 @@
/*
SPDX-FileCopyrightText: 2020 Max Mehl <mail@mehl.mx>
SPDX-License-Identifier: MIT
*/
/** GENERAL FIGURE LAYOUT **/
figure {
max-width: 90%;
margin: 10px auto;
display: block;
text-align: center;
}
/* make box with box-shadow only as large as image */
.snap-wrapper {
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
display: inline-block;
}
figure a:hover {
text-decoration: none;
}
figure img {
max-width: 100%;
max-height: 100%;
}
figure.sm {
max-width: 30%;
}
figure.md {
max-width: 50%;
}
figure.lg {
max-width: 70%;
}
figure.pull-right {
padding: 10px 0 10px 10px;
}
figure.pull-left {
padding: 10px 10px 10px 0;
}
figure figcaption {
background-color: rgba(0, 0, 0, 0.5);
display: block;
font-size: .8em;
padding: 1px;
position: static;
text-align: center;
bottom: 0;
left: 0;
right: 0;
color: #FFF;
}
/* Extra classes for figures */
figure.no-border .snap-wrapper {
box-shadow: none;
}
/** GALLERY MARKUP **/
.snap-gallery {
margin: 10px;
display: flex;
justify-content: center;
flex-wrap: wrap;
}
/* avoid sick effects of inline-block on gallery elements */
.snap-gallery .snap-wrapper {
display: block;
}
.snap-gallery figure {
position: relative;
width: 30%;
padding-bottom: 30%;
margin: 1%;
text-align: left;
box-shadow: 0 1px 2px 0 rgba(0,0,0,0.2),0 2px 4px 0 rgba(0,0,0,0.19);
}
.snap-gallery figcaption {
position: absolute;
}
.snap-gallery img.snap-thumb {
position: absolute;
object-fit: cover;
object-position: center;
height: 100%;
width: 100%;
}
.snap-gallery figure img.snap-thumb:hover {
transform: scale(1.02);
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
@media screen and (max-width: 767px) {
.snap-gallery figure {
width: 45%;
padding-bottom: 45%;
margin: 2%
}
}
@media screen and (max-width: 479px) {
.snap-gallery figure {
width: 90%;
padding-bottom: 90%;
margin: 3%;
}
}
/** LIGHTBOX MARKUP **/
.snap-lightbox {
/** Default lightbox to hidden */
display: none;
/** Position and style */
position: fixed;
z-index: 999;
width: 100%;
height: 100%;
text-align: center;
white-space: nowrap;
top: 0;
left: 0;
background: rgba(0,0,0,0.8);
}
/* effects when "activating" the figure */
.snap-lightbox:target {
/** Remove default browser outline */
outline: none;
/** Unhide lightbox **/
display: block;
}
/* Click on the complete background closes the lightbox */
/* Exception: arrow in gallery, they have higher z-index */
a.snap-lightbox-close {
position: fixed;
z-index: 800;
width: 100%;
height: 100%;
text-align: center;
white-space: nowrap;
top: 0;
left: 0;
}
/* keep lightbox in middle. TODO: hacky, and not realibly in middle */
.snap-lightbox::before {
content: "";
display: inline-block;
vertical-align: middle;
width: 0;
/* adjust for white space between pseudo element and next sibling */
margin-right: -.25em;
/* stretch line height */
height: 100%;
}
/* Container for image */
.snap-lightbox-inner {
display: inline-block;
vertical-align: middle;
white-space: normal;
max-width: 90%;
max-height: 80%;
height: 100%;
}
.snap-lightbox-inner p {
color: #fff;
z-index: 810;
position: relative;
}
/* prev/next arrows & close button */
.snap-lightbox-close-button {
position: fixed;
z-index: 950;
width: 5%;
height: calc(5vw); /* ~5% width */
right: 0;
top: 0;
}
.snap-lightbox-x::after {
content: "\00d7"; /* This will render the 'X' */
font-size: 3em;
font-style: normal;
font-weight: 700;
color: #000;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.snap-lightbox-close-button:hover .snap-lightbox-x::after {
color: #fff;
transition: all 0.25s ease;
}
.snap-lightbox-prev, .snap-lightbox-next {
position: fixed;
z-index: 800;
width: 5%;
height: 100%;
text-align: center;
top: 0;
}
.snap-lightbox-prev {
left: 0;
}
.snap-lightbox-next {
right: 0;
}
.snap-lightbox-arrow {
display: inline-block;
position: fixed;
top: 50%;
z-index: 900;
border: solid #000;
border-width: 0 7px 7px 0;
display: inline-block;
padding: 1%;
}
span .snap-lightbox-arrow {
border-color: #5e5e5e;
}
.snap-lightbox-prev .snap-lightbox-arrow {
left: 2%;
transform: rotate(135deg);
-webkit-transform: rotate(135deg);
}
.snap-lightbox-next .snap-lightbox-arrow {
right: 2%;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
a.snap-lightbox-prev:hover > .snap-lightbox-arrow,
a.snap-lightbox-next:hover > .snap-lightbox-arrow {
border-color: #fff;
transition: all 0.25s ease;
}
@media screen and (max-width: 767px) {
.snap-lightbox-inner {
max-width: 80%;
}
.snap-lightbox-prev, .snap-lightbox-next {
width: 10%;
}
.snap-lightbox-close-button {
width: 10%;
height: calc(10vw); /* ~10% width */
}
}

75
static/js/snap-gallery.js Normal file
View File

@@ -0,0 +1,75 @@
// Variables
var lightbox_baseid = "snap-lightbox-";
var slideshow_baseid = "snap-slideshow-";
//var imageIndex = {1: 1, 2: 1, 3: 1};
var imageIndex = {}
// Open the Lightbox
function openLightbox(id) {
document.getElementById(lightbox_baseid + id).style.display = "block";
// Kill automatic slideshow when lightbox opened
try {
clearInterval(autoSlideshow);
} catch (e) {
console.log("Lightbox error: " + e)
}
}
// Close the Lightbox
function closeLightbox(id) {
document.getElementById(lightbox_baseid + id).style.display = "none";
}
// Move lightbox to the specified item
function openLightboxItem(id, n) {
showItem(lightbox_baseid, id, imageIndex[id] = n, ".snap-lightbox-inner");
}
// Next/previous controls for lightbox
function moveLightboxItem(id, n) {
showItem(lightbox_baseid, id, imageIndex[id] += n, ".snap-lightbox-inner");
}
// Next/previous controls for slideshow
function moveSlideshowItem(id, n, mode) {
showItem(slideshow_baseid, id, imageIndex[id] += n, ".snap-image");
// Kill automatic slideshow once the slideshow has been moved manually
if (mode !== "auto") {
clearInterval(autoSlideshow);
}
}
// In the slideshow or lightbox, make a specific image visible, make others hidden
function showItem(baseId, id, n, className) {
// Get elements that shall be rotated
const element = document.getElementById(baseId + id);
const items = element.querySelectorAll(className);
// Increment item index
const updateIndex = () => {
if (n > items.length) {
imageIndex[id] = 1;
}
if (n < 1) {
imageIndex[id] = items.length;
}
};
// hide all selected elements
const hideAllItems = () => {
for (let i = 0; i < items.length; i++) {
items[i].style.display = "none";
}
};
// make desired item visible
const showCurrentItem = () => {
items[imageIndex[id] - 1].style.display = "inline-block";
};
updateIndex();
hideAllItems();
showCurrentItem();
}