UNPKG

bootstrap-lightbox-gallery

Version:

A nice lightbox gallery component for Bootstrap 5

106 lines (99 loc) 4.59 kB
/** * Author and copyright: Stefan Haack (https://shaack.com) * Repository: https://github.com/shaack/bootstrap-lightbox-gallery * License: MIT, see file 'LICENSE' */ import {DomUtils} from "cm-web-modules/src/utils/DomUtils.js" import "bootstrap-show-modal/src/ShowModal.js" export class LightboxGallery { constructor(elements, props = {}) { this.props = { id: "lightboxGallery", // change this, if you have multiple galleries on one page title: "Lightbox Gallery", // set the name, it will be displayed theme: "dark" // set to "light", if you want to display the images on light background } Object.assign(this.props, props) this.props.isDark = props.theme === "dark" this.state = { title: props.title, carousel: undefined, itemCount: 0, currentIndex: undefined } this.init(elements) } init(elements) { let carouselItems = "" elements.forEach((element) => { const img = element.querySelector("img") const itemData = { url: element.href, alt: img.alt, title: img.title, caption: element.querySelector("figcaption").innerHTML.trim() } element.addEventListener("click", (event) => { event.preventDefault() const targetLink = event.target.closest("a") this.open(targetLink) }) let caption = "" if (itemData.caption) { caption = `<div class="rounded carousel-caption p-2 ${this.props.isDark ? "text-light bg-dark" : "text-body bg-light"} bg-opacity-75"> ${itemData.caption} </div>` } const carouselItem = ` <div class="carousel-item h-100" data-bs-index="${this.state.itemCount}"> <div class="d-flex align-items-center h-100 w-100 ${this.props.isDark ? "bg-dark" : "bg-white"}"> <img src="${itemData.url}" class="d-block mx-auto img-fluid h-100" title="${itemData.title}" alt="${itemData.alt}"/> ${caption} </div> </div>` carouselItems += carouselItem this.state.itemCount++ }) this.state.carouselElement = DomUtils.createElement(` <div id="${this.props.id}" class="carousel slide h-100 carousel-fade"> <div class="carousel-inner h-100"> ${carouselItems} </div> <button style="filter: invert(1)" class="carousel-control-prev" type="button" data-bs-target="#${this.props.id}" data-bs-slide="prev"> <span class="carousel-control-prev-icon" aria-hidden="true"></span> <span class="visually-hidden">Vorheriges Bild</span> </button> <button style="filter: invert(1)" class="carousel-control-next" type="button" data-bs-target="#${this.props.id}" data-bs-slide="next"> <span class="carousel-control-next-icon" aria-hidden="true"></span> <span class="visually-hidden">Nächstes Bild</span> </button> </div>`) } open(targetLink) { const carouselItems = this.state.carouselElement.querySelectorAll(".carousel-item") carouselItems.forEach((carouselItem) => { carouselItem.classList.remove("active") }) const image = this.state.carouselElement.querySelector(`[src="${targetLink.href}"]`) const activeItem = image.closest(".carousel-item") activeItem.classList.add("active") this.state.currentIndex = parseInt(activeItem.getAttribute("data-bs-index")) if (targetLink) { this.modal = bootstrap.showModal({ theme: this.props.isDark ? "dark" : undefined, title: this.state.title + " <small class='text-muted ms-3 pb-1 carousel-index'></small>", headerClass: "border-0", body: this.state.carouselElement.outerHTML, modalDialogClass: "modal-fullscreen modal-bootstrap-lightbox-gallery" }) const carouselElement = this.modal.element.querySelector(".carousel") carouselElement.addEventListener('slide.bs.carousel', event => { this.state.currentIndex = event.to this.updateIndex() }) } this.updateIndex() } updateIndex() { this.modal.titleElement.querySelector(".carousel-index").innerText = `${this.state.currentIndex + 1} / ${this.state.itemCount}` } }