UNPKG

photoswipe

Version:
234 lines (207 loc) 5.42 kB
/** @typedef {import('../photoswipe.js').Point} Point */ /** * @template {keyof HTMLElementTagNameMap} T * @param {string} className * @param {T} tagName * @param {Node} [appendToEl] * @returns {HTMLElementTagNameMap[T]} */ export function createElement(className, tagName, appendToEl) { const el = document.createElement(tagName); if (className) { el.className = className; } if (appendToEl) { appendToEl.appendChild(el); } return el; } /** * @param {Point} p1 * @param {Point} p2 * @returns {Point} */ export function equalizePoints(p1, p2) { p1.x = p2.x; p1.y = p2.y; if (p2.id !== undefined) { p1.id = p2.id; } return p1; } /** * @param {Point} p */ export function roundPoint(p) { p.x = Math.round(p.x); p.y = Math.round(p.y); } /** * Returns distance between two points. * * @param {Point} p1 * @param {Point} p2 * @returns {number} */ export function getDistanceBetween(p1, p2) { const x = Math.abs(p1.x - p2.x); const y = Math.abs(p1.y - p2.y); return Math.sqrt((x * x) + (y * y)); } /** * Whether X and Y positions of points are equal * * @param {Point} p1 * @param {Point} p2 * @returns {boolean} */ export function pointsEqual(p1, p2) { return p1.x === p2.x && p1.y === p2.y; } /** * The float result between the min and max values. * * @param {number} val * @param {number} min * @param {number} max * @returns {number} */ export function clamp(val, min, max) { return Math.min(Math.max(val, min), max); } /** * Get transform string * * @param {number} x * @param {number} [y] * @param {number} [scale] * @returns {string} */ export function toTransformString(x, y, scale) { let propValue = `translate3d(${x}px,${y || 0}px,0)`; if (scale !== undefined) { propValue += ` scale3d(${scale},${scale},1)`; } return propValue; } /** * Apply transform:translate(x, y) scale(scale) to element * * @param {HTMLElement} el * @param {number} x * @param {number} [y] * @param {number} [scale] */ export function setTransform(el, x, y, scale) { el.style.transform = toTransformString(x, y, scale); } const defaultCSSEasing = 'cubic-bezier(.4,0,.22,1)'; /** * Apply CSS transition to element * * @param {HTMLElement} el * @param {string} [prop] CSS property to animate * @param {number} [duration] in ms * @param {string} [ease] CSS easing function */ export function setTransitionStyle(el, prop, duration, ease) { // inOut: 'cubic-bezier(.4, 0, .22, 1)', // for "toggle state" transitions // out: 'cubic-bezier(0, 0, .22, 1)', // for "show" transitions // in: 'cubic-bezier(.4, 0, 1, 1)'// for "hide" transitions el.style.transition = prop ? `${prop} ${duration}ms ${ease || defaultCSSEasing}` : 'none'; } /** * Apply width and height CSS properties to element * * @param {HTMLElement} el * @param {string | number} w * @param {string | number} h */ export function setWidthHeight(el, w, h) { el.style.width = (typeof w === 'number') ? `${w}px` : w; el.style.height = (typeof h === 'number') ? `${h}px` : h; } /** * @param {HTMLElement} el */ export function removeTransitionStyle(el) { setTransitionStyle(el); } /** * @param {HTMLImageElement} img * @returns {Promise<HTMLImageElement | void>} */ export function decodeImage(img) { if ('decode' in img) { return img.decode().catch(() => {}); } if (img.complete) { return Promise.resolve(img); } return new Promise((resolve, reject) => { img.onload = () => resolve(img); img.onerror = reject; }); } /** @typedef {LOAD_STATE[keyof LOAD_STATE]} LoadState */ /** @type {{ IDLE: 'idle'; LOADING: 'loading'; LOADED: 'loaded'; ERROR: 'error' }} */ export const LOAD_STATE = { IDLE: 'idle', LOADING: 'loading', LOADED: 'loaded', ERROR: 'error', }; /** * Check if click or keydown event was dispatched * with a special key or via mouse wheel. * * @param {MouseEvent | KeyboardEvent} e * @returns {boolean} */ export function specialKeyUsed(e) { return ('button' in e && e.button === 1) || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey; } /** * Parse `gallery` or `children` options. * * @param {import('../photoswipe.js').ElementProvider} [option] * @param {string} [legacySelector] * @param {HTMLElement | Document} [parent] * @returns HTMLElement[] */ export function getElementsFromOption(option, legacySelector, parent = document) { /** @type {HTMLElement[]} */ let elements = []; if (option instanceof Element) { elements = [option]; } else if (option instanceof NodeList || Array.isArray(option)) { elements = Array.from(option); } else { const selector = typeof option === 'string' ? option : legacySelector; if (selector) { elements = Array.from(parent.querySelectorAll(selector)); } } return elements; } /** * Check if variable is PhotoSwipe class * * @param {any} fn * @returns {boolean} */ export function isPswpClass(fn) { return typeof fn === 'function' && fn.prototype && fn.prototype.goTo; } /** * Check if browser is Safari * * @returns {boolean} */ export function isSafari() { return !!(navigator.vendor && navigator.vendor.match(/apple/i)); }