UNPKG

photoswipe

Version:
187 lines (158 loc) 5.48 kB
import Eventable from './eventable.js'; import { getElementsFromOption } from '../util/util.js'; import Content from '../slide/content.js'; import { lazyLoadData } from '../slide/loader.js'; /** @typedef {import("../photoswipe.js").default} PhotoSwipe */ /** @typedef {import("../slide/slide.js").SlideData} SlideData */ /** * PhotoSwipe base class that can retrieve data about every slide. * Shared by PhotoSwipe Core and PhotoSwipe Lightbox */ class PhotoSwipeBase extends Eventable { /** * Get total number of slides * * @returns {number} */ getNumItems() { let numItems = 0; const dataSource = this.options?.dataSource; if (dataSource && 'length' in dataSource) { // may be an array or just object with length property numItems = dataSource.length; } else if (dataSource && 'gallery' in dataSource) { // query DOM elements if (!dataSource.items) { dataSource.items = this._getGalleryDOMElements(dataSource.gallery); } if (dataSource.items) { numItems = dataSource.items.length; } } // legacy event, before filters were introduced const event = this.dispatch('numItems', { dataSource, numItems }); return this.applyFilters('numItems', event.numItems, dataSource); } /** * @param {SlideData} slideData * @param {number} index * @returns {Content} */ createContentFromData(slideData, index) { return new Content(slideData, this, index); } /** * Get item data by index. * * "item data" should contain normalized information that PhotoSwipe needs to generate a slide. * For example, it may contain properties like * `src`, `srcset`, `w`, `h`, which will be used to generate a slide with image. * * @param {number} index * @returns {SlideData} */ getItemData(index) { const dataSource = this.options?.dataSource; /** @type {SlideData | HTMLElement} */ let dataSourceItem = {}; if (Array.isArray(dataSource)) { // Datasource is an array of elements dataSourceItem = dataSource[index]; } else if (dataSource && 'gallery' in dataSource) { // dataSource has gallery property, // thus it was created by Lightbox, based on // gallery and children options // query DOM elements if (!dataSource.items) { dataSource.items = this._getGalleryDOMElements(dataSource.gallery); } dataSourceItem = dataSource.items[index]; } let itemData = dataSourceItem; if (itemData instanceof Element) { itemData = this._domElementToItemData(itemData); } // Dispatching the itemData event, // it's a legacy verion before filters were introduced const event = this.dispatch('itemData', { itemData: itemData || {}, index }); return this.applyFilters('itemData', event.itemData, index); } /** * Get array of gallery DOM elements, * based on childSelector and gallery element. * * @param {HTMLElement} galleryElement * @returns {HTMLElement[]} */ _getGalleryDOMElements(galleryElement) { if (this.options?.children || this.options?.childSelector) { return getElementsFromOption( this.options.children, this.options.childSelector, galleryElement ) || []; } return [galleryElement]; } /** * Converts DOM element to item data object. * * @param {HTMLElement} element DOM element * @returns {SlideData} */ _domElementToItemData(element) { /** @type {SlideData} */ const itemData = { element }; const linkEl = /** @type {HTMLAnchorElement} */ ( element.tagName === 'A' ? element : element.querySelector('a') ); if (linkEl) { // src comes from data-pswp-src attribute, // if it's empty link href is used itemData.src = linkEl.dataset.pswpSrc || linkEl.href; if (linkEl.dataset.pswpSrcset) { itemData.srcset = linkEl.dataset.pswpSrcset; } itemData.width = linkEl.dataset.pswpWidth ? parseInt(linkEl.dataset.pswpWidth, 10) : 0; itemData.height = linkEl.dataset.pswpHeight ? parseInt(linkEl.dataset.pswpHeight, 10) : 0; // support legacy w & h properties itemData.w = itemData.width; itemData.h = itemData.height; if (linkEl.dataset.pswpType) { itemData.type = linkEl.dataset.pswpType; } const thumbnailEl = element.querySelector('img'); if (thumbnailEl) { // msrc is URL to placeholder image that's displayed before large image is loaded // by default it's displayed only for the first slide itemData.msrc = thumbnailEl.currentSrc || thumbnailEl.src; itemData.alt = thumbnailEl.getAttribute('alt') ?? ''; } if (linkEl.dataset.pswpCropped || linkEl.dataset.cropped) { itemData.thumbCropped = true; } } return this.applyFilters('domItemData', itemData, element, linkEl); } /** * Lazy-load by slide data * * @param {SlideData} itemData Data about the slide * @param {number} index * @returns {Content} Image that is being decoded or false. */ lazyLoadData(itemData, index) { return lazyLoadData(itemData, this, index); } } export default PhotoSwipeBase;