Add gallery

main
Timo Montalto 2025-06-17 15:55:00 +02:00
parent 66afbb611a
commit f15dcf4ca7
6 changed files with 215 additions and 0 deletions

10
assets/css/custom.css Normal file
View File

@ -0,0 +1,10 @@
/* Styles für Blogpost-Zusammenfassungen */
li.post {
margin-bottom: 1.5rem;
}
.post-summary {
margin-top: 0.5rem;
color: #666;
font-size: 0.9rem;
}

106
assets/css/gallery.css Normal file
View File

@ -0,0 +1,106 @@
/* Image Gallery Styles */
.image-gallery {
position: relative;
max-width: 100%;
margin: 20px auto;
overflow: hidden;
}
.gallery-slider {
width: 100%;
position: relative;
}
.slide {
display: none;
width: 100%;
}
.slide.active {
display: block;
}
.slide img {
width: 100%;
height: auto;
display: block;
}
.gallery-navigation {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
}
.prev-slide, .next-slide {
position: absolute;
top: 50%;
transform: translateY(-50%);
color: white;
font-size: 24px;
font-weight: bold;
padding: 16px;
background-color: rgba(0, 0, 0, 0.3);
cursor: pointer;
pointer-events: auto;
border-radius: 50%;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.prev-slide:hover, .next-slide:hover {
background-color: rgba(0, 0, 0, 0.6);
}
.prev-slide {
left: 10px;
}
.next-slide {
right: 10px;
}
.gallery-indicator {
text-align: center;
margin-top: 10px;
}
.dot {
height: 10px;
width: 10px;
margin: 0 5px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.3s ease;
cursor: pointer;
}
.dot.active {
background-color: #555;
}
.slide-caption {
padding: 10px;
background-color: rgba(0, 0, 0, 0.7);
color: white;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
@media (max-width: 768px) {
.prev-slide, .next-slide {
font-size: 18px;
padding: 12px;
}
}

65
assets/js/gallery.js Normal file
View File

@ -0,0 +1,65 @@
function showSlide(galleryId, slideIndex) {
const slides = document.querySelectorAll(`#${galleryId} .slide`);
const dots = document.querySelectorAll(`#${galleryId} .dot`);
// Hide all slides
slides.forEach(slide => {
slide.classList.remove('active');
});
// Remove active class from all dots
dots.forEach(dot => {
dot.classList.remove('active');
});
// Show the selected slide and activate dot
slides[slideIndex].classList.add('active');
dots[slideIndex].classList.add('active');
}
function moveSlide(galleryId, direction) {
const slides = document.querySelectorAll(`#${galleryId} .slide`);
let currentIndex = 0;
// Find current active slide
slides.forEach((slide, index) => {
if (slide.classList.contains('active')) {
currentIndex = index;
}
});
// Calculate new index
let newIndex = currentIndex + direction;
if (newIndex < 0) newIndex = slides.length - 1;
if (newIndex >= slides.length) newIndex = 0;
// Show the new slide
showSlide(galleryId, newIndex);
}
// Handle keyboard navigation
document.addEventListener('keydown', function(event) {
// Only handle if a gallery is present
const galleries = document.querySelectorAll('.image-gallery');
if (galleries.length === 0) return;
// Find gallery with active slide
let activeGalleryId = null;
galleries.forEach(gallery => {
const activeSlide = gallery.querySelector('.slide.active');
if (activeSlide) {
activeGalleryId = gallery.id;
}
});
if (!activeGalleryId) return;
// Left arrow
if (event.keyCode === 37) {
moveSlide(activeGalleryId, -1);
}
// Right arrow
else if (event.keyCode === 39) {
moveSlide(activeGalleryId, 1);
}
});

View File

@ -10,6 +10,7 @@
{{- if (not (in (.Site.Params.excludedTypes | default (slice "page")) .Type)) -}} {{- if (not (in (.Site.Params.excludedTypes | default (slice "page")) .Type)) -}}
<li class="post"> <li class="post">
<a href="{{ .RelPermalink }}">{{.Title}}</a> <span class="meta">{{ dateFormat ":date_medium" .Date }}{{ if .Draft }} <span class="draft-label">DRAFT</span> {{ end }}</span> <a href="{{ .RelPermalink }}">{{.Title}}</a> <span class="meta">{{ dateFormat ":date_medium" .Date }}{{ if .Draft }} <span class="draft-label">DRAFT</span> {{ end }}</span>
<p class="post-summary">{{ .Summary | plainify | truncate 200 }}</p>
</li> </li>
{{- end -}} {{- end -}}
{{- end -}} {{- end -}}

View File

@ -54,6 +54,16 @@
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="{{ $darkstyle.Permalink }}" {{ if eq .Site.Params.mode "auto" }}media="(prefers-color-scheme: dark)"{{ end }} {{ if eq .Site.Params.mode "toggle" }}disabled{{ end }} /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="{{ $darkstyle.Permalink }}" {{ if eq .Site.Params.mode "auto" }}media="(prefers-color-scheme: dark)"{{ end }} {{ if eq .Site.Params.mode "toggle" }}disabled{{ end }} />
{{- end -}} {{- end -}}
<!-- Load gallery resources -->
{{ $galleryCss := resources.Get "css/gallery.css" | minify | fingerprint }}
<link rel="stylesheet" href="{{ $galleryCss.RelPermalink }}">
{{ $galleryJs := resources.Get "js/gallery.js" | minify | fingerprint }}
<script defer src="{{ $galleryJs.RelPermalink }}"></script>
<!-- Custom styles -->
{{ $customstyle := resources.Get "css/custom.css" | fingerprint }}
<link rel="stylesheet" type="text/css" href="{{ $customstyle.RelPermalink }}" />
<!-- Mathjax support --> <!-- Mathjax support -->
{{- if .Site.Params.mathjax | default false -}} {{- if .Site.Params.mathjax | default false -}}
<script type="text/javascript" <script type="text/javascript"

View File

@ -0,0 +1,23 @@
{{ $id := default (printf "gallery-%d" (now.UnixNano)) (.Get "id") }}
<div class="image-gallery" id="{{ $id }}">
<div class="gallery-slider">
{{ $images := .Inner | transform.Unmarshal }}
{{ range $index, $image := $images }}
<div class="slide{{ if eq $index 0 }} active{{ end }}" data-index="{{ $index }}">
<img src="{{ $image.src }}" alt="{{ $image.alt | default "" }}">
<div class="gallery-navigation">
<div class="prev-slide" onclick="moveSlide('{{ $id }}', -1)">&#10094;</div>
<div class="next-slide" onclick="moveSlide('{{ $id }}', 1)">&#10095;</div>
</div>
{{ if $image.caption }}
<div class="slide-caption">{{ $image.caption | markdownify }}</div>
{{ end }}
</div>
{{ end }}
</div>
<div class="gallery-indicator">
{{ range $index, $image := $images }}
<span class="dot{{ if eq $index 0 }} active{{ end }}" onclick="showSlide('{{ $id }}', {{ $index }})"></span>
{{ end }}
</div>
</div>