Dynamische Bildergalerie

Anwendungen für Webseiten. Künstliche Intelligenz verwenden.
Volker
Moderator
Moderator
Beiträge: 1542
Registriert: Sa 12. Dez 2020, 22:35

Dynamische Bildergalerie

Ungelesener Beitrag von Volker »

Moin :D

Hab es mal als extra Thema hier neu gemacht.

Meine neuste Entwicklung



Hier die Codes die Ihr braucht:

HTML Block:

Code: Alles auswählen

<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 Block:

Code: Alles auswählen

.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;
}
htaccess Datei :

Code: Alles auswählen

Options +Indexes
IndexOptions FancyIndexing NameWidth=*
AddType text/html .html .htm
Gruß Volker
Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste