UNPKG

@randstad-design/orbit-multitheme

Version:

multitheme Front-end code based on Randstad Human Forward components

268 lines (217 loc) 6.58 kB
/** * image-gallery.js * * */ import PhotoSwipe from 'photoswipe/dist/photoswipe' import PhotoSwipeUI_Default from 'photoswipe/dist/photoswipe-ui-default'; import ElementHelpers from '../helpers/element-helpers'; /** * Declare constants */ const attributeBase = 'data-rs-image-gallery'; export class ImageGallery { constructor(element) { this.element = element; this.initPhotoSwipeFromDOM(this.classes.gallerySelector); } /** * Declare attribute constants */ get attributes() { return { imageSize: `${attributeBase}-image-size`, totalsOverlay: `${attributeBase}-totals-overlay`, totalPhotos: `${attributeBase}-total-photos`, photoSwipeUid: 'data-pswp-uid' } } /** * Declare classes */ get classes() { return { gallerySelector: '.image-gallery-selector', photoTotalsOverlay: 'photo-totals-overlay', photoswipeElement: '.pswp', hidden: 'hidden' } } initPhotoSwipeFromDOM(gallerySelector) { // loop through all gallery elements and bind events const galleryElements = document.querySelectorAll(gallerySelector); galleryElements.forEach((item, index) => { item.setAttribute(this.attributes.photoSwipeUid, index + 1); item.onclick = this.onThumbnailsClick.bind(this); let figureArray = [...item.childNodes]; const figureElements = figureArray.filter(element => { return element.nodeName === 'FIGURE'; }); let count = 0; figureElements.forEach((element, index) => { if (index === 2) { element.setAttribute(this.attributes.totalsOverlay, true) } else if (index > 2) { element.classList.add(this.classes.hidden); } count++; }); this.thirdPhoto = ElementHelpers.getElementByAttributeWithinElement(this.element, this.attributes.totalsOverlay, true); this.thirdPhoto.setAttribute(this.attributes.totalPhotos, count); this.setTotalsOverlay(); }); // Parse URL and open gallery if it contains #&pid=3&gid=1 const hashData = this.photoswipeParseHash(); if (hashData.pid && hashData.gid) { this.openPhotoSwipe(hashData.pid, galleryElements[hashData.gid - 1], true, true); } } setTotalsOverlay() { const totalPhotoTextBefore = this.element.dataset.rsImageGalleryTotalPhotoTextBefore || ' '; const totalPhotoTextAfter = this.element.dataset.rsImageGalleryTotalPhotoTextAfter || ' '; const photoAmount = this.thirdPhoto.dataset.rsImageGalleryTotalPhotos || ''; this.thirdPhoto.insertAdjacentHTML('beforeend', `<div class=${this.classes.photoTotalsOverlay}>${totalPhotoTextBefore} ${photoAmount} ${totalPhotoTextAfter}</div>`); } // triggers when user clicks on thumbnail onThumbnailsClick(event) { event.preventDefault ? event.preventDefault() : event.returnValue = false; const eTarget = event.target; // find nearest parent element const closest = function closest(element, fn) { return element && (fn(element) ? element : closest(element.parentNode, fn)); }; // find root element of slide const clickedListItem = closest(eTarget, function (element) { return (element.tagName && element.tagName.toUpperCase() === 'FIGURE'); }); if (!clickedListItem) { return; } // find index of clicked item by looping through all child nodes let clickedGallery = clickedListItem.parentNode, childNodes = clickedListItem.parentNode.childNodes, numChildNodes = childNodes.length, nodeIndex = 0, index; for (let i = 0; i < numChildNodes; i++) { if (childNodes[i].nodeType !== 1) { continue; } if (childNodes[i] === clickedListItem) { index = nodeIndex; break; } nodeIndex++; } if (index >= 0) { // open PhotoSwipe if valid index found this.openPhotoSwipe(index, clickedGallery, true, false) } return false; } // parse picture index and gallery index from URL (#&pid=1&gid=2) photoswipeParseHash() { const hash = window.location.hash.substring(1), params = {}; if (hash.length < 5) { return params; } const vars = hash.split('&'); for (let i = 0; i < vars.length; i++) { if (!vars[i]) { continue; } const pair = vars[i].split('='); if (pair.length < 2) { continue; } params[pair[0]] = pair[1]; } if (params.gid) { params.gid = parseInt(params.gid, 10); } return params; } openPhotoSwipe(index, galleryElement, disableAnimation, fromURL) { let pswpElement = document.querySelectorAll(this.classes.photoswipeElement)[0], gallery, options, items; items = this.parseThumbnailElements(galleryElement); // define options (if needed) options = { // define gallery index (for URL) galleryUID: galleryElement.getAttribute(this.attributes.photoSwipeUid), showAnimationDuration: 300, showHideOpacity: true, spacing: 0.5 }; // PhotoSwipe opened from URL if (fromURL) { if (options.galleryPIDs) { // parse real index when custom PIDs are used // http://photoswipe.com/documentation/faq.html#custom-pid-in-url for (let j = 0; j < items.length; j++) { if (items[j].pid === index) { options.index = j; break; } } } else { // in URL indexes start from 1 options.index = parseInt(index, 10) - 1; } } else { options.index = parseInt(index, 10); } // exit if index not found if (isNaN(options.index)) { return; } if (disableAnimation) { options.showAnimationDuration = 0; } // Pass data to PhotoSwipe and initialize it gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options); gallery.init(); } // parse slide data (url, title, size ...) from DOM elements // (children of gallerySelector) parseThumbnailElements(el) { let thumbElements = el.childNodes, numNodes = thumbElements.length, items = [], figureEl, linkEl, size, item; for (let i = 0; i < numNodes; i++) { figureEl = thumbElements[i]; // <figure> element // include only element nodes if (figureEl.nodeType !== 1) { continue; } linkEl = figureEl.children[0]; // <a> element size = linkEl.getAttribute(this.attributes.imageSize).split('x'); // create slide object item = { src: linkEl.getAttribute('href'), w: parseInt(size[0], 10), h: parseInt(size[1], 10) }; if (linkEl.children.length > 0) { // <img> thumbnail element, retrieving thumbnail url item.msrc = linkEl.children[0].getAttribute('src'); } item.el = figureEl; // save link to element for getThumbBoundsFn items.push(item); } return items; } /** * Get selector */ static getSelector() { return `[${attributeBase}]`; } }