From 11f7ee34de01cc051dff7f8c7e76d1ecb1cf9e32 Mon Sep 17 00:00:00 2001 From: gaoxiongzaq Date: Mon, 25 Mar 2024 13:49:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E9=A2=84=E8=A7=88=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E7=BB=84=E4=BB=B6=20=E4=BF=AE=E5=A4=8Decs=E9=80=80?= =?UTF-8?q?=E5=87=BA=E9=BB=91=E5=B1=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/static/js/viewer.min.js | 1006 ++++++----------- 1 file changed, 326 insertions(+), 680 deletions(-) diff --git a/server/src/main/resources/static/js/viewer.min.js b/server/src/main/resources/static/js/viewer.min.js index 21dc28c84..232bafed0 100644 --- a/server/src/main/resources/static/js/viewer.min.js +++ b/server/src/main/resources/static/js/viewer.min.js @@ -1,11 +1,11 @@ /*! - * Viewer.js v1.10.5 + * Viewer.js v1.11.6 * https://fengyuanchen.github.io/viewerjs * * Copyright 2015-present Chen Fengyuan * Released under the MIT license * - * Date: 2022-04-05T08:21:02.491Z + * Date: 2023-09-17T03:16:38.052Z */ (function (global, factory) { @@ -14,58 +14,50 @@ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Viewer = factory()); })(this, (function () { 'use strict'; - function ownKeys(object, enumerableOnly) { - var keys = Object.keys(object); - + function ownKeys(e, r) { + var t = Object.keys(e); 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); + var o = Object.getOwnPropertySymbols(e); + r && (o = o.filter(function (r) { + return Object.getOwnPropertyDescriptor(e, r).enumerable; + })), t.push.apply(t, o); } - - return keys; + return t; } - - 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)); + function _objectSpread2(e) { + for (var r = 1; r < arguments.length; r++) { + var t = null != arguments[r] ? arguments[r] : {}; + r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { + _defineProperty(e, r, t[r]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { + Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } - - return target; + return e; } - - function _typeof(obj) { + function _typeof(o) { "@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); + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { + return typeof o; + } : function (o) { + return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; + }, _typeof(o); } - 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); + Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } - function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); @@ -74,8 +66,8 @@ }); return Constructor; } - function _defineProperty(obj, key, value) { + key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, @@ -86,9 +78,22 @@ } else { obj[key] = value; } - return obj; } + function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); + } + function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + return typeof key === "symbol" ? key : String(key); + } var DEFAULTS = { /** @@ -97,213 +102,183 @@ * @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. + * Define the initial coverage of the viewing image. + * @type {number} + */ + initialCoverage: 0.9, + /** + * Define the initial index of the 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} @@ -333,12 +308,14 @@ 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 NAMESPACE = 'viewer'; + // Actions var ACTION_MOVE = 'move'; var ACTION_SWITCH = 'switch'; - var ACTION_ZOOM = 'zoom'; // Classes + var ACTION_ZOOM = 'zoom'; + // Classes var CLASS_ACTIVE = "".concat(NAMESPACE, "-active"); var CLASS_CLOSE = "".concat(NAMESPACE, "-close"); var CLASS_FADE = "".concat(NAMESPACE, "-fade"); @@ -355,8 +332,9 @@ 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 CLASS_TRANSITION = "".concat(NAMESPACE, "-transition"); + // Native events var EVENT_CLICK = 'click'; var EVENT_DBLCLICK = 'dblclick'; var EVENT_DRAG_START = 'dragstart'; @@ -372,8 +350,9 @@ 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_WHEEL = 'wheel'; + // Custom events var EVENT_READY = 'ready'; var EVENT_SHOW = 'show'; var EVENT_SHOWN = 'shown'; @@ -390,12 +369,15 @@ var EVENT_ZOOM = 'zoom'; var EVENT_ZOOMED = 'zoomed'; var EVENT_PLAY = 'play'; - var EVENT_STOP = 'stop'; // Data keys + var EVENT_STOP = 'stop'; - var DATA_ACTION = "".concat(NAMESPACE, "Action"); // RegExps + // Data keys + var DATA_ACTION = "".concat(NAMESPACE, "Action"); - var REGEXP_SPACES = /\s\s*/; // Misc + // 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']; /** @@ -403,54 +385,52 @@ * @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; @@ -459,30 +439,27 @@ 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 */ - ) { + 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; @@ -494,21 +471,19 @@ }); } } - 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)) { @@ -518,127 +493,116 @@ } }); } - 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` - + } + // IE10-11 doesn't support the second parameter of `classList.toggle` if (added) { addClass(element, value); } else { @@ -646,40 +610,38 @@ } } 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; @@ -689,21 +651,16 @@ 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} @@ -716,9 +673,9 @@ 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. @@ -726,32 +683,27 @@ * @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. @@ -759,41 +711,34 @@ * @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; - + 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. @@ -802,10 +747,10 @@ * @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 + 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, @@ -816,15 +761,14 @@ 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 { @@ -832,41 +776,36 @@ 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; + 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 - + } + // 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, @@ -874,6 +813,7 @@ transform: transform }; } + /** * Get an image name from an image url. * @param {string} url - The target url. @@ -882,11 +822,11 @@ * 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); + var IS_SAFARI = WINDOW.navigator && /Version\/\d+(\.\d+)+?\s+Safari/i.test(WINDOW.navigator.userAgent); + /** * Get an image's natural sizes. * @param {string} image - The target image. @@ -894,72 +834,63 @@ * @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) + 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 + 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]; @@ -979,16 +910,16 @@ }); 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; + pageY = _ref2.pageY; var end = { endX: pageX, endY: pageY @@ -999,19 +930,19 @@ 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; + startY = _ref3.startY; pageX += startX; pageY += startY; count += 1; @@ -1047,9 +978,8 @@ }, initViewer: function initViewer() { var options = this.options, - parent = this.parent; + parent = this.parent; var viewerData; - if (options.inline) { viewerData = { width: Math.max(parent.offsetWidth, options.minWidth), @@ -1057,11 +987,9 @@ }; this.parentData = viewerData; } - if (this.fulled || !viewerData) { viewerData = this.containerData; } - this.viewerData = assign({}, viewerData); }, renderViewer: function renderViewer() { @@ -1071,40 +999,37 @@ }, 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 + 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; + if (options.navbar) { + 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); @@ -1116,25 +1041,20 @@ 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); } @@ -1142,7 +1062,6 @@ once: true }); }); - if (options.transition) { addListener(element, EVENT_VIEWED, function () { addClass(list, CLASS_TRANSITION); @@ -1154,16 +1073,15 @@ 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 + var outerWidth = offsetWidth + gutter; + // Place the active item in the center of the screen setStyle(this.list, assign({ width: outerWidth * this.length - gutter }, getTransforms({ @@ -1180,10 +1098,9 @@ }, initImage: function initImage(done) { var _this2 = this; - var options = this.options, - image = this.image, - viewerData = this.viewerData; + image = this.image, + viewerData = this.viewerData; var footerHeight = this.footer.offsetHeight; var viewerWidth = viewerData.width; var viewerHeight = Math.max(viewerData.height - footerHeight, footerHeight); @@ -1196,18 +1113,18 @@ }; sizingImage = getImageNaturalSizes(image, options, function (naturalWidth, naturalHeight) { var aspectRatio = naturalWidth / naturalHeight; + var initialCoverage = Math.max(0, Math.min(1, options.initialCoverage)); 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); + initialCoverage = isNumber(initialCoverage) ? initialCoverage : 0.9; + width = Math.min(width * initialCoverage, naturalWidth); + height = Math.min(height * initialCoverage, naturalHeight); var left = (viewerWidth - width) / 2; var top = (viewerHeight - height) / 2; var imageData = { @@ -1224,22 +1141,18 @@ 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(); } @@ -1247,9 +1160,8 @@ }, renderImage: function renderImage(done) { var _this3 = this; - var image = this.image, - imageData = this.imageData; + imageData = this.imageData; setStyle(image, assign({ width: imageData.width, height: imageData.height, @@ -1257,14 +1169,12 @@ 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); @@ -1279,16 +1189,14 @@ } }, resetImage: function resetImage() { - // this.image only defined after viewed - if (this.viewing || this.viewed) { - var image = this.image; - + var image = this.image; + if (image) { if (this.viewing) { this.viewing.abort(); } - image.parentNode.removeChild(image); this.image = null; + this.title.innerHTML = ''; } } }; @@ -1296,8 +1204,8 @@ var events = { bind: function bind() { var options = this.options, - viewer = this.viewer, - canvas = this.canvas; + 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)); @@ -1306,22 +1214,20 @@ 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; + viewer = this.viewer, + canvas = this.canvas; var document = this.element.ownerDocument; removeListener(viewer, EVENT_CLICK, this.onClick); removeListener(viewer, EVENT_DRAG_START, this.onDragStart); @@ -1330,14 +1236,12 @@ 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); } @@ -1347,20 +1251,18 @@ var handlers = { click: function click(event) { var options = this.options, - imageData = this.imageData; + imageData = this.imageData; var target = event.target; var 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. - + } + // 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) { @@ -1374,115 +1276,93 @@ } else { this.hide(); } - break; - case 'hide': - this.hide(); + if (!this.pointerMoved) { + 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. - + } + // 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; + 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, @@ -1503,7 +1383,6 @@ var aspectRatio = naturalWidth / naturalHeight; var width = parentWidth; var height = parentHeight; - if (parentHeight * aspectRatio > parentWidth) { if (filled) { width = parentHeight * aspectRatio; @@ -1515,7 +1394,6 @@ } else { width = parentHeight * aspectRatio; } - setStyle(image, assign({ width: width, height: height @@ -1527,27 +1405,21 @@ }, 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: @@ -1558,56 +1430,64 @@ this.exit(); } } else { - this.hide(); + this.reset(); } - break; - // Space + // Space case 32: if (this.played) { this.stop(); } - break; - // ArrowLeft + // ArrowLeft case 37: - this.prev(options.loop); + if (this.played && this.playing) { + this.playing.prev(); + } else { + this.prev(options.loop); + } break; - // ArrowUp + // ArrowUp case 38: // Prevent scroll on Firefox - event.preventDefault(); // Zoom in + event.preventDefault(); + // Zoom in this.zoom(options.zoomRatio, true); break; - // ArrowRight + // ArrowRight case 39: - this.next(options.loop); + if (this.played && this.playing) { + this.playing.next(); + } else { + this.next(options.loop); + } break; - // ArrowDown + // ArrowDown case 40: // Prevent scroll on Firefox - event.preventDefault(); // Zoom out + event.preventDefault(); + // Zoom out this.zoom(-options.zoomRatio, true); break; + // Ctrl + 0 + case 48: + // Fall through - case 48: // Fall through // Ctrl + 1 // eslint-disable-next-line no-fallthrough - case 49: if (event.ctrlKey) { event.preventDefault(); this.toggle(); } - break; } }, @@ -1618,20 +1498,24 @@ }, pointerdown: function pointerdown(event) { var options = this.options, - pointers = this.pointers; + pointers = this.pointers; var buttons = event.buttons, - button = event.button; + button = event.button; + this.pointerMoved = false; + 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 - 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 + // Open context menu || event.ctrlKey)) { return; - } // Prevent default behaviours as page zooming in touch devices. - + } + // Prevent default behaviours as page zooming in touch devices. event.preventDefault(); - if (event.changedTouches) { forEach(event.changedTouches, function (touch) { pointers[touch.identifier] = getPointer(touch); @@ -1639,31 +1523,24 @@ } 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; - + 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)); @@ -1671,17 +1548,14 @@ } 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; + action = this.action, + pointers = this.pointers; var pointer; - if (event.changedTouches) { forEach(event.changedTouches, function (touch) { pointer = pointers[touch.identifier]; @@ -1691,42 +1565,39 @@ 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; - this.action = false; // Emulate click and double click in touch devices to support backdrop and image zooming (#210). - + // 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.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.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 () { @@ -1740,34 +1611,28 @@ }, 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 @@ -1778,24 +1643,21 @@ }, wheel: function wheel(event) { var _this4 = this; - if (!this.viewed) { return; } + event.preventDefault(); - event.preventDefault(); // Limit wheel speed to prevent zoom too fast - + // 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) { @@ -1803,8 +1665,7 @@ } else if (event.detail) { delta = event.detail > 0 ? 1 : -1; } - - this.zoom(-delta * ratio, true, event); + this.zoom(-delta * ratio, true, null, event); } }; @@ -1816,36 +1677,28 @@ show: function show() { var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var element = this.element, - options = this.options; - + 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; @@ -1854,7 +1707,6 @@ 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 = { @@ -1863,8 +1715,9 @@ removeClass(viewer, CLASS_IN); } }; - addClass(viewer, CLASS_TRANSITION); // Force reflow to enable CSS3 transition + addClass(viewer, CLASS_TRANSITION); + // Force reflow to enable CSS3 transition viewer.initialOffsetWidth = viewer.offsetWidth; addListener(viewer, EVENT_TRANSITION_END, shown, { once: true @@ -1874,10 +1727,8 @@ 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. @@ -1885,56 +1736,43 @@ */ hide: function hide() { var _this = this; - var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var element = this.element, - options = this.options; - + 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; - + 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)) { @@ -1944,7 +1782,6 @@ hideImmediately(); } }; - this.transitioning = { abort: function abort() { if (_this.viewed && hasClass(image, CLASS_TRANSITION)) { @@ -1953,24 +1790,23 @@ 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. + }; + // 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); + this.zoomTo(0, false, null, 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. @@ -1978,27 +1814,22 @@ */ 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; + options = this.options, + title = this.title, + canvas = this.canvas; var item = this.items[index]; var img = item.querySelector('img'); var url = getData(img, 'originalUrl'); @@ -2006,20 +1837,17 @@ 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, @@ -2027,44 +1855,39 @@ }) === 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 + canvas.appendChild(image); - this.renderList(); // Clear title + // Center current item + this.renderList(); - title.innerHTML = ''; // Generate title after viewed + // 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, { @@ -2073,7 +1896,6 @@ this.viewing = { abort: function abort() { removeListener(element, EVENT_VIEWED, onViewed); - if (image.complete) { if (_this2.imageRendering) { _this2.imageRendering.abort(); @@ -2084,55 +1906,46 @@ // 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 - + } + // 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 @@ -2142,15 +1955,12 @@ 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 @@ -2161,15 +1971,12 @@ 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. @@ -2182,7 +1989,6 @@ 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. @@ -2192,41 +1998,33 @@ */ 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; + 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, @@ -2236,7 +2034,6 @@ }) === false) { return this; } - imageData.x = x; imageData.y = y; imageData.left = x; @@ -2244,13 +2041,11 @@ 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, @@ -2263,10 +2058,8 @@ }); } } - return this; }, - /** * Rotate the image with a relative degree. * @param {number} degree - The rotate degree. @@ -2276,7 +2069,6 @@ this.rotateTo((this.imageData.rotate || 0) + Number(degree)); return this; }, - /** * Rotate the image to an absolute degree. * @param {number} degree - The rotate degree. @@ -2284,39 +2076,32 @@ */ rotateTo: function rotateTo(degree) { var _this4 = this; - var element = this.element, - options = this.options, - imageData = this.imageData; + 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 @@ -2325,10 +2110,8 @@ }); }); } - return this; }, - /** * Scale the image on the x-axis. * @param {number} scaleX - The scale ratio on the x-axis. @@ -2338,7 +2121,6 @@ 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. @@ -2348,7 +2130,6 @@ this.scale(this.imageData.scaleX, _scaleY); return this; }, - /** * Scale the image. * @param {number} scaleX - The scale ratio on the x-axis. @@ -2357,38 +2138,32 @@ */ 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; + 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, @@ -2397,19 +2172,16 @@ }) === 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, @@ -2421,103 +2193,88 @@ }); } } - 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 {boolean} [showTooltip=false] - Indicates whether to show the tooltip. + * @param {Object} [pivot] - The pivot point coordinate for zooming. * @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 showTooltip = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var pivot = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + var _originalEvent = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 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); + this.zoomTo(imageData.width * ratio / imageData.naturalWidth, showTooltip, pivot, _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 {boolean} [showTooltip] - Indicates whether to show the tooltip. + * @param {Object} [pivot] - The pivot point coordinate for zooming. * @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 showTooltip = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var pivot = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + var _originalEvent = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + var _zoomable = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; var element = this.element, - options = this.options, - pointers = this.pointers, - imageData = this.imageData; + 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; + 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, @@ -2525,24 +2282,25 @@ }) === 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 + }; + // 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 if (isPlainObject(pivot) && isNumber(pivot.x) && isNumber(pivot.y)) { + imageData.x -= offsetWidth * ((pivot.x - x) / width); + imageData.y -= offsetHeight * ((pivot.y - 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; @@ -2551,13 +2309,11 @@ 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, @@ -2566,15 +2322,12 @@ cancelable: false }); }); - - if (hasTooltip) { + if (showTooltip) { this.tooltip(); } } - return this; }, - /** * Play the images * @param {boolean|FullscreenOptions} [fullscreen=false] - Indicate if request fullscreen or not. @@ -2582,26 +2335,20 @@ */ 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; - + 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 = []; @@ -2609,11 +2356,9 @@ 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'); @@ -2624,61 +2369,63 @@ 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); + var prev = function prev() { + clearTimeout(_this7.playing.timeout); + removeClass(list[index], CLASS_IN); + index -= 1; + index = index >= 0 ? index : total - 1; + addClass(list[index], CLASS_IN); + _this7.playing.timeout = setTimeout(prev, options.interval); + }; + var next = function next() { + clearTimeout(_this7.playing.timeout); + removeClass(list[index], CLASS_IN); + index += 1; + index = index < total ? index : 0; + addClass(list[index], CLASS_IN); + _this7.playing.timeout = setTimeout(next, options.interval); }; - if (total > 1) { - play(); + this.playing = { + prev: prev, + next: next, + timeout: setTimeout(next, options.interval) + }; } } - return this; }, // Stop play stop: function stop() { var _this8 = this; - if (!this.played) { return this; } - var element = this.element, - options = this.options; - + 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; + clearTimeout(this.playing.timeout); + this.playing = false; this.played = false; - clearTimeout(this.playing); forEach(player.getElementsByTagName('img'), function (image) { removeListener(image, EVENT_LOAD, _this8.onLoadWhenPlay); }); @@ -2690,28 +2437,22 @@ // 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; - + 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); @@ -2720,15 +2461,12 @@ 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 () { @@ -2741,38 +2479,30 @@ }); }); } - 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; - + 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'); @@ -2783,7 +2513,6 @@ this.viewerData = assign({}, this.parentData); this.renderViewer(); this.renderList(); - if (this.viewed) { this.initImage(function () { _this10.renderImage(function () { @@ -2796,34 +2525,29 @@ }); }); } - 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; - + 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.removeAttribute('aria-hidden'); + // Force reflow to enable CSS3 transition tooltipBox.initialOffsetWidth = tooltipBox.offsetWidth; addClass(tooltipBox, CLASS_IN); } else { @@ -2833,7 +2557,6 @@ } else { clearTimeout(this.tooltipping); } - this.tooltipping = setTimeout(function () { if (options.transition) { addListener(tooltipBox, EVENT_TRANSITION_END, function () { @@ -2851,12 +2574,10 @@ 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. @@ -2864,13 +2585,11 @@ */ 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); + this.zoomTo(this.imageData.oldRatio, true, null, _originalEvent); } else { - this.zoomTo(1, true, _originalEvent); + this.zoomTo(1, true, null, _originalEvent); } - return this; }, // Reset the image to its initial state @@ -2879,21 +2598,19 @@ 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 + 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)) { @@ -2904,22 +2621,20 @@ 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) + if (image.src !== img.src + + // Title changed (#408) || image.alt !== img.alt) { changedIndexes.push(i); } @@ -2931,18 +2646,17 @@ 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. + var activeItem = this.items[this.index]; + // Reactivate the current viewing item after reset the list. addClass(activeItem, CLASS_ACTIVE); activeItem.setAttribute('aria-selected', true); } @@ -2959,30 +2673,24 @@ } else { this.build(); } - return this; }, // Destroy the viewer destroy: function destroy() { var element = this.element, - options = this.options; - + 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) { @@ -2992,17 +2700,14 @@ 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) { @@ -3012,11 +2717,9 @@ this.initializing.abort(); } } - if (!options.inline) { removeListener(element, EVENT_CLICK, this.onStart); } - element[NAMESPACE] = undefined; return this; } @@ -3025,7 +2728,6 @@ var others = { getImageURL: function getImageURL(image) { var url = this.options.url; - if (isString(url)) { url = image.getAttribute(url); } else if (isFunction(url)) { @@ -3033,30 +2735,24 @@ } 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)) { return; } - while (target) { // Avoid conflicts with other modals (#474, #540) if (target.getAttribute('tabindex') !== null || target.getAttribute('aria-modal') === 'true') { return; } - target = target.parentElement; } - viewer.focus(); }); }, @@ -3069,54 +2765,49 @@ open: function open() { var body = this.body; addClass(body, CLASS_OPEN); - body.style.paddingRight = "".concat(this.scrollbarWidth + (parseFloat(this.initialBodyComputedPaddingRight) || 0), "px"); + if (this.scrollbarWidth > 0) { + 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; + if (this.scrollbarWidth > 0) { + body.style.paddingRight = this.initialBodyPaddingRight; + } }, shown: function shown() { var element = this.element, - options = this.options, - viewer = this.viewer; + 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; - + 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); @@ -3126,15 +2817,16 @@ viewer.setAttribute('aria-hidden', true); this.resetList(); this.resetImage(); + this.fulled = false; + this.viewed = false; + this.isShown = false; this.hiding = false; - if (!this.destroyed) { if (isFunction(options.hidden)) { addListener(element, EVENT_HIDDEN, options.hidden, { once: true }); } - dispatchEvent(element, EVENT_HIDDEN, null, { cancelable: false }); @@ -3142,10 +2834,10 @@ }, 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() + var documentElement = document.documentElement; + // Element.requestFullscreen() if (documentElement.requestFullscreen) { // Avoid TypeError when convert `options` to dictionary if (isPlainObject(options)) { @@ -3164,7 +2856,6 @@ }, exitFullscreen: function exitFullscreen() { var document = this.element.ownerDocument; - if (this.fulled && (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement)) { // Document.exitFullscreen() if (document.exitFullscreen) { @@ -3180,48 +2871,46 @@ }, 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) + 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); + if (offsetX !== 0 || offsetY !== 0) { + this.pointerMoved = true; + this.move(offsetX, offsetY, event); + } break; - // Zoom the current image + // Zoom the current image case ACTION_ZOOM: - this.zoom(getMaxZoomRatio(pointers), false, event); + this.zoom(getMaxZoomRatio(pointers), false, null, 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 - + } + // Override forEach(pointers, function (p) { p.startX = p.endX; p.startY = p.endY; @@ -3229,20 +2918,18 @@ }, isSwitchable: function isSwitchable() { var imageData = this.imageData, - viewerData = this.viewerData; + 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. @@ -3251,13 +2938,10 @@ */ 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; @@ -3284,28 +2968,25 @@ this.viewing = false; this.wheeling = false; this.zooming = false; + this.pointerMoved = false; this.id = getUniqueID(); this.init(); } - _createClass(Viewer, [{ key: "init", value: function init() { var _this = this; - var element = this.element, - options = this.options; - + options = this.options; if (element[NAMESPACE]) { return; } + element[NAMESPACE] = this; - element[NAMESPACE] = this; // The `focus` option requires the `keyboard` option set to `true`. - + // 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) { @@ -3320,18 +3001,16 @@ this.isImg = isImg; this.length = images.length; this.images = images; - this.initBody(); // Override `transition` option if it is not supported + 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; @@ -3339,16 +3018,15 @@ abort: function abort() { clearTimeout(timeout); } - }; // build asynchronously to keep `this.viewer` is accessible in `ready` event handler. + }; + // 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) { @@ -3382,7 +3060,6 @@ } 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)); } @@ -3395,9 +3072,8 @@ if (this.ready) { return; } - var element = this.element, - options = this.options; + options = this.options; var parent = element.parentNode; var template = document.createElement('div'); template.innerHTML = TEMPLATE; @@ -3423,82 +3099,65 @@ 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); } - 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); @@ -3506,19 +3165,16 @@ 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); @@ -3529,69 +3185,59 @@ 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; -})); +})); \ No newline at end of file