UNPKG

rizzo-next

Version:

The next generation of Lonely Planet's style guide and pattern library.

205 lines (171 loc) 5.28 kB
import { Component } from "../../core/bane"; import $ from "jquery"; import PhotoSwipe from "photoswipe"; import PhotoSwipeUI_Default from "photoswipe/dist/photoswipe-ui-default"; import Video from "../video"; // Keep track of instance IDs let instanceId = 0; /** * A component for creating an Image Gallery */ export default class ImageGalleryComponent extends Component { /** * Render the gallery viewer * @return {jQuery} Returns the gallery element */ get $pswp() { if (this._$pswp) { return this._$pswp; } return this._$pswp = $(this.template({})).appendTo("body"); } initialize({ galleryImageSelector = ".stack__article__image-container", autoplayVideos = true } = {}) { this.template = require("./image_gallery.hbs"); this.autplayVideos = autoplayVideos; this.$images = this.$el.find(galleryImageSelector); this.events = { ["click " + galleryImageSelector]: "onGalleryClick" }; this.$el.attr({ "data-pswp-uid": ++instanceId, "data-gallery": this }); } _parseThumbnailElements() { if (this._items) { return this._items; } let items = this._items = []; this.$images.each((i, el) => { let $galleryImage = $(el), $linkEl = $galleryImage.find("a"), size = $linkEl.attr("data-size").split("x"), image = $linkEl.find("img").attr("src"), link = $linkEl.attr("href"), largeImage = link.match(/\.(jpg|png|gif)/) ? link : image, youtubeID = this._youtubeID(link), brightcoveID = this._brightcoveID(link); let item = { src: largeImage, msrc: image, el: $linkEl.find("img")[0], w: parseInt(size[0], 10), h: parseInt(size[1], 10), videoID: youtubeID || brightcoveID, videoType: youtubeID ? "youtube" : brightcoveID ? "brightcove" : null }; let $caption; if (($caption = $galleryImage.find("span")).length) { item.title = $caption.html(); } else if (($caption = $galleryImage.next(".copy--caption")).length) { item.title = $caption.html(); } else if (($caption = $galleryImage.next("p").find(".caption")).length) { item.title = $caption.html(); } if (item.videoID) { item.youtubeID = youtubeID; item.html = "<div class='pswp__player' id='" + item.videoID + "'></div>"; item.title = null; item.src = null; item.msrc = null; } items.push(item); }); return items; } /** * Callback from photoswipe gallery close */ onGalleryClose() { this._videoStop(); } /** * Callback from photoswipe item change */ onGalleryChange() { this._videoPlay(this._gallery.currItem); } /** * Plays movie if given proper movie ID */ _videoPlay(galleryItem) { this._videoStop(); if (galleryItem.videoID) { Video.addPlayer( galleryItem.videoID, { type: galleryItem.videoType, videoId: galleryItem.videoID, autoplay: this.autoplayVideos }).then(this.playerReady.bind(this)); } } playerReady(player) { this._player = player; } /** * Stops movie and destroys the player */ _videoStop() { if (this._player) { this._player.dispose(); this._player = null; } } /** * Gets youtube movie id from given youtube movie url */ _youtubeID(url) { let regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/, match = url.match(regExp); return match && match[2].length == 11 ? match[2] : null; } /** * Gets brightcove movie id from given brightcove movie url */ _brightcoveID(url) { let regExp = /^.*\.brightcove\..*(\/videos\/|\?videoId=)([0-9]+).*/, match = url.match(regExp); return match ? match[2] : null; } /** * Callback from clicking on a gallery image * @param {Event} event Event * @return {Object} Returns an object to send data to GA for tracking */ onGalleryClick(event) { event.preventDefault(); let clickedListItem = event.currentTarget, index = this.$images.index(clickedListItem), src = $(clickedListItem).find("img").attr("src"); if (index >= 0) { this.openPhotoSwipe(index); } return src; } /** * Open the photo gallery * @param {[type]} index [description] * @return {[type]} [description] */ openPhotoSwipe(index = 0) { let items = this._parseThumbnailElements(); let options = { galleryUID: this.$el.attr("data-pswp-uid"), getThumbBoundsFn: function(index) { let thumbnail = items[index].el, // find thumbnail pageYScroll = window.pageYOffset || document.documentElement.scrollTop, rect = thumbnail.getBoundingClientRect(); return { x: rect.left, y: rect.top + pageYScroll, w: rect.width }; }, history: false, counterEl: false, index }; this._gallery = new PhotoSwipe( this.$pswp[0], PhotoSwipeUI_Default, items, options ); this._gallery.listen("afterChange", this.onGalleryChange.bind(this)); this._gallery.listen("close", this.onGalleryClose.bind(this)); this._gallery.init(); } }