{"version":3,"file":"extensions.js","sources":["../../node_modules/photoviewer/dist/photoviewer.esm.js","../../Extensions/GalleryModule/index.js","../../node_modules/readmore-js/dist/readmore.es6.js","../../Client/utils/dom.js","../../node_modules/whatwg-fetch/fetch.js","../../Client/utils/fetch.js","../../Extensions/ViewerModule/index.js","../../Extensions/ContentListViewer/index.js","../../Extensions/EditProfileViewer/index.js","../../Extensions/HeaderModule/index.js","../../Extensions/ForumModule/index.js","../../Extensions/SpacePlayerModule/howler.min.js","../../client/extensions.js"],"sourcesContent":["/*!\n * ____ __ ______ __________ _ _____________ ____________ \n * / __ \\/ / / / __ \\/_ __/ __ \\ | / / _/ ____/ | / / ____/ __ \\\n * / /_/ / /_/ / / / / / / / / / / | / // // __/ | | /| / / __/ / /_/ /\n * / ____/ __ / /_/ / / / / /_/ /| |/ // // /___ | |/ |/ / /___/ _, _/\n * /_/ /_/ /_/\\____/ /_/ \\____/ |___/___/_____/ |__/|__/_____/_/ |_| \n *\n * photoviewer - v3.4.0\n * A JS plugin to view images just like in Windows\n * https://nzbin.github.io/photoviewer/\n *\n * Copyright (c) 2018 nzbin\n * Released under MIT License\n */\n\n// Class D\r\nvar D = function (selector, context) {\r\n return new D.fn.init(selector, context);\r\n};\n\nvar document = window.document,\r\n emptyArray = [],\r\n concat = emptyArray.concat,\r\n filter = emptyArray.filter,\r\n slice = emptyArray.slice,\r\n classCache = {},\r\n cssNumber = {\r\n 'column-count': 1,\r\n 'columns': 1,\r\n 'font-weight': 1,\r\n 'line-height': 1,\r\n 'opacity': 1,\r\n 'z-index': 1,\r\n 'zoom': 1\r\n },\r\n fragmentRE = /^\\s*<(\\w+|!)[^>]*>/,\r\n singleTagRE = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\r\n tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\r\n rootNodeRE = /^(?:body|html)$/i,\r\n // special attributes that should be get/set via method calls\r\n methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'],\r\n\r\n table = document.createElement('table'),\r\n tableRow = document.createElement('tr'),\r\n containers = {\r\n 'tr': document.createElement('tbody'),\r\n 'tbody': table,\r\n 'thead': table,\r\n 'tfoot': table,\r\n 'td': tableRow,\r\n 'th': tableRow,\r\n '*': document.createElement('div')\r\n },\r\n simpleSelectorRE = /^[\\w-]*$/,\r\n class2type = {},\r\n toString = class2type.toString,\r\n tempParent = document.createElement('div'),\r\n isArray = Array.isArray || function (arg) {\r\n return Object.prototype.toString.call(arg) === '[object Array]';\r\n },\r\n contains = document.documentElement.contains\r\n ? function (parent, node) {\r\n return parent !== node && parent.contains(node)\r\n }\r\n : function (parent, node) {\r\n while (node && (node = node.parentNode))\r\n if (node === parent) return true\r\n return false\r\n };\n\nfunction type(obj) {\r\n return obj == null\r\n ? String(obj)\r\n : class2type[toString.call(obj)] || 'object'\r\n}\r\n\r\nfunction isFunction(value) {\r\n return type(value) == 'function'\r\n}\r\n\r\nfunction isWindow(obj) {\r\n return obj != null && obj == obj.window\r\n}\r\n\r\nfunction isDocument(obj) {\r\n return obj != null && obj.nodeType == obj.DOCUMENT_NODE\r\n}\r\n\r\nfunction isObject(obj) {\r\n return type(obj) == 'object'\r\n}\r\n\r\nfunction isPlainObject(obj) {\r\n return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype\r\n}\r\n\r\nfunction likeArray(obj) {\r\n var length = !!obj && 'length' in obj && obj.length,\r\n typeRes = type(obj);\r\n\r\n return 'function' != typeRes && !isWindow(obj) && (\r\n 'array' == typeRes || length === 0 ||\r\n (typeof length == 'number' && length > 0 && (length - 1) in obj)\r\n )\r\n}\r\n\r\nfunction compact(array) {\r\n return filter.call(array, function (item) {\r\n return item != null\r\n })\r\n}\r\n\r\nfunction dasherize(str) {\r\n return str.replace(/::/g, '/')\r\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')\r\n .replace(/([a-z\\d])([A-Z])/g, '$1_$2')\r\n .replace(/_/g, '-')\r\n .toLowerCase()\r\n}\r\n\r\nfunction maybeAddPx(name, value) {\r\n return (typeof value == 'number' && !cssNumber[dasherize(name)]) ? value + 'px' : value\r\n}\r\n\r\nfunction camelize(str) {\r\n return str.replace(/-+(.)?/g, function (match, chr) {\r\n return chr ? chr.toUpperCase() : ''\r\n })\r\n}\r\n\r\nfunction classRE(name) {\r\n return name in classCache ?\r\n classCache[name] : (classCache[name] = new RegExp('(^|\\\\s)' + name + '(\\\\s|$)'))\r\n}\r\n\r\nfunction flatten(array) {\r\n return array.length > 0 ? D.fn.concat.apply([], array) : array\r\n}\r\n\r\nfunction isD(object) {\r\n return object instanceof D\r\n}\r\n\r\nfunction funcArg(context, arg, idx, payload) {\r\n return isFunction(arg) ? arg.call(context, idx, payload) : arg\r\n}\r\n\r\nfunction setAttribute(node, name, value) {\r\n value == null ? node.removeAttribute(name) : node.setAttribute(name, value);\r\n}\r\n\r\n// access className property while respecting SVGAnimatedString\r\nfunction className(node, value) {\r\n var klass = node.className || '',\r\n svg = klass && klass.baseVal !== undefined;\r\n\r\n if (value === undefined) return svg ? klass.baseVal : klass\r\n svg ? (klass.baseVal = value) : (node.className = value);\r\n}\n\nD.fn = D.prototype = {\r\n constuctor: D,\r\n length: 0,\r\n // Because a collection acts like an array\r\n // copy over these useful array functions.\r\n forEach: emptyArray.forEach,\r\n reduce: emptyArray.reduce,\r\n push: emptyArray.push,\r\n sort: emptyArray.sort,\r\n splice: emptyArray.splice,\r\n indexOf: emptyArray.indexOf,\r\n // D's counterpart to jQuery's `$.fn.init` and\r\n // takes a CSS selector and an optional context (and handles various\r\n // special cases).\r\n init: function (selector, context) {\r\n var dom;\r\n // If nothing given, return an empty D collection\r\n if (!selector) {\r\n return this\r\n }\r\n // Optimize for string selectors\r\n else if (typeof selector == 'string') {\r\n selector = selector.trim();\r\n // If it's a html fragment, create nodes from it\r\n // Note: In both Chrome 21 and Firefox 15, DOM error 12\r\n // is thrown if the fragment doesn't begin with <\r\n if (selector[0] == '<' && fragmentRE.test(selector)) {\r\n dom = D.fragment(selector, RegExp.$1, context);\r\n selector = null;\r\n }\r\n // If there's a context, create a collection on that context first, and select\r\n // nodes from there\r\n else if (context !== undefined) {\r\n return D(context).find(selector)\r\n }\r\n // If it's a CSS selector, use it to select nodes.\r\n else {\r\n dom = D.qsa(document, selector);\r\n }\r\n }\r\n // If a function is given, call it when the DOM is ready\r\n else if (isFunction(selector)) {\r\n return D(document).ready(selector)\r\n }\r\n // If a D collection is given, just return it\r\n else if (isD(selector)) {\r\n return selector\r\n }\r\n // normalize array if an array of nodes is given\r\n else if (isArray(selector)) {\r\n dom = compact(selector);\r\n }\r\n // Wrap DOM nodes.\r\n else if (isObject(selector)) {\r\n dom = [selector], selector = null;\r\n }\r\n // If there's a context, create a collection on that context first, and select\r\n // nodes from there\r\n else if (context !== undefined) {\r\n return D(context).find(selector)\r\n }\r\n // And last but no least, if it's a CSS selector, use it to select nodes.\r\n else {\r\n dom = D.qsa(document, selector);\r\n }\r\n // create a new D collection from the nodes found\r\n return D.makeArray(dom, selector, this);\r\n },\r\n // Modify the collection by adding elements to it\r\n concat: function () {\r\n var i, value, args = [];\r\n for (i = 0; i < arguments.length; i++) {\r\n value = arguments[i];\r\n args[i] = isD(value) ? value.toArray() : value;\r\n }\r\n return concat.apply(isD(this) ? this.toArray() : this, args)\r\n },\r\n // `pluck` is borrowed from Prototype.js\r\n pluck: function (property) {\r\n return D.map(this, function (el) { return el[property] })\r\n },\r\n toArray: function () {\r\n return this.get()\r\n },\r\n get: function (idx) {\r\n return idx === undefined\r\n ? slice.call(this)\r\n : this[idx >= 0 ? idx : idx + this.length]\r\n },\r\n size: function () {\r\n return this.length\r\n },\r\n each: function (callback) {\r\n emptyArray.every.call(this, function (el, idx) {\r\n return callback.call(el, idx, el) !== false\r\n });\r\n return this\r\n },\r\n map: function (fn) {\r\n return D(D.map(this, function (el, i) { return fn.call(el, i, el) }))\r\n },\r\n slice: function () {\r\n return D(slice.apply(this, arguments))\r\n },\r\n first: function () {\r\n var el = this[0];\r\n return el && !isObject(el) ? el : D(el)\r\n },\r\n last: function () {\r\n var el = this[this.length - 1];\r\n return el && !isObject(el) ? el : D(el)\r\n },\r\n eq: function (idx) {\r\n return idx === -1 ? this.slice(idx) : this.slice(idx, +idx + 1)\r\n }\r\n};\r\n\r\nD.extend = D.fn.extend = function () {\r\n var options, name, src, copy, copyIsArray, clone,\r\n target = arguments[0] || {},\r\n i = 1,\r\n length = arguments.length,\r\n deep = false;\r\n\r\n // Handle a deep copy situation\r\n if (typeof target === 'boolean') {\r\n deep = target;\r\n\r\n // Skip the boolean and the target\r\n target = arguments[i] || {};\r\n i++;\r\n }\r\n // Handle case when target is a string or something (possible in deep copy)\r\n if (typeof target !== 'object' && !isFunction(target)) {\r\n target = {};\r\n }\r\n // Extend D itself if only one argument is passed\r\n if (i === length) {\r\n target = this;\r\n i--;\r\n }\r\n for (; i < length; i++) {\r\n // Only deal with non-null/undefined values\r\n if ((options = arguments[i]) != null) {\r\n // Extend the base object\r\n for (name in options) {\r\n src = target[name];\r\n copy = options[name];\r\n // Prevent never-ending loop\r\n if (target === copy) {\r\n continue;\r\n }\r\n // Recurse if we're merging plain objects or arrays\r\n if (deep && copy && (isPlainObject(copy) ||\r\n (copyIsArray = isArray(copy)))) {\r\n if (copyIsArray) {\r\n copyIsArray = false;\r\n clone = src && isArray(src) ? src : [];\r\n } else {\r\n clone = src && isPlainObject(src) ? src : {};\r\n }\r\n // Never move original objects, clone them\r\n target[name] = D.extend(deep, clone, copy);\r\n // Don't bring in undefined values\r\n } else if (copy !== undefined) {\r\n target[name] = copy;\r\n }\r\n }\r\n }\r\n }\r\n // Return the modified object\r\n return target;\r\n};\r\n\r\nD.extend({\r\n // Make DOM Array\r\n makeArray: function (dom, selector, me) {\r\n var i, len = dom ? dom.length : 0;\r\n for (i = 0; i < len; i++) me[i] = dom[i];\r\n me.length = len;\r\n me.selector = selector || '';\r\n return me;\r\n },\r\n // D's CSS selector\r\n qsa: function (element, selector) {\r\n var found,\r\n maybeID = selector[0] == '#',\r\n maybeClass = !maybeID && selector[0] == '.',\r\n // Ensure that a 1 char tag name still gets checked\r\n nameOnly = maybeID || maybeClass ? selector.slice(1) : selector,\r\n isSimple = simpleSelectorRE.test(nameOnly);\r\n return (\r\n // Safari DocumentFragment doesn't have getElementById\r\n element.getElementById && isSimple && maybeID)\r\n ? (found = element.getElementById(nameOnly))\r\n ? [found]\r\n : []\r\n : element.nodeType !== 1 && element.nodeType !== 9 && element.nodeType !== 11\r\n ? []\r\n : slice.call(\r\n // DocumentFragment doesn't have getElementsByClassName/TagName\r\n isSimple && !maybeID && element.getElementsByClassName\r\n ? maybeClass\r\n // If it's simple, it could be a class\r\n ? element.getElementsByClassName(nameOnly)\r\n // Or a tag\r\n : element.getElementsByTagName(selector)\r\n // Or it's not simple, and we need to query all\r\n : element.querySelectorAll(selector)\r\n )\r\n },\r\n // Html -> Node\r\n fragment: function (html, name, properties) {\r\n var dom, nodes, container;\r\n\r\n // A special case optimization for a single tag\r\n if (singleTagRE.test(html)) dom = D(document.createElement(RegExp.$1));\r\n\r\n if (!dom) {\r\n if (html.replace) html = html.replace(tagExpanderRE, '<$1>$2>');\r\n if (name === undefined) name = fragmentRE.test(html) && RegExp.$1;\r\n if (!(name in containers)) name = '*';\r\n\r\n container = containers[name];\r\n container.innerHTML = '' + html;\r\n dom = D.each(slice.call(container.childNodes), function () {\r\n container.removeChild(this);\r\n });\r\n }\r\n\r\n if (isPlainObject(properties)) {\r\n nodes = D(dom);\r\n D.each(properties, function (key, value) {\r\n if (methodAttributes.indexOf(key) > -1) nodes[key](value);\r\n else nodes.attr(key, value);\r\n });\r\n }\r\n\r\n return dom\r\n },\r\n matches: function (element, selector) {\r\n if (!selector || !element || element.nodeType !== 1) return false\r\n var matchesSelector = element.matches || element.webkitMatchesSelector ||\r\n element.mozMatchesSelector || element.oMatchesSelector ||\r\n element.matchesSelector;\r\n if (matchesSelector) return matchesSelector.call(element, selector)\r\n // fall back to performing a selector:\r\n var match, parent = element.parentNode,\r\n temp = !parent;\r\n if (temp) (parent = tempParent).appendChild(element);\r\n match = ~D.qsa(parent, selector).indexOf(element);\r\n temp && tempParent.removeChild(element);\r\n return match\r\n },\r\n each: function (elements, callback) {\r\n var i, key;\r\n if (likeArray(elements)) {\r\n for (i = 0; i < elements.length; i++)\r\n if (callback.call(elements[i], i, elements[i]) === false) return elements\r\n } else {\r\n for (key in elements)\r\n if (callback.call(elements[key], key, elements[key]) === false) return elements\r\n }\r\n\r\n return elements\r\n },\r\n map: function (elements, callback) {\r\n var value, values = [],\r\n i, key;\r\n if (likeArray(elements))\r\n for (i = 0; i < elements.length; i++) {\r\n value = callback(elements[i], i);\r\n if (value != null) values.push(value);\r\n }\r\n else\r\n for (key in elements) {\r\n value = callback(elements[key], key);\r\n if (value != null) values.push(value);\r\n }\r\n return flatten(values)\r\n }\r\n});\r\n\r\n// Populate the class2type map\r\nD.each('Boolean Number String Function Array Date RegExp Object Error'.split(' '), function (i, name) {\r\n class2type['[object ' + name + ']'] = name.toLowerCase();\r\n});\r\n\r\nD.fn.init.prototype = D.fn;\r\n\r\nfunction noop() {\r\n}\n\nfunction css(property, value) {\r\n if (arguments.length < 2) {\r\n var element = this[0];\r\n if (typeof property == 'string') {\r\n if (!element) return\r\n return element.style[camelize(property)] || getComputedStyle(element, '').getPropertyValue(property)\r\n } else if (isArray(property)) {\r\n if (!element) return\r\n var props = {};\r\n var computedStyle = getComputedStyle(element, '');\r\n D.each(property, function (_, prop) {\r\n props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop));\r\n });\r\n return props\r\n }\r\n }\r\n\r\n var css = '';\r\n if (type(property) == 'string') {\r\n if (!value && value !== 0) {\r\n this.each(function () {\r\n this.style.removeProperty(dasherize(property));\r\n });\r\n } else {\r\n css = dasherize(property) + \":\" + maybeAddPx(property, value);\r\n }\r\n } else {\r\n for (var key in property) {\r\n if (!property[key] && property[key] !== 0) {\r\n this.each(function () { this.style.removeProperty(dasherize(key)); });\r\n } else {\r\n css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';';\r\n }\r\n }\r\n }\r\n\r\n return this.each(function () { this.style.cssText += ';' + css; })\r\n}\n\nfunction hasClass(name) {\r\n if (!name) return false\r\n return emptyArray.some.call(this, function (el) {\r\n return this.test(className(el))\r\n }, classRE(name))\r\n}\r\n\r\nfunction addClass(name) {\r\n var classList = [];\r\n if (!name) return this\r\n return this.each(function (idx) {\r\n if (!('className' in this)) return\r\n classList = [];\r\n var cls = className(this),\r\n newName = funcArg(this, name, idx, cls);\r\n newName.split(/\\s+/g).forEach(function (klass) {\r\n if (!D(this).hasClass(klass)) classList.push(klass);\r\n }, this);\r\n classList.length && className(this, cls + (cls ? ' ' : '') + classList.join(' '));\r\n })\r\n}\r\n\r\nfunction removeClass(name) {\r\n var classList = [];\r\n return this.each(function (idx) {\r\n if (!('className' in this)) return\r\n if (name === undefined) return className(this, '')\r\n classList = className(this);\r\n funcArg(this, name, idx, classList).split(/\\s+/g).forEach(function (klass) {\r\n classList = classList.replace(classRE(klass), ' ');\r\n });\r\n className(this, classList.trim());\r\n })\r\n}\n\nfunction offset(coordinates) {\r\n if (coordinates) return this.each(function (index) {\r\n var $this = D(this),\r\n coords = funcArg(this, coordinates, index, $this.offset()),\r\n parentOffset = $this.offsetParent().offset(),\r\n props = {\r\n top: coords.top - parentOffset.top,\r\n left: coords.left - parentOffset.left\r\n };\r\n\r\n if ($this.css('position') == 'static') props['position'] = 'relative';\r\n $this.css(props);\r\n })\r\n if (!this.length) return null\r\n if (document.documentElement !== this[0] && !contains(document.documentElement, this[0]))\r\n return { top: 0, left: 0 }\r\n var obj = this[0].getBoundingClientRect();\r\n return {\r\n left: obj.left + window.pageXOffset,\r\n top: obj.top + window.pageYOffset,\r\n width: Math.round(obj.width),\r\n height: Math.round(obj.height)\r\n }\r\n}\r\n\r\nfunction position() {\r\n if (!this.length) return\r\n\r\n var elem = this[0],\r\n // Get *real* offsetParent\r\n offsetParent = this.offsetParent(),\r\n // Get correct offsets\r\n offset = this.offset(),\r\n parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\r\n\r\n // Subtract element margins\r\n // note: when an element has margin: auto the offsetLeft and marginLeft\r\n // are the same in Safari causing offset.left to incorrectly be 0\r\n offset.top -= parseFloat(D(elem).css('margin-top')) || 0;\r\n offset.left -= parseFloat(D(elem).css('margin-left')) || 0;\r\n\r\n // Add offsetParent borders\r\n parentOffset.top += parseFloat(D(offsetParent[0]).css('border-top-width')) || 0;\r\n parentOffset.left += parseFloat(D(offsetParent[0]).css('border-left-width')) || 0;\r\n\r\n // Subtract the two offsets\r\n return {\r\n top: offset.top - parentOffset.top,\r\n left: offset.left - parentOffset.left\r\n }\r\n}\r\n\r\nfunction scrollTop(value) {\r\n if (!this.length) return\r\n var hasScrollTop = 'scrollTop' in this[0];\r\n if (value === undefined) return hasScrollTop\r\n ? this[0].scrollTop\r\n : isWindow(this[0])\r\n ? this[0].pageYOffset\r\n : this[0].defaultView.pageYOffset;\r\n return this.each(hasScrollTop ?\r\n function () { this.scrollTop = value; } :\r\n function () { this.scrollTo(this.scrollX, value); })\r\n}\r\n\r\nfunction scrollLeft(value) {\r\n if (!this.length) return\r\n var hasScrollLeft = 'scrollLeft' in this[0];\r\n if (value === undefined) return hasScrollLeft\r\n ? this[0].scrollLeft\r\n : isWindow(this[0])\r\n ? this[0].pageXOffset\r\n : this[0].defaultView.pageXOffset;\r\n return this.each(hasScrollLeft ?\r\n function () { this.scrollLeft = value; } :\r\n function () { this.scrollTo(value, this.scrollY); })\r\n}\r\n\r\nfunction offsetParent() {\r\n return this.map(function () {\r\n var parent = this.offsetParent || document.body;\r\n while (parent && !rootNodeRE.test(parent.nodeName) && D(parent).css('position') == 'static')\r\n parent = parent.offsetParent;\r\n return parent\r\n })\r\n}\n\nfunction attr(name, value) {\r\n var result;\r\n return (typeof name == 'string' && !(1 in arguments))\r\n ? (0 in this && this[0].nodeType == 1 && (result = this[0].getAttribute(name)) != null ? result : undefined)\r\n : this.each(function (idx) {\r\n if (this.nodeType !== 1) return\r\n if (isObject(name))\r\n for (var key in name) setAttribute(this, key, name[key]);\r\n else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)));\r\n })\r\n}\r\n\r\nfunction removeAttr(name) {\r\n return this.each(function () {\r\n this.nodeType === 1 && name.split(' ').forEach(function (attribute) {\r\n setAttribute(this, attribute);\r\n }, this);\r\n })\r\n}\n\nfunction find(selector) {\r\n var result, $this = this;\r\n if (!selector) result = D();\r\n else if (typeof selector == 'object')\r\n result = D(selector).filter(function () {\r\n var node = this;\r\n return emptyArray.some.call($this, function (parent) {\r\n return contains(parent, node)\r\n })\r\n });\r\n else if (this.length == 1) result = D(D.qsa(this[0], selector));\r\n else result = this.map(function () { return D.qsa(this, selector) });\r\n return result\r\n}\r\n\r\nfunction closest(selector, context) {\r\n var nodes = [],\r\n collection = typeof selector == 'object' && D(selector);\r\n this.each(function (_, node) {\r\n while (node && !(collection ? collection.indexOf(node) >= 0 : D.matches(node, selector)))\r\n node = node !== context && !isDocument(node) && node.parentNode;\r\n if (node && nodes.indexOf(node) < 0) nodes.push(node);\r\n });\r\n return D(nodes)\r\n}\n\nfunction subtract(el, dimen) {\r\n return el.css('box-sizing') === 'border-box'\r\n ? dimen === 'width'\r\n ? (parseFloat(el.css(dimen))\r\n - parseFloat(el.css('padding-left'))\r\n - parseFloat(el.css('padding-right'))\r\n - parseFloat(el.css('border-left-width'))\r\n - parseFloat(el.css('border-right-width')))\r\n : (parseFloat(el.css(dimen))\r\n - parseFloat(el.css('padding-top'))\r\n - parseFloat(el.css('padding-bottom'))\r\n - parseFloat(el.css('border-top-width'))\r\n - parseFloat(el.css('border-bottom-width')))\r\n : parseFloat(el.css(dimen))\r\n}\r\n\r\nfunction calc(dimension, value) {\r\n var dimensionProperty =\r\n dimension.replace(/./, function (m) { return m[0].toUpperCase() });\r\n\r\n var el = this[0];\r\n if (value === undefined) return isWindow(el)\r\n ? el['inner' + dimensionProperty]\r\n : isDocument(el)\r\n ? el.documentElement['scroll' + dimensionProperty]\r\n : subtract(this, dimension)\r\n else return this.each(function (idx) {\r\n el = D(this);\r\n el.css(dimension, funcArg(this, value, idx, el[dimension]()));\r\n });\r\n}\r\n\r\n// Export\r\nfunction width(value) {\r\n return calc.call(this, 'width', value);\r\n}\r\n\r\nfunction height(value) {\r\n return calc.call(this, 'height', value);\r\n}\n\nvar traverseNode = function (node, fn) {\r\n fn(node);\r\n for (var i = 0, len = node.childNodes.length; i < len; i++)\r\n traverseNode(node.childNodes[i], fn);\r\n};\r\n\r\n// inside => append, prepend\r\nvar domMani = function (elem, args, fn, inside) {\r\n // arguments can be nodes, arrays of nodes, D objects and HTML strings\r\n var argType,\r\n nodes = D.map(args, function (arg) {\r\n var arr = [];\r\n argType = type(arg);\r\n if (argType == 'array') {\r\n arg.forEach(function (el) {\r\n if (el.nodeType !== undefined) return arr.push(el)\r\n else if (isD(el)) return arr = arr.concat(el.get())\r\n arr = arr.concat(D.fragment(el));\r\n });\r\n return arr\r\n }\r\n return argType == 'object' || arg == null ? arg : D.fragment(arg)\r\n }),\r\n parent,\r\n copyByClone = elem.length > 1;\r\n\r\n if (nodes.length < 1) return elem\r\n\r\n return elem.each(function (_, target) {\r\n parent = inside ? target : target.parentNode;\r\n var parentInDocument = contains(document.documentElement, parent);\r\n\r\n nodes.forEach(function (node) {\r\n if (copyByClone) node = node.cloneNode(true);\r\n else if (!parent) return D(node).remove()\r\n\r\n fn.call(target, node);\r\n\r\n if (parentInDocument) {\r\n traverseNode(node, function (el) {\r\n if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' &&\r\n (!el.type || el.type === 'text/javascript') && !el.src) {\r\n var target = el.ownerDocument ? el.ownerDocument.defaultView : window;\r\n target['eval'].call(target, el.innerHTML);\r\n }\r\n });\r\n }\r\n });\r\n });\r\n};\r\n\r\n// Export\r\nfunction remove() {\r\n return this.each(function () {\r\n if (this.parentNode != null)\r\n this.parentNode.removeChild(this);\r\n })\r\n}\r\n\r\nfunction empty() {\r\n return this.each(function () { this.innerHTML = ''; })\r\n}\r\n\r\nfunction html(html) {\r\n return 0 in arguments\r\n ? this.each(function (idx) {\r\n var originHtml = this.innerHTML;\r\n D(this).empty().append(funcArg(this, html, idx, originHtml));\r\n })\r\n : (0 in this ? this[0].innerHTML : null)\r\n}\r\n\r\nfunction append() {\r\n return domMani(this, arguments, function (elem) {\r\n this.insertBefore(elem, null);\r\n }, true);\r\n}\n\nvar _zid = 1;\r\nfunction zid(element) {\r\n return element._zid || (element._zid = _zid++)\r\n}\r\n\r\nfunction isString(obj) {\r\n return typeof obj == 'string'\r\n}\r\n\r\nvar returnTrue = function () { return true },\r\n returnFalse = function () { return false },\r\n eventMethods = {\r\n preventDefault: 'isDefaultPrevented',\r\n stopImmediatePropagation: 'isImmediatePropagationStopped',\r\n stopPropagation: 'isPropagationStopped'\r\n };\r\n\r\nfunction compatible(event, source) {\r\n if (source || !event.isDefaultPrevented) {\r\n source || (source = event);\r\n\r\n D.each(eventMethods, function (name, predicate) {\r\n var sourceMethod = source[name];\r\n event[name] = function () {\r\n this[predicate] = returnTrue;\r\n return sourceMethod && sourceMethod.apply(source, arguments)\r\n };\r\n event[predicate] = returnFalse;\r\n });\r\n\r\n try {\r\n event.timeStamp || (event.timeStamp = Date.now());\r\n } catch (ignored) { }\r\n\r\n if (source.defaultPrevented !== undefined ? source.defaultPrevented :\r\n 'returnValue' in source ? source.returnValue === false :\r\n source.getPreventDefault && source.getPreventDefault())\r\n event.isDefaultPrevented = returnTrue;\r\n }\r\n return event\r\n}\n\nvar handlers = {},\r\n focusinSupported = 'onfocusin' in window,\r\n focus = { focus: 'focusin', blur: 'focusout' },\r\n hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' },\r\n ignoreProperties = /^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/;\r\n\r\nfunction parse(event) {\r\n var parts = ('' + event).split('.');\r\n return { e: parts[0], ns: parts.slice(1).sort().join(' ') }\r\n}\r\nfunction matcherFor(ns) {\r\n return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')\r\n}\r\n\r\nfunction findHandlers(element, event, fn, selector) {\r\n event = parse(event);\r\n if (event.ns) var matcher = matcherFor(event.ns);\r\n return (handlers[zid(element)] || []).filter(function (handler) {\r\n return handler\r\n && (!event.e || handler.e == event.e)\r\n && (!event.ns || matcher.test(handler.ns))\r\n && (!fn || zid(handler.fn) === zid(fn))\r\n && (!selector || handler.sel == selector)\r\n })\r\n}\r\n\r\nfunction eventCapture(handler, captureSetting) {\r\n return handler.del &&\r\n (!focusinSupported && (handler.e in focus)) ||\r\n !!captureSetting\r\n}\r\n\r\nfunction realEvent(type$$1) {\r\n return hover[type$$1] || (focusinSupported && focus[type$$1]) || type$$1\r\n}\r\n\r\nfunction add$1(element, events, fn, data, selector, delegator, capture) {\r\n var id = zid(element), set = (handlers[id] || (handlers[id] = []));\r\n events.split(/\\s/).forEach(function (event) {\r\n if (event == 'ready') return D(document).ready(fn)\r\n var handler = parse(event);\r\n handler.fn = fn;\r\n handler.sel = selector;\r\n // emulate mouseenter, mouseleave\r\n if (handler.e in hover) fn = function (e) {\r\n var related = e.relatedTarget;\r\n if (!related || (related !== this && !contains(this, related)))\r\n return handler.fn.apply(this, arguments)\r\n };\r\n handler.del = delegator;\r\n var callback = delegator || fn;\r\n handler.proxy = function (e) {\r\n e = compatible(e);\r\n if (e.isImmediatePropagationStopped()) return\r\n e.data = data;\r\n var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args));\r\n if (result === false) e.preventDefault(), e.stopPropagation();\r\n return result\r\n };\r\n handler.i = set.length;\r\n set.push(handler);\r\n if ('addEventListener' in element)\r\n element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture));\r\n });\r\n}\r\n\r\nfunction remove$1(element, events, fn, selector, capture) {\r\n var id = zid(element)\r\n ; (events || '').split(/\\s/).forEach(function (event) {\r\n findHandlers(element, event, fn, selector).forEach(function (handler) {\r\n delete handlers[id][handler.i];\r\n if ('removeEventListener' in element)\r\n element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture));\r\n });\r\n });\r\n}\r\n\r\nfunction createProxy(event) {\r\n var key, proxy = { originalEvent: event };\r\n for (key in event)\r\n if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key];\r\n\r\n return compatible(proxy, event)\r\n}\r\n\r\nvar on = function (event, selector, data, callback, one) {\r\n var autoRemove, delegator, $this = this;\r\n if (event && !isString(event)) {\r\n D.each(event, function (type$$1, fn) {\r\n $this.on(type$$1, selector, data, fn, one);\r\n });\r\n return $this\r\n }\r\n\r\n if (!isString(selector) && !isFunction(callback) && callback !== false)\r\n callback = data, data = selector, selector = undefined;\r\n if (callback === undefined || data === false)\r\n callback = data, data = undefined;\r\n\r\n if (callback === false) callback = returnFalse;\r\n\r\n return $this.each(function (_, element) {\r\n if (one) autoRemove = function (e) {\r\n remove$1(element, e.type, callback);\r\n return callback.apply(this, arguments)\r\n };\r\n\r\n if (selector) delegator = function (e) {\r\n var evt, match = D(e.target).closest(selector, element).get(0);\r\n if (match && match !== element) {\r\n evt = D.extend(createProxy(e), { currentTarget: match, liveFired: element });\r\n return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))\r\n }\r\n };\r\n\r\n add$1(element, event, callback, data, selector, delegator || autoRemove);\r\n })\r\n};\r\n\r\nvar off = function (event, selector, callback) {\r\n var $this = this;\r\n if (event && !isString(event)) {\r\n D.each(event, function (type$$1, fn) {\r\n $this.off(type$$1, selector, fn);\r\n });\r\n return $this\r\n }\r\n\r\n if (!isString(selector) && !isFunction(callback) && callback !== false)\r\n callback = selector, selector = undefined;\r\n\r\n if (callback === false) callback = returnFalse;\r\n\r\n return $this.each(function () {\r\n remove$1(this, event, callback, selector);\r\n })\r\n};\n\nvar prefix = '',\r\n eventPrefix,\r\n vendors = { Webkit: 'webkit', Moz: '', O: 'o' },\r\n testEl = document.createElement('div'),\r\n testTransitionProperty = testEl.style.transitionProperty;\r\nif (testEl.style.transform === undefined) D.each(vendors, function (vendor, event) {\r\n if (testEl.style[vendor + 'TransitionProperty'] !== undefined) {\r\n prefix = '-' + vendor.toLowerCase() + '-';\r\n eventPrefix = event;\r\n return false\r\n }\r\n});\r\n\r\ntestEl = null;\n\n// fx cannot seperate\r\nfunction normalizeEvent(name) {\r\n return eventPrefix ? eventPrefix + name : name.toLowerCase()\r\n}\r\n\r\nD.fx = {\r\n off: (eventPrefix === undefined && testTransitionProperty === undefined),\r\n speeds: { _default: 400, fast: 200, slow: 600 },\r\n cssPrefix: prefix,\r\n transitionEnd: normalizeEvent('TransitionEnd'),\r\n animationEnd: normalizeEvent('AnimationEnd')\r\n};\r\n\r\nvar supportedTransforms = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,\r\n transform,\r\n transitionProperty, transitionDuration, transitionTiming, transitionDelay,\r\n animationName, animationDuration, animationTiming, animationDelay,\r\n cssReset = {};\r\n\r\nfunction dasherize$1(str) { return str.replace(/([A-Z])/g, '-$1').toLowerCase() }\r\n\r\ntransform = prefix + 'transform';\r\ncssReset[transitionProperty = prefix + 'transition-property'] =\r\n cssReset[transitionDuration = prefix + 'transition-duration'] =\r\n cssReset[transitionDelay = prefix + 'transition-delay'] =\r\n cssReset[transitionTiming = prefix + 'transition-timing-function'] =\r\n cssReset[animationName = prefix + 'animation-name'] =\r\n cssReset[animationDuration = prefix + 'animation-duration'] =\r\n cssReset[animationDelay = prefix + 'animation-delay'] =\r\n cssReset[animationTiming = prefix + 'animation-timing-function'] = '';\r\n\r\nvar anim = function (properties, duration, ease, callback, delay) {\r\n var key, cssValues = {}, cssProperties, transforms = '',\r\n that = this, wrappedCallback, endEvent = D.fx.transitionEnd,\r\n fired = false;\r\n\r\n if (duration === undefined) duration = D.fx.speeds._default / 1000;\r\n if (delay === undefined) delay = 0;\r\n if (D.fx.off) duration = 0;\r\n\r\n if (typeof properties == 'string') {\r\n // keyframe animation\r\n cssValues[animationName] = properties;\r\n cssValues[animationDuration] = duration + 's';\r\n cssValues[animationDelay] = delay + 's';\r\n cssValues[animationTiming] = (ease || 'linear');\r\n endEvent = D.fx.animationEnd;\r\n } else {\r\n cssProperties = [];\r\n // CSS transitions\r\n for (key in properties)\r\n if (supportedTransforms.test(key)) transforms += key + '(' + properties[key] + ') ';\r\n else cssValues[key] = properties[key], cssProperties.push(dasherize$1(key));\r\n\r\n if (transforms) cssValues[transform] = transforms, cssProperties.push(transform);\r\n if (duration > 0 && typeof properties === 'object') {\r\n cssValues[transitionProperty] = cssProperties.join(', ');\r\n cssValues[transitionDuration] = duration + 's';\r\n cssValues[transitionDelay] = delay + 's';\r\n cssValues[transitionTiming] = (ease || 'linear');\r\n }\r\n }\r\n\r\n wrappedCallback = function (event) {\r\n if (typeof event !== 'undefined') {\r\n if (event.target !== event.currentTarget) return // makes sure the event didn't bubble from \"below\"\r\n D(event.target).off(endEvent, wrappedCallback);\r\n } else\r\n D(this).off(endEvent, wrappedCallback); // triggered by setTimeout\r\n\r\n fired = true;\r\n D(this).css(cssReset);\r\n callback && callback.call(this);\r\n };\r\n if (duration > 0) {\r\n this.on(endEvent, wrappedCallback);\r\n // transitionEnd is not always firing on older Android phones\r\n // so make sure it gets fired\r\n setTimeout(function () {\r\n if (fired) return\r\n wrappedCallback.call(that);\r\n }, ((duration + delay) * 1000) + 25);\r\n }\r\n\r\n // trigger page reflow so new elements can animate\r\n this.size() && this.get(0).clientLeft;\r\n\r\n this.css(cssValues);\r\n\r\n if (duration <= 0) setTimeout(function () {\r\n that.each(function () { wrappedCallback.call(this); });\r\n }, 0);\r\n\r\n return this\r\n};\r\n\r\nvar animate = function (properties, duration, ease, callback, delay) {\r\n if (isFunction(duration))\r\n callback = duration, ease = undefined, duration = undefined;\r\n if (isFunction(ease))\r\n callback = ease, ease = undefined;\r\n if (isPlainObject(duration))\r\n ease = duration.easing, callback = duration.complete, delay = duration.delay, duration = duration.duration;\r\n if (duration) duration = (typeof duration == 'number' ? duration :\r\n (D.fx.speeds[duration] || D.fx.speeds._default)) / 1000;\r\n if (delay) delay = parseFloat(delay) / 1000;\r\n return this.anim(properties, duration, ease, callback, delay)\r\n};\n\nvar origShow = function () {\r\n return this.each(function () {\r\n this.style.display == \"none\" && (this.style.display = '');\r\n if (getComputedStyle(this, '').getPropertyValue(\"display\") == \"none\")\r\n this.style.display = defaultDisplay(this.nodeName);\r\n })\r\n};\r\n\r\nvar origHide = function () {\r\n return this.css(\"display\", \"none\")\r\n};\r\n\r\nfunction anim$1(el, speed, opacity, scale, callback) {\r\n if (typeof speed == 'function' && !callback) callback = speed, speed = undefined;\r\n var props = { opacity: opacity };\r\n if (scale) {\r\n props.scale = scale;\r\n el.css(D.fx.cssPrefix + 'transform-origin', '0 0');\r\n }\r\n return el.animate(props, speed, null, callback)\r\n}\r\n\r\nfunction hideHelper(el, speed, scale, callback) {\r\n return anim$1(el, speed, 0, scale, function () {\r\n origHide.call(D(this));\r\n callback && callback.call(this);\r\n })\r\n}\r\n\r\n// Export\r\nvar show = function (speed, callback) {\r\n origShow.call(this);\r\n if (speed === undefined) speed = 0;\r\n else this.css('opacity', 0);\r\n return anim$1(this, speed, 1, '1,1', callback)\r\n};\r\n\r\nvar hide = function (speed, callback) {\r\n if (speed === undefined) return origHide.call(this)\r\n else return hideHelper(this, speed, '0,0', callback)\r\n};\r\n\r\nvar fadeTo = function (speed, opacity, callback) {\r\n return anim$1(this, speed, opacity, null, callback)\r\n};\r\n\r\nvar fadeIn = function (speed, callback) {\r\n var target = this.css('opacity');\r\n if (target > 0) this.css('opacity', 0);\r\n else target = 1;\r\n return origShow.call(this).fadeTo(speed, target, callback)\r\n};\n\nvar $$1 = D;\nvar methods = {\n isArray: isArray,\n noop: noop\n};\nvar fnMethods = {\n find: find,\n closest: closest,\n css: css,\n addClass: addClass,\n hasClass: hasClass,\n removeClass: removeClass,\n attr: attr,\n removeAttr: removeAttr,\n append: append,\n remove: remove,\n empty: empty,\n html: html,\n width: width,\n height: height,\n scrollTop: scrollTop,\n scrollLeft: scrollLeft,\n offset: offset,\n offsetParent: offsetParent,\n position: position,\n on: on,\n off: off,\n show: show,\n hide: hide,\n anim: anim,\n animate: animate,\n fadeTo: fadeTo,\n fadeIn: fadeIn\n};\n$$1.extend(methods);\n$$1.fn.extend(fnMethods);\n\nvar DEFAULTS = {\n // Enable modal to drag\n draggable: true,\n // Enable modal to resize\n resizable: true,\n // Enable image to move\n movable: true,\n // Enable keyboard navigation\n keyboard: true,\n // Shows the title\n title: true,\n // Min width of modal\n modalWidth: 320,\n // Min height of modal\n modalHeight: 320,\n // Enable the page content fixed\n fixedContent: true,\n // Disable the modal size fixed\n fixedModalSize: false,\n // Disable the image viewer maximized on init\n initMaximized: false,\n // Threshold of modal to browser window\n gapThreshold: 0.02,\n // Threshold of image ratio\n ratioThreshold: 0.1,\n // Min ratio of image when zoom out\n minRatio: 0.05,\n // Max ratio of image when zoom in\n maxRatio: 16,\n // Toolbar options in header\n headToolbar: ['maximize', 'close'],\n // Toolbar options in footer\n footToolbar: ['zoomIn', 'zoomOut', 'prev', 'fullscreen', 'next', 'actualSize', 'rotateRight'],\n // Customize button icon\n icons: {\n minimize: \"\",\n maximize: \"\",\n close: \"\",\n zoomIn: \"\",\n zoomOut: \"\",\n prev: \"\",\n next: \"\",\n fullscreen: \"\",\n actualSize: \"\",\n rotateLeft: \"\",\n rotateRight: \"\"\n },\n // Customize language of button title\n i18n: {\n minimize: 'minimize',\n maximize: 'maximize',\n close: 'close',\n zoomIn: 'zoom-in(+)',\n zoomOut: 'zoom-out(-)',\n prev: 'prev(←)',\n next: 'next(→)',\n fullscreen: 'fullscreen',\n actualSize: 'actual-size(Ctrl+Alt+0)',\n rotateLeft: 'rotate-left(Ctrl+,)',\n rotateRight: 'rotate-right(Ctrl+.)'\n },\n // Enable multiple instances\n multiInstances: true,\n // Enable animation\n initAnimation: true,\n // Disable modal position fixed when change images\n fixedModalPos: false,\n // Modal z-index\n zIndex: 1090,\n // Selector of drag handler\n dragHandle: false,\n // Callback events\n callbacks: {\n beforeOpen: $$1.noop,\n opened: $$1.noop,\n beforeClose: $$1.noop,\n closed: $$1.noop,\n beforeChange: $$1.noop,\n changed: $$1.noop\n },\n // Start images index\n index: 0,\n // Load the image progressively\n progressiveLoading: true,\n // The DOM element to which viewer will be added\n appendTo: 'body'\n};\n\nvar document$1 = window.document;\n/**\n * Throttle function\n * @param {Function} fn - The function will be triggered\n * @param {Number} delay - The throttle delay time\n * @return {Function}\n */\n\nfunction throttle(fn, delay) {\n var timer = null;\n return function () {\n var context = this,\n args = arguments;\n clearTimeout(timer);\n timer = setTimeout(function () {\n fn.apply(context, args);\n }, delay);\n };\n}\n/**\n * Preload a image\n * @param {String} src - The image src\n * @param {Function} success - The callback of success\n * @param {Function} error - The callback of error\n */\n\nfunction preloadImg(src, success, error) {\n var img = new Image();\n\n img.onload = function () {\n success(img);\n };\n\n img.onerror = function () {\n error(img);\n };\n\n img.src = src;\n}\n/**\n * Request fullscreen\n * @param {type} element\n */\n\nfunction requestFullscreen(element) {\n if (element.requestFullscreen) {\n element.requestFullscreen();\n } else if (element.mozRequestFullScreen) {\n element.mozRequestFullScreen();\n } else if (element.webkitRequestFullscreen) {\n element.webkitRequestFullscreen();\n } else if (element.msRequestFullscreen) {\n element.msRequestFullscreen();\n }\n}\n/**\n * Get the image name from its url\n * @param {String} url- The image src\n * @return {String}\n */\n\nfunction getImageNameFromUrl(url) {\n var reg = /^.*?\\/*([^/?]*)\\.[a-z]+(\\?.+|$)/gi,\n txt = url.replace(reg, '$1');\n return txt;\n}\n/**\n * Check if the document has a scrollbar\n * @return {Boolean}\n */\n\nfunction hasScrollbar() {\n return document$1.body.scrollHeight > (window.innerHeight || document$1.documentElement.clientHeight);\n}\n/**\n * Get the scrollbar width\n * @return {Number}\n */\n\nfunction getScrollbarWidth() {\n var scrollDiv = document$1.createElement('div');\n scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';\n document$1.body.appendChild(scrollDiv);\n var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;\n document$1.body.removeChild(scrollDiv);\n return scrollbarWidth;\n}\n/**\n * Set grab cursor when move image\n * @param {Object} imageData - The image data\n * @param {Object} stageData - The stage data\n * @param {Object} stage - The stage element\n * @param {Boolean} isRotate - The image rotated flag\n */\n\nfunction setGrabCursor(imageData, stageData, stage, isRotated) {\n var imageWidth = !isRotated ? imageData.w : imageData.h,\n imageHeight = !isRotated ? imageData.h : imageData.w;\n\n if (imageHeight > stageData.h || imageWidth > stageData.w) {\n stage.addClass('is-grab');\n }\n\n if (imageHeight <= stageData.h && imageWidth <= stageData.w) {\n stage.removeClass('is-grab');\n }\n}\n/**\n * Check if browser support touch event\n * @return {Boolean}\n */\n\nfunction supportTouch() {\n return !!('ontouchstart' in window || window.DocumentTouch && document$1 instanceof DocumentTouch);\n}\n\nvar $W = $$1(window);\nvar $D = $$1(document$1);\nvar CLICK_EVENT = 'click';\nvar RESIZE_EVENT = 'resize';\nvar KEYDOWN_EVENT = 'keydown';\nvar WHEEL_EVENT = 'wheel mousewheel DOMMouseScroll';\nvar TOUCH_START_EVENT = supportTouch() ? 'touchstart' : 'mousedown';\nvar TOUCH_MOVE_EVENT = supportTouch() ? 'touchmove' : 'mousemove';\nvar TOUCH_END_EVENT = supportTouch() ? 'touchend' : 'mouseup';\nvar NS = 'photoviewer';\nvar CLASS_NS = '.' + NS;\nvar EVENT_NS = '.' + NS;\nvar PUBLIC_VARS = {\n // Image moving flag\n isMoving: false,\n // Modal resizing flag\n isResizing: false,\n // Modal z-index setting\n zIndex: 0\n};\n\nvar draggable = {\n /**\n * Draggable\n * @param {Object} modal - The modal element\n * @param {Object} dragHandle - The handle element when dragging\n * @param {Object} dragCancel - The cancel element when dragging\n */\n draggable: function draggable(modal, dragHandle, dragCancel) {\n var _this = this;\n\n var isDragging = false;\n var startX = 0,\n startY = 0,\n left = 0,\n top = 0;\n\n var dragStart = function dragStart(e) {\n e = e || window.event; // Must be removed\n // e.preventDefault();\n // Get clicked button\n\n var elemCancel = $$1(e.target).closest(dragCancel); // Stop modal moving when click buttons\n\n if (elemCancel.length) {\n return true;\n }\n\n if (_this.options.multiInstances) {\n modal.css('z-index', ++PUBLIC_VARS['zIndex']);\n }\n\n isDragging = true;\n startX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.clientX;\n startY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.clientY;\n left = $$1(modal).offset().left;\n top = $$1(modal).offset().top;\n $D.on(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).on(TOUCH_END_EVENT + EVENT_NS, dragEnd);\n };\n\n var dragMove = function dragMove(e) {\n e = e || window.event;\n e.preventDefault();\n\n if (isDragging && !PUBLIC_VARS['isMoving'] && !PUBLIC_VARS['isResizing'] && !_this.isMaximized) {\n var endX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.clientX,\n endY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.clientY,\n relativeX = endX - startX,\n relativeY = endY - startY;\n $$1(modal).css({\n left: relativeX + left + 'px',\n top: relativeY + top + 'px'\n });\n }\n };\n\n var dragEnd = function dragEnd() {\n $D.off(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).off(TOUCH_END_EVENT + EVENT_NS, dragEnd);\n isDragging = false;\n };\n\n $$1(dragHandle).on(TOUCH_START_EVENT + EVENT_NS, dragStart);\n }\n};\n\nvar ELEMS_WITH_GRABBING_CURSOR = \"html,body,.\" + NS + \"-modal,.\" + NS + \"-stage,.\" + NS + \"-button,.\" + NS + \"-resizable-handle\";\nvar movable = {\n /**\n * --------------------------------------------------------------------------\n * 1. No movable\n * 2. Vertical movable\n * 3. Horizontal movable\n * 4. Vertical & Horizontal movable\n * --------------------------------------------------------------------------\n *\n * Image movable\n * @param {Object} stage - The stage element\n * @param {Object} image - The image element\n */\n movable: function movable(stage, image) {\n var _this = this;\n\n var isDragging = false;\n var startX = 0,\n startY = 0,\n left = 0,\n top = 0,\n widthDiff = 0,\n heightDiff = 0,\n δ = 0;\n\n var dragStart = function dragStart(e) {\n e = e || window.event;\n e.preventDefault();\n var imageWidth = $$1(image).width(),\n imageHeight = $$1(image).height(),\n stageWidth = $$1(stage).width(),\n stageHeight = $$1(stage).height();\n startX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.clientX;\n startY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.clientY; // δ is the difference between image width and height\n\n δ = !_this.isRotated ? 0 : (imageWidth - imageHeight) / 2; // Width or height difference can be use to limit image right or top position\n\n widthDiff = !_this.isRotated ? imageWidth - stageWidth : imageHeight - stageWidth;\n heightDiff = !_this.isRotated ? imageHeight - stageHeight : imageWidth - stageHeight; // Modal can be dragging if image is smaller to stage\n\n isDragging = widthDiff > 0 || heightDiff > 0 ? true : false;\n PUBLIC_VARS['isMoving'] = widthDiff > 0 || heightDiff > 0 ? true : false; // Reclac the element position when mousedown\n // Fixed the issue of stage with a border\n\n left = $$1(image).position().left - δ;\n top = $$1(image).position().top + δ; // Add grabbing cursor\n\n if (stage.hasClass('is-grab')) {\n $$1(ELEMS_WITH_GRABBING_CURSOR).addClass('is-grabbing');\n }\n\n $D.on(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).on(TOUCH_END_EVENT + EVENT_NS, dragEnd);\n };\n\n var dragMove = function dragMove(e) {\n e = e || window.event;\n e.preventDefault();\n\n if (isDragging) {\n var endX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.clientX,\n endY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.clientY,\n relativeX = endX - startX,\n relativeY = endY - startY,\n newLeft = relativeX + left,\n newTop = relativeY + top; // Vertical limit\n\n if (heightDiff > 0) {\n if (relativeY + top > δ) {\n newTop = δ;\n } else if (relativeY + top < -heightDiff + δ) {\n newTop = -heightDiff + δ;\n }\n } else {\n newTop = top;\n } // Horizontal limit\n\n\n if (widthDiff > 0) {\n if (relativeX + left > -δ) {\n newLeft = -δ;\n } else if (relativeX + left < -widthDiff - δ) {\n newLeft = -widthDiff - δ;\n }\n } else {\n newLeft = left;\n }\n\n $$1(image).css({\n left: newLeft + 'px',\n top: newTop + 'px'\n }); // Update image initial data\n\n $$1.extend(_this.imageData, {\n left: newLeft,\n top: newTop\n });\n }\n };\n\n var dragEnd = function dragEnd() {\n $D.off(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).off(TOUCH_END_EVENT + EVENT_NS, dragEnd);\n isDragging = false;\n PUBLIC_VARS['isMoving'] = false; // Remove grabbing cursor\n\n $$1(ELEMS_WITH_GRABBING_CURSOR).removeClass('is-grabbing');\n };\n\n $$1(stage).on(TOUCH_START_EVENT + EVENT_NS, dragStart);\n }\n};\n\nvar ELEMS_WITH_RESIZE_CURSOR = \"html,body,.\" + NS + \"-modal,.\" + NS + \"-stage,.\" + NS + \"-button\";\nvar resizable = {\n /**\n * --------------------------------------------------------------------------\n * 1. Modal resizable\n * 2. Keep image in stage center\n * 3. Other image limitations\n * --------------------------------------------------------------------------\n *\n * Resizable\n * @param {Object} modal - The modal element\n * @param {Object} stage - The stage element\n * @param {Object} image - The image element\n * @param {Number} minWidth - The option of modalWidth\n * @param {Number} minHeight - The option of modalHeight\n */\n resizable: function resizable(modal, stage, image, minWidth, minHeight) {\n var _this = this;\n\n var resizableHandleE = $$1(\"
\"),\n resizableHandleW = $$1(\"\"),\n resizableHandleS = $$1(\"\"),\n resizableHandleN = $$1(\"\"),\n resizableHandleSE = $$1(\"\"),\n resizableHandleSW = $$1(\"\"),\n resizableHandleNE = $$1(\"\"),\n resizableHandleNW = $$1(\"\");\n var resizableHandles = {\n e: resizableHandleE,\n s: resizableHandleS,\n se: resizableHandleSE,\n n: resizableHandleN,\n w: resizableHandleW,\n nw: resizableHandleNW,\n ne: resizableHandleNE,\n sw: resizableHandleSW\n };\n $$1(modal).append(resizableHandleE, resizableHandleW, resizableHandleS, resizableHandleN, resizableHandleSE, resizableHandleSW, resizableHandleNE, resizableHandleNW);\n var isDragging = false;\n var startX = 0,\n startY = 0,\n modalData = {\n w: 0,\n h: 0,\n l: 0,\n t: 0\n },\n stageData = {\n w: 0,\n h: 0,\n l: 0,\n t: 0\n },\n imageData = {\n w: 0,\n h: 0,\n l: 0,\n t: 0\n },\n // δ is the difference between image width and height\n δ = 0,\n imgWidth = 0,\n imgHeight = 0,\n direction = ''; // Modal CSS options\n\n var getModalOpts = function getModalOpts(dir, offsetX, offsetY) {\n // Modal should not move when its width to the minwidth\n var modalLeft = -offsetX + modalData.w > minWidth ? offsetX + modalData.l : modalData.l + modalData.w - minWidth,\n modalTop = -offsetY + modalData.h > minHeight ? offsetY + modalData.t : modalData.t + modalData.h - minHeight;\n var opts = {\n e: {\n width: Math.max(offsetX + modalData.w, minWidth) + 'px'\n },\n s: {\n height: Math.max(offsetY + modalData.h, minHeight) + 'px'\n },\n se: {\n width: Math.max(offsetX + modalData.w, minWidth) + 'px',\n height: Math.max(offsetY + modalData.h, minHeight) + 'px'\n },\n w: {\n width: Math.max(-offsetX + modalData.w, minWidth) + 'px',\n left: modalLeft + 'px'\n },\n n: {\n height: Math.max(-offsetY + modalData.h, minHeight) + 'px',\n top: modalTop + 'px'\n },\n nw: {\n width: Math.max(-offsetX + modalData.w, minWidth) + 'px',\n height: Math.max(-offsetY + modalData.h, minHeight) + 'px',\n top: modalTop + 'px',\n left: modalLeft + 'px'\n },\n ne: {\n width: Math.max(offsetX + modalData.w, minWidth) + 'px',\n height: Math.max(-offsetY + modalData.h, minHeight) + 'px',\n top: modalTop + 'px'\n },\n sw: {\n width: Math.max(-offsetX + modalData.w, minWidth) + 'px',\n height: Math.max(offsetY + modalData.h, minHeight) + 'px',\n left: modalLeft + 'px'\n }\n };\n return opts[dir];\n }; // Image CSS options\n\n\n var getImageOpts = function getImageOpts(dir, offsetX, offsetY) {\n // Image should not move when modal width to the min width\n // The minwidth is modal width, so we should clac the stage minwidth\n var widthDiff = offsetX + modalData.w > minWidth ? stageData.w - imgWidth + offsetX - δ : minWidth - (modalData.w - stageData.w) - imgWidth - δ,\n heightDiff = offsetY + modalData.h > minHeight ? stageData.h - imgHeight + offsetY + δ : minHeight - (modalData.h - stageData.h) - imgHeight + δ,\n widthDiff2 = -offsetX + modalData.w > minWidth ? stageData.w - imgWidth - offsetX - δ : minWidth - (modalData.w - stageData.w) - imgWidth - δ,\n heightDiff2 = -offsetY + modalData.h > minHeight ? stageData.h - imgHeight - offsetY + δ : minHeight - (modalData.h - stageData.h) - imgHeight + δ; // Get image position in dragging\n\n var imgLeft = (widthDiff > 0 ? $$1(image).position().left : $$1(image).position().left < 0 ? $$1(image).position().left : 0) - δ,\n imgTop = (heightDiff > 0 ? $$1(image).position().top : $$1(image).position().top < 0 ? $$1(image).position().top : 0) + δ,\n imgLeft2 = (widthDiff2 > 0 ? $$1(image).position().left : $$1(image).position().left < 0 ? $$1(image).position().left : 0) - δ,\n imgTop2 = (heightDiff2 > 0 ? $$1(image).position().top : $$1(image).position().top < 0 ? $$1(image).position().top : 0) + δ;\n var opts = {\n e: {\n left: widthDiff >= -δ ? (widthDiff - δ) / 2 + 'px' : imgLeft > widthDiff ? imgLeft + 'px' : widthDiff + 'px'\n },\n s: {\n top: heightDiff >= δ ? (heightDiff + δ) / 2 + 'px' : imgTop > heightDiff ? imgTop + 'px' : heightDiff + 'px'\n },\n se: {\n top: heightDiff >= δ ? (heightDiff + δ) / 2 + 'px' : imgTop > heightDiff ? imgTop + 'px' : heightDiff + 'px',\n left: widthDiff >= -δ ? (widthDiff - δ) / 2 + 'px' : imgLeft > widthDiff ? imgLeft + 'px' : widthDiff + 'px'\n },\n w: {\n left: widthDiff2 >= -δ ? (widthDiff2 - δ) / 2 + 'px' : imgLeft2 > widthDiff2 ? imgLeft2 + 'px' : widthDiff2 + 'px'\n },\n n: {\n top: heightDiff2 >= δ ? (heightDiff2 + δ) / 2 + 'px' : imgTop2 > heightDiff2 ? imgTop2 + 'px' : heightDiff2 + 'px'\n },\n nw: {\n top: heightDiff2 >= δ ? (heightDiff2 + δ) / 2 + 'px' : imgTop2 > heightDiff2 ? imgTop2 + 'px' : heightDiff2 + 'px',\n left: widthDiff2 >= -δ ? (widthDiff2 - δ) / 2 + 'px' : imgLeft2 > widthDiff2 ? imgLeft2 + 'px' : widthDiff2 + 'px'\n },\n ne: {\n top: heightDiff2 >= δ ? (heightDiff2 + δ) / 2 + 'px' : imgTop2 > heightDiff2 ? imgTop2 + 'px' : heightDiff2 + 'px',\n left: widthDiff >= -δ ? (widthDiff - δ) / 2 + 'px' : imgLeft > widthDiff ? imgLeft + 'px' : widthDiff + 'px'\n },\n sw: {\n top: heightDiff >= δ ? (heightDiff + δ) / 2 + 'px' : imgTop > heightDiff ? imgTop + 'px' : heightDiff + 'px',\n left: widthDiff2 >= -δ ? (widthDiff2 - δ) / 2 + 'px' : imgLeft2 > widthDiff2 ? imgLeft2 + 'px' : widthDiff2 + 'px'\n }\n };\n return opts[dir];\n };\n\n var dragStart = function dragStart(dir, e) {\n e = e || window.event;\n e.preventDefault();\n isDragging = true;\n PUBLIC_VARS['isResizing'] = true;\n startX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.clientX;\n startY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.clientY; // Reclac the modal data when mousedown\n\n modalData = {\n w: $$1(modal).width(),\n h: $$1(modal).height(),\n l: $$1(modal).offset().left,\n t: $$1(modal).offset().top\n };\n stageData = {\n w: $$1(stage).width(),\n h: $$1(stage).height(),\n l: $$1(stage).offset().left,\n t: $$1(stage).offset().top\n };\n imageData = {\n w: $$1(image).width(),\n h: $$1(image).height(),\n l: $$1(image).position().left,\n t: $$1(image).position().top\n }; // δ is the difference between image width and height\n\n δ = !_this.isRotated ? 0 : (imageData.w - imageData.h) / 2;\n imgWidth = !_this.isRotated ? imageData.w : imageData.h;\n imgHeight = !_this.isRotated ? imageData.h : imageData.w;\n direction = dir; // Add resizable cursor\n\n $$1(ELEMS_WITH_RESIZE_CURSOR).css('cursor', dir + '-resize');\n $D.on(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).on(TOUCH_END_EVENT + EVENT_NS, dragEnd);\n };\n\n var dragMove = function dragMove(e) {\n e = e || window.event;\n e.preventDefault();\n\n if (isDragging && !_this.isMaximized) {\n var endX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.clientX,\n endY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.clientY,\n relativeX = endX - startX,\n relativeY = endY - startY;\n var modalOpts = getModalOpts(direction, relativeX, relativeY);\n $$1(modal).css(modalOpts);\n var imageOpts = getImageOpts(direction, relativeX, relativeY);\n $$1(image).css(imageOpts);\n _this.isDoResize = true;\n }\n };\n\n var dragEnd = function dragEnd() {\n $D.off(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).off(TOUCH_END_EVENT + EVENT_NS, dragEnd); // Set grab cursor\n\n if (PUBLIC_VARS['isResizing']) {\n setGrabCursor({\n w: imgWidth,\n h: imgHeight\n }, {\n w: $$1(stage).width(),\n h: $$1(stage).height()\n }, stage);\n }\n\n isDragging = false;\n PUBLIC_VARS['isResizing'] = false; // Remove resizable cursor\n\n $$1(ELEMS_WITH_RESIZE_CURSOR).css('cursor', ''); // Update image initial data\n\n var scale = _this.getImageScaleToStage($$1(stage).width(), $$1(stage).height());\n\n $$1.extend(_this.imageData, {\n initWidth: _this.img.width * scale,\n initHeight: _this.img.height * scale,\n initLeft: ($$1(stage).width() - _this.img.width * scale) / 2,\n initTop: ($$1(stage).height() - _this.img.height * scale) / 2\n });\n };\n\n $$1.each(resizableHandles, function (dir, handle) {\n handle.on(TOUCH_START_EVENT + EVENT_NS, function (e) {\n dragStart(dir, e);\n });\n });\n }\n};\n\n/**\n * PhotoViewer class\n */\n\nvar PhotoViewer =\n/*#__PURE__*/\nfunction () {\n function PhotoViewer(items, options, el) {\n this.options = $$1.extend(true, {}, DEFAULTS, options);\n\n if (options && $$1.isArray(options.footToolbar)) {\n this.options.footToolbar = options.footToolbar;\n }\n\n if (options && $$1.isArray(options.headToolbar)) {\n this.options.headToolbar = options.headToolbar;\n } // Store element of clicked\n\n\n this.$el = $$1(el); // As we have multiple instances,\n // so every instance has following variables.\n // Modal open flag\n\n this.isOpened = false; // Modal maximize flag\n\n this.isMaximized = false; // Image rotate 90*(2n+1) flag\n\n this.isRotated = false; // Image rotate angle\n\n this.rotateAngle = 0; // If modal do resize\n\n this.isDoResize = false; // Store image data in every instance\n\n this.imageData = {}; // Store modal data in every instance\n\n this.modalData = {\n width: null,\n height: null,\n left: null,\n top: null\n };\n this.init(items, this.options);\n }\n\n var _proto = PhotoViewer.prototype;\n\n _proto.init = function init(items, opts) {\n this.groupData = items;\n this.groupIndex = opts['index']; // Fix https://github.com/nzbin/photoviewer/issues/7\n\n PUBLIC_VARS['zIndex'] = PUBLIC_VARS['zIndex'] === 0 ? opts['zIndex'] : PUBLIC_VARS['zIndex']; // Get image src\n\n var imgSrc = items[this.groupIndex]['src'];\n this.open();\n this.loadImg(imgSrc); // Draggable & Movable & Resizable\n\n if (opts.draggable) {\n this.draggable(this.$photoviewer, this.dragHandle, CLASS_NS + '-button');\n }\n\n if (opts.movable) {\n this.movable(this.$stage, this.$image);\n }\n\n if (opts.resizable) {\n this.resizable(this.$photoviewer, this.$stage, this.$image, opts.modalWidth, opts.modalHeight);\n }\n };\n\n _proto._createBtns = function _createBtns(toolbar, btns) {\n var btnsStr = '';\n $$1.each(toolbar, function (index, item) {\n btnsStr += btns[item];\n });\n return btnsStr;\n };\n\n _proto._createTitle = function _createTitle() {\n return this.options.title ? \"\" : '';\n };\n\n _proto.render = function render() {\n var btnsTpl = {\n minimize: \"\",\n maximize: \"\",\n close: \"\",\n zoomIn: \"\",\n zoomOut: \"\",\n prev: \"\",\n next: \"\",\n fullscreen: \"\",\n actualSize: \"\",\n rotateLeft: \"\",\n rotateRight: \"\"\n }; // PhotoViewer base HTML\n\n var photoviewerHTML = \"