@patternslib/patternslib
Version:
Patternslib is a JavaScript library that enables designers to build rich interactive prototypes without the need for writing any Javascript. All events are triggered by classes and other attributes in the HTML, without abusing the HTML as a programming la
171 lines (144 loc) • 5.89 kB
JavaScript
// pat-gallery - A gallery pattern.
import Base from "../../core/base";
import Parser from "../../core/parser";
import dom from "../../core/dom";
import events from "../../core/events";
import logging from "../../core/logging";
import utils from "../../core/utils";
const log = logging.getLogger("pat.gallery");
export const parser = new Parser("gallery");
parser.addArgument("item-selector", "a"); // selector for anchor element, which is added to the gallery.
parser.addArgument("loop", true);
parser.addArgument("scale-method", "fit", ["fit", "fitNoUpscale", "zoom"]);
parser.addArgument("delay", 30000);
parser.addArgument("effect-duration", 250);
let PhotoSwipe;
let PhotoSwipeUI;
export default Base.extend({
name: "gallery",
trigger: ".pat-gallery",
orig_body_overflow: "auto",
images: [],
async init() {
if (window.__patternslib_import_styles) {
import("photoswipe/dist/photoswipe.css");
import("photoswipe/dist/default-skin/default-skin.css");
}
PhotoSwipe = (await import("photoswipe")).default;
PhotoSwipeUI = (await import("photoswipe/dist/photoswipe-ui-default")).default; // prettier-ignore
this.options = parser.parse(this.el, this.options);
this.template = await this.get_template();
const gallery_observer = new MutationObserver(
this.initialize_trigger.bind(this)
);
gallery_observer.observe(this.el, {
subtree: true,
childList: true,
});
this.initialize_trigger();
},
async get_template() {
// Check for already defined templates.
let template = document.querySelector(
".pat-gallery__template-wrapper, #photoswipe-template"
);
// Otherwise, use default template.
if (!template) {
const raw_template = (await import("./template.html")).default;
template = document.createElement("div");
template.setAttribute("class", "pat-gallery__template-wrapper");
template.setAttribute("hidden", "");
template.innerHTML = raw_template;
document.body.appendChild(template);
}
return template;
},
initialize_trigger() {
const image_wrapper_els = dom.querySelectorAllAndMe(
this.el,
this.options.itemSelector
);
this.images = [...image_wrapper_els].map((it) => {
events.add_event_listener(
it,
"click",
"pat-gallery--image_handler",
this.initialize_gallery.bind(this)
);
const src =
it.getAttribute("href") ||
it.getAttribute("src") ||
it.querySelector("img")?.getAttribute("src");
const title =
it.getAttribute("title") ||
it.querySelector("img")?.getAttribute("title");
return {
w: 0,
h: 0,
src: src,
title: title,
};
});
},
initialize_gallery(e) {
const trigger_el = e.currentTarget;
this.template.removeAttribute("hidden");
const pswp_el = dom.querySelectorAllAndMe(this.template, ".pswp")?.[0];
if (!pswp_el) {
log.warn("No photoswipe template found.");
}
// Now - when all is set - prevent default action.
e.preventDefault();
const index =
this.images
.map((it) => it.src)
.indexOf(
trigger_el.getAttribute("href") || trigger_el.getAttribute("src")
) || 0;
const options = {
// Get the index of the clicked gallery item in the list of images.
index: index,
scaleMode: this.options.scaleMethod,
loop: this.options.loop,
slideshowDelay: this.options.delay,
hideAnimationDuration: this.options.effectDuration,
showAnimationDuration: this.options.effectDuration,
pinchToClose: false,
closeOnScroll: false,
// Fix reload on gallery close which was induced by a history back call.
history: false,
};
const gallery = new PhotoSwipe(pswp_el, PhotoSwipeUI, this.images, options);
const gallery_reinit_sizes_debouncer = utils.debounce(() => {
gallery.updateSize(true); // reinit Items
}, 50);
gallery.listen("gettingData", function (index, item) {
// Workaround for the fact that we don't know the image sizes.
// https://github.com/dimsemenov/PhotoSwipe/issues/796
if (item.w < 1 || item.h < 1) {
// unknown size
const img = new Image();
img.onload = (_e) => {
const img_el = _e.target;
// will get size after load
item.w = img_el.width; // set image width
item.h = img_el.height; // set image height
item.needsUpdate = true;
gallery_reinit_sizes_debouncer(); // debounce to not land in a re-init loop.
};
img.src = item.src; // let's download image
}
});
gallery.listen("initialZoomInEnd", () => {
// don't show body scrollbars when overlay is open
this.orig_body_overflow = dom.get_css_value(document.body, "overflow");
document.body.style.overflow = "hidden";
});
gallery.listen("destroy", () => {
// show original overlay value on body after closing
document.body.style.overflow = this.orig_body_overflow;
this.template.setAttribute("hidden", "");
});
gallery.init();
},
});