import { ACTION_MOVE, ACTION_SWITCH, ACTION_ZOOM, CLASS_HIDE, CLASS_OPEN, EVENT_FOCUSIN, EVENT_HIDDEN, EVENT_SHOWN, } from './constants'; import { addClass, addListener, dispatchEvent, forEach, getMaxZoomRatio, isFunction, isPlainObject, isString, removeClass, removeListener, } from './utilities'; export default { getImageURL(image) { let { url } = this.options; if (isString(url)) { url = image.getAttribute(url); } else if (isFunction(url)) { url = url.call(this, image); } else { url = ''; } return url; }, enforceFocus() { this.clearEnforceFocus(); addListener(document, EVENT_FOCUSIN, (this.onFocusin = (event) => { const { viewer } = this; let { target } = event; if (target === document || target === viewer || viewer.contains(target)) { return; } while (target) { // Avoid conflicts with other modals (#474, #540) if ((target.getAttribute('tabindex') !== null || target.getAttribute('aria-modal') === 'true')) { return; } target = target.parentElement; } viewer.focus(); })); }, clearEnforceFocus() { if (this.onFocusin) { removeListener(document, EVENT_FOCUSIN, this.onFocusin); this.onFocusin = null; } }, open() { const { body } = this; addClass(body, CLASS_OPEN); if (this.scrollbarWidth > 0) { body.style.paddingRight = `${this.scrollbarWidth + (parseFloat(this.initialBodyComputedPaddingRight) || 0)}px`; } }, close() { const { body } = this; removeClass(body, CLASS_OPEN); if (this.scrollbarWidth > 0) { body.style.paddingRight = this.initialBodyPaddingRight; } }, shown() { const { element, options, viewer } = this; this.fulled = true; this.isShown = true; this.render(); this.bind(); this.showing = false; if (options.focus) { viewer.focus(); this.enforceFocus(); } if (isFunction(options.shown)) { addListener(element, EVENT_SHOWN, options.shown, { once: true, }); } if (dispatchEvent(element, EVENT_SHOWN) === false) { return; } if (this.ready && this.isShown && !this.hiding) { this.view(this.index); } }, hidden() { const { element, options, viewer } = this; if (options.fucus) { this.clearEnforceFocus(); } this.close(); this.unbind(); addClass(viewer, CLASS_HIDE); viewer.removeAttribute('role'); viewer.removeAttribute('aria-labelledby'); viewer.removeAttribute('aria-modal'); viewer.setAttribute('aria-hidden', true); this.resetList(); this.resetImage(); this.fulled = false; this.viewed = false; this.isShown = false; this.hiding = false; if (!this.destroyed) { if (isFunction(options.hidden)) { addListener(element, EVENT_HIDDEN, options.hidden, { once: true, }); } dispatchEvent(element, EVENT_HIDDEN, null, { cancelable: false, }); } }, requestFullscreen(options) { const document = this.element.ownerDocument; if (this.fulled && !( document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement )) { const { documentElement } = document; // Element.requestFullscreen() if (documentElement.requestFullscreen) { // Avoid TypeError when convert `options` to dictionary if (isPlainObject(options)) { documentElement.requestFullscreen(options); } else { documentElement.requestFullscreen(); } } else if (documentElement.webkitRequestFullscreen) { documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); } else if (documentElement.mozRequestFullScreen) { documentElement.mozRequestFullScreen(); } else if (documentElement.msRequestFullscreen) { documentElement.msRequestFullscreen(); } } }, exitFullscreen() { const document = this.element.ownerDocument; if (this.fulled && ( document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement )) { // Document.exitFullscreen() if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } } }, change(event) { const { options, pointers } = this; const pointer = pointers[Object.keys(pointers)[0]]; // In the case of the `pointers` object is empty (#421) if (!pointer) { return; } const offsetX = pointer.endX - pointer.startX; const offsetY = pointer.endY - pointer.startY; switch (this.action) { // Move the current image case ACTION_MOVE: if (offsetX !== 0 || offsetY !== 0) { this.pointerMoved = true; this.move(offsetX, offsetY, event); } break; // Zoom the current image case ACTION_ZOOM: this.zoom(getMaxZoomRatio(pointers), false, null, event); break; case ACTION_SWITCH: { this.action = 'switched'; const absoluteOffsetX = Math.abs(offsetX); if (absoluteOffsetX > 1 && absoluteOffsetX > Math.abs(offsetY)) { // Empty `pointers` as `touchend` event will not be fired after swiped in iOS browsers. this.pointers = {}; if (offsetX > 1) { this.prev(options.loop); } else if (offsetX < -1) { this.next(options.loop); } } break; } default: } // Override forEach(pointers, (p) => { p.startX = p.endX; p.startY = p.endY; }); }, isSwitchable() { const { imageData, viewerData } = this; return this.length > 1 && imageData.x >= 0 && imageData.y >= 0 && imageData.width <= viewerData.width && imageData.height <= viewerData.height; }, };