Dynamische Bilder Galerie
als Mobirise Block

Hier das Video zum Block
einfach die Codes unten kopieren und in einen beliebigen Block in Mobirise diesen Code jeweils ersetzen. Dann als User Block speichern
Der Java Code ist die .htaccess Datei. Die bitte mit einem Editor erstellen und zwingend .htaccess nennen !

HTML-Code
<section data-bs-version="5.1" class="content-gallery" group="Content" mbr-style="{
'padding-top': paddingTop + 'rem',
'padding-bottom': paddingBottom + 'rem',
'background-color': bgColor,
'--btnColor': btnColor
}" data-thumbsize="{{thumbSize}}" data-perrow="{{perRow}}" data-maximages="{{maxImages}}">
<mbr-parameters>
<header>Abstände</header>
<input type="range" inline title="Abstand oben" name="paddingTop" min="0" max="10" step="1" value="6">
<input type="range" inline title="Abstand unten" name="paddingBottom" min="0" max="10" step="1" value="6">
<header>Galerie-Einstellungen</header>
<input type="range" title="Größe der Vorschaubilder (px)" name="thumbSize" min="80" max="240" step="10" value="210">
<input type="range" title="Bilder pro Reihe" name="perRow" min="2" max="10" step="1" value="5">
<input type="range" title="Bilder pro Seite" name="maxImages" min="1" max="50" step="1" value="10">
<header>Farben</header>
<input type="color" title="Hintergrundfarbe" name="bgColor" value="#000000">
<input type="color" title="Buttonfarbe (Ordner)" name="btnColor" value="#ffa600">
<header>Inhalt</header>
<input type="text" title="Titel" name="title" value="Unsere Foto-Galerien">
<textarea title="Beschreibung" name="text">Klicke auf ein Thema, um die Fotos anzuzeigen.</textarea>
</mbr-parameters>
<div class="container text-center">
<h3 class="mbr-section-title mbr-fonts-style mb-3" mbr-theme-style="display-5">Dynamische Bilder Galerie</h3>
<p class="mbr-text mbr-fonts-style mb-4" mbr-theme-style="display-7">Bilder werden einfach aus Ordnern eingelesen</p>
<div id="galleryButtons" class="mb-4 d-flex flex-wrap justify-content-center gap-2"></div>
<h5 id="currentGalleryTitle" class="text-center mb-4 text-muted"></h5>
<div id="galleryGrid" class="gallery-grid"></div>
<!-- Pagination -->
<div id="pagination" class="mt-4 d-flex justify-content-center flex-wrap gap-1">
<button id="prevPage" class="btn btn-outline-primary m-1">Zurück</button>
<div id="pageNumbers" class="d-flex flex-wrap justify-content-center"></div>
<button id="nextPage" class="btn btn-outline-primary m-1">Weiter</button>
</div>
</div>
<!-- Lightbox -->
<div id="lightbox-gallery" class="lightbox">
<span class="close" onclick="closeGallery()">×</span>
<div class="lightbox-content">
<img class="lightbox-image" id="lightbox-image" src alt>
<a class="prev" onclick="changeSlide(-1)">❮</a>
<a class="next" onclick="changeSlide(1)">❯</a>
</div>
</div>
<script>
let galleryImages = [], currentSlide = 0, currentPage = 1, totalPages = 1;
async function loadGalleries() {
const res = await fetch('galerien/');
const text = await res.text();
const doc = new DOMParser().parseFromString(text, 'text/html');
const folders = [...doc.querySelectorAll('a')]
.map(a => a.getAttribute('href'))
.filter(h => h && h.endsWith('/') && !h.includes('../') && !h.toLowerCase().includes('blogblock'))
.map(h => h.replace('/', ''));
const btns = document.getElementById('galleryButtons');
btns.innerHTML = '';
folders.forEach(f => {
const b = document.createElement('button');
b.className = 'btn m-1 gal-btn';
b.textContent = f.charAt(0).toUpperCase() + f.slice(1);
b.onclick = () => loadFolder(f);
btns.appendChild(b);
});
if (folders.length) loadFolder(folders[0]);
}
async function loadFolder(folder) {
const res = await fetch('galerien/' + folder + '/');
const text = await res.text();
const doc = new DOMParser().parseFromString(text, 'text/html');
galleryImages = [...doc.querySelectorAll('a')]
.map(a => a.getAttribute('href'))
.filter(h => h && h.match(/\.(jpg|jpeg|png|gif|webp)$/i))
.map(h => 'galerien/' + folder + '/' + h);
currentPage = 1;
renderGallery();
document.getElementById('currentGalleryTitle').textContent =
'Aktuelle Galerie: ' + folder.charAt(0).toUpperCase() + folder.slice(1);
}
function renderGallery() {
const section = document.querySelector('.content-gallery');
const perRow = parseInt(section.getAttribute('data-perRow')) || 4;
const thumb = parseInt(section.getAttribute('data-thumbSize')) || 150;
const perPage = parseInt(section.getAttribute('data-maxImages')) || 6;
const grid = document.getElementById('galleryGrid');
grid.innerHTML = '';
grid.style.gridTemplateColumns = `repeat(${perRow}, 1fr)`;
totalPages = Math.ceil(galleryImages.length / perPage);
const start = (currentPage - 1) * perPage;
const end = start + perPage;
galleryImages.slice(start, end).forEach((src, i) => {
const img = document.createElement('img');
img.src = src;
img.className = 'gallery-thumb-small';
img.style.width = thumb + 'px';
img.alt = 'Bild ' + (i + 1);
img.onclick = () => openGallery(start + i);
grid.appendChild(img);
});
updatePagination();
}
function updatePagination() {
const prevBtn = document.getElementById('prevPage');
const nextBtn = document.getElementById('nextPage');
const pageContainer = document.getElementById('pageNumbers');
prevBtn.disabled = currentPage === 1;
nextBtn.disabled = currentPage === totalPages;
pageContainer.innerHTML = '';
for (let i = 1; i <= totalPages; i++) {
const btn = document.createElement('button');
btn.className = 'btn btn-sm m-1 page-btn ' + (i === currentPage ? 'active' : '');
btn.textContent = i;
btn.onclick = () => { currentPage = i; renderGallery(); };
pageContainer.appendChild(btn);
}
prevBtn.onclick = () => {
if (currentPage > 1) { currentPage--; renderGallery(); }
};
nextBtn.onclick = () => {
if (currentPage < totalPages) { currentPage++; renderGallery(); }
};
}
function openGallery(i) {
currentSlide = i;
document.getElementById('lightbox-gallery').style.display = 'block';
showSlide(i);
}
function closeGallery() {
document.getElementById('lightbox-gallery').style.display = 'none';
}
function changeSlide(n) {
currentSlide = (currentSlide + n + galleryImages.length) % galleryImages.length;
showSlide(currentSlide);
}
function showSlide(i) {
document.getElementById('lightbox-image').src = galleryImages[i];
}
document.addEventListener('DOMContentLoaded', loadGalleries);
</script>
</section>
CSS-Code
.content-gallery {
position: relative;
}
.gal-btn {
background-color: var(--btnColor, #007bff) !important;
border-color: var(--btnColor, #007bff) !important;
color: #fff !important;
border-radius: 6px;
transition: all 0.3s ease;
}
.gal-btn:hover {
opacity: 0.85;
}
.page-btn {
background-color: transparent;
color: var(--btnColor, #007bff);
border: 1px solid var(--btnColor, #007bff);
border-radius: 4px;
min-width: 40px;
transition: all 0.3s ease;
}
.page-btn.active, .page-btn:hover {
background-color: var(--btnColor, #007bff);
color: #fff;
}
.gallery-grid {
display: grid;
gap: 10px;
justify-items: center;
}
.gallery-thumb-small {
cursor: pointer;
border-radius: 8px;
transition: transform 0.3s ease, opacity 0.3s ease;
}
.gallery-thumb-small:hover {
transform: scale(1.05);
opacity: 0.8;
}
#pagination button {
min-width: 80px;
}
.lightbox {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.9);
z-index: 9999;
}
.lightbox-content {
position: relative;
margin: 60px auto;
max-width: 80%;
text-align: center;
}
.lightbox-image {
width: 100%;
max-height: 80vh;
object-fit: contain;
border-radius: 10px;
}
.close, .prev, .next {
color: #fff;
cursor: pointer;
font-size: 40px;
font-weight: bold;
user-select: none;
transition: color .3s;
}
.close:hover, .prev:hover, .next:hover {
color: #bbb;
}
.close {
position: absolute;
top: 15px;
right: 35px;
}
.prev, .next {
position: absolute;
top: 50%;
transform: translateY(-50%);
padding: 16px;
}
.prev {
left: 0;
}
.next {
right: 0;
}
P {
color: #ffffff;
}
H3 {
color: #ffffff;
}
JavaScript-Code
Options +Indexes
IndexOptions FancyIndexing NameWidth=*
AddType text/html .html .htm

© Copyright 2025 Volker Niederastroth

Besucherstatistik

Besucher online: 3

Besucher heute: 77

Besucher diese Woche: 581

Besucher diesen Monat: 2653

Gesamtbesucher: 6685