diff --git a/app/src/assets/scss/viewerjs/_viewer.scss b/app/src/assets/scss/viewerjs/_viewer.scss index 423133f70..3de101399 100644 --- a/app/src/assets/scss/viewerjs/_viewer.scss +++ b/app/src/assets/scss/viewerjs/_viewer.scss @@ -244,11 +244,18 @@ display: inline-block; font-size: 12px; line-height: 1.2; - margin: 0 5% 5px; + margin: 5px 5%; max-width: 90%; + min-height: 14px; + opacity: 0.8; overflow: hidden; text-overflow: ellipsis; + transition: opacity 0.15s; white-space: nowrap; + + &:hover { + opacity: 1; + } } &-button { diff --git a/app/src/protyle/preview/image.ts b/app/src/protyle/preview/image.ts index 66447a3cf..fd06d233b 100644 --- a/app/src/protyle/preview/image.ts +++ b/app/src/protyle/preview/image.ts @@ -3,46 +3,46 @@ import {addScript} from "../util/addScript"; import {fetchPost} from "../../util/fetch"; export const previewImage = (src: string) => { - addScript(`${Constants.PROTYLE_CDN}/js/viewerjs/viewer.js?v=1.10.4`, "protyleViewerScript").then(() => { - const imagesElement = document.createElement("ul"); - imagesElement.innerHTML = `
  • `; - window.siyuan.viewer = new Viewer(imagesElement, { - title: [1, (image: HTMLImageElement, imageData: IObject) => { - let name = image.alt; - if (!name) { - name = image.src.substring(image.src.lastIndexOf("/") + 1); - } - name = name.substring(0, name.lastIndexOf(".")).replace(/-\d{14}-\w{7}$/, ""); - return `${name} [${imageData.naturalWidth} × ${imageData.naturalHeight}]`; - }], - button: false, - transition: false, - hidden: function () { + addScript(`${Constants.PROTYLE_CDN}/js/viewerjs/viewer.js?v=1.11.7`, "protyleViewerScript").then(() => { + const imagesElement = document.createElement("ul"); + imagesElement.innerHTML = `
  • `; + window.siyuan.viewer = new Viewer(imagesElement, { + title: [1, (image: HTMLImageElement, imageData: IObject) => { + let name = image.alt; + if (!name) { + name = image.src.substring(image.src.lastIndexOf("/") + 1); + } + name = name.substring(0, name.lastIndexOf(".")).replace(/-\d{14}-\w{7}$/, ""); + return `${name} [${imageData.naturalWidth} × ${imageData.naturalHeight}]`; + }], + button: false, + transition: false, + hidden: function () { + window.siyuan.viewer.destroy(); + }, + toolbar: { + zoomIn: true, + zoomOut: true, + oneToOne: true, + reset: true, + prev: true, + play: true, + next: true, + rotateLeft: true, + rotateRight: true, + flipHorizontal: true, + flipVertical: true, + close: function () { window.siyuan.viewer.destroy(); }, - toolbar: { - zoomIn: true, - zoomOut: true, - oneToOne: true, - reset: true, - prev: true, - play: true, - next: true, - rotateLeft: true, - rotateRight: true, - flipHorizontal: true, - flipVertical: true, - close: function () { - window.siyuan.viewer.destroy(); - }, - }, - }); - window.siyuan.viewer.show(); + }, + }); + window.siyuan.viewer.show(); }); }; export const previewDocImage = (src: string, id: string) => { - addScript(`${Constants.PROTYLE_CDN}/js/viewerjs/viewer.js?v=1.10.4`, "protyleViewerScript").then(() => { + addScript(`${Constants.PROTYLE_CDN}/js/viewerjs/viewer.js?v=1.11.7`, "protyleViewerScript").then(() => { fetchPost("/api/asset/getDocImageAssets", {id}, (response) => { const imagesElement = document.createElement("ul"); let html = ""; diff --git a/app/src/protyle/preview/index.ts b/app/src/protyle/preview/index.ts index 54791f88d..446d370f9 100644 --- a/app/src/protyle/preview/index.ts +++ b/app/src/protyle/preview/index.ts @@ -113,7 +113,7 @@ export class Preview { } break; } else if (target.tagName === "IMG") { - previewDocImage((event.target as HTMLImageElement).src, protyle.block.rootID); + previewDocImage((event.target as HTMLElement).getAttribute("src"), protyle.block.rootID); event.stopPropagation(); event.preventDefault(); break; diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 0e0a24cff..44c9f7b17 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -2150,7 +2150,7 @@ export class WYSIWYG { this.element.addEventListener("dblclick", (event: MouseEvent & { target: HTMLElement }) => { if (event.target.tagName === "IMG" && !event.target.classList.contains("emoji")) { - previewDocImage((event.target as HTMLImageElement).src, protyle.block.rootID); + previewDocImage((event.target as HTMLElement).getAttribute("src"), protyle.block.rootID); return; } }); diff --git a/app/stage/protyle/js/viewerjs/viewer.js b/app/stage/protyle/js/viewerjs/viewer.js index 3c67f9293..c659da620 100644 --- a/app/stage/protyle/js/viewerjs/viewer.js +++ b/app/stage/protyle/js/viewerjs/viewer.js @@ -1,3685 +1,10 @@ /*! - * Viewer.js v1.10.4 + * Viewer.js v1.11.7 * https://fengyuanchen.github.io/viewerjs * * Copyright 2015-present Chen Fengyuan * Released under the MIT license * - * Date: 2022-02-13T08:40:00.127Z + * Date: 2024-12-07T02:18:04.739Z */ - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' - ? module.exports = factory() - : typeof define === 'function' && define.amd - ? define(factory) - : (global = typeof globalThis !== 'undefined' ? globalThis : global || - self, global.Viewer = factory()) -})(this, (function () { - 'use strict' - - function ownKeys (object, enumerableOnly) { - var keys = Object.keys(object) - - if (Object.getOwnPropertySymbols) { - var symbols = Object.getOwnPropertySymbols(object) - enumerableOnly && (symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable - })), keys.push.apply(keys, symbols) - } - - return keys - } - - function _objectSpread2 (target) { - for (var i = 1; i < arguments.length; i++) { - var source = null != arguments[i] ? arguments[i] : {} - i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { - _defineProperty(target, key, source[key]) - }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, - Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)). - forEach(function (key) { - Object.defineProperty(target, key, - Object.getOwnPropertyDescriptor(source, key)) - }) - } - - return target - } - - function _typeof (obj) { - '@babel/helpers - typeof' - - return _typeof = 'function' == typeof Symbol && 'symbol' == - typeof Symbol.iterator ? function (obj) { - return typeof obj - } : function (obj) { - return obj && 'function' == typeof Symbol && obj.constructor === Symbol && - obj !== Symbol.prototype ? 'symbol' : typeof obj - }, _typeof(obj) - } - - function _classCallCheck (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError('Cannot call a class as a function') - } - } - - function _defineProperties (target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i] - descriptor.enumerable = descriptor.enumerable || false - descriptor.configurable = true - if ('value' in descriptor) descriptor.writable = true - Object.defineProperty(target, descriptor.key, descriptor) - } - } - - function _createClass (Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps) - if (staticProps) _defineProperties(Constructor, staticProps) - Object.defineProperty(Constructor, 'prototype', { - writable: false, - }) - return Constructor - } - - function _defineProperty (obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, enumerable: true, configurable: true, writable: true, - }) - } else { - obj[key] = value - } - - return obj - } - - var DEFAULTS = { - /** - * Enable a modal backdrop, specify `static` for a backdrop - * which doesn't close the modal on click. - * @type {boolean} - */ - backdrop: true, - - /** - * Show the button on the top-right of the viewer. - * @type {boolean} - */ - button: true, - - /** - * Show the navbar. - * @type {boolean | number} - */ - navbar: true, - - /** - * Specify the visibility and the content of the title. - * @type {boolean | number | Function | Array} - */ - title: true, - - /** - * Show the toolbar. - * @type {boolean | number | Object} - */ - toolbar: true, - - /** - * Custom class name(s) to add to the viewer's root element. - * @type {string} - */ - className: '', - - /** - * Define where to put the viewer in modal mode. - * @type {string | Element} - */ - container: 'body', - - /** - * Filter the images for viewing. Return true if the image is viewable. - * @type {Function} - */ - filter: null, - - /** - * Enable to request fullscreen when play. - * {@link https://developer.mozilla.org/en-US/docs/Web/API/FullscreenOptions} - * @type {boolean|FullscreenOptions} - */ - fullscreen: true, - - /** - * Define the extra attributes to inherit from the original image. - * @type {Array} - */ - inheritedAttributes: [ - 'crossOrigin', - 'decoding', - 'isMap', - 'loading', - 'referrerPolicy', - 'sizes', - 'srcset', - 'useMap'], - - /** - * Define the initial index of image for viewing. - * @type {number} - */ - initialViewIndex: 0, - - /** - * Enable inline mode. - * @type {boolean} - */ - inline: false, - - /** - * The amount of time to delay between automatically cycling an image when playing. - * @type {number} - */ - interval: 5000, - - /** - * Enable keyboard support. - * @type {boolean} - */ - keyboard: true, - - /** - * Focus the viewer when initialized. - * @type {boolean} - */ - focus: true, - - /** - * Indicate if show a loading spinner when load image or not. - * @type {boolean} - */ - loading: true, - - /** - * Indicate if enable loop viewing or not. - * @type {boolean} - */ - loop: true, - - /** - * Min width of the viewer in inline mode. - * @type {number} - */ - minWidth: 200, - - /** - * Min height of the viewer in inline mode. - * @type {number} - */ - minHeight: 100, - - /** - * Enable to move the image. - * @type {boolean} - */ - movable: true, - - /** - * Enable to rotate the image. - * @type {boolean} - */ - rotatable: true, - - /** - * Enable to scale the image. - * @type {boolean} - */ - scalable: true, - - /** - * Enable to zoom the image. - * @type {boolean} - */ - zoomable: true, - - /** - * Enable to zoom the current image by dragging on the touch screen. - * @type {boolean} - */ - zoomOnTouch: true, - - /** - * Enable to zoom the image by wheeling mouse. - * @type {boolean} - */ - zoomOnWheel: true, - - /** - * Enable to slide to the next or previous image by swiping on the touch screen. - * @type {boolean} - */ - slideOnTouch: true, - - /** - * Indicate if toggle the image size between its natural size - * and initial size when double click on the image or not. - * @type {boolean} - */ - toggleOnDblclick: true, - - /** - * Show the tooltip with image ratio (percentage) when zoom in or zoom out. - * @type {boolean} - */ - tooltip: true, - - /** - * Enable CSS3 Transition for some special elements. - * @type {boolean} - */ - transition: true, - - /** - * Define the CSS `z-index` value of viewer in modal mode. - * @type {number} - */ - zIndex: 2015, - - /** - * Define the CSS `z-index` value of viewer in inline mode. - * @type {number} - */ - zIndexInline: 0, - - /** - * Define the ratio when zoom the image by wheeling mouse. - * @type {number} - */ - zoomRatio: 0.1, - - /** - * Define the min ratio of the image when zoom out. - * @type {number} - */ - minZoomRatio: 0.01, - - /** - * Define the max ratio of the image when zoom in. - * @type {number} - */ - maxZoomRatio: 100, - - /** - * Define where to get the original image URL for viewing. - * @type {string | Function} - */ - url: 'src', - - /** - * Event shortcuts. - * @type {Function} - */ - ready: null, - show: null, - shown: null, - hide: null, - hidden: null, - view: null, - viewed: null, - move: null, - moved: null, - rotate: null, - rotated: null, - scale: null, - scaled: null, - zoom: null, - zoomed: null, - play: null, - stop: null, - } - - var TEMPLATE = '
    ' + - '
    ' + '' + - '' + - '
    ' + - '
    ' + '
    ' - - var IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== - 'undefined' - var WINDOW = IS_BROWSER ? window : {} - var IS_TOUCH_DEVICE = IS_BROWSER && WINDOW.document.documentElement - ? 'ontouchstart' in WINDOW.document.documentElement - : false - var HAS_POINTER_EVENT = IS_BROWSER ? 'PointerEvent' in WINDOW : false - var NAMESPACE = 'viewer' // Actions - - var ACTION_MOVE = 'move' - var ACTION_SWITCH = 'switch' - var ACTION_ZOOM = 'zoom' // Classes - - var CLASS_ACTIVE = ''.concat(NAMESPACE, '-active') - var CLASS_CLOSE = ''.concat(NAMESPACE, '-close') - var CLASS_FADE = ''.concat(NAMESPACE, '-fade') - var CLASS_FIXED = ''.concat(NAMESPACE, '-fixed') - var CLASS_FULLSCREEN = ''.concat(NAMESPACE, '-fullscreen') - var CLASS_FULLSCREEN_EXIT = ''.concat(NAMESPACE, '-fullscreen-exit') - var CLASS_HIDE = ''.concat(NAMESPACE, '-hide') - var CLASS_HIDE_MD_DOWN = ''.concat(NAMESPACE, '-hide-md-down') - var CLASS_HIDE_SM_DOWN = ''.concat(NAMESPACE, '-hide-sm-down') - var CLASS_HIDE_XS_DOWN = ''.concat(NAMESPACE, '-hide-xs-down') - var CLASS_IN = ''.concat(NAMESPACE, '-in') - var CLASS_INVISIBLE = ''.concat(NAMESPACE, '-invisible') - var CLASS_LOADING = ''.concat(NAMESPACE, '-loading') - var CLASS_MOVE = ''.concat(NAMESPACE, '-move') - var CLASS_OPEN = ''.concat(NAMESPACE, '-open') - var CLASS_SHOW = ''.concat(NAMESPACE, '-show') - var CLASS_TRANSITION = ''.concat(NAMESPACE, '-transition') // Native events - - var EVENT_CLICK = 'click' - var EVENT_DBLCLICK = 'dblclick' - var EVENT_DRAG_START = 'dragstart' - var EVENT_FOCUSIN = 'focusin' - var EVENT_KEY_DOWN = 'keydown' - var EVENT_LOAD = 'load' - var EVENT_ERROR = 'error' - var EVENT_TOUCH_END = IS_TOUCH_DEVICE ? 'touchend touchcancel' : 'mouseup' - var EVENT_TOUCH_MOVE = IS_TOUCH_DEVICE ? 'touchmove' : 'mousemove' - var EVENT_TOUCH_START = IS_TOUCH_DEVICE ? 'touchstart' : 'mousedown' - var EVENT_POINTER_DOWN = HAS_POINTER_EVENT ? 'pointerdown' : EVENT_TOUCH_START - var EVENT_POINTER_MOVE = HAS_POINTER_EVENT ? 'pointermove' : EVENT_TOUCH_MOVE - var EVENT_POINTER_UP = HAS_POINTER_EVENT - ? 'pointerup pointercancel' - : EVENT_TOUCH_END - var EVENT_RESIZE = 'resize' - var EVENT_TRANSITION_END = 'transitionend' - var EVENT_WHEEL = 'wheel' // Custom events - - var EVENT_READY = 'ready' - var EVENT_SHOW = 'show' - var EVENT_SHOWN = 'shown' - var EVENT_HIDE = 'hide' - var EVENT_HIDDEN = 'hidden' - var EVENT_VIEW = 'view' - var EVENT_VIEWED = 'viewed' - var EVENT_MOVE = 'move' - var EVENT_MOVED = 'moved' - var EVENT_ROTATE = 'rotate' - var EVENT_ROTATED = 'rotated' - var EVENT_SCALE = 'scale' - var EVENT_SCALED = 'scaled' - var EVENT_ZOOM = 'zoom' - var EVENT_ZOOMED = 'zoomed' - var EVENT_PLAY = 'play' - var EVENT_STOP = 'stop' // Data keys - - var DATA_ACTION = ''.concat(NAMESPACE, 'Action') // RegExps - - var REGEXP_SPACES = /\s\s*/ // Misc - - var BUTTONS = [ - 'zoom-in', - 'zoom-out', - 'one-to-one', - 'reset', - 'prev', - 'play', - 'next', - 'rotate-left', - 'rotate-right', - 'flip-horizontal', - 'flip-vertical'] - - /** - * Check if the given value is a string. - * @param {*} value - The value to check. - * @returns {boolean} Returns `true` if the given value is a string, else `false`. - */ - - function isString (value) { - return typeof value === 'string' - } - - /** - * Check if the given value is not a number. - */ - - var isNaN = Number.isNaN || WINDOW.isNaN - - /** - * Check if the given value is a number. - * @param {*} value - The value to check. - * @returns {boolean} Returns `true` if the given value is a number, else `false`. - */ - - function isNumber (value) { - return typeof value === 'number' && !isNaN(value) - } - - /** - * Check if the given value is undefined. - * @param {*} value - The value to check. - * @returns {boolean} Returns `true` if the given value is undefined, else `false`. - */ - - function isUndefined (value) { - return typeof value === 'undefined' - } - - /** - * Check if the given value is an object. - * @param {*} value - The value to check. - * @returns {boolean} Returns `true` if the given value is an object, else `false`. - */ - - function isObject (value) { - return _typeof(value) === 'object' && value !== null - } - - var hasOwnProperty = Object.prototype.hasOwnProperty - - /** - * Check if the given value is a plain object. - * @param {*} value - The value to check. - * @returns {boolean} Returns `true` if the given value is a plain object, else `false`. - */ - - function isPlainObject (value) { - if (!isObject(value)) { - return false - } - - try { - var _constructor = value.constructor - var prototype = _constructor.prototype - return _constructor && prototype && - hasOwnProperty.call(prototype, 'isPrototypeOf') - } catch (error) { - return false - } - } - - /** - * Check if the given value is a function. - * @param {*} value - The value to check. - * @returns {boolean} Returns `true` if the given value is a function, else `false`. - */ - - function isFunction (value) { - return typeof value === 'function' - } - - /** - * Iterate the given data. - * @param {*} data - The data to iterate. - * @param {Function} callback - The process function for each element. - * @returns {*} The original data. - */ - - function forEach (data, callback) { - if (data && isFunction(callback)) { - if (Array.isArray(data) || isNumber(data.length) - /* array-like */) { - var length = data.length - var i - - for (i = 0; i < length; i += 1) { - if (callback.call(data, data[i], i, data) === false) { - break - } - } - } else if (isObject(data)) { - Object.keys(data).forEach(function (key) { - callback.call(data, data[key], key, data) - }) - } - } - - return data - } - - /** - * Extend the given object. - * @param {*} obj - The object to be extended. - * @param {*} args - The rest objects which will be merged to the first object. - * @returns {Object} The extended object. - */ - - var assign = Object.assign || function assign (obj) { - for (var _len = arguments.length, args = new Array( - _len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key] - } - - if (isObject(obj) && args.length > 0) { - args.forEach(function (arg) { - if (isObject(arg)) { - Object.keys(arg).forEach(function (key) { - obj[key] = arg[key] - }) - } - }) - } - - return obj - } - var REGEXP_SUFFIX = /^(?:width|height|left|top|marginLeft|marginTop)$/ - - /** - * Apply styles to the given element. - * @param {Element} element - The target element. - * @param {Object} styles - The styles for applying. - */ - - function setStyle (element, styles) { - var style = element.style - forEach(styles, function (value, property) { - if (REGEXP_SUFFIX.test(property) && isNumber(value)) { - value += 'px' - } - - style[property] = value - }) - } - - /** - * Escape a string for using in HTML. - * @param {String} value - The string to escape. - * @returns {String} Returns the escaped string. - */ - - function escapeHTMLEntities (value) { - return isString(value) ? value.replace(/&(?!amp;|quot;|#39;|lt;|gt;)/g, - '&'). - replace(/"/g, '"'). - replace(/'/g, '''). - replace(//g, '>') : value - } - - /** - * Check if the given element has a special class. - * @param {Element} element - The element to check. - * @param {string} value - The class to search. - * @returns {boolean} Returns `true` if the special class was found. - */ - - function hasClass (element, value) { - if (!element || !value) { - return false - } - - return element.classList - ? element.classList.contains(value) - : element.className.indexOf(value) > -1 - } - - /** - * Add classes to the given element. - * @param {Element} element - The target element. - * @param {string} value - The classes to be added. - */ - - function addClass (element, value) { - if (!element || !value) { - return - } - - if (isNumber(element.length)) { - forEach(element, function (elem) { - addClass(elem, value) - }) - return - } - - if (element.classList) { - element.classList.add(value) - return - } - - var className = element.className.trim() - - if (!className) { - element.className = value - } else if (className.indexOf(value) < 0) { - element.className = ''.concat(className, ' ').concat(value) - } - } - - /** - * Remove classes from the given element. - * @param {Element} element - The target element. - * @param {string} value - The classes to be removed. - */ - - function removeClass (element, value) { - if (!element || !value) { - return - } - - if (isNumber(element.length)) { - forEach(element, function (elem) { - removeClass(elem, value) - }) - return - } - - if (element.classList) { - element.classList.remove(value) - return - } - - if (element.className.indexOf(value) >= 0) { - element.className = element.className.replace(value, '') - } - } - - /** - * Add or remove classes from the given element. - * @param {Element} element - The target element. - * @param {string} value - The classes to be toggled. - * @param {boolean} added - Add only. - */ - - function toggleClass (element, value, added) { - if (!value) { - return - } - - if (isNumber(element.length)) { - forEach(element, function (elem) { - toggleClass(elem, value, added) - }) - return - } // IE10-11 doesn't support the second parameter of `classList.toggle` - - if (added) { - addClass(element, value) - } else { - removeClass(element, value) - } - } - - var REGEXP_HYPHENATE = /([a-z\d])([A-Z])/g - - /** - * Transform the given string from camelCase to kebab-case - * @param {string} value - The value to transform. - * @returns {string} The transformed value. - */ - - function hyphenate (value) { - return value.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase() - } - - /** - * Get data from the given element. - * @param {Element} element - The target element. - * @param {string} name - The data key to get. - * @returns {string} The data value. - */ - - function getData (element, name) { - if (isObject(element[name])) { - return element[name] - } - - if (element.dataset) { - return element.dataset[name] - } - - return element.getAttribute('data-'.concat(hyphenate(name))) - } - - /** - * Set data to the given element. - * @param {Element} element - The target element. - * @param {string} name - The data key to set. - * @param {string} data - The data value. - */ - - function setData (element, name, data) { - if (isObject(data)) { - element[name] = data - } else if (element.dataset) { - element.dataset[name] = data - } else { - element.setAttribute('data-'.concat(hyphenate(name)), data) - } - } - - var onceSupported = function () { - var supported = false - - if (IS_BROWSER) { - var once = false - - var listener = function listener () {} - - var options = Object.defineProperty({}, 'once', { - get: function get () { - supported = true - return once - }, - - /** - * This setter can fix a `TypeError` in strict mode - * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only} - * @param {boolean} value - The value to set - */ - set: function set (value) { - once = value - }, - }) - WINDOW.addEventListener('test', listener, options) - WINDOW.removeEventListener('test', listener, options) - } - - return supported - }() - - /** - * Remove event listener from the target element. - * @param {Element} element - The event target. - * @param {string} type - The event type(s). - * @param {Function} listener - The event listener. - * @param {Object} options - The event options. - */ - - - function removeListener (element, type, listener) { - var options = arguments.length > 3 && arguments[3] !== undefined - ? arguments[3] - : {} - var handler = listener - type.trim().split(REGEXP_SPACES).forEach(function (event) { - if (!onceSupported) { - var listeners = element.listeners - - if (listeners && listeners[event] && listeners[event][listener]) { - handler = listeners[event][listener] - delete listeners[event][listener] - - if (Object.keys(listeners[event]).length === 0) { - delete listeners[event] - } - - if (Object.keys(listeners).length === 0) { - delete element.listeners - } - } - } - - element.removeEventListener(event, handler, options) - }) - } - - /** - * Add event listener to the target element. - * @param {Element} element - The event target. - * @param {string} type - The event type(s). - * @param {Function} listener - The event listener. - * @param {Object} options - The event options. - */ - - function addListener (element, type, listener) { - var options = arguments.length > 3 && arguments[3] !== undefined - ? arguments[3] - : {} - var _handler = listener - type.trim().split(REGEXP_SPACES).forEach(function (event) { - if (options.once && !onceSupported) { - var _element$listeners = element.listeners, - listeners = _element$listeners === void 0 ? {} : _element$listeners - - _handler = function handler () { - delete listeners[event][listener] - element.removeEventListener(event, _handler, options) - - for (var _len2 = arguments.length, args = new Array( - _len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2] - } - - listener.apply(element, args) - } - - if (!listeners[event]) { - listeners[event] = {} - } - - if (listeners[event][listener]) { - element.removeEventListener(event, listeners[event][listener], - options) - } - - listeners[event][listener] = _handler - element.listeners = listeners - } - - element.addEventListener(event, _handler, options) - }) - } - - /** - * Dispatch event on the target element. - * @param {Element} element - The event target. - * @param {string} type - The event type(s). - * @param {Object} data - The additional event data. - * @param {Object} options - The additional event options. - * @returns {boolean} Indicate if the event is default prevented or not. - */ - - function dispatchEvent (element, type, data, options) { - var event // Event and CustomEvent on IE9-11 are global objects, not constructors - - if (isFunction(Event) && isFunction(CustomEvent)) { - event = new CustomEvent(type, _objectSpread2({ - bubbles: true, cancelable: true, detail: data, - }, options)) - } else { - event = document.createEvent('CustomEvent') - event.initCustomEvent(type, true, true, data) - } - - return element.dispatchEvent(event) - } - - /** - * Get the offset base on the document. - * @param {Element} element - The target element. - * @returns {Object} The offset data. - */ - - function getOffset (element) { - var box = element.getBoundingClientRect() - return { - left: box.left + - (window.pageXOffset - document.documentElement.clientLeft), - top: box.top + (window.pageYOffset - document.documentElement.clientTop), - } - } - - /** - * Get transforms base on the given object. - * @param {Object} obj - The target object. - * @returns {string} A string contains transform values. - */ - - function getTransforms (_ref) { - var rotate = _ref.rotate, scaleX = _ref.scaleX, scaleY = _ref.scaleY, - translateX = _ref.translateX, translateY = _ref.translateY - var values = [] - - if (isNumber(translateX) && translateX !== 0) { - values.push('translateX('.concat(translateX, 'px)')) - } - - if (isNumber(translateY) && translateY !== 0) { - values.push('translateY('.concat(translateY, 'px)')) - } // Rotate should come first before scale to match orientation transform - - if (isNumber(rotate) && rotate !== 0) { - values.push('rotate('.concat(rotate, 'deg)')) - } - - if (isNumber(scaleX) && scaleX !== 1) { - values.push('scaleX('.concat(scaleX, ')')) - } - - if (isNumber(scaleY) && scaleY !== 1) { - values.push('scaleY('.concat(scaleY, ')')) - } - - var transform = values.length ? values.join(' ') : 'none' - return { - WebkitTransform: transform, msTransform: transform, transform: transform, - } - } - - /** - * Get an image name from an image url. - * @param {string} url - The target url. - * @example - * // picture.jpg - * getImageNameFromURL('https://domain.com/path/to/picture.jpg?size=1280×960') - * @returns {string} A string contains the image name. - */ - - function getImageNameFromURL (url) { - return isString(url) ? decodeURIComponent( - url.replace(/^.*\//, '').replace(/[?&#].*$/, '')) : '' - } - - var IS_SAFARI = WINDOW.navigator && - /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i.test( - WINDOW.navigator.userAgent) - - /** - * Get an image's natural sizes. - * @param {string} image - The target image. - * @param {Object} options - The viewer options. - * @param {Function} callback - The callback function. - * @returns {HTMLImageElement} The new image. - */ - - function getImageNaturalSizes (image, options, callback) { - var newImage = document.createElement('img') // Modern browsers (except Safari) - - if (image.naturalWidth && !IS_SAFARI) { - callback(image.naturalWidth, image.naturalHeight) - return newImage - } - - var body = document.body || document.documentElement - - newImage.onload = function () { - callback(newImage.width, newImage.height) - - if (!IS_SAFARI) { - body.removeChild(newImage) - } - } - - forEach(options.inheritedAttributes, function (name) { - var value = image.getAttribute(name) - - if (value !== null) { - newImage.setAttribute(name, value) - } - }) - newImage.src = image.src // iOS Safari will convert the image automatically - // with its orientation once append it into DOM - - if (!IS_SAFARI) { - newImage.style.cssText = 'left:0;' + 'max-height:none!important;' + - 'max-width:none!important;' + 'min-height:0!important;' + - 'min-width:0!important;' + 'opacity:0;' + 'position:absolute;' + - 'top:0;' + 'z-index:-1;' - body.appendChild(newImage) - } - - return newImage - } - - /** - * Get the related class name of a responsive type number. - * @param {string} type - The responsive type. - * @returns {string} The related class name. - */ - - function getResponsiveClass (type) { - switch (type) { - case 2: - return CLASS_HIDE_XS_DOWN - - case 3: - return CLASS_HIDE_SM_DOWN - - case 4: - return CLASS_HIDE_MD_DOWN - - default: - return '' - } - } - - /** - * Get the max ratio of a group of pointers. - * @param {string} pointers - The target pointers. - * @returns {number} The result ratio. - */ - - function getMaxZoomRatio (pointers) { - var pointers2 = _objectSpread2({}, pointers) - - var ratios = [] - forEach(pointers, function (pointer, pointerId) { - delete pointers2[pointerId] - forEach(pointers2, function (pointer2) { - var x1 = Math.abs(pointer.startX - pointer2.startX) - var y1 = Math.abs(pointer.startY - pointer2.startY) - var x2 = Math.abs(pointer.endX - pointer2.endX) - var y2 = Math.abs(pointer.endY - pointer2.endY) - var z1 = Math.sqrt(x1 * x1 + y1 * y1) - var z2 = Math.sqrt(x2 * x2 + y2 * y2) - var ratio = (z2 - z1) / z1 - ratios.push(ratio) - }) - }) - ratios.sort(function (a, b) { - return Math.abs(a) < Math.abs(b) - }) - return ratios[0] - } - - /** - * Get a pointer from an event object. - * @param {Object} event - The target event object. - * @param {boolean} endOnly - Indicates if only returns the end point coordinate or not. - * @returns {Object} The result pointer contains start and/or end point coordinates. - */ - - function getPointer (_ref2, endOnly) { - var pageX = _ref2.pageX, pageY = _ref2.pageY - var end = { - endX: pageX, endY: pageY, - } - return endOnly ? end : _objectSpread2({ - timeStamp: Date.now(), startX: pageX, startY: pageY, - }, end) - } - - /** - * Get the center point coordinate of a group of pointers. - * @param {Object} pointers - The target pointers. - * @returns {Object} The center point coordinate. - */ - - function getPointersCenter (pointers) { - var pageX = 0 - var pageY = 0 - var count = 0 - forEach(pointers, function (_ref3) { - var startX = _ref3.startX, startY = _ref3.startY - pageX += startX - pageY += startY - count += 1 - }) - pageX /= count - pageY /= count - return { - pageX: pageX, pageY: pageY, - } - } - - var render = { - render: function render () { - this.initContainer() - this.initViewer() - this.initList() - this.renderViewer() - }, initBody: function initBody () { - var ownerDocument = this.element.ownerDocument - var body = ownerDocument.body || ownerDocument.documentElement - this.body = body - this.scrollbarWidth = window.innerWidth - - ownerDocument.documentElement.clientWidth - this.initialBodyPaddingRight = body.style.paddingRight - this.initialBodyComputedPaddingRight = window.getComputedStyle( - body).paddingRight - }, initContainer: function initContainer () { - this.containerData = { - width: window.innerWidth, height: window.innerHeight, - } - }, initViewer: function initViewer () { - var options = this.options, parent = this.parent - var viewerData - - if (options.inline) { - viewerData = { - width: Math.max(parent.offsetWidth, options.minWidth), - height: Math.max(parent.offsetHeight, options.minHeight), - } - this.parentData = viewerData - } - - if (this.fulled || !viewerData) { - viewerData = this.containerData - } - - this.viewerData = assign({}, viewerData) - }, renderViewer: function renderViewer () { - if (this.options.inline && !this.fulled) { - setStyle(this.viewer, this.viewerData) - } - }, initList: function initList () { - var _this = this - - var element = this.element, options = this.options, list = this.list - var items = [] // initList may be called in this.update, so should keep idempotent - - list.innerHTML = '' - forEach(this.images, function (image, index) { - var src = image.src - var alt = image.alt || getImageNameFromURL(src) - - var url = _this.getImageURL(image) - - if (src || url) { - var item = document.createElement('li') - var img = document.createElement('img') - forEach(options.inheritedAttributes, function (name) { - var value = image.getAttribute(name) - - if (value !== null) { - img.setAttribute(name, value) - } - }) - img.src = src || url - img.alt = alt - img.setAttribute('data-original-url', url || src) - item.setAttribute('data-index', index) - item.setAttribute('data-viewer-action', 'view') - item.setAttribute('role', 'button') - - if (options.keyboard) { - item.setAttribute('tabindex', 0) - } - - item.appendChild(img) - list.appendChild(item) - items.push(item) - } - }) - this.items = items - forEach(items, function (item) { - var image = item.firstElementChild - var onLoad - var onError - setData(image, 'filled', true) - - if (options.loading) { - addClass(item, CLASS_LOADING) - } - - addListener(image, EVENT_LOAD, onLoad = function onLoad (event) { - removeListener(image, EVENT_ERROR, onError) - - if (options.loading) { - removeClass(item, CLASS_LOADING) - } - - _this.loadImage(event) - }, { - once: true, - }) - addListener(image, EVENT_ERROR, onError = function onError () { - removeListener(image, EVENT_LOAD, onLoad) - - if (options.loading) { - removeClass(item, CLASS_LOADING) - } - }, { - once: true, - }) - }) - - if (options.transition) { - addListener(element, EVENT_VIEWED, function () { - addClass(list, CLASS_TRANSITION) - }, { - once: true, - }) - } - }, renderList: function renderList () { - var index = this.index - var item = this.items[index] - - if (!item) { - return - } - - var next = item.nextElementSibling - var gutter = parseInt(window.getComputedStyle(next || item).marginLeft, - 10) - var offsetWidth = item.offsetWidth - var outerWidth = offsetWidth + gutter // Place the active item in the center of the screen - - setStyle(this.list, assign({ - width: outerWidth * this.length - gutter, - }, getTransforms({ - translateX: (this.viewerData.width - offsetWidth) / 2 - outerWidth * - index, - }))) - }, resetList: function resetList () { - var list = this.list - list.innerHTML = '' - removeClass(list, CLASS_TRANSITION) - setStyle(list, getTransforms({ - translateX: 0, - })) - }, initImage: function initImage (done) { - var _this2 = this - - var options = this.options, image = this.image, - viewerData = this.viewerData - var footerHeight = this.footer.offsetHeight - var viewerWidth = viewerData.width - var viewerHeight = Math.max(viewerData.height - footerHeight, - footerHeight) - var oldImageData = this.imageData || {} - var sizingImage - this.imageInitializing = { - abort: function abort () { - sizingImage.onload = null - }, - } - sizingImage = getImageNaturalSizes(image, options, - function (naturalWidth, naturalHeight) { - var aspectRatio = naturalWidth / naturalHeight - var width = viewerWidth - var height = viewerHeight - _this2.imageInitializing = false - - if (viewerHeight * aspectRatio > viewerWidth) { - height = viewerWidth / aspectRatio - } else { - width = viewerHeight * aspectRatio - } - - width = Math.min(width * 0.9, naturalWidth) - height = Math.min(height * 0.9, naturalHeight) - var left = (viewerWidth - width) / 2 - var top = (viewerHeight - height) / 2 - var imageData = { - left: left, - top: top, - x: left, - y: top, - width: width, - height: height, - oldRatio: 1, - ratio: width / naturalWidth, - aspectRatio: aspectRatio, - naturalWidth: naturalWidth, - naturalHeight: naturalHeight, - } - var initialImageData = assign({}, imageData) - - if (options.rotatable) { - imageData.rotate = oldImageData.rotate || 0 - initialImageData.rotate = 0 - } - - if (options.scalable) { - imageData.scaleX = oldImageData.scaleX || 1 - imageData.scaleY = oldImageData.scaleY || 1 - initialImageData.scaleX = 1 - initialImageData.scaleY = 1 - } - - _this2.imageData = imageData - _this2.initialImageData = initialImageData - - if (done) { - done() - } - }) - }, renderImage: function renderImage (done) { - var _this3 = this - - var image = this.image, imageData = this.imageData - setStyle(image, assign({ - width: imageData.width, - height: imageData.height, // XXX: Not to use translateX/Y to avoid image shaking when zooming - marginLeft: imageData.x, - marginTop: imageData.y, - }, getTransforms(imageData))) - - if (done) { - if ((this.viewing || this.moving || this.rotating || this.scaling || - this.zooming) && this.options.transition && - hasClass(image, CLASS_TRANSITION)) { - var onTransitionEnd = function onTransitionEnd () { - _this3.imageRendering = false - done() - } - - this.imageRendering = { - abort: function abort () { - removeListener(image, EVENT_TRANSITION_END, onTransitionEnd) - }, - } - addListener(image, EVENT_TRANSITION_END, onTransitionEnd, { - once: true, - }) - } else { - done() - } - } - }, resetImage: function resetImage () { - // this.image only defined after viewed - if (this.viewing || this.viewed) { - var image = this.image - - if (this.viewing) { - this.viewing.abort() - } - - image.parentNode.removeChild(image) - this.image = null - } - }, - } - - var events = { - bind: function bind () { - var options = this.options, viewer = this.viewer, canvas = this.canvas - var document = this.element.ownerDocument - addListener(viewer, EVENT_CLICK, this.onClick = this.click.bind(this)) - addListener(viewer, EVENT_DRAG_START, - this.onDragStart = this.dragstart.bind(this)) - addListener(canvas, EVENT_POINTER_DOWN, - this.onPointerDown = this.pointerdown.bind(this)) - addListener(document, EVENT_POINTER_MOVE, - this.onPointerMove = this.pointermove.bind(this)) - addListener(document, EVENT_POINTER_UP, - this.onPointerUp = this.pointerup.bind(this)) - addListener(document, EVENT_KEY_DOWN, - this.onKeyDown = this.keydown.bind(this)) - addListener(window, EVENT_RESIZE, this.onResize = this.resize.bind(this)) - - if (options.zoomable && options.zoomOnWheel) { - addListener(viewer, EVENT_WHEEL, this.onWheel = this.wheel.bind(this), { - passive: false, capture: true, - }) - } - - if (options.toggleOnDblclick) { - addListener(canvas, EVENT_DBLCLICK, - this.onDblclick = this.dblclick.bind(this)) - } - }, unbind: function unbind () { - var options = this.options, viewer = this.viewer, canvas = this.canvas - var document = this.element.ownerDocument - removeListener(viewer, EVENT_CLICK, this.onClick) - removeListener(viewer, EVENT_DRAG_START, this.onDragStart) - removeListener(canvas, EVENT_POINTER_DOWN, this.onPointerDown) - removeListener(document, EVENT_POINTER_MOVE, this.onPointerMove) - removeListener(document, EVENT_POINTER_UP, this.onPointerUp) - removeListener(document, EVENT_KEY_DOWN, this.onKeyDown) - removeListener(window, EVENT_RESIZE, this.onResize) - - if (options.zoomable && options.zoomOnWheel) { - removeListener(viewer, EVENT_WHEEL, this.onWheel, { - passive: false, capture: true, - }) - } - - if (options.toggleOnDblclick) { - removeListener(canvas, EVENT_DBLCLICK, this.onDblclick) - } - }, - } - - var handlers = { - click: function click (event) { - var options = this.options, imageData = this.imageData - var target = event.target - var action = getData(target, DATA_ACTION) - - // NOTE: updated by Vanessa - if (!action && - (target.localName === 'svg' || target.localName === 'use')) { - target = target.localName === 'use' - ? target.parentElement.parentElement - : target.parentElement - action = getData(target, DATA_ACTION) - } - - if (!action && target.localName === 'img' && - target.parentElement.localName === 'li') { - target = target.parentElement - action = getData(target, DATA_ACTION) - } // Cancel the emulated click when the native click event was triggered. - - if (IS_TOUCH_DEVICE && event.isTrusted && target === this.canvas) { - clearTimeout(this.clickCanvasTimeout) - } - - switch (action) { - case 'mix': - if (this.played) { - this.stop() - } else if (options.inline) { - if (this.fulled) { - this.exit() - } else { - this.full() - } - } else { - this.hide() - } - - break - - case 'hide': - this.hide() - break - - case 'view': - this.view(getData(target, 'index')) - break - - case 'zoom-in': - this.zoom(0.1, true) - break - - case 'zoom-out': - this.zoom(-0.1, true) - break - - case 'one-to-one': - this.toggle() - break - - case 'reset': - this.reset() - break - - case 'prev': - this.prev(options.loop) - break - - case 'play': - this.play(options.fullscreen) - break - - case 'next': - this.next(options.loop) - break - - case 'rotate-left': - this.rotate(-90) - break - - case 'rotate-right': - this.rotate(90) - break - - case 'flip-horizontal': - this.scaleX(-imageData.scaleX || -1) - break - - case 'flip-vertical': - this.scaleY(-imageData.scaleY || -1) - break - - default: - if (this.played) { - this.stop() - } - - } - }, dblclick: function dblclick (event) { - event.preventDefault() - - if (this.viewed && event.target === this.image) { - // Cancel the emulated double click when the native dblclick event was triggered. - if (IS_TOUCH_DEVICE && event.isTrusted) { - clearTimeout(this.doubleClickImageTimeout) - } // XXX: No pageX/Y properties in custom event, fallback to the original event. - - this.toggle( - event.isTrusted ? event : event.detail && event.detail.originalEvent) - } - }, load: function load () { - var _this = this - - if (this.timeout) { - clearTimeout(this.timeout) - this.timeout = false - } - - var element = this.element, options = this.options, image = this.image, - index = this.index, viewerData = this.viewerData - removeClass(image, CLASS_INVISIBLE) - - if (options.loading) { - removeClass(this.canvas, CLASS_LOADING) - } - - image.style.cssText = 'height:0;' + - 'margin-left:'.concat(viewerData.width / 2, 'px;') + - 'margin-top:'.concat(viewerData.height / 2, 'px;') + - 'max-width:none!important;' + 'position:relative;' + 'width:0;' - this.initImage(function () { - toggleClass(image, CLASS_MOVE, options.movable) - toggleClass(image, CLASS_TRANSITION, options.transition) - - _this.renderImage(function () { - _this.viewed = true - _this.viewing = false - - if (isFunction(options.viewed)) { - addListener(element, EVENT_VIEWED, options.viewed, { - once: true, - }) - } - - dispatchEvent(element, EVENT_VIEWED, { - originalImage: _this.images[index], index: index, image: image, - }, { - cancelable: false, - }) - }) - }) - }, loadImage: function loadImage (event) { - var image = event.target - var parent = image.parentNode - var parentWidth = parent.offsetWidth || 30 - var parentHeight = parent.offsetHeight || 50 - var filled = !!getData(image, 'filled') - getImageNaturalSizes(image, this.options, - function (naturalWidth, naturalHeight) { - var aspectRatio = naturalWidth / naturalHeight - var width = parentWidth - var height = parentHeight - - if (parentHeight * aspectRatio > parentWidth) { - if (filled) { - width = parentHeight * aspectRatio - } else { - height = parentWidth / aspectRatio - } - } else if (filled) { - height = parentWidth / aspectRatio - } else { - width = parentHeight * aspectRatio - } - - setStyle(image, assign({ - width: width, height: height, - }, getTransforms({ - translateX: (parentWidth - width) / 2, - translateY: (parentHeight - height) / 2, - }))) - }) - }, keydown: function keydown (event) { - var options = this.options - - if (!options.keyboard) { - return - } - - var keyCode = event.keyCode || event.which || event.charCode - - switch (keyCode) { - // Enter - case 13: - if (this.viewer.contains(event.target)) { - this.click(event) - } - - break - } - - if (!this.fulled) { - return - } - - switch (keyCode) { - // Escape - case 27: - if (this.played) { - this.stop() - } else if (options.inline) { - if (this.fulled) { - this.exit() - } - } else { - this.hide() - } - - break - // Space - - case 32: - if (this.played) { - this.stop() - } - - break - // ArrowLeft - - case 37: - this.prev(options.loop) - break - // ArrowUp - - case 38: - // Prevent scroll on Firefox - event.preventDefault() // Zoom in - - this.zoom(options.zoomRatio, true) - break - // ArrowRight - - case 39: - this.next(options.loop) - break - // ArrowDown - - case 40: - // Prevent scroll on Firefox - event.preventDefault() // Zoom out - - this.zoom(-options.zoomRatio, true) - break - // Ctrl + 0 - - case 48: // Fall through - // Ctrl + 1 - // eslint-disable-next-line no-fallthrough - - case 49: - if (event.ctrlKey) { - event.preventDefault() - this.toggle() - } - - break - } - }, dragstart: function dragstart (event) { - if (event.target.localName === 'img') { - event.preventDefault() - } - }, pointerdown: function pointerdown (event) { - var options = this.options, pointers = this.pointers - var buttons = event.buttons, button = event.button - - if (!this.viewed || this.showing || this.viewing || this.hiding // Handle mouse event and pointer event and ignore touch event - || (event.type === 'mousedown' || event.type === 'pointerdown' && - event.pointerType === 'mouse') && ( // No primary button (Usually the left button) - isNumber(buttons) && buttons !== 1 || isNumber(button) && button !== 0 // Open context menu - || event.ctrlKey)) { - return - } // Prevent default behaviours as page zooming in touch devices. - - event.preventDefault() - - if (event.changedTouches) { - forEach(event.changedTouches, function (touch) { - pointers[touch.identifier] = getPointer(touch) - }) - } else { - pointers[event.pointerId || 0] = getPointer(event) - } - - var action = options.movable ? ACTION_MOVE : false - - if (options.zoomOnTouch && options.zoomable && - Object.keys(pointers).length > 1) { - action = ACTION_ZOOM - } else if (options.slideOnTouch && - (event.pointerType === 'touch' || event.type === 'touchstart') && - this.isSwitchable()) { - action = ACTION_SWITCH - } - - if (options.transition && - (action === ACTION_MOVE || action === ACTION_ZOOM)) { - removeClass(this.image, CLASS_TRANSITION) - } - - this.action = action - }, pointermove: function pointermove (event) { - var pointers = this.pointers, action = this.action - - if (!this.viewed || !action) { - return - } - - event.preventDefault() - - if (event.changedTouches) { - forEach(event.changedTouches, function (touch) { - assign(pointers[touch.identifier] || {}, getPointer(touch, true)) - }) - } else { - assign(pointers[event.pointerId || 0] || {}, getPointer(event, true)) - } - - this.change(event) - }, pointerup: function pointerup (event) { - var _this2 = this - - var options = this.options, action = this.action, pointers = this.pointers - var pointer - - if (event.changedTouches) { - forEach(event.changedTouches, function (touch) { - pointer = pointers[touch.identifier] - delete pointers[touch.identifier] - }) - } else { - pointer = pointers[event.pointerId || 0] - delete pointers[event.pointerId || 0] - } - - if (!action) { - return - } - - event.preventDefault() - - if (options.transition && - (action === ACTION_MOVE || action === ACTION_ZOOM)) { - addClass(this.image, CLASS_TRANSITION) - } - - this.action = false // Emulate click and double click in touch devices to support backdrop and image zooming (#210). - - if (IS_TOUCH_DEVICE && action !== ACTION_ZOOM && pointer && Date.now() - - pointer.timeStamp < 500) { - clearTimeout(this.clickCanvasTimeout) - clearTimeout(this.doubleClickImageTimeout) - - if (options.toggleOnDblclick && this.viewed && event.target === - this.image) { - if (this.imageClicked) { - this.imageClicked = false // This timeout will be cleared later when a native dblclick event is triggering - - this.doubleClickImageTimeout = setTimeout(function () { - dispatchEvent(_this2.image, EVENT_DBLCLICK, { - originalEvent: event, - }) - }, 50) - } else { - this.imageClicked = true // The default timing of a double click in Windows is 500 ms - - this.doubleClickImageTimeout = setTimeout(function () { - _this2.imageClicked = false - }, 500) - } - } else { - this.imageClicked = false - - if (options.backdrop && options.backdrop !== 'static' && - event.target === this.canvas) { - // This timeout will be cleared later when a native click event is triggering - this.clickCanvasTimeout = setTimeout(function () { - dispatchEvent(_this2.canvas, EVENT_CLICK, { - originalEvent: event, - }) - }, 50) - } - } - } - }, resize: function resize () { - var _this3 = this - - if (!this.isShown || this.hiding) { - return - } - - if (this.fulled) { - this.close() - this.initBody() - this.open() - } - - this.initContainer() - this.initViewer() - this.renderViewer() - this.renderList() - - if (this.viewed) { - this.initImage(function () { - _this3.renderImage() - }) - } - - if (this.played) { - if (this.options.fullscreen && this.fulled && - !(document.fullscreenElement || document.webkitFullscreenElement || - document.mozFullScreenElement || document.msFullscreenElement)) { - this.stop() - return - } - - forEach(this.player.getElementsByTagName('img'), function (image) { - addListener(image, EVENT_LOAD, _this3.loadImage.bind(_this3), { - once: true, - }) - dispatchEvent(image, EVENT_LOAD) - }) - } - }, wheel: function wheel (event) { - var _this4 = this - - if (!this.viewed) { - return - } - - event.preventDefault() // Limit wheel speed to prevent zoom too fast - - if (this.wheeling) { - return - } - - this.wheeling = true - setTimeout(function () { - _this4.wheeling = false - }, 50) - var ratio = Number(this.options.zoomRatio) || 0.1 - var delta = 1 - - if (event.deltaY) { - delta = event.deltaY > 0 ? 1 : -1 - } else if (event.wheelDelta) { - delta = -event.wheelDelta / 120 - } else if (event.detail) { - delta = event.detail > 0 ? 1 : -1 - } - - this.zoom(-delta * ratio, true, event) - }, - } - - var methods = { - /** Show the viewer (only available in modal mode) - * @param {boolean} [immediate=false] - Indicates if show the viewer immediately or not. - * @returns {Viewer} this - */ - show: function show () { - var immediate = arguments.length > 0 && arguments[0] !== undefined - ? arguments[0] - : false - var element = this.element, options = this.options - - if (options.inline || this.showing || this.isShown || this.showing) { - return this - } - - if (!this.ready) { - this.build() - - if (this.ready) { - this.show(immediate) - } - - return this - } - - if (isFunction(options.show)) { - addListener(element, EVENT_SHOW, options.show, { - once: true, - }) - } - - if (dispatchEvent(element, EVENT_SHOW) === false || !this.ready) { - return this - } - - if (this.hiding) { - this.transitioning.abort() - } - - this.showing = true - this.open() - var viewer = this.viewer - removeClass(viewer, CLASS_HIDE) - viewer.setAttribute('role', 'dialog') - viewer.setAttribute('aria-labelledby', this.title.id) - viewer.setAttribute('aria-modal', true) - viewer.removeAttribute('aria-hidden') - - if (options.transition && !immediate) { - var shown = this.shown.bind(this) - this.transitioning = { - abort: function abort () { - removeListener(viewer, EVENT_TRANSITION_END, shown) - removeClass(viewer, CLASS_IN) - }, - } - addClass(viewer, CLASS_TRANSITION) // Force reflow to enable CSS3 transition - - viewer.initialOffsetWidth = viewer.offsetWidth - addListener(viewer, EVENT_TRANSITION_END, shown, { - once: true, - }) - addClass(viewer, CLASS_IN) - } else { - addClass(viewer, CLASS_IN) - this.shown() - } - - return this - }, - - /** - * Hide the viewer (only available in modal mode) - * @param {boolean} [immediate=false] - Indicates if hide the viewer immediately or not. - * @returns {Viewer} this - */ - hide: function hide () { - var _this = this - - var immediate = arguments.length > 0 && arguments[0] !== undefined - ? arguments[0] - : false - var element = this.element, options = this.options - - if (options.inline || this.hiding || !(this.isShown || this.showing)) { - return this - } - - if (isFunction(options.hide)) { - addListener(element, EVENT_HIDE, options.hide, { - once: true, - }) - } - - if (dispatchEvent(element, EVENT_HIDE) === false) { - return this - } - - if (this.showing) { - this.transitioning.abort() - } - - this.hiding = true - - if (this.played) { - this.stop() - } else if (this.viewing) { - this.viewing.abort() - } - - var viewer = this.viewer, image = this.image - - var hideImmediately = function hideImmediately () { - removeClass(viewer, CLASS_IN) - - _this.hidden() - } - - if (options.transition && !immediate) { - var onViewerTransitionEnd = function onViewerTransitionEnd (event) { - // Ignore all propagating `transitionend` events (#275). - if (event && event.target === viewer) { - removeListener(viewer, EVENT_TRANSITION_END, onViewerTransitionEnd) - - _this.hidden() - } - } - - var onImageTransitionEnd = function onImageTransitionEnd () { - // In case of show the viewer by `viewer.show(true)` previously (#407). - if (hasClass(viewer, CLASS_TRANSITION)) { - addListener(viewer, EVENT_TRANSITION_END, onViewerTransitionEnd) - removeClass(viewer, CLASS_IN) - } else { - hideImmediately() - } - } - - this.transitioning = { - abort: function abort () { - if (_this.viewed && hasClass(image, CLASS_TRANSITION)) { - removeListener(image, EVENT_TRANSITION_END, onImageTransitionEnd) - } else if (hasClass(viewer, CLASS_TRANSITION)) { - removeListener(viewer, EVENT_TRANSITION_END, - onViewerTransitionEnd) - } - }, - } // In case of hiding the viewer when holding on the image (#255), - // note that the `CLASS_TRANSITION` class will be removed on pointer down. - - if (this.viewed && hasClass(image, CLASS_TRANSITION)) { - addListener(image, EVENT_TRANSITION_END, onImageTransitionEnd, { - once: true, - }) - this.zoomTo(0, false, null, true) - } else { - onImageTransitionEnd() - } - } else { - hideImmediately() - } - - return this - }, - - /** - * View one of the images with image's index - * @param {number} index - The index of the image to view. - * @returns {Viewer} this - */ - view: function view () { - var _this2 = this - - var index = arguments.length > 0 && arguments[0] !== undefined - ? arguments[0] - : this.options.initialViewIndex - index = Number(index) || 0 - - if (this.hiding || this.played || index < 0 || index >= this.length || - this.viewed && index === this.index) { - return this - } - - if (!this.isShown) { - this.index = index - return this.show() - } - - if (this.viewing) { - this.viewing.abort() - } - - var element = this.element, options = this.options, title = this.title, - canvas = this.canvas - var item = this.items[index] - var img = item.querySelector('img') - var url = getData(img, 'originalUrl') - var alt = img.getAttribute('alt') - var image = document.createElement('img') - forEach(options.inheritedAttributes, function (name) { - var value = img.getAttribute(name) - - if (value !== null) { - image.setAttribute(name, value) - } - }) - image.src = url - image.alt = alt - - if (isFunction(options.view)) { - addListener(element, EVENT_VIEW, options.view, { - once: true, - }) - } - - if (dispatchEvent(element, EVENT_VIEW, { - originalImage: this.images[index], index: index, image: image, - }) === false || !this.isShown || this.hiding || this.played) { - return this - } - - var activeItem = this.items[this.index] - - if (activeItem) { - removeClass(activeItem, CLASS_ACTIVE) - activeItem.removeAttribute('aria-selected') - } - - addClass(item, CLASS_ACTIVE) - item.setAttribute('aria-selected', true) - - if (options.focus) { - item.focus() - } - - this.image = image - this.viewed = false - this.index = index - this.imageData = {} - addClass(image, CLASS_INVISIBLE) - - if (options.loading) { - addClass(canvas, CLASS_LOADING) - } - - canvas.innerHTML = '' - canvas.appendChild(image) // Center current item - - this.renderList() // Clear title - - title.innerHTML = '' // Generate title after viewed - - var onViewed = function onViewed () { - var imageData = _this2.imageData - var render = Array.isArray(options.title) - ? options.title[1] - : options.title - title.innerHTML = escapeHTMLEntities(isFunction(render) - ? render.call(_this2, image, imageData) - : ''.concat(alt, ' ('). - concat(imageData.naturalWidth, ' \xD7 '). - concat(imageData.naturalHeight, ')')) - } - - var onLoad - var onError - addListener(element, EVENT_VIEWED, onViewed, { - once: true, - }) - this.viewing = { - abort: function abort () { - removeListener(element, EVENT_VIEWED, onViewed) - - if (image.complete) { - if (_this2.imageRendering) { - _this2.imageRendering.abort() - } else if (_this2.imageInitializing) { - _this2.imageInitializing.abort() - } - } else { - // Cancel download to save bandwidth. - image.src = '' - removeListener(image, EVENT_LOAD, onLoad) - - if (_this2.timeout) { - clearTimeout(_this2.timeout) - } - } - }, - } - - if (image.complete) { - this.load() - } else { - addListener(image, EVENT_LOAD, onLoad = function onLoad () { - removeListener(image, EVENT_ERROR, onError) - - _this2.load() - }, { - once: true, - }) - addListener(image, EVENT_ERROR, onError = function onError () { - removeListener(image, EVENT_LOAD, onLoad) - - if (_this2.timeout) { - clearTimeout(_this2.timeout) - _this2.timeout = false - } - - removeClass(image, CLASS_INVISIBLE) - - if (options.loading) { - removeClass(_this2.canvas, CLASS_LOADING) - } - }, { - once: true, - }) - - if (this.timeout) { - clearTimeout(this.timeout) - } // Make the image visible if it fails to load within 1s - - this.timeout = setTimeout(function () { - removeClass(image, CLASS_INVISIBLE) - _this2.timeout = false - }, 1000) - } - - return this - }, - - /** - * View the previous image - * @param {boolean} [loop=false] - Indicate if view the last one - * when it is the first one at present. - * @returns {Viewer} this - */ - prev: function prev () { - var loop = arguments.length > 0 && arguments[0] !== undefined - ? arguments[0] - : false - var index = this.index - 1 - - if (index < 0) { - index = loop ? this.length - 1 : 0 - } - - this.view(index) - return this - }, - - /** - * View the next image - * @param {boolean} [loop=false] - Indicate if view the first one - * when it is the last one at present. - * @returns {Viewer} this - */ - next: function next () { - var loop = arguments.length > 0 && arguments[0] !== undefined - ? arguments[0] - : false - var maxIndex = this.length - 1 - var index = this.index + 1 - - if (index > maxIndex) { - index = loop ? 0 : maxIndex - } - - this.view(index) - return this - }, - - /** - * Move the image with relative offsets. - * @param {number} x - The moving distance in the horizontal direction. - * @param {number} [y=x] The moving distance in the vertical direction. - * @returns {Viewer} this - */ - move: function move (x) { - var y = arguments.length > 1 && arguments[1] !== undefined - ? arguments[1] - : x - var imageData = this.imageData - this.moveTo(isUndefined(x) ? x : imageData.x + Number(x), - isUndefined(y) ? y : imageData.y + Number(y)) - return this - }, - - /** - * Move the image to an absolute point. - * @param {number} x - The new position in the horizontal direction. - * @param {number} [y=x] - The new position in the vertical direction. - * @param {Event} [_originalEvent=null] - The original event if any. - * @returns {Viewer} this - */ - moveTo: function moveTo (x) { - var _this3 = this - - var y = arguments.length > 1 && arguments[1] !== undefined - ? arguments[1] - : x - - var _originalEvent = arguments.length > 2 && arguments[2] !== undefined - ? arguments[2] - : null - - var element = this.element, options = this.options, - imageData = this.imageData - x = Number(x) - y = Number(y) - - if (this.viewed && !this.played && options.movable) { - var oldX = imageData.x - var oldY = imageData.y - var changed = false - - if (isNumber(x)) { - changed = true - } else { - x = oldX - } - - if (isNumber(y)) { - changed = true - } else { - y = oldY - } - - if (changed) { - if (isFunction(options.move)) { - addListener(element, EVENT_MOVE, options.move, { - once: true, - }) - } - - if (dispatchEvent(element, EVENT_MOVE, { - x: x, y: y, oldX: oldX, oldY: oldY, originalEvent: _originalEvent, - }) === false) { - return this - } - - imageData.x = x - imageData.y = y - imageData.left = x - imageData.top = y - this.moving = true - this.renderImage(function () { - _this3.moving = false - - if (isFunction(options.moved)) { - addListener(element, EVENT_MOVED, options.moved, { - once: true, - }) - } - - dispatchEvent(element, EVENT_MOVED, { - x: x, y: y, oldX: oldX, oldY: oldY, originalEvent: _originalEvent, - }, { - cancelable: false, - }) - }) - } - } - - return this - }, - - /** - * Rotate the image with a relative degree. - * @param {number} degree - The rotate degree. - * @returns {Viewer} this - */ - rotate: function rotate (degree) { - this.rotateTo((this.imageData.rotate || 0) + Number(degree)) - return this - }, - - /** - * Rotate the image to an absolute degree. - * @param {number} degree - The rotate degree. - * @returns {Viewer} this - */ - rotateTo: function rotateTo (degree) { - var _this4 = this - - var element = this.element, options = this.options, - imageData = this.imageData - degree = Number(degree) - - if (isNumber(degree) && this.viewed && !this.played && - options.rotatable) { - var oldDegree = imageData.rotate - - if (isFunction(options.rotate)) { - addListener(element, EVENT_ROTATE, options.rotate, { - once: true, - }) - } - - if (dispatchEvent(element, EVENT_ROTATE, { - degree: degree, oldDegree: oldDegree, - }) === false) { - return this - } - - imageData.rotate = degree - this.rotating = true - this.renderImage(function () { - _this4.rotating = false - - if (isFunction(options.rotated)) { - addListener(element, EVENT_ROTATED, options.rotated, { - once: true, - }) - } - - dispatchEvent(element, EVENT_ROTATED, { - degree: degree, oldDegree: oldDegree, - }, { - cancelable: false, - }) - }) - } - - return this - }, - - /** - * Scale the image on the x-axis. - * @param {number} scaleX - The scale ratio on the x-axis. - * @returns {Viewer} this - */ - scaleX: function scaleX (_scaleX) { - this.scale(_scaleX, this.imageData.scaleY) - return this - }, - - /** - * Scale the image on the y-axis. - * @param {number} scaleY - The scale ratio on the y-axis. - * @returns {Viewer} this - */ - scaleY: function scaleY (_scaleY) { - this.scale(this.imageData.scaleX, _scaleY) - return this - }, - - /** - * Scale the image. - * @param {number} scaleX - The scale ratio on the x-axis. - * @param {number} [scaleY=scaleX] - The scale ratio on the y-axis. - * @returns {Viewer} this - */ - scale: function scale (scaleX) { - var _this5 = this - - var scaleY = arguments.length > 1 && arguments[1] !== undefined - ? arguments[1] - : scaleX - var element = this.element, options = this.options, - imageData = this.imageData - scaleX = Number(scaleX) - scaleY = Number(scaleY) - - if (this.viewed && !this.played && options.scalable) { - var oldScaleX = imageData.scaleX - var oldScaleY = imageData.scaleY - var changed = false - - if (isNumber(scaleX)) { - changed = true - } else { - scaleX = oldScaleX - } - - if (isNumber(scaleY)) { - changed = true - } else { - scaleY = oldScaleY - } - - if (changed) { - if (isFunction(options.scale)) { - addListener(element, EVENT_SCALE, options.scale, { - once: true, - }) - } - - if (dispatchEvent(element, EVENT_SCALE, { - scaleX: scaleX, - scaleY: scaleY, - oldScaleX: oldScaleX, - oldScaleY: oldScaleY, - }) === false) { - return this - } - - imageData.scaleX = scaleX - imageData.scaleY = scaleY - this.scaling = true - this.renderImage(function () { - _this5.scaling = false - - if (isFunction(options.scaled)) { - addListener(element, EVENT_SCALED, options.scaled, { - once: true, - }) - } - - dispatchEvent(element, EVENT_SCALED, { - scaleX: scaleX, - scaleY: scaleY, - oldScaleX: oldScaleX, - oldScaleY: oldScaleY, - }, { - cancelable: false, - }) - }) - } - } - - return this - }, - - /** - * Zoom the image with a relative ratio. - * @param {number} ratio - The target ratio. - * @param {boolean} [hasTooltip=false] - Indicates if it has a tooltip or not. - * @param {Event} [_originalEvent=null] - The original event if any. - * @returns {Viewer} this - */ - zoom: function zoom (ratio) { - var hasTooltip = arguments.length > 1 && arguments[1] !== undefined - ? arguments[1] - : false - - var _originalEvent = arguments.length > 2 && arguments[2] !== undefined - ? arguments[2] - : null - - var imageData = this.imageData - ratio = Number(ratio) - - if (ratio < 0) { - ratio = 1 / (1 - ratio) - } else { - ratio = 1 + ratio - } - - this.zoomTo(imageData.width * ratio / imageData.naturalWidth, hasTooltip, - _originalEvent) - return this - }, - - /** - * Zoom the image to an absolute ratio. - * @param {number} ratio - The target ratio. - * @param {boolean} [hasTooltip=false] - Indicates if it has a tooltip or not. - * @param {Event} [_originalEvent=null] - The original event if any. - * @param {Event} [_zoomable=false] - Indicates if the current zoom is available or not. - * @returns {Viewer} this - */ - zoomTo: function zoomTo (ratio) { - var _this6 = this - - var hasTooltip = arguments.length > 1 && arguments[1] !== undefined - ? arguments[1] - : false - - var _originalEvent = arguments.length > 2 && arguments[2] !== undefined - ? arguments[2] - : null - - var _zoomable = arguments.length > 3 && arguments[3] !== undefined - ? arguments[3] - : false - - var element = this.element, options = this.options, - pointers = this.pointers, imageData = this.imageData - var x = imageData.x, y = imageData.y, width = imageData.width, - height = imageData.height, naturalWidth = imageData.naturalWidth, - naturalHeight = imageData.naturalHeight - ratio = Math.max(0, ratio) - - if (isNumber(ratio) && this.viewed && !this.played && - (_zoomable || options.zoomable)) { - if (!_zoomable) { - var minZoomRatio = Math.max(0.01, options.minZoomRatio) - var maxZoomRatio = Math.min(100, options.maxZoomRatio) - ratio = Math.min(Math.max(ratio, minZoomRatio), maxZoomRatio) - } - - if (_originalEvent) { - switch (_originalEvent.type) { - case 'wheel': - if (options.zoomRatio >= 0.055 && ratio > 0.95 && ratio < 1.05) { - ratio = 1 - } - - break - - case 'pointermove': - case 'touchmove': - case 'mousemove': - if (ratio > 0.99 && ratio < 1.01) { - ratio = 1 - } - - break - } - } - - var newWidth = naturalWidth * ratio - var newHeight = naturalHeight * ratio - var offsetWidth = newWidth - width - var offsetHeight = newHeight - height - var oldRatio = imageData.ratio - - if (isFunction(options.zoom)) { - addListener(element, EVENT_ZOOM, options.zoom, { - once: true, - }) - } - - if (dispatchEvent(element, EVENT_ZOOM, { - ratio: ratio, oldRatio: oldRatio, originalEvent: _originalEvent, - }) === false) { - return this - } - - this.zooming = true - - if (_originalEvent) { - var offset = getOffset(this.viewer) - var center = pointers && Object.keys(pointers).length > 0 - ? getPointersCenter(pointers) - : { - pageX: _originalEvent.pageX, pageY: _originalEvent.pageY, - } // Zoom from the triggering point of the event - - imageData.x -= offsetWidth * - ((center.pageX - offset.left - x) / width) - imageData.y -= offsetHeight * - ((center.pageY - offset.top - y) / height) - } else { - // Zoom from the center of the image - imageData.x -= offsetWidth / 2 - imageData.y -= offsetHeight / 2 - } - - imageData.left = imageData.x - imageData.top = imageData.y - imageData.width = newWidth - imageData.height = newHeight - imageData.oldRatio = oldRatio - imageData.ratio = ratio - this.renderImage(function () { - _this6.zooming = false - - if (isFunction(options.zoomed)) { - addListener(element, EVENT_ZOOMED, options.zoomed, { - once: true, - }) - } - - dispatchEvent(element, EVENT_ZOOMED, { - ratio: ratio, oldRatio: oldRatio, originalEvent: _originalEvent, - }, { - cancelable: false, - }) - }) - - if (hasTooltip) { - this.tooltip() - } - } - - return this - }, - - /** - * Play the images - * @param {boolean|FullscreenOptions} [fullscreen=false] - Indicate if request fullscreen or not. - * @returns {Viewer} this - */ - play: function play () { - var _this7 = this - - var fullscreen = arguments.length > 0 && arguments[0] !== undefined - ? arguments[0] - : false - - if (!this.isShown || this.played) { - return this - } - - var element = this.element, options = this.options - - if (isFunction(options.play)) { - addListener(element, EVENT_PLAY, options.play, { - once: true, - }) - } - - if (dispatchEvent(element, EVENT_PLAY) === false) { - return this - } - - var player = this.player - var onLoad = this.loadImage.bind(this) - var list = [] - var total = 0 - var index = 0 - this.played = true - this.onLoadWhenPlay = onLoad - - if (fullscreen) { - this.requestFullscreen(fullscreen) - } - - addClass(player, CLASS_SHOW) - forEach(this.items, function (item, i) { - var img = item.querySelector('img') - var image = document.createElement('img') - image.src = getData(img, 'originalUrl') - image.alt = img.getAttribute('alt') - image.referrerPolicy = img.referrerPolicy - total += 1 - addClass(image, CLASS_FADE) - toggleClass(image, CLASS_TRANSITION, options.transition) - - if (hasClass(item, CLASS_ACTIVE)) { - addClass(image, CLASS_IN) - index = i - } - - list.push(image) - addListener(image, EVENT_LOAD, onLoad, { - once: true, - }) - player.appendChild(image) - }) - - if (isNumber(options.interval) && options.interval > 0) { - var play = function play () { - _this7.playing = setTimeout(function () { - removeClass(list[index], CLASS_IN) - index += 1 - index = index < total ? index : 0 - addClass(list[index], CLASS_IN) - play() - }, options.interval) - } - - if (total > 1) { - play() - } - } - - return this - }, // Stop play - stop: function stop () { - var _this8 = this - - if (!this.played) { - return this - } - - var element = this.element, options = this.options - - if (isFunction(options.stop)) { - addListener(element, EVENT_STOP, options.stop, { - once: true, - }) - } - - if (dispatchEvent(element, EVENT_STOP) === false) { - return this - } - - var player = this.player - this.played = false - clearTimeout(this.playing) - forEach(player.getElementsByTagName('img'), function (image) { - removeListener(image, EVENT_LOAD, _this8.onLoadWhenPlay) - }) - removeClass(player, CLASS_SHOW) - player.innerHTML = '' - this.exitFullscreen() - return this - }, // Enter modal mode (only available in inline mode) - full: function full () { - var _this9 = this - - var options = this.options, viewer = this.viewer, image = this.image, - list = this.list - - if (!this.isShown || this.played || this.fulled || !options.inline) { - return this - } - - this.fulled = true - this.open() - addClass(this.button, CLASS_FULLSCREEN_EXIT) - - if (options.transition) { - removeClass(list, CLASS_TRANSITION) - - if (this.viewed) { - removeClass(image, CLASS_TRANSITION) - } - } - - addClass(viewer, CLASS_FIXED) - viewer.setAttribute('role', 'dialog') - viewer.setAttribute('aria-labelledby', this.title.id) - viewer.setAttribute('aria-modal', true) - viewer.removeAttribute('style') - setStyle(viewer, { - zIndex: options.zIndex, - }) - - if (options.focus) { - this.enforceFocus() - } - - this.initContainer() - this.viewerData = assign({}, this.containerData) - this.renderList() - - if (this.viewed) { - this.initImage(function () { - _this9.renderImage(function () { - if (options.transition) { - setTimeout(function () { - addClass(image, CLASS_TRANSITION) - addClass(list, CLASS_TRANSITION) - }, 0) - } - }) - }) - } - - return this - }, // Exit modal mode (only available in inline mode) - exit: function exit () { - var _this10 = this - - var options = this.options, viewer = this.viewer, image = this.image, - list = this.list - - if (!this.isShown || this.played || !this.fulled || !options.inline) { - return this - } - - this.fulled = false - this.close() - removeClass(this.button, CLASS_FULLSCREEN_EXIT) - - if (options.transition) { - removeClass(list, CLASS_TRANSITION) - - if (this.viewed) { - removeClass(image, CLASS_TRANSITION) - } - } - - if (options.focus) { - this.clearEnforceFocus() - } - - viewer.removeAttribute('role') - viewer.removeAttribute('aria-labelledby') - viewer.removeAttribute('aria-modal') - removeClass(viewer, CLASS_FIXED) - setStyle(viewer, { - zIndex: options.zIndexInline, - }) - this.viewerData = assign({}, this.parentData) - this.renderViewer() - this.renderList() - - if (this.viewed) { - this.initImage(function () { - _this10.renderImage(function () { - if (options.transition) { - setTimeout(function () { - addClass(image, CLASS_TRANSITION) - addClass(list, CLASS_TRANSITION) - }, 0) - } - }) - }) - } - - return this - }, // Show the current ratio of the image with percentage - tooltip: function tooltip () { - var _this11 = this - - var options = this.options, tooltipBox = this.tooltipBox, - imageData = this.imageData - - if (!this.viewed || this.played || !options.tooltip) { - return this - } - - tooltipBox.textContent = ''.concat(Math.round(imageData.ratio * 100), '%') - - if (!this.tooltipping) { - if (options.transition) { - if (this.fading) { - dispatchEvent(tooltipBox, EVENT_TRANSITION_END) - } - - addClass(tooltipBox, CLASS_SHOW) - addClass(tooltipBox, CLASS_FADE) - addClass(tooltipBox, CLASS_TRANSITION) - tooltipBox.removeAttribute('aria-hidden') // Force reflow to enable CSS3 transition - - tooltipBox.initialOffsetWidth = tooltipBox.offsetWidth - addClass(tooltipBox, CLASS_IN) - } else { - addClass(tooltipBox, CLASS_SHOW) - tooltipBox.removeAttribute('aria-hidden') - } - } else { - clearTimeout(this.tooltipping) - } - - this.tooltipping = setTimeout(function () { - if (options.transition) { - addListener(tooltipBox, EVENT_TRANSITION_END, function () { - removeClass(tooltipBox, CLASS_SHOW) - removeClass(tooltipBox, CLASS_FADE) - removeClass(tooltipBox, CLASS_TRANSITION) - tooltipBox.setAttribute('aria-hidden', true) - _this11.fading = false - }, { - once: true, - }) - removeClass(tooltipBox, CLASS_IN) - _this11.fading = true - } else { - removeClass(tooltipBox, CLASS_SHOW) - tooltipBox.setAttribute('aria-hidden', true) - } - - _this11.tooltipping = false - }, 1000) - return this - }, - - /** - * Toggle the image size between its current size and natural size - * @param {Event} [_originalEvent=null] - The original event if any. - * @returns {Viewer} this - */ - toggle: function toggle () { - var _originalEvent = arguments.length > 0 && arguments[0] !== undefined - ? arguments[0] - : null - - if (this.imageData.ratio === 1) { - this.zoomTo(this.imageData.oldRatio, true, _originalEvent) - } else { - this.zoomTo(1, true, _originalEvent) - } - - return this - }, // Reset the image to its initial state - reset: function reset () { - if (this.viewed && !this.played) { - this.imageData = assign({}, this.initialImageData) - this.renderImage() - } - - return this - }, // Update viewer when images changed - update: function update () { - var _this12 = this - - var element = this.element, options = this.options, isImg = this.isImg // Destroy viewer if the target image was deleted - - if (isImg && !element.parentNode) { - return this.destroy() - } - - var images = [] - forEach(isImg ? [element] : element.querySelectorAll('img'), - function (image) { - if (isFunction(options.filter)) { - if (options.filter.call(_this12, image)) { - images.push(image) - } - } else if (_this12.getImageURL(image)) { - images.push(image) - } - }) - - if (!images.length) { - return this - } - - this.images = images - this.length = images.length - - if (this.ready) { - var changedIndexes = [] - forEach(this.items, function (item, i) { - var img = item.querySelector('img') - var image = images[i] - - if (image && img) { - if (image.src !== img.src // Title changed (#408) - || image.alt !== img.alt) { - changedIndexes.push(i) - } - } else { - changedIndexes.push(i) - } - }) - setStyle(this.list, { - width: 'auto', - }) - this.initList() - - if (this.isShown) { - if (this.length) { - if (this.viewed) { - var changedIndex = changedIndexes.indexOf(this.index) - - if (changedIndex >= 0) { - this.viewed = false - this.view( - Math.max(Math.min(this.index - changedIndex, this.length - 1), - 0)) - } else { - var activeItem = this.items[this.index] // Reactivate the current viewing item after reset the list. - - addClass(activeItem, CLASS_ACTIVE) - activeItem.setAttribute('aria-selected', true) - } - } - } else { - this.image = null - this.viewed = false - this.index = 0 - this.imageData = {} - this.canvas.innerHTML = '' - this.title.innerHTML = '' - } - } - } else { - this.build() - } - - return this - }, // Destroy the viewer - destroy: function destroy () { - var element = this.element, options = this.options - - if (!element[NAMESPACE]) { - return this - } - - this.destroyed = true - - if (this.ready) { - if (this.played) { - this.stop() - } - - if (options.inline) { - if (this.fulled) { - this.exit() - } - - this.unbind() - } else if (this.isShown) { - if (this.viewing) { - if (this.imageRendering) { - this.imageRendering.abort() - } else if (this.imageInitializing) { - this.imageInitializing.abort() - } - } - - if (this.hiding) { - this.transitioning.abort() - } - - this.hidden() - } else if (this.showing) { - this.transitioning.abort() - this.hidden() - } - - this.ready = false - this.viewer.parentNode.removeChild(this.viewer) - } else if (options.inline) { - if (this.delaying) { - this.delaying.abort() - } else if (this.initializing) { - this.initializing.abort() - } - } - - if (!options.inline) { - removeListener(element, EVENT_CLICK, this.onStart) - } - - element[NAMESPACE] = undefined - return this - }, - } - - var others = { - getImageURL: function getImageURL (image) { - var url = this.options.url - - if (isString(url)) { - url = image.getAttribute(url) - } else if (isFunction(url)) { - url = url.call(this, image) - } else { - url = '' - } - - return url - }, enforceFocus: function enforceFocus () { - var _this = this - - this.clearEnforceFocus() - addListener(document, EVENT_FOCUSIN, this.onFocusin = function (event) { - var viewer = _this.viewer - var target = event.target - - if (target !== document && target !== viewer && !viewer.contains(target) // Avoid conflicts with other modals (#474) - && (target.getAttribute('tabindex') === null || - target.getAttribute('aria-modal') !== 'true')) { - viewer.focus() - } - }) - }, clearEnforceFocus: function clearEnforceFocus () { - if (this.onFocusin) { - removeListener(document, EVENT_FOCUSIN, this.onFocusin) - this.onFocusin = null - } - }, open: function open () { - var body = this.body - addClass(body, CLASS_OPEN) - body.style.paddingRight = ''.concat(this.scrollbarWidth + - (parseFloat(this.initialBodyComputedPaddingRight) || 0), 'px') - }, close: function close () { - var body = this.body - removeClass(body, CLASS_OPEN) - body.style.paddingRight = this.initialBodyPaddingRight - }, shown: function shown () { - var element = this.element, options = this.options, viewer = this.viewer - 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: function hidden () { - var element = this.element, options = this.options, viewer = this.viewer - - if (options.fucus) { - this.clearEnforceFocus() - } - - this.fulled = false - this.viewed = false - this.isShown = false - 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.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: function requestFullscreen (options) { - var document = this.element.ownerDocument - - if (this.fulled && - !(document.fullscreenElement || document.webkitFullscreenElement || - document.mozFullScreenElement || document.msFullscreenElement)) { - var documentElement = document.documentElement // 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: function exitFullscreen () { - var 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: function change (event) { - var options = this.options, pointers = this.pointers - var pointer = pointers[Object.keys(pointers)[0]] // In the case of the `pointers` object is empty (#421) - - if (!pointer) { - return - } - - var offsetX = pointer.endX - pointer.startX - var offsetY = pointer.endY - pointer.startY - - switch (this.action) { - // Move the current image - case ACTION_MOVE: - this.move(offsetX, offsetY, event) - break - // Zoom the current image - - case ACTION_ZOOM: - this.zoom(getMaxZoomRatio(pointers), false, event) - break - - case ACTION_SWITCH: { - this.action = 'switched' - var 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 - } - } // Override - - forEach(pointers, function (p) { - p.startX = p.endX - p.startY = p.endY - }) - }, isSwitchable: function isSwitchable () { - var imageData = this.imageData, viewerData = this.viewerData - return this.length > 1 && imageData.x >= 0 && imageData.y >= 0 && - imageData.width <= viewerData.width && imageData.height <= - viewerData.height - }, - } - - var AnotherViewer = WINDOW.Viewer - - var getUniqueID = function (id) { - return function () { - id += 1 - return id - } - }(-1) - - var Viewer = /*#__PURE__*/function () { - /** - * Create a new Viewer. - * @param {Element} element - The target element for viewing. - * @param {Object} [options={}] - The configuration options. - */ - function Viewer (element) { - var options = arguments.length > 1 && arguments[1] !== undefined - ? arguments[1] - : {} - - _classCallCheck(this, Viewer) - - if (!element || element.nodeType !== 1) { - throw new Error( - 'The first argument is required and must be an element.') - } - - this.element = element - this.options = assign({}, DEFAULTS, isPlainObject(options) && options) - this.action = false - this.fading = false - this.fulled = false - this.hiding = false - this.imageClicked = false - this.imageData = {} - this.index = this.options.initialViewIndex - this.isImg = false - this.isShown = false - this.length = 0 - this.moving = false - this.played = false - this.playing = false - this.pointers = {} - this.ready = false - this.rotating = false - this.scaling = false - this.showing = false - this.timeout = false - this.tooltipping = false - this.viewed = false - this.viewing = false - this.wheeling = false - this.zooming = false - this.id = getUniqueID() - this.init() - } - - _createClass(Viewer, [ - { - key: 'init', value: function init () { - var _this = this - - var element = this.element, options = this.options - - if (element[NAMESPACE]) { - return - } - - element[NAMESPACE] = this // The `focus` option requires the `keyboard` option set to `true`. - - if (options.focus && !options.keyboard) { - options.focus = false - } - - var isImg = element.localName === 'img' - var images = [] - forEach(isImg ? [element] : element.querySelectorAll('img'), - function (image) { - if (isFunction(options.filter)) { - if (options.filter.call(_this, image)) { - images.push(image) - } - } else if (_this.getImageURL(image)) { - images.push(image) - } - }) - this.isImg = isImg - this.length = images.length - this.images = images - this.initBody() // Override `transition` option if it is not supported - - if (isUndefined(document.createElement(NAMESPACE).style.transition)) { - options.transition = false - } - - if (options.inline) { - var count = 0 - - var progress = function progress () { - count += 1 - - if (count === _this.length) { - var timeout - _this.initializing = false - _this.delaying = { - abort: function abort () { - clearTimeout(timeout) - }, - } // build asynchronously to keep `this.viewer` is accessible in `ready` event handler. - - timeout = setTimeout(function () { - _this.delaying = false - - _this.build() - }, 0) - } - } - - this.initializing = { - abort: function abort () { - forEach(images, function (image) { - if (!image.complete) { - removeListener(image, EVENT_LOAD, progress) - } - }) - }, - } - forEach(images, function (image) { - if (image.complete) { - progress() - } else { - addListener(image, EVENT_LOAD, progress, { - once: true, - }) - } - }) - } else { - addListener(element, EVENT_CLICK, this.onStart = function (_ref) { - var target = _ref.target - - if (target.localName === 'img' && (!isFunction(options.filter) || - options.filter.call(_this, target))) { - _this.view(_this.images.indexOf(target)) - } - }) - } - }, - }, { - key: 'build', value: function build () { - if (this.ready) { - return - } - - var element = this.element, options = this.options - var parent = element.parentNode - var template = document.createElement('div') - template.innerHTML = TEMPLATE - var viewer = template.querySelector( - '.'.concat(NAMESPACE, '-container')) - var title = viewer.querySelector('.'.concat(NAMESPACE, '-title')) - var toolbar = viewer.querySelector('.'.concat(NAMESPACE, '-toolbar')) - var navbar = viewer.querySelector('.'.concat(NAMESPACE, '-navbar')) - var button = viewer.querySelector('.'.concat(NAMESPACE, '-button')) - var canvas = viewer.querySelector('.'.concat(NAMESPACE, '-canvas')) - this.parent = parent - this.viewer = viewer - this.title = title - this.toolbar = toolbar - this.navbar = navbar - this.button = button - this.canvas = canvas - this.footer = viewer.querySelector('.'.concat(NAMESPACE, '-footer')) - this.tooltipBox = viewer.querySelector( - '.'.concat(NAMESPACE, '-tooltip')) - this.player = viewer.querySelector('.'.concat(NAMESPACE, '-player')) - this.list = viewer.querySelector('.'.concat(NAMESPACE, '-list')) - viewer.id = ''.concat(NAMESPACE).concat(this.id) - title.id = ''.concat(NAMESPACE, 'Title').concat(this.id) - addClass(title, !options.title ? CLASS_HIDE : getResponsiveClass( - Array.isArray(options.title) ? options.title[0] : options.title)) - addClass(navbar, - !options.navbar ? CLASS_HIDE : getResponsiveClass(options.navbar)) - toggleClass(button, CLASS_HIDE, !options.button) - - if (options.keyboard) { - button.setAttribute('tabindex', 0) - } - - if (options.backdrop) { - addClass(viewer, ''.concat(NAMESPACE, '-backdrop')) - - if (!options.inline && options.backdrop !== 'static') { - setData(canvas, DATA_ACTION, 'hide') - } - } - - if (isString(options.className) && options.className) { - // In case there are multiple class names - options.className.split(REGEXP_SPACES). - forEach(function (className) { - addClass(viewer, className) - }) - } - - if (options.toolbar) { - var list = document.createElement('ul') - var custom = isPlainObject(options.toolbar) - var zoomButtons = BUTTONS.slice(0, 3) - var rotateButtons = BUTTONS.slice(7, 9) - var scaleButtons = BUTTONS.slice(9) - - if (!custom) { - addClass(toolbar, getResponsiveClass(options.toolbar)) - } - - forEach(custom ? options.toolbar : BUTTONS, - function (value, index) { - var deep = custom && isPlainObject(value) - var name = custom ? hyphenate(index) : value - var show = deep && !isUndefined(value.show) ? value.show : value - - if (!show || !options.zoomable && zoomButtons.indexOf(name) !== - -1 || !options.rotatable && rotateButtons.indexOf(name) !== - -1 || !options.scalable && scaleButtons.indexOf(name) !== - -1) { - return - } - - var size = deep && !isUndefined(value.size) ? value.size : value - var click = deep && !isUndefined(value.click) - ? value.click - : value - var item = document.createElement('li') - - if (options.keyboard) { - item.setAttribute('tabindex', 0) - } - - item.setAttribute('role', 'button') - addClass(item, ''.concat(NAMESPACE, '-').concat(name)) - - if (!isFunction(click)) { - setData(item, DATA_ACTION, name) - } - - if (isNumber(show)) { - addClass(item, getResponsiveClass(show)) - } - - if (['small', 'large'].indexOf(size) !== -1) { - addClass(item, ''.concat(NAMESPACE, '-').concat(size)) - } else if (name === 'play') { - addClass(item, ''.concat(NAMESPACE, '-large')) - } - - if (isFunction(click)) { - addListener(item, EVENT_CLICK, click) - } - // NOTE: updated by Vanessa - let iconName = '' - switch (name) { - case 'zoom-in': - iconName = 'Add' - break - case 'zoom-out': - iconName = 'Line' - break - case 'one-to-one': - iconName = 'Pause' - break - case 'reset': - iconName = 'Refresh' - break - case 'prev': - iconName = 'Left' - break - case 'play': - iconName = 'Play' - break - case'next': - iconName = 'Right' - break - case 'rotate-left': - iconName = 'Undo' - break - case 'rotate-right': - iconName = 'Redo' - break - case 'flip-horizontal': - iconName = 'SplitLR' - break - case 'flip-vertical': - iconName = 'SplitTB' - break - case 'close': - iconName = 'Close' - break - } - item.innerHTML = `` - list.appendChild(item) - }) - toolbar.appendChild(list) - } else { - addClass(toolbar, CLASS_HIDE) - } - - if (!options.rotatable) { - var rotates = toolbar.querySelectorAll('li[class*="rotate"]') - addClass(rotates, CLASS_INVISIBLE) - forEach(rotates, function (rotate) { - toolbar.appendChild(rotate) - }) - } - - if (options.inline) { - addClass(button, CLASS_FULLSCREEN) - setStyle(viewer, { - zIndex: options.zIndexInline, - }) - - if (window.getComputedStyle(parent).position === 'static') { - setStyle(parent, { - position: 'relative', - }) - } - - parent.insertBefore(viewer, element.nextSibling) - } else { - addClass(button, CLASS_CLOSE) - addClass(viewer, CLASS_FIXED) - addClass(viewer, CLASS_FADE) - addClass(viewer, CLASS_HIDE) - setStyle(viewer, { - zIndex: options.zIndex, - }) - var container = options.container - - if (isString(container)) { - container = element.ownerDocument.querySelector(container) - } - - if (!container) { - container = this.body - } - - container.appendChild(viewer) - } - - if (options.inline) { - this.render() - this.bind() - this.isShown = true - } - - this.ready = true - - if (isFunction(options.ready)) { - addListener(element, EVENT_READY, options.ready, { - once: true, - }) - } - - if (dispatchEvent(element, EVENT_READY) === false) { - this.ready = false - return - } - - if (this.ready && options.inline) { - this.view(this.index) - } - }, /** - * Get the no conflict viewer class. - * @returns {Viewer} The viewer class. - */ - - }], [ - { - key: 'noConflict', value: function noConflict () { - window.Viewer = AnotherViewer - return Viewer - }, /** - * Change the default options. - * @param {Object} options - The new default options. - */ - - }, { - key: 'setDefaults', value: function setDefaults (options) { - assign(DEFAULTS, isPlainObject(options) && options) - }, - }]) - - return Viewer - }() - - assign(Viewer.prototype, render, events, handlers, methods, others) - - return Viewer - -})) +((t,e)=>{"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Viewer=e()})(this,function(){function n(t,e){for(var i=0;i{if("object"!=typeof t||!t)return t;var i=t[Symbol.toPrimitive];if(void 0===i)return("string"===e?String:Number)(t);if("object"!=typeof(i=i.call(t,e||"default")))return i;throw new TypeError("@@toPrimitive must return a primitive value.")})(t,"string");return"symbol"==typeof t?t:t+""}function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var W={backdrop:!0,button:!0,navbar:!0,title:!0,toolbar:!0,className:"",container:"body",filter:null,fullscreen:!0,inheritedAttributes:["crossOrigin","decoding","isMap","loading","referrerPolicy","sizes","srcset","useMap"],initialCoverage:.9,initialViewIndex:0,inline:!1,interval:5e3,keyboard:!0,focus:!0,loading:!0,loop:!0,minWidth:200,minHeight:100,movable:!0,rotatable:!0,scalable:!0,zoomable:!0,zoomOnTouch:!0,zoomOnWheel:!0,slideOnTouch:!0,toggleOnDblclick:!0,tooltip:!0,transition:!0,zIndex:2015,zIndexInline:0,zoomRatio:.1,minZoomRatio:.01,maxZoomRatio:100,url:"src",ready:null,show:null,shown:null,hide:null,hidden:null,view:null,viewed:null,move:null,moved:null,rotate:null,rotated:null,scale:null,scaled:null,zoom:null,zoomed:null,play:null,stop:null},t="undefined"!=typeof window&&void 0!==window.document,e=t?window:{},a=!(!t||!e.document.documentElement)&&"ontouchstart"in e.document.documentElement,i=t&&"PointerEvent"in e,g="viewer",h="move",j="switch",c="zoom",f="".concat(g,"-active"),H="".concat(g,"-close"),B="".concat(g,"-fade"),V="".concat(g,"-fixed"),U="".concat(g,"-fullscreen"),K="".concat(g,"-fullscreen-exit"),v="".concat(g,"-hide"),Z="".concat(g,"-hide-md-down"),$="".concat(g,"-hide-sm-down"),_="".concat(g,"-hide-xs-down"),u="".concat(g,"-in"),p="".concat(g,"-invisible"),b="".concat(g,"-loading"),G="".concat(g,"-move"),J="".concat(g,"-open"),d="".concat(g,"-show"),m="".concat(g,"-transition"),w="click",Q="dblclick",tt="dragstart",et="focusin",it="keydown",y="load",x="error",nt=i?"pointerdown":a?"touchstart":"mousedown",ot=i?"pointermove":a?"touchmove":"mousemove",st=i?"pointerup pointercancel":a?"touchend touchcancel":"mouseup",at="resize",k="transitionend",rt="wheel",z="viewed",lt="rotated",ht="".concat(g,"Action"),ct=/\s\s*/,ut=["zoom-in","zoom-out","one-to-one","reset","prev","play","next","rotate-left","rotate-right","flip-horizontal","flip-vertical"];function T(t){return"string"==typeof t}var dt=Number.isNaN||e.isNaN;function E(t){return"number"==typeof t&&!dt(t)}function D(t){return void 0===t}function o(t){return"object"===l(t)&&null!==t}var mt=Object.prototype.hasOwnProperty;function S(t){if(!o(t))return!1;try{var e=t.constructor,i=e.prototype;return e&&i&&mt.call(i,"isPrototypeOf")}catch(t){return!1}}function I(t){return"function"==typeof t}function A(e,i){if(e&&I(i))if(Array.isArray(e)||E(e.length))for(var t=e.length,n=0;n{if(!T(e))return"";e=e.replace(/^.*\//,"").replace(/[?&#].*$/,"");try{return decodeURIComponent(e)}catch(t){return e}})(o),a=r.getImageURL(i);(o||a)&&(e=document.createElement("li"),n=document.createElement("img"),A(l.inheritedAttributes,function(t){var e=i.getAttribute(t);null!==e&&n.setAttribute(t,e)}),l.navbar&&(n.src=o||a),n.alt=s,n.setAttribute("data-original-url",a||o),e.setAttribute("data-index",t),e.setAttribute("data-viewer-action","view"),e.setAttribute("role","button"),l.keyboard&&e.setAttribute("tabindex",0),e.appendChild(n),h.appendChild(e),c.push(e))}),A(this.items=c,function(e){var t,i,n=e.firstElementChild;pt(n,"filled",!0),l.loading&&R(e,b),X(n,y,t=function(t){Y(n,x,i),l.loading&&M(e,b),r.loadImage(t)},{once:!0}),X(n,x,i=function(){Y(n,y,t),l.loading&&M(e,b)},{once:!0})}),l.transition&&X(t,z,function(){R(h,m)},{once:!0})},renderList:function(){var t,e,i=this.index,n=this.items[i];n&&(t=n.nextElementSibling,t=parseInt(window.getComputedStyle(t||n).marginLeft,10),n=n.offsetWidth,C(this.list,O({width:(e=n+t)*this.length-t},xt({translateX:(this.viewerData.width-n)/2-e*i}))))},resetList:function(){var t=this.list;t.innerHTML="",M(t,m),C(t,xt({translateX:0}))},initImage:function(r){var t,l=this,h=this.options,e=this.image,i=this.viewerData,n=this.footer.offsetHeight,c=i.width,u=Math.max(i.height-n,n),d=this.imageData||{};this.imageInitializing={abort:function(){t.onload=null}},t=zt(e,h,function(t,e){var i=t/e,n=Math.max(0,Math.min(1,h.initialCoverage)),o=c,s=u,n=(l.imageInitializing=!1,c=this.length||this.viewed&&t===this.index)){if(!this.isShown)return this.index=t,this.show();this.viewing&&this.viewing.abort();var e,n,o,s=this.element,a=this.options,r=this.title,l=this.canvas,h=this.items[t],c=h.querySelector("img"),u=N(c,"originalUrl"),d=c.getAttribute("alt"),m=document.createElement("img");A(a.inheritedAttributes,function(t){var e=c.getAttribute(t);null!==e&&m.setAttribute(t,e)}),m.src=u,m.alt=d,I(a.view)&&X(s,"view",a.view,{once:!0}),!1===P(s,"view",{originalImage:this.images[t],index:t,image:m})||!this.isShown||this.hiding||this.played||((u=this.items[this.index])&&(M(u,f),u.removeAttribute("aria-selected")),R(h,f),h.setAttribute("aria-selected",!0),a.focus&&h.focus(),this.image=m,this.viewed=!1,this.index=t,this.imageData={},R(m,p),a.loading&&R(l,b),l.innerHTML="",l.appendChild(m),this.renderList(),r.innerHTML="",X(s,z,e=function(){var t=i.imageData,e=Array.isArray(a.title)?a.title[1]:a.title;r.innerHTML=T(e=I(e)?e.call(i,m,t):"".concat(d," (").concat(t.naturalWidth," × ").concat(t.naturalHeight,")"))?e.replace(/&(?!amp;|quot;|#39;|lt;|gt;)/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">"):e},{once:!0}),this.viewing={abort:function(){Y(s,z,e),m.complete?i.imageRendering?i.imageRendering.abort():i.imageInitializing&&i.imageInitializing.abort():(m.src="",Y(m,y,n),i.timeout&&clearTimeout(i.timeout))}},m.complete?this.load():(X(m,y,n=function(){Y(m,x,o),i.load()},{once:!0}),X(m,x,o=function(){Y(m,y,n),i.timeout&&(clearTimeout(i.timeout),i.timeout=!1),M(m,p),a.loading&&M(i.canvas,b)},{once:!0}),this.timeout&&clearTimeout(this.timeout),this.timeout=setTimeout(function(){M(m,p),i.timeout=!1},1e3)))}return this},prev:function(){var t=this.index-1;return t<0&&(t=0Math.abs(r)&&(this.pointers={},1{function o(t){var e=1
    ',d=(i=d.querySelector(".".concat(g,"-container"))).querySelector(".".concat(g,"-title")),n=i.querySelector(".".concat(g,"-toolbar")),m=i.querySelector(".".concat(g,"-navbar")),o=i.querySelector(".".concat(g,"-button")),a=i.querySelector(".".concat(g,"-canvas")),this.parent=e,this.viewer=i,this.title=d,this.toolbar=n,this.navbar=m,this.button=o,this.canvas=a,this.footer=i.querySelector(".".concat(g,"-footer")),this.tooltipBox=i.querySelector(".".concat(g,"-tooltip")),this.player=i.querySelector(".".concat(g,"-player")),this.list=i.querySelector(".".concat(g,"-list")),i.id="".concat(g).concat(this.id),d.id="".concat(g,"Title").concat(this.id),R(d,s.title?Tt(Array.isArray(s.title)?s.title[0]:s.title):v),R(m,s.navbar?Tt(s.navbar):v),F(o,v,!s.button),s.keyboard&&o.setAttribute("tabindex",0),s.backdrop&&(R(i,"".concat(g,"-backdrop")),s.inline||"static"===s.backdrop||pt(a,ht,"hide")),T(s.className)&&s.className&&s.className.split(ct).forEach(function(t){R(i,t)}),s.toolbar?(r=document.createElement("ul"),l=S(s.toolbar),h=ut.slice(0,3),c=ut.slice(7,9),u=ut.slice(9),l||R(n,Tt(s.toolbar)),A(l?s.toolbar:ut,function(t,e){var i,n=l&&S(t),e=l?vt(e):t,o=n&&!D(t.show)?t.show:t;!o||!s.zoomable&&-1!==h.indexOf(e)||!s.rotatable&&-1!==c.indexOf(e)||!s.scalable&&-1!==u.indexOf(e)||(i=n&&!D(t.size)?t.size:t,n=n&&!D(t.click)?t.click:t,t=document.createElement("li"),s.keyboard&&t.setAttribute("tabindex",0),t.setAttribute("role","button"),R(t,"".concat(g,"-").concat(e)),I(n)||pt(t,ht,e),E(o)&&R(t,Tt(o)),-1!==["small","large"].indexOf(i)?R(t,"".concat(g,"-").concat(i)):"play"===e&&R(t,"".concat(g,"-large")),I(n)&&X(t,w,n),o="","zoom-in"===e?o="Add":"zoom-out"===e?o="Line":"one-to-one"===e?o="Pause":"reset"===e?o="Refresh":"prev"===e?o="Left":"play"===e?o="Play":"next"===e?o="Right":"rotate-left"===e?o="Undo":"rotate-right"===e?o="Redo":"flip-horizontal"===e?o="SplitLR":"flip-vertical"===e?o="SplitTB":"close"===e&&(o="Close"),t.innerHTML="'),r.appendChild(t))}),n.appendChild(r)):R(n,v),s.rotatable||(R(d=n.querySelectorAll('li[class*="rotate"]'),p),A(d,function(t){n.appendChild(t)})),s.inline?(R(o,U),C(i,{zIndex:s.zIndexInline}),"static"===window.getComputedStyle(e).position&&C(e,{position:"relative"}),e.insertBefore(i,t.nextSibling)):(R(o,H),R(i,V),R(i,B),R(i,v),C(i,{zIndex:s.zIndex}),(m=(m=T(m=s.container)?t.ownerDocument.querySelector(m):m)||this.body).appendChild(i)),s.inline&&(this.render(),this.bind(),this.isShown=!0),this.ready=!0,I(s.ready)&&X(t,"ready",s.ready,{once:!0}),!1===P(t,"ready")?this.ready=!1:this.ready&&s.inline&&this.view(this.index))}}])&&n(t.prototype,e),i&&n(t,i),Object.defineProperty(t,"prototype",{writable:!1}),t;var t,e,i})();return O(e.prototype,i,t,St,It,At),e});