https://www.mobirise-tutorials.com/Tuto ... Upload.php
Bildergalerie extra für den Einbau in Mobirise
- Tommy Herrmann
- Site Admin

- Beiträge: 7971
- Registriert: So 6. Dez 2020, 07:37
- Wohnort: Berlin
- Kontaktdaten:
Re: Bildergalerie extra für den Einbau in Mobirise
warte - vielleicht habe ich es zur falschen Zeit runter geladen, denn jetzt sind die Bilder komplett unscharf 
https://www.mobirise-tutorials.com/Tuto ... Upload.php
https://www.mobirise-tutorials.com/Tuto ... Upload.php
Re: Bildergalerie extra für den Einbau in Mobirise
die sind ja total unscharf bei dir
- Tommy Herrmann
- Site Admin

- Beiträge: 7971
- Registriert: So 6. Dez 2020, 07:37
- Wohnort: Berlin
- Kontaktdaten:
Re: Bildergalerie extra für den Einbau in Mobirise
Jetzt ist das mit der Lightbox am Smartphone gut und OK.
Die Bilder sind nun auch nach Bildnamen sortiert.
Dafür sind die Thumbs wieder da und noch unschärfer als je zuvor
https://www.mobirise-tutorials.com/Tuto ... Upload.php
Die Bilder sind nun auch nach Bildnamen sortiert.
Dafür sind die Thumbs wieder da und noch unschärfer als je zuvor
https://www.mobirise-tutorials.com/Tuto ... Upload.php
Re: Bildergalerie extra für den Einbau in Mobirise
Warum sind deine so groß ? Bei mir zeigt es doch auch die richtige Größe
Hast du was an der CSS geändert ?
Nimm doch mal die original galerie.php
Hast du was an der CSS geändert ?
Nimm doch mal die original galerie.php
- Tommy Herrmann
- Site Admin

