/*! * viewer.js v1.10.4 * https://fengyuanchen.github.io/viewerjs * * copyright 2015-present chen fengyuan * released under the mit license * * date: 2022-02-13t08:40:00.127z */ (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); 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); } 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; }));