{"version":3,"file":"photoviewer.js","sources":["../src/js/defaults.js","../src/js/utilities.js","../src/js/constants.js","../src/js/draggable.js","../src/js/movable.js","../src/js/resizable.js","../src/js/core.js"],"sourcesContent":["export default {\r\n\r\n // Enable modal to drag\r\n draggable: true,\r\n\r\n // Enable modal to resize\r\n resizable: true,\r\n\r\n // Enable image to move\r\n movable: true,\r\n\r\n // Enable keyboard navigation\r\n keyboard: true,\r\n\r\n // Shows the title\r\n title: true,\r\n\r\n // Min width of modal\r\n modalWidth: 320,\r\n\r\n // Min height of modal\r\n modalHeight: 320,\r\n\r\n // Enable the page content fixed\r\n fixedContent: true,\r\n\r\n // Disable the modal size fixed\r\n fixedModalSize: false,\r\n\r\n // Disable the image viewer maximized on init\r\n initMaximized: false,\r\n\r\n // Threshold of modal to browser window\r\n gapThreshold: 0.02,\r\n\r\n // Threshold of image ratio\r\n ratioThreshold: 0.1,\r\n\r\n // Min ratio of image when zoom out\r\n minRatio: 0.05,\r\n\r\n // Max ratio of image when zoom in\r\n maxRatio: 16,\r\n\r\n // Toolbar options in header\r\n headToolbar: [\r\n 'maximize',\r\n 'close'\r\n ],\r\n\r\n // Toolbar options in footer\r\n footToolbar: [\r\n 'zoomIn',\r\n 'zoomOut',\r\n 'prev',\r\n 'fullscreen',\r\n 'next',\r\n 'actualSize',\r\n 'rotateRight'\r\n ],\r\n\r\n // Customize button icon\r\n icons: {\r\n minimize: ``,\r\n maximize: ``,\r\n close: ``,\r\n zoomIn: ``,\r\n zoomOut: ``,\r\n prev: ``,\r\n next: ``,\r\n fullscreen: ``,\r\n actualSize: ``,\r\n rotateLeft: ``,\r\n rotateRight: ``\r\n },\r\n\r\n // Customize language of button title\r\n i18n: {\r\n minimize: 'minimize',\r\n maximize: 'maximize',\r\n close: 'close',\r\n zoomIn: 'zoom-in(+)',\r\n zoomOut: 'zoom-out(-)',\r\n prev: 'prev(←)',\r\n next: 'next(→)',\r\n fullscreen: 'fullscreen',\r\n actualSize: 'actual-size(Ctrl+Alt+0)',\r\n rotateLeft: 'rotate-left(Ctrl+,)',\r\n rotateRight: 'rotate-right(Ctrl+.)'\r\n },\r\n\r\n // Enable multiple instances\r\n multiInstances: true,\r\n\r\n // Enable animation\r\n initAnimation: true,\r\n\r\n // Disable modal position fixed when change images\r\n fixedModalPos: false,\r\n\r\n // Modal z-index\r\n zIndex: 1090,\r\n\r\n // Selector of drag handler\r\n dragHandle: false,\r\n\r\n // Callback events\r\n callbacks: {\r\n beforeOpen: $.noop,\r\n opened: $.noop,\r\n beforeClose: $.noop,\r\n closed: $.noop,\r\n beforeChange: $.noop,\r\n changed: $.noop\r\n },\r\n\r\n // Start images index\r\n index: 0,\r\n\r\n // Load the image progressively\r\n progressiveLoading: true\r\n\r\n}\r\n","/**\r\n * [getImgSrc]\r\n * @param {[Object]} el [description]\r\n */\r\nexport function getImgSrc(el) {\r\n // Get data-src as image src at first\r\n let src = $(el).attr('data-src')\r\n ? $(el).attr('data-src')\r\n : $(el).attr('href');\r\n return src;\r\n}\r\n\r\n/**\r\n * [throttle]\r\n * @param {Function} fn [description]\r\n * @param {[Number]} delay [description]\r\n * @return {Function} [description]\r\n */\r\nexport function throttle(fn, delay) {\r\n\r\n let timer = null;\r\n\r\n return function () {\r\n let context = this,\r\n args = arguments;\r\n\r\n clearTimeout(timer);\r\n\r\n timer = setTimeout(function () {\r\n fn.apply(context, args);\r\n }, delay);\r\n };\r\n\r\n}\r\n\r\n/**\r\n * [preloadImg]\r\n * @param {[String]} src [image src]\r\n * @param {Function} success [callbacks]\r\n * @param {Function} error [callbacks]\r\n */\r\nexport function preloadImg(src, success, error) {\r\n\r\n let img = new Image();\r\n\r\n img.onload = function () {\r\n success(img);\r\n };\r\n\r\n img.onerror = function () {\r\n error(img);\r\n };\r\n\r\n img.src = src;\r\n\r\n}\r\n\r\n/**\r\n * [requestFullscreen]\r\n * @param {[type]} element [description]\r\n */\r\nexport function requestFullscreen(element) {\r\n if (element.requestFullscreen) {\r\n element.requestFullscreen();\r\n } else if (element.mozRequestFullScreen) {\r\n element.mozRequestFullScreen();\r\n } else if (element.webkitRequestFullscreen) {\r\n element.webkitRequestFullscreen();\r\n } else if (element.msRequestFullscreen) {\r\n element.msRequestFullscreen();\r\n }\r\n}\r\n\r\n/**\r\n * [exitFullscreen]\r\n */\r\nexport function exitFullscreen() {\r\n if (document.exitFullscreen) {\r\n document.exitFullscreen();\r\n } else if (document.mozCancelFullScreen) {\r\n document.mozCancelFullScreen();\r\n } else if (document.webkitExitFullscreen) {\r\n document.webkitExitFullscreen();\r\n }\r\n}\r\n\r\n/**\r\n * [getImageNameFromUrl]\r\n * @param {[String]} url [description]\r\n * @return {[String]} [description]\r\n */\r\nexport function getImageNameFromUrl(url) {\r\n let reg = /^.*?\\/*([^/?]*)\\.[a-z]+(\\?.+|$)/ig,\r\n txt = url.replace(reg, '$1');\r\n return txt;\r\n}\r\n\r\n/**\r\n * [getNumFromCSSValue]\r\n * @param {[String]} value [description]\r\n * @return {[Number]} [description]\r\n */\r\nexport function getNumFromCSSValue(value) {\r\n let reg = /\\d+/g,\r\n arr = value.match(reg),\r\n num = parseFloat(arr[0]);\r\n return num;\r\n}\r\n\r\n/**\r\n * [hasScrollbar]\r\n * @return {[Boolean]} [description]\r\n */\r\nexport function hasScrollbar() {\r\n return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight);\r\n}\r\n\r\n/**\r\n * [getScrollbarWidth]\r\n * @return {[Number]} [description]\r\n */\r\nexport function getScrollbarWidth() {\r\n\r\n let scrollDiv = document.createElement('div');\r\n scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';\r\n document.body.appendChild(scrollDiv);\r\n let scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;\r\n document.body.removeChild(scrollDiv);\r\n\r\n return scrollbarWidth;\r\n\r\n}\r\n\r\n/**\r\n * [setGrabCursor]\r\n * @param {[Object]} imageData [description]\r\n * @param {[Object]} stageData [description]\r\n * @param {[Object]} stage [description]\r\n * @param {[Boolean]} isRotate [description]\r\n */\r\nexport function setGrabCursor(imageData, stageData, stage, isRotated) {\r\n\r\n let imageWidth = !isRotated ? imageData.w : imageData.h,\r\n imageHeight = !isRotated ? imageData.h : imageData.w;\r\n\r\n if (imageHeight > stageData.h || imageWidth > stageData.w) {\r\n stage.addClass('is-grab');\r\n }\r\n if (imageHeight <= stageData.h && imageWidth <= stageData.w) {\r\n stage.removeClass('is-grab');\r\n }\r\n}\r\n\r\n/**\r\n * [supportTouch]\r\n * @return {[Boolean]} [description]\r\n */\r\nexport function supportTouch() {\r\n return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);\r\n}\r\n","import defaults from './defaults';\nimport { supportTouch } from './utilities';\n\nexport const $W = $(window);\nexport const $D = $(document);\n\nexport const CLICK_EVENT = 'click';\nexport const RESIZE_EVENT = 'resize';\nexport const KEYDOWN_EVENT = 'keydown';\nexport const WHEEL_EVENT = 'wheel mousewheel DOMMouseScroll';\n\nexport const TOUCH_START_EVENT = supportTouch() ? 'touchstart' : 'mousedown';\nexport const TOUCH_MOVE_EVENT = supportTouch() ? 'touchmove' : 'mousemove';\nexport const TOUCH_END_EVENT = supportTouch() ? 'touchend' : 'mouseup';\n\nexport const NS = 'photoviewer';\nexport const CLASS_NS = '.' + NS;\nexport const EVENT_NS = '.' + NS;\n\nexport const PUBLIC_VARS = {\n // image moving flag\n isMoving: false,\n // modal resizing flag\n isResizing: false,\n // modal z-index setting\n zIndex: defaults.zIndex,\n};\n","import {\r\n $D,\r\n TOUCH_START_EVENT,\r\n TOUCH_MOVE_EVENT,\r\n TOUCH_END_EVENT,\r\n EVENT_NS,\r\n PUBLIC_VARS\r\n} from './constants';\r\n\r\nexport default {\r\n\r\n /**\r\n * [draggable]\r\n * @param {[Object]} modal [the modal element]\r\n * @param {[Object]} dragHandle [the handle element when dragging]\r\n * @param {[Object]} dragCancel [the cancel element when dragging]\r\n */\r\n draggable(modal, dragHandle, dragCancel) {\r\n\r\n let isDragging = false;\r\n\r\n let startX = 0,\r\n startY = 0,\r\n\r\n left = 0,\r\n top = 0;\r\n\r\n let dragStart = (e) => {\r\n\r\n e = e || window.event;\r\n\r\n // Must be removed\r\n // e.preventDefault();\r\n\r\n if (this.options.multiInstances) {\r\n modal.css('z-index', ++PUBLIC_VARS['zIndex']);\r\n }\r\n\r\n // Get clicked button\r\n let elemCancel = $(e.target).closest(dragCancel);\r\n // Stop modal moving when click buttons\r\n if (elemCancel.length) {\r\n return true;\r\n }\r\n\r\n isDragging = true;\r\n\r\n startX = e.type === 'touchstart'\r\n ? e.originalEvent.targetTouches[0].pageX\r\n : e.clientX;\r\n startY = e.type === 'touchstart'\r\n ? e.originalEvent.targetTouches[0].pageY\r\n : e.clientY;\r\n\r\n left = $(modal).offset().left;\r\n top = $(modal).offset().top;\r\n\r\n $D.on(TOUCH_MOVE_EVENT + EVENT_NS, dragMove)\r\n .on(TOUCH_END_EVENT + EVENT_NS, dragEnd);\r\n\r\n };\r\n\r\n let dragMove = (e) => {\r\n\r\n e = e || window.event;\r\n\r\n e.preventDefault();\r\n\r\n if (isDragging && !PUBLIC_VARS['isMoving'] && !PUBLIC_VARS['isResizing'] && !this.isMaximized) {\r\n\r\n let endX = e.type === 'touchmove'\r\n ? e.originalEvent.targetTouches[0].pageX\r\n : e.clientX,\r\n endY = e.type === 'touchmove'\r\n ? e.originalEvent.targetTouches[0].pageY\r\n : e.clientY,\r\n\r\n relativeX = endX - startX,\r\n relativeY = endY - startY;\r\n\r\n $(modal).css({\r\n left: relativeX + left + 'px',\r\n top: relativeY + top + 'px'\r\n });\r\n\r\n }\r\n\r\n };\r\n\r\n let dragEnd = () => {\r\n\r\n $D.off(TOUCH_MOVE_EVENT + EVENT_NS, dragMove)\r\n .off(TOUCH_END_EVENT + EVENT_NS, dragEnd);\r\n\r\n isDragging = false;\r\n\r\n };\r\n\r\n $(dragHandle).on(TOUCH_START_EVENT + EVENT_NS, dragStart);\r\n\r\n }\r\n\r\n}\r\n","import {\r\n $D,\r\n TOUCH_START_EVENT,\r\n TOUCH_MOVE_EVENT,\r\n TOUCH_END_EVENT,\r\n NS,\r\n EVENT_NS,\r\n PUBLIC_VARS\r\n} from './constants';\r\n\r\nconst ELEMS_WITH_GRABBING_CURSOR = `html,body,.${NS}-modal,.${NS}-stage,.${NS}-button,.${NS}-resizable-handle`;\r\n\r\nexport default {\r\n\r\n /**\r\n * --------------------------------------\r\n * 1.no movable\r\n * 2.vertical movable\r\n * 3.horizontal movable\r\n * 4.vertical & horizontal movable\r\n * --------------------------------------\r\n *\r\n * [image movable]\r\n * @param {[Object]} stage [the stage element]\r\n * @param {[Object]} image [the image element]\r\n */\r\n movable(stage, image) {\r\n\r\n let isDragging = false;\r\n\r\n let startX = 0,\r\n startY = 0,\r\n\r\n left = 0,\r\n top = 0,\r\n\r\n widthDiff = 0,\r\n heightDiff = 0,\r\n\r\n δ = 0;\r\n\r\n let dragStart = (e) => {\r\n\r\n e = e || window.event;\r\n\r\n e.preventDefault();\r\n\r\n let imageWidth = $(image).width(),\r\n imageHeight = $(image).height(),\r\n stageWidth = $(stage).width(),\r\n stageHeight = $(stage).height();\r\n\r\n startX = e.type === 'touchstart'\r\n ? e.originalEvent.targetTouches[0].pageX\r\n : e.clientX;\r\n startY = e.type === 'touchstart'\r\n ? e.originalEvent.targetTouches[0].pageY\r\n : e.clientY;\r\n\r\n // δ is the difference between image width and height\r\n δ = !this.isRotated ? 0 : (imageWidth - imageHeight) / 2;\r\n\r\n // Width or height difference can be use to limit image right or top position\r\n widthDiff = !this.isRotated\r\n ? (imageWidth - stageWidth)\r\n : (imageHeight - stageWidth);\r\n heightDiff = !this.isRotated\r\n ? (imageHeight - stageHeight)\r\n : (imageWidth - stageHeight);\r\n\r\n // Modal can be dragging if image is smaller to stage\r\n isDragging = (widthDiff > 0 || heightDiff > 0) ? true : false;\r\n PUBLIC_VARS['isMoving'] = (widthDiff > 0 || heightDiff > 0) ? true : false;\r\n\r\n // Reclac the element position when mousedown\r\n // Fixed the issue of stage with a border\r\n left = $(image).position().left - δ;\r\n top = $(image).position().top + δ;\r\n\r\n // Add grabbing cursor\r\n if (stage.hasClass('is-grab')) {\r\n $(ELEMS_WITH_GRABBING_CURSOR).addClass('is-grabbing');\r\n }\r\n\r\n $D.on(TOUCH_MOVE_EVENT + EVENT_NS, dragMove)\r\n .on(TOUCH_END_EVENT + EVENT_NS, dragEnd);\r\n\r\n };\r\n\r\n let dragMove = (e) => {\r\n\r\n e = e || window.event;\r\n\r\n e.preventDefault();\r\n\r\n if (isDragging) {\r\n\r\n let endX = e.type === 'touchmove'\r\n ? e.originalEvent.targetTouches[0].pageX\r\n : e.clientX,\r\n endY = e.type === 'touchmove'\r\n ? e.originalEvent.targetTouches[0].pageY\r\n : e.clientY,\r\n\r\n relativeX = endX - startX,\r\n relativeY = endY - startY,\r\n\r\n newLeft = relativeX + left,\r\n newTop = relativeY + top;\r\n\r\n // vertical limit\r\n if (heightDiff > 0) {\r\n\r\n if ((relativeY + top) > δ) {\r\n newTop = δ;\r\n } else if ((relativeY + top) < -heightDiff + δ) {\r\n newTop = -heightDiff + δ;\r\n }\r\n\r\n } else {\r\n newTop = top;\r\n }\r\n // horizontal limit\r\n if (widthDiff > 0) {\r\n\r\n if ((relativeX + left) > -δ) {\r\n newLeft = -δ;\r\n } else if ((relativeX + left) < -widthDiff - δ) {\r\n newLeft = -widthDiff - δ;\r\n }\r\n\r\n } else {\r\n newLeft = left;\r\n }\r\n\r\n $(image).css({\r\n left: newLeft + 'px',\r\n top: newTop + 'px'\r\n });\r\n\r\n // Update image initial data\r\n $.extend(this.imageData, {\r\n left: newLeft,\r\n top: newTop\r\n });\r\n\r\n }\r\n\r\n };\r\n\r\n let dragEnd = () => {\r\n\r\n $D.off(TOUCH_MOVE_EVENT + EVENT_NS, dragMove)\r\n .off(TOUCH_END_EVENT + EVENT_NS, dragEnd);\r\n\r\n isDragging = false;\r\n PUBLIC_VARS['isMoving'] = false;\r\n\r\n // Remove grabbing cursor\r\n $(ELEMS_WITH_GRABBING_CURSOR).removeClass('is-grabbing');\r\n\r\n };\r\n\r\n $(stage).on(TOUCH_START_EVENT + EVENT_NS, dragStart);\r\n\r\n }\r\n\r\n}\r\n","import {\r\n $D,\r\n TOUCH_START_EVENT,\r\n TOUCH_MOVE_EVENT,\r\n TOUCH_END_EVENT,\r\n NS,\r\n EVENT_NS,\r\n PUBLIC_VARS\r\n} from './constants';\r\n\r\nimport {\r\n setGrabCursor\r\n} from './utilities';\r\n\r\nconst ELEMS_WITH_RESIZE_CURSOR = `html,body,.${NS}-modal,.${NS}-stage,.${NS}-button`;\r\n\r\nexport default {\r\n\r\n /**\r\n * ------------------------------\r\n * 1.modal resizable\r\n * 2.keep image in stage center\r\n * 3.other image limitations\r\n * ------------------------------\r\n *\r\n * [resizable]\r\n * @param {[Object]} modal [the modal element]\r\n * @param {[Object]} stage [the stage element]\r\n * @param {[Object]} image [the image element]\r\n * @param {[Number]} minWidth [the option of modalWidth]\r\n * @param {[Number]} minHeight [the option of modalHeight]\r\n */\r\n resizable(modal, stage, image, minWidth, minHeight) {\r\n\r\n let resizableHandleE = $(`
`),\r\n resizableHandleW = $(``),\r\n resizableHandleS = $(``),\r\n resizableHandleN = $(``),\r\n resizableHandleSE = $(``),\r\n resizableHandleSW = $(``),\r\n resizableHandleNE = $(``),\r\n resizableHandleNW = $(``);\r\n\r\n let resizableHandles = {\r\n 'e': resizableHandleE,\r\n 's': resizableHandleS,\r\n 'se': resizableHandleSE,\r\n 'n': resizableHandleN,\r\n 'w': resizableHandleW,\r\n 'nw': resizableHandleNW,\r\n 'ne': resizableHandleNE,\r\n 'sw': resizableHandleSW\r\n };\r\n\r\n $(modal).append(\r\n resizableHandleE, resizableHandleW, resizableHandleS, resizableHandleN,\r\n resizableHandleSE, resizableHandleSW, resizableHandleNE, resizableHandleNW\r\n );\r\n\r\n let isDragging = false;\r\n\r\n let startX = 0,\r\n startY = 0,\r\n\r\n modalData = {\r\n w: 0,\r\n h: 0,\r\n l: 0,\r\n t: 0\r\n },\r\n stageData = {\r\n w: 0,\r\n h: 0,\r\n l: 0,\r\n t: 0\r\n },\r\n imageData = {\r\n w: 0,\r\n h: 0,\r\n l: 0,\r\n t: 0\r\n },\r\n\r\n // δ is the difference between image width and height\r\n δ = 0,\r\n imgWidth = 0,\r\n imgHeight = 0,\r\n\r\n direction = '';\r\n\r\n // modal CSS options\r\n let getModalOpts = function (dir, offsetX, offsetY) {\r\n\r\n // Modal should not move when its width to the minwidth\r\n let modalLeft = (-offsetX + modalData.w) > minWidth\r\n ? (offsetX + modalData.l)\r\n : (modalData.l + modalData.w - minWidth),\r\n modalTop = (-offsetY + modalData.h) > minHeight\r\n ? (offsetY + modalData.t)\r\n : (modalData.t + modalData.h - minHeight);\r\n\r\n let opts = {\r\n 'e': {\r\n width: Math.max((offsetX + modalData.w), minWidth) + 'px'\r\n },\r\n 's': {\r\n height: Math.max((offsetY + modalData.h), minHeight) + 'px'\r\n },\r\n 'se': {\r\n width: Math.max((offsetX + modalData.w), minWidth) + 'px',\r\n height: Math.max((offsetY + modalData.h), minHeight) + 'px'\r\n },\r\n 'w': {\r\n width: Math.max((-offsetX + modalData.w), minWidth) + 'px',\r\n left: modalLeft + 'px'\r\n },\r\n 'n': {\r\n height: Math.max((-offsetY + modalData.h), minHeight) + 'px',\r\n top: modalTop + 'px'\r\n },\r\n 'nw': {\r\n width: Math.max((-offsetX + modalData.w), minWidth) + 'px',\r\n height: Math.max((-offsetY + modalData.h), minHeight) + 'px',\r\n top: modalTop + 'px',\r\n left: modalLeft + 'px'\r\n },\r\n 'ne': {\r\n width: Math.max((offsetX + modalData.w), minWidth) + 'px',\r\n height: Math.max((-offsetY + modalData.h), minHeight) + 'px',\r\n top: modalTop + 'px'\r\n },\r\n 'sw': {\r\n width: Math.max((-offsetX + modalData.w), minWidth) + 'px',\r\n height: Math.max((offsetY + modalData.h), minHeight) + 'px',\r\n left: modalLeft + 'px'\r\n }\r\n };\r\n\r\n return opts[dir];\r\n };\r\n\r\n // image CSS options\r\n let getImageOpts = function (dir, offsetX, offsetY) {\r\n\r\n // Image should not move when modal width to the min width\r\n // The minwidth is modal width, so we should clac the stage minwidth\r\n let widthDiff = (offsetX + modalData.w) > minWidth\r\n ? (stageData.w - imgWidth + offsetX - δ)\r\n : (minWidth - (modalData.w - stageData.w) - imgWidth - δ),\r\n heightDiff = (offsetY + modalData.h) > minHeight\r\n ? (stageData.h - imgHeight + offsetY + δ)\r\n : (minHeight - (modalData.h - stageData.h) - imgHeight + δ),\r\n\r\n widthDiff2 = (-offsetX + modalData.w) > minWidth\r\n ? (stageData.w - imgWidth - offsetX - δ)\r\n : (minWidth - (modalData.w - stageData.w) - imgWidth - δ),\r\n heightDiff2 = (-offsetY + modalData.h) > minHeight\r\n ? (stageData.h - imgHeight - offsetY + δ)\r\n : (minHeight - (modalData.h - stageData.h) - imgHeight + δ);\r\n\r\n // Get image position in dragging\r\n let imgLeft = (widthDiff > 0\r\n ? $(image).position().left\r\n : ($(image).position().left < 0\r\n ? $(image).position().left\r\n : 0)) - δ,\r\n imgTop = (heightDiff > 0\r\n ? $(image).position().top\r\n : ($(image).position().top < 0\r\n ? $(image).position().top\r\n : 0)) + δ,\r\n\r\n imgLeft2 = (widthDiff2 > 0\r\n ? $(image).position().left\r\n : ($(image).position().left < 0\r\n ? $(image).position().left\r\n : 0)) - δ,\r\n imgTop2 = (heightDiff2 > 0\r\n ? $(image).position().top\r\n : ($(image).position().top < 0\r\n ? $(image).position().top\r\n : 0)) + δ;\r\n\r\n let opts = {\r\n 'e': {\r\n left: widthDiff >= -δ\r\n ? ((widthDiff - δ) / 2 + 'px')\r\n : (imgLeft > widthDiff\r\n ? (imgLeft + 'px')\r\n : (widthDiff + 'px'))\r\n },\r\n 's': {\r\n top: heightDiff >= δ\r\n ? ((heightDiff + δ) / 2 + 'px')\r\n : (imgTop > heightDiff\r\n ? (imgTop + 'px')\r\n : (heightDiff + 'px'))\r\n },\r\n 'se': {\r\n top: heightDiff >= δ\r\n ? ((heightDiff + δ) / 2 + 'px')\r\n : (imgTop > heightDiff\r\n ? (imgTop + 'px')\r\n : (heightDiff + 'px')),\r\n left: widthDiff >= -δ\r\n ? ((widthDiff - δ) / 2 + 'px')\r\n : (imgLeft > widthDiff\r\n ? (imgLeft + 'px')\r\n : (widthDiff + 'px'))\r\n },\r\n 'w': {\r\n left: widthDiff2 >= -δ\r\n ? ((widthDiff2 - δ) / 2 + 'px')\r\n : (imgLeft2 > widthDiff2\r\n ? (imgLeft2 + 'px')\r\n : (widthDiff2 + 'px'))\r\n },\r\n 'n': {\r\n top: heightDiff2 >= δ\r\n ? ((heightDiff2 + δ) / 2 + 'px')\r\n : (imgTop2 > heightDiff2\r\n ? (imgTop2 + 'px')\r\n : (heightDiff2 + 'px'))\r\n },\r\n 'nw': {\r\n top: heightDiff2 >= δ\r\n ? ((heightDiff2 + δ) / 2 + 'px')\r\n : (imgTop2 > heightDiff2\r\n ? (imgTop2 + 'px')\r\n : (heightDiff2 + 'px')),\r\n left: widthDiff2 >= -δ\r\n ? ((widthDiff2 - δ) / 2 + 'px')\r\n : (imgLeft2 > widthDiff2\r\n ? (imgLeft2 + 'px')\r\n : (widthDiff2 + 'px'))\r\n },\r\n 'ne': {\r\n top: heightDiff2 >= δ\r\n ? ((heightDiff2 + δ) / 2 + 'px')\r\n : (imgTop2 > heightDiff2\r\n ? (imgTop2 + 'px')\r\n : (heightDiff2 + 'px')),\r\n left: widthDiff >= -δ\r\n ? ((widthDiff - δ) / 2 + 'px')\r\n : (imgLeft > widthDiff\r\n ? (imgLeft + 'px')\r\n : (widthDiff + 'px'))\r\n },\r\n 'sw': {\r\n top: heightDiff >= δ\r\n ? ((heightDiff + δ) / 2 + 'px')\r\n : (imgTop > heightDiff\r\n ? (imgTop + 'px')\r\n : (heightDiff + 'px')),\r\n left: widthDiff2 >= -δ\r\n ? ((widthDiff2 - δ) / 2 + 'px')\r\n : (imgLeft2 > widthDiff2\r\n ? (imgLeft2 + 'px')\r\n : (widthDiff2 + 'px'))\r\n }\r\n };\r\n\r\n return opts[dir];\r\n };\r\n\r\n let dragStart = (dir, e) => {\r\n\r\n e = e || window.event;\r\n\r\n e.preventDefault();\r\n\r\n isDragging = true;\r\n PUBLIC_VARS['isResizing'] = true;\r\n\r\n startX = e.type === 'touchstart'\r\n ? e.originalEvent.targetTouches[0].pageX\r\n : e.clientX;\r\n startY = e.type === 'touchstart'\r\n ? e.originalEvent.targetTouches[0].pageY\r\n : e.clientY;\r\n\r\n // Reclac the modal data when mousedown\r\n modalData = {\r\n w: $(modal).width(),\r\n h: $(modal).height(),\r\n l: $(modal).offset().left,\r\n t: $(modal).offset().top\r\n };\r\n\r\n stageData = {\r\n w: $(stage).width(),\r\n h: $(stage).height(),\r\n l: $(stage).offset().left,\r\n t: $(stage).offset().top\r\n };\r\n\r\n imageData = {\r\n w: $(image).width(),\r\n h: $(image).height(),\r\n l: $(image).position().left,\r\n t: $(image).position().top\r\n };\r\n\r\n // δ is the difference between image width and height\r\n δ = !this.isRotated\r\n ? 0\r\n : (imageData.w - imageData.h) / 2;\r\n imgWidth = !this.isRotated\r\n ? imageData.w\r\n : imageData.h;\r\n imgHeight = !this.isRotated\r\n ? imageData.h\r\n : imageData.w;\r\n\r\n direction = dir;\r\n\r\n // Add resizable cursor\r\n $(ELEMS_WITH_RESIZE_CURSOR).css('cursor', dir + '-resize');\r\n\r\n $D.on(TOUCH_MOVE_EVENT + EVENT_NS, dragMove)\r\n .on(TOUCH_END_EVENT + EVENT_NS, dragEnd);\r\n\r\n };\r\n\r\n let dragMove = (e) => {\r\n\r\n e = e || window.event;\r\n\r\n e.preventDefault();\r\n\r\n if (isDragging && !this.isMaximized) {\r\n\r\n let endX = e.type === 'touchmove'\r\n ? e.originalEvent.targetTouches[0].pageX\r\n : e.clientX,\r\n endY = e.type === 'touchmove'\r\n ? e.originalEvent.targetTouches[0].pageY\r\n : e.clientY,\r\n\r\n relativeX = endX - startX,\r\n relativeY = endY - startY;\r\n\r\n let modalOpts = getModalOpts(direction, relativeX, relativeY);\r\n\r\n $(modal).css(modalOpts);\r\n\r\n let imageOpts = getImageOpts(direction, relativeX, relativeY);\r\n\r\n $(image).css(imageOpts);\r\n\r\n this.isDoResize = true;\r\n\r\n }\r\n\r\n };\r\n\r\n let dragEnd = () => {\r\n\r\n $D.off(TOUCH_MOVE_EVENT + EVENT_NS, dragMove)\r\n .off(TOUCH_END_EVENT + EVENT_NS, dragEnd);\r\n\r\n // Set grab cursor\r\n if (PUBLIC_VARS['isResizing']) {\r\n setGrabCursor(\r\n {\r\n w: imgWidth,\r\n h: imgHeight\r\n },\r\n {\r\n w: $(stage).width(),\r\n h: $(stage).height()\r\n },\r\n stage\r\n );\r\n }\r\n\r\n isDragging = false;\r\n PUBLIC_VARS['isResizing'] = false;\r\n\r\n // Remove resizable cursor\r\n $(ELEMS_WITH_RESIZE_CURSOR).css('cursor', '');\r\n\r\n // Update image initial data\r\n let scale = this.getImageScaleToStage(\r\n $(stage).width(),\r\n $(stage).height()\r\n );\r\n\r\n $.extend(this.imageData, {\r\n initWidth: this.img.width * scale,\r\n initHeight: this.img.height * scale,\r\n initLeft: ($(stage).width() - this.img.width * scale) / 2,\r\n initTop: ($(stage).height() - this.img.height * scale) / 2\r\n });\r\n\r\n };\r\n\r\n $.each(resizableHandles, function (dir, handle) {\r\n handle.on(TOUCH_START_EVENT + EVENT_NS, function (e) {\r\n dragStart(dir, e);\r\n });\r\n });\r\n\r\n }\r\n\r\n}\r\n","import $ from 'jquery';\n\nimport DEFAULTS from './defaults';\n\nimport {\n $W,\n $D,\n CLICK_EVENT,\n RESIZE_EVENT,\n KEYDOWN_EVENT,\n WHEEL_EVENT,\n NS,\n CLASS_NS,\n EVENT_NS,\n PUBLIC_VARS\n} from './constants';\n\nimport {\n getImgSrc,\n throttle,\n preloadImg,\n requestFullscreen,\n getImageNameFromUrl,\n getNumFromCSSValue,\n hasScrollbar,\n getScrollbarWidth,\n setGrabCursor\n} from './utilities';\n\nimport draggable from './draggable';\nimport movable from './movable';\nimport resizable from './resizable';\n\n/**\n * PhotoViewer Class\n */\nclass PhotoViewer {\n\n constructor(items, options, el) {\n\n this.options = $.extend(true, {}, DEFAULTS, options);\n\n if (options && $.isArray(options.footToolbar)) {\n this.options.footToolbar = options.footToolbar;\n }\n\n if (options && $.isArray(options.headToolbar)) {\n this.options.headToolbar = options.headToolbar;\n }\n\n // Store element of clicked\n this.$el = $(el);\n\n // As we have multiple instances,\n // so every instance has following variables.\n\n // modal open flag\n this.isOpened = false;\n // modal maximize flag\n this.isMaximized = false;\n // image rotate 90*(2n+1) flag\n this.isRotated = false;\n // image rotate angle\n this.rotateAngle = 0;\n\n // if modal do resize\n this.isDoResize = false;\n\n // Store image data in every instance\n this.imageData = {};\n // Store modal data in every instance\n this.modalData = {\n width: null,\n height: null,\n left: null,\n top: null\n };\n\n this.init(items, this.options, el);\n\n }\n\n init(items, opts, el) {\n\n this.groupData = items;\n this.groupIndex = opts['index'];\n\n // Get image src\n let imgSrc = items[this.groupIndex]['src'];\n\n this.open();\n\n this.loadImg(imgSrc);\n\n // draggable & movable & resizable\n if (opts.draggable) {\n this.draggable(this.$photoviewer, this.dragHandle, CLASS_NS + '-button');\n }\n if (opts.movable) {\n this.movable(this.$stage, this.$image);\n }\n if (opts.resizable) {\n this.resizable(\n this.$photoviewer,\n this.$stage,\n this.$image,\n opts.modalWidth,\n opts.modalHeight\n );\n }\n\n }\n\n _creatBtns(toolbar, btns) {\n\n let btnsStr = '';\n\n $.each(toolbar, function (index, item) {\n btnsStr += btns[item];\n });\n\n return btnsStr;\n\n }\n\n _creatTitle() {\n return (this.options.title ? `` : '');\n }\n\n _creatDOM() {\n\n let btnsTpl = {\n minimize: ``,\n maximize: ``,\n close: ``,\n zoomIn: ``,\n zoomOut: ``,\n prev: ``,\n next: ``,\n fullscreen: ``,\n actualSize: ``,\n rotateLeft: ``,\n rotateRight: ``\n };\n\n // photoviewer base HTML\n let photoviewerHTML =\n `