- Beiträge: 7971
- Registriert: So 6. Dez 2020, 07:37
- Wohnort: Berlin
- Kontaktdaten:
Re: Bildergalerie extra für den Einbau in Mobirise
Ich habe nichts außern das Passwort geändert.
Deine Thumbs sind zwar besser aber auch leicht unscharf - alle!
Vorhin hattest Du das doch schon im Griff
Lasse die scheiß Thumbs doch einfach weg.
Deine Thumbs sind zwar besser aber auch leicht unscharf - alle!
Vorhin hattest Du das doch schon im Griff
Re: Bildergalerie extra für den Einbau in Mobirise
Du hast doch blauen hintergrund, in der original ist der weiß. Ich hab keine Ahnung was da schon wieder nicht richtig ist. hier der code der galerie.php:
Code: Alles auswählen
<?php
// Konfiguration - Pfade zur Bildergalerie
define('UPLOAD_DIR', 'uploads/');
define('THUMB_DIR', 'uploads/thumbs/');
// Funktion zum Abrufen der Bilder
function getGalleryImages() {
$images = [];
if (!is_dir(UPLOAD_DIR)) {
return $images;
}
$files = glob(UPLOAD_DIR . '*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE);
foreach ($files as $file) {
$filename = basename($file);
$thumbPath = THUMB_DIR . $filename;
$images[] = [
'filename' => $filename,
'full_path' => $file,
'thumb_path' => file_exists($thumbPath) ? $thumbPath : $file,
'size' => filesize($file),
'modified' => filemtime($file)
];
}
// Sortiere nach Dateiname (aufsteigend, numerisch korrekt)
usort($images, function($a, $b) {
return strnatcmp($a['filename'], $b['filename']);
});
return $images;
}
$galleryImages = getGalleryImages();
// Parameter für Paginierung
$imagesPerPage = isset($_GET['per_page']) ? max(6, min(50, intval($_GET['per_page']))) : 12;
$currentPage = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$totalImages = count($galleryImages);
$totalPages = ceil($totalImages / $imagesPerPage);
$startIndex = ($currentPage - 1) * $imagesPerPage;
$currentImages = array_slice($galleryImages, $startIndex, $imagesPerPage);
?>
<style>
body {
background-color: white;
}
.gallery-container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.gallery-header {
text-align: center;
margin-bottom: 40px;
}
.gallery-title {
font-size: 2.5rem;
color: #333;
margin-bottom: 10px;
background: linear-gradient(45deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.gallery-stats {
color: #666;
font-size: 1.1rem;
margin-bottom: 20px;
}
.gallery-controls {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
margin-bottom: 30px;
flex-wrap: wrap;
}
.per-page-selector {
display: flex;
align-items: center;
gap: 10px;
}
.per-page-selector select {
padding: 8px 12px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 14px;
background: white;
cursor: pointer;
}
.gallery-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 25px;
margin-bottom: 40px;
}
.gallery-item {
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
cursor: pointer;
}
.gallery-item:hover {
transform: translateY(-8px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
}
.gallery-item img {
width: 100%;
height: 250px;
object-fit: cover;
transition: transform 0.3s ease;
}
.gallery-item:hover img {
transform: scale(1.1);
}
.gallery-item-info {
padding: 15px;
text-align: center;
}
.image-title {
font-weight: 600;
color: #333;
font-size: 14px;
margin-bottom: 5px;
word-break: break-word;
}
.image-meta {
font-size: 12px;
color: #888;
}
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
margin-top: 40px;
flex-wrap: wrap;
}
.pagination a, .pagination span {
padding: 10px 15px;
text-decoration: none;
border: 2px solid #e1e5e9;
border-radius: 8px;
color: #333;
font-weight: 500;
transition: all 0.3s ease;
min-width: 45px;
text-align: center;
}
.pagination a:hover {
background: linear-gradient(45deg, #667eea, #764ba2);
color: white;
border-color: transparent;
}
.pagination .current {
background: linear-gradient(45deg, #667eea, #764ba2);
color: white;
border-color: transparent;
}
.pagination .disabled {
opacity: 0.5;
cursor: not-allowed;
}
.pagination .disabled:hover {
background: white;
color: #333;
border-color: #e1e5e9;
}
.lightbox {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
z-index: 10000;
cursor: pointer;
justify-content: center;
align-items: center;
}
.lightbox-content {
display: flex;
flex-direction: column;
align-items: center;
max-width: 95vw;
max-height: 95vh;
text-align: center;
}
.lightbox img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
border-radius: 10px;
box-shadow: 0 0 50px rgba(0, 0, 0, 0.5);
}
.lightbox-info {
color: white;
margin-top: 20px;
font-size: 16px;
}
.lightbox-close {
position: absolute;
top: 20px;
right: 30px;
color: white;
font-size: 40px;
cursor: pointer;
z-index: 10001;
transition: opacity 0.3s ease;
}
.lightbox-close:hover {
opacity: 0.7;
}
.lightbox-nav {
position: absolute;
top: 50%;
transform: translateY(-50%);
color: white;
font-size: 30px;
cursor: pointer;
background: rgba(0, 0, 0, 0.5);
padding: 20px;
border-radius: 50%;
transition: all 0.3s ease;
user-select: none;
}
.lightbox-nav:hover {
background: rgba(0, 0, 0, 0.8);
}
.lightbox-prev {
left: 30px;
}
.lightbox-next {
right: 30px;
}
.empty-gallery {
text-align: center;
padding: 80px 20px;
color: #666;
}
.empty-gallery h3 {
font-size: 1.5rem;
margin-bottom: 10px;
}
/* Responsive */
@media (max-width: 768px) {
.gallery-container {
padding: 15px;
}
.gallery-title {
font-size: 2rem;
}
.gallery-grid {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
}
.gallery-controls {
flex-direction: column;
gap: 15px;
}
.pagination {
gap: 5px;
}
.pagination a, .pagination span {
padding: 8px 12px;
font-size: 14px;
}
.lightbox-nav {
font-size: 24px;
padding: 15px;
}
.lightbox-close {
font-size: 30px;
top: 15px;
right: 20px;
}
}
@media (max-width: 480px) {
.gallery-grid {
grid-template-columns: 1fr;
gap: 15px;
}
.lightbox-nav {
display: none;
}
}
/* NEU: Bilder in der Lightbox auf größeren Bildschirmen verkleinern */
@media (min-width: 769px) {
.lightbox img {
max-width: 80vw;
max-height: 80vh;
}
}
</style>
<div id="galerie" class="gallery-container">
<div class="gallery-header">
<h1 class="gallery-title"> Bilder der Rehmühle</h1>
<div class="gallery-stats">
<?php echo $totalImages; ?> Bilder
<?php if ($totalPages > 1): ?>
• Seite <?php echo $currentPage; ?> von <?php echo $totalPages; ?>
<?php endif; ?>
</div>
</div>
<?php if ($totalImages > 0): ?>
<div class="gallery-controls">
<div class="per-page-selector">
<label for="per-page">Bilder pro Seite:</label>
<select id="per-page" onchange="changePerPage(this.value)">
<option value="6" <?php echo $imagesPerPage == 6 ? 'selected' : ''; ?>>6</option>
<option value="12" <?php echo $imagesPerPage == 12 ? 'selected' : ''; ?>>12</option>
<option value="24" <?php echo $imagesPerPage == 24 ? 'selected' : ''; ?>>24</option>
<option value="48" <?php echo $imagesPerPage == 48 ? 'selected' : ''; ?>>48</option>
</select>
</div>
</div>
<div class="gallery-grid">
<?php foreach ($currentImages as $index => $image): ?>
<div class="gallery-item" onclick="openLightbox(event, <?php echo $startIndex + $index; ?>)">
<img
src="<?php echo htmlspecialchars($image['thumb_path']); ?>"
alt="<?php echo htmlspecialchars($image['filename']); ?>"
loading="lazy"
>
<div class="gallery-item-info">
<div class="image-title">
<?php echo htmlspecialchars($image['filename']); ?>
</div>
<div class="image-meta">
<?php echo date('d.m.Y', $image['modified']); ?> •
<?php echo number_format($image['size'] / 1024, 1); ?> KB
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php if ($totalPages > 1): ?>
<div class="pagination">
<?php if ($currentPage > 1): ?>
<a href="?page=1&per_page=<?php echo $imagesPerPage; ?>">«</a>
<a href="?page=<?php echo $currentPage - 1; ?>&per_page=<?php echo $imagesPerPage; ?>">‹</a>
<?php else: ?>
<span class="disabled">«</span>
<span class="disabled">‹</span>
<?php endif; ?>
<?php
$start = max(1, $currentPage - 2);
$end = min($totalPages, $currentPage + 2);
if ($start > 1) {
echo '<a href="?page=1&per_page=' . $imagesPerPage . '">1</a>';
if ($start > 2) echo '<span>...</span>';
}
for ($i = $start; $i <= $end; $i++): ?>
<?php if ($i == $currentPage): ?>
<span class="current"><?php echo $i; ?></span>
<?php else: ?>
<a href="?page=<?php echo $i; ?>&per_page=<?php echo $imagesPerPage; ?>"><?php echo $i; ?></a>
<?php endif; ?>
<?php endfor;
if ($end < $totalPages) {
if ($end < $totalPages - 1) echo '<span>...</span>';
echo '<a href="?page=' . $totalPages . '&per_page=' . $imagesPerPage . '">' . $totalPages . '</a>';
}
?>
<?php if ($currentPage < $totalPages): ?>
<a href="?page=<?php echo $currentPage + 1; ?>&per_page=<?php echo $imagesPerPage; ?>">›</a>
<a href="?page=<?php echo $totalPages; ?>&per_page=<?php echo $imagesPerPage; ?>">»</a>
<?php else: ?>
<span class="disabled">›</span>
<span class="disabled">»</span>
<?php endif; ?>
</div>
<?php endif; ?>
<?php else: ?>
<div class="empty-gallery">
<h3>Noch keine Bilder verfügbar</h3>
<p>Die Galerie ist momentan leer.</p>
</div>
<?php endif; ?>
</div>
<div id="lightbox" class="lightbox" onclick="closeLightbox()">
<span class="lightbox-close" onclick="closeLightbox()">×</span>
<div class="lightbox-prev lightbox-nav" onclick="event.stopPropagation(); prevImage()">‹</div>
<div class="lightbox-next lightbox-nav" onclick="event.stopPropagation(); nextImage()">›</div>
<div class="lightbox-content">
<img id="lightbox-img" src="" alt="">
<div id="lightbox-info" class="lightbox-info"></div>
</div>
</div>
<script>
// Galerie-Daten für JavaScript
const allImages = <?php echo json_encode($galleryImages); ?>;
let currentLightboxIndex = 0;
function openLightbox(event, index) {
event.stopPropagation();
currentLightboxIndex = index;
updateLightboxContent();
document.getElementById('lightbox').style.display = 'flex';
document.body.style.overflow = 'hidden';
}
function closeLightbox() {
document.getElementById('lightbox').style.display = 'none';
document.body.style.overflow = 'auto';
}
function updateLightboxContent() {
if (allImages[currentLightboxIndex]) {
const image = allImages[currentLightboxIndex];
document.getElementById('lightbox-img').src = image.full_path;
document.getElementById('lightbox-info').innerHTML =
'<strong>' + image.filename + '</strong><br>' +
new Date(image.modified * 1000).toLocaleDateString('de-DE') + ' • ' +
(image.size / 1024).toFixed(1) + ' KB';
}
}
function nextImage() {
if (currentLightboxIndex < allImages.length - 1) {
currentLightboxIndex++;
updateLightboxContent();
}
}
function prevImage() {
if (currentLightboxIndex > 0) {
currentLightboxIndex--;
updateLightboxContent();
}
}
function changePerPage(value) {
const url = new URL(window.location);
url.searchParams.set('per_page', value);
url.searchParams.set('page', '1');
window.location = url;
}
// Fix für unerwartetes Popup beim Neuladen
window.onload = function() {
document.getElementById('lightbox').style.display = 'none';
}
// Keyboard Navigation
document.addEventListener('keydown', function(e) {
const lightbox = document.getElementById('lightbox');
if (lightbox.style.display === 'flex') {
switch(e.key) {
case 'Escape':
closeLightbox();
break;
case 'ArrowLeft':
prevImage();
break;
case 'ArrowRight':
nextImage();
break;
}
}
});
// Touch/Swipe Support für Mobile
let touchStartX = 0;
let touchEndX = 0;
document.getElementById('lightbox').addEventListener('touchstart', function(e) {
touchStartX = e.changedTouches[0].screenX;
});
document.getElementById('lightbox').addEventListener('touchend', function(e) {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
});
function handleSwipe() {
const swipeDistance = touchEndX - touchStartX;
const minSwipeDistance = 50;
if (Math.abs(swipeDistance) > minSwipeDistance) {
if (swipeDistance > 0) {
prevImage(); // Swipe right = previous image
} else {
nextImage(); // Swipe left = next image
}
}
}
// Lazy Loading für bessere Performance
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => {
imageObserver.observe(img);
});
}
</script>Re: Bildergalerie extra für den Einbau in Mobirise
Tommy schau hier : https://www.niederastroth.de/bilder
wo ist da was unscharf ? Das sind die original bilder nur verkleinert. Tumbs nur für den Admin
wo ist da was unscharf ? Das sind die original bilder nur verkleinert. Tumbs nur für den Admin
Re: Bildergalerie extra für den Einbau in Mobirise
Ich vermute das stört irgend etwas von Mobirise ... wohl in der CSS ??
Ich muss das mal testen
Ich hab ja nur die galerie.php in den articel Block eingefügt ohne sonstige Dinge von Mobirise ich vermute da liegt das Problem
Ich muss das mal testen
Ich hab ja nur die galerie.php in den articel Block eingefügt ohne sonstige Dinge von Mobirise ich vermute da liegt das Problem
- Tommy Herrmann
- Site Admin

- Beiträge: 7971
- Registriert: So 6. Dez 2020, 07:37
- Wohnort: Berlin
- Kontaktdaten:
Re: Bildergalerie extra für den Einbau in Mobirise
So darfst Du Mobirise natürlich nicht testen, denn Mobirise hat doch Hunderte von Bootstrap-Klassen abgeändert und mit eigenen überschrieben. 
Re: Bildergalerie extra für den Einbau in Mobirise
Jetzt sehe ich den Mist auch
https://www.niederastroth.de/page8.html
Da muss ich mal auf die Suche gehen was da stört.
https://www.niederastroth.de/page8.html
Da muss ich mal auf die Suche gehen was da stört.
- Tommy Herrmann
- Site Admin

- Beiträge: 7971
- Registriert: So 6. Dez 2020, 07:37
- Wohnort: Berlin
- Kontaktdaten:
Re: Bildergalerie extra für den Einbau in Mobirise
Wieso - ganz klar - die Thumbs sind zu klein. Mache diese Generierung weg und verwende einfach die Original-Fotos. Das stimmt sonst nie, denn es kann ja auch sein, dass Benutzer Fotos hochladen, die kleiner als die Thumbs von Dir sind.
P.S.:
Gucke bitte auch bei dem limitierten Download. Da ist noch ein Fehler, es wird immer nur der erste Token ausgeführt. Ich kann also nur einen Token erstellen.
P.S.:
Gucke bitte auch bei dem limitierten Download. Da ist noch ein Fehler, es wird immer nur der erste Token ausgeführt. Ich kann also nur einen Token erstellen.
Re: Bildergalerie extra für den Einbau in Mobirise
Problem gelöst Kack Mobirise
https://www.niederastroth.de/page8.html
Habs jetzt riegeros gelöst. Damit Projekt abgeschlossen:
Download hier: https://www.niederastroth.de/bildergalerie.7z
https://www.niederastroth.de/page8.html
Habs jetzt riegeros gelöst. Damit Projekt abgeschlossen:
Download hier: https://www.niederastroth.de/bildergalerie.7z
- Tommy Herrmann
- Site Admin

- Beiträge: 7971
- Registriert: So 6. Dez 2020, 07:37
- Wohnort: Berlin
- Kontaktdaten:
Re: Bildergalerie extra für den Einbau in Mobirise
Ja - jetzt ist es in Ordnung 
https://www.mobirise-tutorials.com/Tuto ... Upload.php
… allerdings wird die Galerie auf der Adminseite immer noch unscharf angezeigt, was aber eher "kosmetisch" ist. Dennoch, sollte das nicht zu viel Arbeit sein, sollte das auch noch korrigiert werden, weil es einfach nicht schön ist. Nur perfekte Anwendungen schaffen Vertrauen.
https://www.mobirise-tutorials.com/Tuto ... Upload.php
… allerdings wird die Galerie auf der Adminseite immer noch unscharf angezeigt, was aber eher "kosmetisch" ist. Dennoch, sollte das nicht zu viel Arbeit sein, sollte das auch noch korrigiert werden, weil es einfach nicht schön ist. Nur perfekte Anwendungen schaffen Vertrauen.
Re: Bildergalerie extra für den Einbau in Mobirise
Vertrauen ist gut - Kontrolle noch besser
Änder ich die Tage. Hab jetzt keinen Bock mehr
Als erstes ist das für mich so OK.
Ich träume schon in klammern und kommas und all dem kack
Änder ich die Tage. Hab jetzt keinen Bock mehr
Als erstes ist das für mich so OK.
Ich träume schon in klammern und kommas und all dem kack
- Tommy Herrmann
- Site Admin

- Beiträge: 7971
- Registriert: So 6. Dez 2020, 07:37
- Wohnort: Berlin
- Kontaktdaten:
Re: Bildergalerie extra für den Einbau in Mobirise
Ja - Du darfst das nicht übertreiben, das geht auf's Herz 
Re: Bildergalerie extra für den Einbau in Mobirise
Noch ein wichtiger Aspekt - hatte ich vergessen zu erwähnen
Anders als bei den Mobirse Blöcken kann der Nutzer natürlich auch durch das Script direkt Bilder von seinem Handy auf seine Webseite bringen
Das kann Mobirise nämlich nicht - ÄTSCH
Das ist eben der Vorteil wenn eine Anwendung online verfügbar ist
Anders als bei den Mobirse Blöcken kann der Nutzer natürlich auch durch das Script direkt Bilder von seinem Handy auf seine Webseite bringen
Das ist eben der Vorteil wenn eine Anwendung online verfügbar ist
Re: Bildergalerie extra für den Einbau in Mobirise
So, damit ich Vertrauen bekomme
Admin hat jetzt auch die original Bilder. Thumb Ordner gibts nicht mehr
Fertig
Alles Neu im ZIP: https://www.niederastroth.de/bildergalerie.7z
Wer noch den Thumb Ordner hat, kann den löschen
Noch ein Hinweis: wer schon eine admin.php oder galerie.php in seinem Verzeichnis hat, kann auch beide Dateien umbenennen. Das sollte kein Problem darstellen.
Admin hat jetzt auch die original Bilder. Thumb Ordner gibts nicht mehr
Fertig
Alles Neu im ZIP: https://www.niederastroth.de/bildergalerie.7z
Wer noch den Thumb Ordner hat, kann den löschen
Noch ein Hinweis: wer schon eine admin.php oder galerie.php in seinem Verzeichnis hat, kann auch beide Dateien umbenennen. Das sollte kein Problem darstellen.
- Tommy Herrmann
- Site Admin

- Beiträge: 7971
- Registriert: So 6. Dez 2020, 07:37
- Wohnort: Berlin
- Kontaktdaten:
Re: Bildergalerie extra für den Einbau in Mobirise
Ich habe alles fertig (eventuell fehlt noch ein Sprunganker) und mein Tutorial auch geschrieben:
https://www.mobirise-tutorials.com/Tuto ... Upload.php
https://www.mobirise-tutorials.com/Tuto ... Upload.php
- Tommy Herrmann
- Site Admin

- Beiträge: 7971
- Registriert: So 6. Dez 2020, 07:37
- Wohnort: Berlin
- Kontaktdaten:
Re: Bildergalerie extra für den Einbau in Mobirise
Moin,
ich habe mal ChatGPT gebeten das Script mit Sprunganker auf die Block id="galerie" zu erstellen. Das hat mehrere Anläufe gebraucht, bis es geklappt hat. Jetzt geht das, denn sonst sieht das nicht gut aus bei größeren Galerien. Sehen kannst Du es wenn Du die Anzahl der Bilder oben auf 6 stellst (wie bei diesem Link bereits eingearbeitet), damit zwei Seiten entstehen:
https://www.mobirise-tutorials.com/Tuto ... =1#galerie
Hier Dein umgeschriebenes Skript "galerie.php", so wie ich es jetzt verwende.
Keine Ahnung, ob Du das so in Deinen Download packen willst, denn es geht ja darum das korrekt in Mobirise einzubauen. So wie es bisher ist, fehlt der Sprunganker. Voraussetzung ist den Mobirise-Block mit dem PHP-Include oben links auch so zu nennen, denn da ist dann die Sprunganker-ID:
galerie
Hier die Erklärung von ChatGPT dazu:
ich habe mal ChatGPT gebeten das Script mit Sprunganker auf die Block id="galerie" zu erstellen. Das hat mehrere Anläufe gebraucht, bis es geklappt hat. Jetzt geht das, denn sonst sieht das nicht gut aus bei größeren Galerien. Sehen kannst Du es wenn Du die Anzahl der Bilder oben auf 6 stellst (wie bei diesem Link bereits eingearbeitet), damit zwei Seiten entstehen:
https://www.mobirise-tutorials.com/Tuto ... =1#galerie
Code: Alles auswählen
https://www.mobirise-tutorials.com/Tutorials-3/Galerie-Upload.php?gal_per_page=6&gal_page=1#galerieKeine Ahnung, ob Du das so in Deinen Download packen willst, denn es geht ja darum das korrekt in Mobirise einzubauen. So wie es bisher ist, fehlt der Sprunganker. Voraussetzung ist den Mobirise-Block mit dem PHP-Include oben links auch so zu nennen, denn da ist dann die Sprunganker-ID:
galerie
Code: Alles auswählen
<?php
// ========== KONFIG ==========
define('UPLOAD_DIR', 'uploads/');
define('THUMB_DIR', 'uploads/thumbs/');
// Optional: Wenn du die Links auf einen *bestimmten* Seitenpfad zwingen willst,
// kannst du hier z.B. '/Tutorials-3/Galerie-Upload.php' setzen.
// Leer lassen => es wird automatisch die aktuelle Seite (PHP_SELF) verwendet.
const GALLERY_SELF_PATH = ''; // z.B. '/deine-seite.php'
// ========== HILFSFUNKTIONEN ==========
function gallery_self_path(): string {
if (GALLERY_SELF_PATH !== '') return GALLERY_SELF_PATH;
// Sicherer, basisrelativer Pfad zur aktuell ausgeführten Seite
$path = parse_url($_SERVER['PHP_SELF'] ?? '', PHP_URL_PATH);
return $path ?: '/';
}
// Baut eine Galerie-URL: NUR die Galerie-Parameter, sonst nichts (robust gegen Konflikte)
function gallery_url_clean(int $page, int $perPage): string {
$path = gallery_self_path();
$query = http_build_query([
'gal_page' => max(1, $page),
'gal_per_page' => max(6, min(50, $perPage)),
]);
$url = $path . '?' . $query . '#galerie';
return htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
}
// Bilder holen
function getGalleryImages(): array {
$images = [];
if (!is_dir(UPLOAD_DIR)) return $images;
$files = glob(UPLOAD_DIR . '*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE) ?: [];
foreach ($files as $file) {
$filename = basename($file);
$images[] = [
'filename' => $filename,
'full_path' => $file,
'thumb_path' => $file, // Original als Thumb
'size' => @filesize($file) ?: 0,
'modified' => @filemtime($file) ?: time(),
];
}
usort($images, fn($a,$b) => strnatcmp($a['filename'], $b['filename']));
return $images;
}
// ========== LOGIK ==========
$galleryImages = getGalleryImages();
$imagesPerPage = isset($_GET['gal_per_page']) ? max(6, min(50, (int)$_GET['gal_per_page'])) : 12;
$currentPage = isset($_GET['gal_page']) ? max(1, (int)$_GET['gal_page']) : 1;
$totalImages = count($galleryImages);
$totalPages = max(1, (int)ceil($totalImages / $imagesPerPage));
$currentPage = min($currentPage, $totalPages);
$startIndex = ($currentPage - 1) * $imagesPerPage;
$currentImages = array_slice($galleryImages, $startIndex, $imagesPerPage);
?>
<style>
/* ... (dein bestehendes CSS, unverändert) ... */
.gallery-container img { image-rendering:-webkit-optimize-contrast!important; image-rendering:optimize-contrast!important; image-rendering:crisp-edges!important; -ms-interpolation-mode:nearest-neighbor!important; transform:none!important; filter:none!important; }
.gallery-container img { max-width:100%!important; height:auto!important; display:block!important; }
body{background-color:white;}
.gallery-container{max-width:1400px;margin:0 auto;padding:20px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;scroll-margin-top:90px;}
.gallery-header{text-align:center;margin-bottom:40px;}
.gallery-title{font-size:2.5rem;color:#333;margin-bottom:10px;background:linear-gradient(45deg,#667eea,#764ba2);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;}
.gallery-stats{color:#666;font-size:1.1rem;margin-bottom:20px;}
.gallery-controls{display:flex;justify-content:center;align-items:center;gap:20px;margin-bottom:30px;flex-wrap:wrap;}
.per-page-selector{display:flex;align-items:center;gap:10px;}
.per-page-selector select{padding:8px 12px;border:2px solid #e1e5e9;border-radius:8px;font-size:14px;background:white;cursor:pointer;}
.gallery-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:25px;margin-bottom:40px;}
.gallery-item{background:white;border-radius:15px;overflow:hidden;box-shadow:0 4px 20px rgba(0,0,0,.08);transition:all .3s ease;cursor:pointer;}
.gallery-item:hover{transform:translateY(-8px);box-shadow:0 12px 40px rgba(0,0,0,.15);}
.gallery-item img{width:100%;height:250px;object-fit:cover;transition:transform .3s ease;}
.gallery-item:hover img{transform:scale(1.1)!important;}
.gallery-item-info{padding:15px;text-align:center;}
.image-title{font-weight:600;color:#333;font-size:14px;margin-bottom:5px;word-break:break-word;}
.image-meta{font-size:12px;color:#888;}
.pagination{display:flex;justify-content:center;align-items:center;gap:10px;margin-top:40px;flex-wrap:wrap;}
.pagination a,.pagination span{padding:10px 15px;text-decoration:none;border:2px solid #e1e5e9;border-radius:8px;color:#333;font-weight:500;transition:all .3s ease;min-width:45px;text-align:center;}
.pagination a:hover{background:linear-gradient(45deg,#667eea,#764ba2);color:white;border-color:transparent;}
.pagination .current{background:linear-gradient(45deg,#667eea,#764ba2);color:white;border-color:transparent;}
.pagination .disabled{opacity:.5;cursor:not-allowed;}
.pagination .disabled:hover{background:white;color:#333;border-color:#e1e5e9;}
.lightbox{display:none;position:fixed;inset:0;background:rgba(0,0,0,.95);z-index:10000;cursor:pointer;justify-content:center;align-items:center;}
.lightbox-content{display:flex;flex-direction:column;align-items:center;max-width:95vw;max-height:95vh;text-align:center;}
.lightbox img{max-width:100%;max-height:100%;object-fit:contain;border-radius:10px;box-shadow:0 0 50px rgba(0,0,0,.5);}
.lightbox-info{color:white;margin-top:20px;font-size:16px;}
.lightbox-close{position:absolute;top:20px;right:30px;color:white;font-size:40px;cursor:pointer;z-index:10001;transition:opacity .3s ease;}
.lightbox-close:hover{opacity:.7;}
.lightbox-nav{position:absolute;top:50%;transform:translateY(-50%);color:white;font-size:30px;cursor:pointer;background:rgba(0,0,0,.5);padding:20px;border-radius:50%;transition:all .3s ease;user-select:none;}
.lightbox-nav:hover{background:rgba(0,0,0,.8);}
.lightbox-prev{left:30px;}
.lightbox-next{right:30px;}
.empty-gallery{text-align:center;padding:80px 20px;color:#666;}
.empty-gallery h3{font-size:1.5rem;margin-bottom:10px;}
@media(max-width:768px){.gallery-container{padding:15px}.gallery-title{font-size:2rem}.gallery-grid{grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:20px}.gallery-controls{flex-direction:column;gap:15px}.pagination{gap:5px}.pagination a,.pagination span{padding:8px 12px;font-size:14px}.lightbox-nav{font-size:24px;padding:15px}.lightbox-close{font-size:30px;top:15px;right:20px}}
@media(max-width:480px){.gallery-grid{grid-template-columns:1fr;gap:15px}.lightbox-nav{display:none}}
@media(min-width:769px){.lightbox img{max-width:80vw;max-height:80vh}}
</style>
<div id="galerie" class="gallery-container">
<div class="gallery-header">
<h1 class="gallery-title">Bilder</h1>
<div class="gallery-stats">
<?php echo $totalImages; ?> Bilder
<?php if ($totalPages > 1): ?> • Seite <?php echo $currentPage; ?> von <?php echo $totalPages; ?> <?php endif; ?>
</div>
</div>
<?php if ($totalImages > 0): ?>
<div class="gallery-controls">
<div class="per-page-selector">
<label for="per-page">Bilder pro Seite:</label>
<select id="per-page" onchange="changePerPage(this.value)">
<option value="6" <?php echo $imagesPerPage == 6 ? 'selected' : ''; ?>>6</option>
<option value="12" <?php echo $imagesPerPage == 12 ? 'selected' : ''; ?>>12</option>
<option value="24" <?php echo $imagesPerPage == 24 ? 'selected' : ''; ?>>24</option>
<option value="48" <?php echo $imagesPerPage == 48 ? 'selected' : ''; ?>>48</option>
</select>
</div>
</div>
<div class="gallery-grid">
<?php foreach ($currentImages as $index => $image): ?>
<div class="gallery-item" onclick="openLightbox(event, <?php echo $startIndex + $index; ?>)">
<img src="<?php echo htmlspecialchars($image['thumb_path']); ?>" alt="<?php echo htmlspecialchars($image['filename']); ?>" loading="lazy">
<div class="gallery-item-info">
<div class="image-title"><?php echo htmlspecialchars($image['filename']); ?></div>
<div class="image-meta"><?php echo date('d.m.Y', $image['modified']); ?> • <?php echo number_format($image['size'] / 1024, 1); ?> KB</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php if ($totalPages > 1): ?>
<div class="pagination" id="gal-pagination">
<?php if ($currentPage > 1): ?>
<a href="<?php echo gallery_url_clean(1, $imagesPerPage); ?>" data-gal-page="1">«</a>
<a href="<?php echo gallery_url_clean($currentPage-1, $imagesPerPage); ?>" data-gal-page="<?php echo $currentPage-1; ?>">‹</a>
<?php else: ?>
<span class="disabled">«</span>
<span class="disabled">‹</span>
<?php endif; ?>
<?php
$start = max(1, $currentPage - 2);
$end = min($totalPages, $currentPage + 2);
if ($start > 1) {
echo '<a href="'.gallery_url_clean(1, $imagesPerPage).'" data-gal-page="1">1</a>';
if ($start > 2) echo '<span>...</span>';
}
for ($i = $start; $i <= $end; $i++) {
if ($i == $currentPage) {
echo '<span class="current">'.$i.'</span>';
} else {
echo '<a href="'.gallery_url_clean($i, $imagesPerPage).'" data-gal-page="'.$i.'">'.$i.'</a>';
}
}
if ($end < $totalPages) {
if ($end < $totalPages - 1) echo '<span>...</span>';
echo '<a href="'.gallery_url_clean($totalPages, $imagesPerPage).'" data-gal-page="'.$totalPages.'">'.$totalPages.'</a>';
}
?>
<?php if ($currentPage < $totalPages): ?>
<a href="<?php echo gallery_url_clean($currentPage+1, $imagesPerPage); ?>" data-gal-page="<?php echo $currentPage+1; ?>">›</a>
<a href="<?php echo gallery_url_clean($totalPages, $imagesPerPage); ?>" data-gal-page="<?php echo $totalPages; ?>">»</a>
<?php else: ?>
<span class="disabled">›</span>
<span class="disabled">»</span>
<?php endif; ?>
</div>
<?php endif; ?>
<?php else: ?>
<div class="empty-gallery">
<h3>Noch keine Bilder verfügbar</h3>
<p>Die Galerie ist momentan leer.</p>
</div>
<?php endif; ?>
</div>
<div id="lightbox" class="lightbox" onclick="closeLightbox()">
<span class="lightbox-close" onclick="closeLightbox()">×</span>
<div class="lightbox-prev lightbox-nav" onclick="event.stopPropagation(); prevImage()">‹</div>
<div class="lightbox-next lightbox-nav" onclick="event.stopPropagation(); nextImage()">›</div>
<div class="lightbox-content">
<img id="lightbox-img" src="" alt="">
<div id="lightbox-info" class="lightbox-info"></div>
</div>
</div>
<script>
// Daten
const allImages = <?php echo json_encode($galleryImages); ?>;
let currentLightboxIndex = 0;
// Lightbox
function openLightbox(e, idx){ e.stopPropagation(); currentLightboxIndex = idx; updateLightbox(); document.getElementById('lightbox').style.display='flex'; document.body.style.overflow='hidden'; }
function closeLightbox(){ document.getElementById('lightbox').style.display='none'; document.body.style.overflow='auto'; }
function updateLightbox(){
const img = allImages[currentLightboxIndex]; if(!img) return;
document.getElementById('lightbox-img').src = img.full_path;
document.getElementById('lightbox-info').innerHTML =
'<strong>'+img.filename+'</strong><br>'+
new Date(img.modified*1000).toLocaleDateString('de-DE')+' • '+(img.size/1024).toFixed(1)+' KB';
}
function nextImage(){ if(currentLightboxIndex < allImages.length-1){ currentLightboxIndex++; updateLightbox(); } }
function prevImage(){ if(currentLightboxIndex > 0){ currentLightboxIndex--; updateLightbox(); } }
// Per-Page
function changePerPage(value){
const url = new URL(window.location.href);
url.searchParams.set('gal_per_page', value);
url.searchParams.set('gal_page', '1');
url.hash = 'galerie';
window.location = url.toString();
}
// Onload: Hash beachten
window.onload = function(){
document.getElementById('lightbox').style.display='none';
if (location.hash === '#galerie') {
const el = document.getElementById('galerie');
if (el) el.scrollIntoView({ behavior: 'instant', block: 'start' });
}
};
// Tastatur
document.addEventListener('keydown', e=>{
const lb = document.getElementById('lightbox');
if (lb.style.display === 'flex') {
if (e.key === 'Escape') closeLightbox();
if (e.key === 'ArrowLeft') prevImage();
if (e.key === 'ArrowRight') nextImage();
}
});
// Touch/Swipe
let touchStartX=0,touchEndX=0;
document.getElementById('lightbox').addEventListener('touchstart', e=>{ touchStartX = e.changedTouches[0].screenX; });
document.getElementById('lightbox').addEventListener('touchend', e=>{
touchEndX = e.changedTouches[0].screenX;
const d = touchEndX - touchStartX; if (Math.abs(d) > 50) { d > 0 ? prevImage() : nextImage(); }
});
// Zusätzliche Absicherung: Pagination-Klicks per JS setzen (falls ein <base> o.ä. stört)
document.getElementById('gal-pagination')?.addEventListener('click', function(e){
const a = e.target.closest('a[data-gal-page]');
if (!a) return;
// Wenn ein Theme/Script das Link-Ziel verbiegt, erzwingen wir unseren Weg:
e.preventDefault();
const url = new URL(window.location.href);
url.searchParams.set('gal_page', a.getAttribute('data-gal-page'));
url.searchParams.set('gal_per_page', '<?php echo $imagesPerPage; ?>');
url.hash = 'galerie';
window.location = url.toString();
});
// Optionales Lazy Loading (nur wenn data-src vorhanden)
if ('IntersectionObserver' in window) {
const obs = new IntersectionObserver((entries,o)=>entries.forEach(en=>{
if (en.isIntersecting) {
const img = en.target;
if (img.dataset && img.dataset.src) { img.src = img.dataset.src; img.classList.remove('lazy'); o.unobserve(img); }
}
}));
document.querySelectorAll('img[data-src]').forEach(img=>obs.observe(img));
}
</script>
Hier die Erklärung von ChatGPT dazu:
ChatGPT hat geschrieben:
Was das Problem war
Parameter-Konflikt
Dein ursprüngliches Skript verwendete ?page=... und ?per_page=....
Mobirise verwendet aber intern auch die Parameter page und per_page in manchen Blöcken oder beim internen Routing.
Wenn dein Include auf einer Mobirise-Seite eingebettet war, kollidierten diese Parameter.
Ergebnis:
Dein Link änderte zwar ?page=2
Aber Mobirise interpretierte diesen Wert selbst – und lieferte weiter Seite 1 der Galerie zurück.
Doppelte IDs & Hash-Verhalten
Dein Mobirise-Block und das Galerie-Skript hatten beide id="galerie".
Das war kein direkter Fehler, aber Mobirise hat auf Klicks mit JavaScript gescrollt und das Neuladen der Galerie teilweise blockiert.
Basis-URL & <base href>
Mobirise setzt in vielen Projekten <base href="..."> in den <head>.
Dadurch haben relative Links wie ?page=2 manchmal nicht auf die gleiche Seite gezeigt, sondern wurden durch die Base-URL umgeleitet.
Teilweise blieb man deshalb visuell auf Seite 1 hängen, obwohl sich die URL änderte.
Was wir geändert haben
Eigene Parameter verwendet
Statt page / per_page nehmen wir jetzt gal_page und gal_per_page.
Diese sind eindeutig und können nicht mit Mobirise kollidieren.
Links explizit auf dieselbe Seite gesetzt
Alle Paginierungs-Links werden jetzt dynamisch mit $_SERVER['PHP_SELF'] gebaut.
Dadurch zeigen sie immer auf das richtige PHP-Skript – egal, wie Mobirise-URLs, Includes oder Unterverzeichnisse strukturiert sind.
Hash #galerie am Ende
Der Hash sorgt dafür, dass der Browser nach dem Reload automatisch zum Galerie-Bereich springt.
Das machen wir sauber und konsistent in allen Links.
JavaScript-Fallback eingebaut
Falls Mobirise per JavaScript einen Link-Click überschreibt, fängt unser Skript den Klick ab und setzt die URL aktiv neu.
Damit erzwingen wir, dass wirklich die nächste Galerie-Seite geladen wird.
In einfachen Worten
Vorher:
→ Klick auf „Seite 2“ → Mobirise fing ?page=2 ab → Galerie blieb auf Seite 1 → Sprunganker funktionierte trotzdem, weil der Hash ja da war.
Jetzt:
→ Klick auf „Seite 2“ → unser Link geht mit eigenen Parametern → keine Kollision mehr → PHP lädt Seite 2 → Browser springt zur Galerie.
- Tommy Herrmann
- Site Admin

- Beiträge: 7971
- Registriert: So 6. Dez 2020, 07:37
- Wohnort: Berlin
- Kontaktdaten:
Re: Bildergalerie extra für den Einbau in Mobirise
noch was - fast vergessen ...
... Deine Navigationspfeile in der Lightbox haben übrigens einen sehr unschönen, eierförmigen Hintergrund. Vielleicht magst Du das noch in der CSS anpassen. Ich Habe das für mich auf die Schnelle mit dem Padding zurecht gerückt:
.lightbox-nav{position:absolute;top:50%;transform:translateY(-50%);color:white;font-size:40px;cursor:pointer;background:rgba(0,0,139,.5);padding: 0px 26px 6px 26px;border-radius:50%;transition:all .3s ease;user-select:none;}
... Deine Navigationspfeile in der Lightbox haben übrigens einen sehr unschönen, eierförmigen Hintergrund. Vielleicht magst Du das noch in der CSS anpassen. Ich Habe das für mich auf die Schnelle mit dem Padding zurecht gerückt:
.lightbox-nav{position:absolute;top:50%;transform:translateY(-50%);color:white;font-size:40px;cursor:pointer;background:rgba(0,0,139,.5);padding: 0px 26px 6px 26px;border-radius:50%;transition:all .3s ease;user-select:none;}
Wer ist online?
Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste
