Add gallery
parent
66afbb611a
commit
f15dcf4ca7
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -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 -}}
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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)">❮</div>
|
||||||
|
<div class="next-slide" onclick="moveSlide('{{ $id }}', 1)">❯</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>
|
||||||
Loading…
Reference in New Issue