From 3e58573d2c8ea79d4d3aea1888bd08592769c595 Mon Sep 17 00:00:00 2001 From: kingdido999 Date: Mon, 2 Jan 2017 11:22:17 -0800 Subject: [PATCH] fix #18 and refactor --- bower.json | 2 +- build/zooming.js | 340 +++++++++++++++--------------- build/zooming.js.map | 2 +- build/zooming.min.js | 2 +- build/zooming.min.js.map | 2 +- package.json | 2 +- src/EventHandler.js | 14 +- src/Overlay.js | 2 +- src/Zooming.js | 8 +- src/_helpers.js | 27 ++- src/{_defaults.js => _options.js} | 31 +-- src/main.js | 2 +- 12 files changed, 210 insertions(+), 224 deletions(-) rename src/{_defaults.js => _options.js} (85%) diff --git a/bower.json b/bower.json index a71da1a6..74b5eeac 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "zooming", - "version": "1.0.5", + "version": "1.0.6", "homepage": "https://github.com/kingdido999/zooming", "authors": [ "Desmond Ding " diff --git a/build/zooming.js b/build/zooming.js index c9a03c40..7db67468 100644 --- a/build/zooming.js +++ b/build/zooming.js @@ -8,6 +8,16 @@ var body = document.body; var docElm = document.documentElement; var webkitPrefix = 'WebkitAppearance' in document.documentElement.style ? '-webkit-' : ''; +var cursor = { + default: 'auto', + zoomIn: webkitPrefix + 'zoom-in', + zoomOut: webkitPrefix + 'zoom-out', + grab: webkitPrefix + 'grab', + move: 'move' +}; + +var EVENT_TYPES_GRAB = ['mousedown', 'mousemove', 'mouseup', 'touchstart', 'touchmove', 'touchend']; + var divide = function divide(denominator) { return function (numerator) { return numerator / denominator; @@ -50,6 +60,10 @@ var toggleListeners = function toggleListeners(el, types, handler) { }); }; +var toggleGrabListeners = function toggleGrabListeners(el, handler, add) { + return toggleListeners(el, EVENT_TYPES_GRAB, handler, add); +}; + var sniffTransition = function sniffTransition(el) { var ret = {}; var trans = ['webkitTransition', 'transition', 'mozTransition']; @@ -109,14 +123,6 @@ var setStyle = function setStyle(el, styles, remember) { return original; }; -var cursor = { - default: 'auto', - zoomIn: webkitPrefix + 'zoom-in', - zoomOut: webkitPrefix + 'zoom-out', - grab: webkitPrefix + 'grab', - move: 'move' -}; - var bind = function bind(_this, that) { var methods = Object.getOwnPropertyNames(Object.getPrototypeOf(_this)); @@ -393,6 +399,8 @@ var Overlay = function () { createClass(Overlay, [{ key: 'init', value: function init() { + var _this = this; + var options = this.instance.options; setStyle(this.el, { @@ -407,7 +415,9 @@ var Overlay = function () { transition: 'opacity\n ' + options.transitionDuration + 's\n ' + options.transitionTimingFunction }); - this.el.addEventListener('click', this.instance.close()); + this.el.addEventListener('click', function () { + return _this.instance.close(); + }); } }, { key: 'updateStyle', @@ -437,10 +447,10 @@ var Overlay = function () { }, { key: 'show', value: function show() { - var _this = this; + var _this2 = this; setTimeout(function () { - return _this.el.style.opacity = _this.instance.options.bgOpacity; + return _this2.el.style.opacity = _this2.instance.options.bgOpacity; }, 30); } }, { @@ -452,166 +462,8 @@ var Overlay = function () { return Overlay; }(); -/** - * A list of options. - * - * @type {Object} - * @example - * // Default options - * var options = { - * defaultZoomable: 'img[data-action="zoom"]', - * enableGrab: true, - * preloadImage: true, - * transitionDuration: 0.4, - * transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)', - * bgColor: 'rgb(255, 255, 255)', - * bgOpacity: 1, - * scaleBase: 1.0, - * scaleExtra: 0.5, - * scrollThreshold: 40, - * customSize: null, - * onOpen: null, - * onClose: null, - * onRelease: null, - * onBeforeOpen: null, - * onBeforeClose: null, - * onBeforeGrab: null, - * onBeforeMove: null, - * onBeforeRelease: null - * } - */ -var OPTIONS = { - /** - * Zoomable elements by default. It can be a css selector or an element. - * @type {string|Element} - */ - defaultZoomable: 'img[data-action="zoom"]', - - /** - * To be able to grab and drag the image for extra zoom-in. - * @type {boolean} - */ - enableGrab: true, - - /** - * Preload images with attribute "data-original". - * @type {boolean} - */ - preloadImage: true, - - /** - * Transition duration in seconds. - * @type {number} - */ - transitionDuration: 0.4, - - /** - * Transition timing function. - * @type {string} - */ - transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)', - - /** - * Overlay background color. - * @type {string} - */ - bgColor: 'rgb(255, 255, 255)', - - /** - * Overlay background opacity. - * @type {number} - */ - bgOpacity: 1, - - /** - * The base scale factor for zooming. By default scale to fit the window. - * @type {number} - */ - scaleBase: 1.0, - - /** - * The extra scale factor when grabbing the image. - * @type {number} - */ - scaleExtra: 0.5, - - /** - * How much scrolling it takes before closing out. - * @type {number} - */ - scrollThreshold: 40, - - /** - * Scale (zoom in) to given width and height. Ignore scaleBase if set. - * @type {Object} - * @example - * customSize: { width: 800, height: 400 } - */ - customSize: null, - - /** - * A callback function that will be called when a target is opened and - * transition has ended. It will get the target element as the argument. - * @type {Function} - */ - onOpen: null, - - /** - * Same as above, except fired when closed. - * @type {Function} - */ - onClose: null, - - /** - * Same as above, except fired when released. - * @type {Function} - */ - onRelease: null, - - /** - * A callback function that will be called before open. - * @type {Function} - */ - onBeforeOpen: null, - - /** - * A callback function that will be called before close. - * @type {Function} - */ - onBeforeClose: null, - - /** - * A callback function that will be called before grab. - * @type {Function} - */ - onBeforeGrab: null, - - /** - * A callback function that will be called before move. - * @type {Function} - */ - onBeforeMove: null, - - /** - * A callback function that will be called before release. - * @type {Function} - */ - onBeforeRelease: null -}; - -/** - * Duration (ms) longer than or equal to this value will be recognized as grab, - * otherwise click. - * @type {number} - */ var PRESS_DELAY = 200; -/** - * Event types related to grab. - * @type {Array} - */ -var EVENT_TYPES_GRAB = ['mousedown', 'mousemove', 'mouseup', 'touchstart', 'touchmove', 'touchend']; - /** * Scale factor for multi-touch. * @type {number} @@ -782,9 +634,151 @@ function processTouches(touches, currScaleExtra, cb) { } /** - * Zooming instance. - * @param {Object} [options] Update default options if provided. + * A list of options. + * + * @type {Object} + * @example + * // Default options + * var options = { + * defaultZoomable: 'img[data-action="zoom"]', + * enableGrab: true, + * preloadImage: true, + * transitionDuration: 0.4, + * transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)', + * bgColor: 'rgb(255, 255, 255)', + * bgOpacity: 1, + * scaleBase: 1.0, + * scaleExtra: 0.5, + * scrollThreshold: 40, + * customSize: null, + * onOpen: null, + * onClose: null, + * onRelease: null, + * onBeforeOpen: null, + * onBeforeClose: null, + * onBeforeGrab: null, + * onBeforeMove: null, + * onBeforeRelease: null + * } */ +var OPTIONS = { + /** + * Zoomable elements by default. It can be a css selector or an element. + * @type {string|Element} + */ + defaultZoomable: 'img[data-action="zoom"]', + + /** + * To be able to grab and drag the image for extra zoom-in. + * @type {boolean} + */ + enableGrab: true, + + /** + * Preload images with attribute "data-original". + * @type {boolean} + */ + preloadImage: true, + + /** + * Transition duration in seconds. + * @type {number} + */ + transitionDuration: 0.4, + + /** + * Transition timing function. + * @type {string} + */ + transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)', + + /** + * Overlay background color. + * @type {string} + */ + bgColor: 'rgb(255, 255, 255)', + + /** + * Overlay background opacity. + * @type {number} + */ + bgOpacity: 1, + + /** + * The base scale factor for zooming. By default scale to fit the window. + * @type {number} + */ + scaleBase: 1.0, + + /** + * The extra scale factor when grabbing the image. + * @type {number} + */ + scaleExtra: 0.5, + + /** + * How much scrolling it takes before closing out. + * @type {number} + */ + scrollThreshold: 40, + + /** + * Scale (zoom in) to given width and height. Ignore scaleBase if set. + * @type {Object} + * @example + * customSize: { width: 800, height: 400 } + */ + customSize: null, + + /** + * A callback function that will be called when a target is opened and + * transition has ended. It will get the target element as the argument. + * @type {Function} + */ + onOpen: null, + + /** + * Same as above, except fired when closed. + * @type {Function} + */ + onClose: null, + + /** + * Same as above, except fired when released. + * @type {Function} + */ + onRelease: null, + + /** + * A callback function that will be called before open. + * @type {Function} + */ + onBeforeOpen: null, + + /** + * A callback function that will be called before close. + * @type {Function} + */ + onBeforeClose: null, + + /** + * A callback function that will be called before grab. + * @type {Function} + */ + onBeforeGrab: null, + + /** + * A callback function that will be called before move. + * @type {Function} + */ + onBeforeMove: null, + + /** + * A callback function that will be called before release. + * @type {Function} + */ + onBeforeRelease: null +}; var Zooming$1 = function () { function Zooming(options) { @@ -886,7 +880,7 @@ var Zooming$1 = function () { _this.lock = false; if (_this.options.enableGrab) { - toggleListeners(document, EVENT_TYPES_GRAB, _this.eventHandler, true); + toggleGrabListeners(document, _this.eventHandler, true); } if (target.hasAttribute('data-original')) { @@ -939,7 +933,7 @@ var Zooming$1 = function () { _this2.lock = false; if (_this2.options.enableGrab) { - toggleListeners(document, EVENT_TYPES_GRAB, _this2.eventHandler, false); + toggleGrabListeners(document, _this2.eventHandler, false); } if (target.hasAttribute('data-original')) { diff --git a/build/zooming.js.map b/build/zooming.js.map index b7a98339..378155cc 100644 --- a/build/zooming.js.map +++ b/build/zooming.js.map @@ -1 +1 @@ -{"version":3,"file":null,"sources":["../src/_helpers.js","../src/Target.js","../src/Overlay.js","../src/_defaults.js","../src/EventHandler.js","../src/Zooming.js","../src/main.js"],"sourcesContent":["const body = document.body\nconst docElm = document.documentElement\nconst webkitPrefix = 'WebkitAppearance' in document.documentElement.style\n ? '-webkit-'\n : ''\n\nconst divide = (denominator) => {\n return (numerator) => {\n return numerator / denominator\n }\n}\n\nconst half = divide(2)\n\nconst loadImage = (url, cb) => {\n const img = new Image()\n img.onload = () => {\n if (cb) cb(img)\n }\n img.src = url\n}\n\nconst scrollTop = () => {\n return window.pageYOffset ||\n (docElm || body.parentNode || body).scrollTop\n}\n\nconst getWindowCenter = () => {\n const docWidth = docElm.clientWidth || body.clientWidth\n const docHeight = docElm.clientHeight || body.clientHeight\n\n return {\n x: half(docWidth),\n y: half(docHeight)\n }\n}\n\nconst toggleListeners = (el, types, handler, add = true) => {\n types.forEach(t => {\n if (add) {\n el.addEventListener(t, handler[t])\n } else {\n el.removeEventListener(t, handler[t])\n }\n })\n}\n\nconst sniffTransition = (el) => {\n let ret = {}\n const trans = ['webkitTransition', 'transition', 'mozTransition']\n const tform = ['webkitTransform', 'transform', 'mozTransform']\n const end = {\n 'transition' : 'transitionend',\n 'mozTransition' : 'transitionend',\n 'webkitTransition' : 'webkitTransitionEnd'\n }\n\n trans.some(prop => {\n if (el.style[prop] !== undefined) {\n ret.transitionProp = prop\n ret.transEndEvent = end[prop]\n return true\n }\n })\n\n tform.some(prop => {\n if (el.style[prop] !== undefined) {\n ret.transformProp = prop\n ret.transformCssProp = prop.replace(/(.*)Transform/, '-$1-transform')\n return true\n }\n })\n\n return ret\n}\n\nconst trans = sniffTransition(document.createElement('div'))\nconst transitionProp = trans.transitionProp\nconst transformProp = trans.transformProp\nconst transformCssProp = trans.transformCssProp\nconst transEndEvent = trans.transEndEvent\n\nconst setStyle = (el, styles, remember) => {\n let value\n if (styles.transition) {\n value = styles.transition\n delete styles.transition\n styles[transitionProp] = value\n }\n if (styles.transform) {\n value = styles.transform\n delete styles.transform\n styles[transformProp] = value\n }\n\n let s = el.style\n let original = {}\n\n for (let key in styles) {\n if (remember) original[key] = s[key] || ''\n s[key] = styles[key]\n }\n\n return original\n}\n\nconst cursor = {\n default: 'auto',\n zoomIn: `${webkitPrefix}zoom-in`,\n zoomOut: `${webkitPrefix}zoom-out`,\n grab: `${webkitPrefix}grab`,\n move: 'move'\n}\n\nconst bind = (_this, that) => {\n const methods = (\n Object.getOwnPropertyNames(\n Object.getPrototypeOf(_this)\n )\n )\n\n methods.forEach(m => {\n _this[m] = _this[m].bind(that)\n })\n}\n\nexport {\n webkitPrefix,\n half,\n loadImage,\n scrollTop,\n getWindowCenter,\n toggleListeners,\n transformCssProp,\n transEndEvent,\n setStyle,\n cursor,\n bind\n}\n","import { transformCssProp, setStyle, half, getWindowCenter, loadImage, cursor } from './_helpers'\n\nexport default class Target {\n\n constructor (el, instance) {\n this.el = el\n this.instance = instance\n this.body = document.body\n this.translate = null\n this.scale = null\n this.srcThumbnail = null\n this.style = {\n open: null,\n close: null\n }\n }\n\n open () {\n const options = this.instance.options\n\n // load hi-res image if preloadImage option is disabled\n if (!options.preloadImage && this.el.hasAttribute('data-original')) {\n loadImage(this.el.getAttribute('data-original'))\n }\n\n const rect = this.el.getBoundingClientRect()\n this.translate = calculateTranslate(rect)\n this.scale = calculateScale(rect, options.scaleBase, options.customSize)\n\n // force layout update\n this.el.offsetWidth\n\n this.style.open = {\n position: 'relative',\n zIndex: 999,\n cursor: options.enableGrab\n ? cursor.grab\n : cursor.zoomOut,\n transition: `${transformCssProp}\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`,\n transform: `translate(${this.translate.x}px, ${this.translate.y}px)\n scale(${this.scale.x},${this.scale.y})`\n }\n\n // trigger transition\n this.style.close = setStyle(this.el, this.style.open, true)\n }\n\n close () {\n // force layout update\n this.el.offsetWidth\n\n setStyle(this.el, { transform: 'none' })\n }\n\n grab (x, y, scaleExtra) {\n const windowCenter = getWindowCenter()\n const [dx, dy] = [windowCenter.x - x, windowCenter.y - y]\n\n setStyle(this.el, {\n cursor: cursor.move,\n transform: `translate(\n ${this.translate.x + dx}px, ${this.translate.y + dy}px)\n scale(${this.scale.x + scaleExtra},${this.scale.y + scaleExtra})`\n })\n }\n\n move (x, y, scaleExtra) {\n const windowCenter = getWindowCenter()\n const [dx, dy] = [windowCenter.x - x, windowCenter.y - y]\n\n setStyle(this.el, {\n transition: transformCssProp,\n transform: `translate(\n ${this.translate.x + dx}px, ${this.translate.y + dy}px)\n scale(${this.scale.x + scaleExtra},${this.scale.y + scaleExtra})`\n })\n }\n\n restoreCloseStyle () {\n setStyle(this.el, this.style.close)\n }\n\n restoreOpenStyle () {\n setStyle(this.el, this.style.open)\n }\n\n upgradeSource () {\n this.srcThumbnail = this.el.getAttribute('src')\n const dataOriginal = this.el.getAttribute('data-original')\n const temp = this.el.cloneNode(false)\n\n // force compute the hi-res image in DOM to prevent\n // image flickering while updating src\n temp.setAttribute('src', dataOriginal)\n temp.style.position = 'fixed'\n temp.style.visibility = 'hidden'\n this.body.appendChild(temp)\n\n setTimeout(() => {\n this.el.setAttribute('src', dataOriginal)\n this.body.removeChild(temp)\n }, 10)\n }\n\n downgradeSource () {\n this.el.setAttribute('src', this.srcThumbnail)\n }\n}\n\nfunction calculateTranslate (rect) {\n const windowCenter = getWindowCenter()\n const targetCenter = {\n x: rect.left + half(rect.width),\n y: rect.top + half(rect.height)\n }\n\n // The vector to translate image to the window center\n return {\n x: windowCenter.x - targetCenter.x,\n y: windowCenter.y - targetCenter.y\n }\n}\n\nfunction calculateScale (rect, scaleBase, customSize) {\n if (customSize) {\n return {\n x: customSize.width / rect.width,\n y: customSize.height / rect.height\n }\n } else {\n const targetHalfWidth = half(rect.width)\n const targetHalfHeight = half(rect.height)\n const windowCenter = getWindowCenter()\n\n // The distance between target edge and window edge\n const targetEdgeToWindowEdge = {\n x: windowCenter.x - targetHalfWidth,\n y: windowCenter.y - targetHalfHeight\n }\n\n const scaleHorizontally = targetEdgeToWindowEdge.x / targetHalfWidth\n const scaleVertically = targetEdgeToWindowEdge.y / targetHalfHeight\n\n // The additional scale is based on the smaller value of\n // scaling horizontally and scaling vertically\n const scale = scaleBase + Math.min(scaleHorizontally, scaleVertically)\n\n return {\n x: scale,\n y: scale\n }\n }\n}\n","import { setStyle } from './_helpers'\n\nexport default class Overlay {\n\n constructor (el, instance) {\n this.el = el\n this.instance = instance\n this.parent = null\n }\n\n init () {\n const options = this.instance.options\n\n setStyle(this.el, {\n zIndex: 998,\n backgroundColor: options.bgColor,\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n opacity: 0,\n transition: `opacity\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`\n })\n\n this.el.addEventListener('click', this.instance.close())\n }\n\n updateStyle () {\n const options = this.instance.options\n\n setStyle(this.el, {\n backgroundColor: options.bgColor,\n transition: `opacity\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`\n })\n }\n\n setParent (parent) {\n this.parent = parent\n }\n\n insert () {\n this.parent.appendChild(this.el)\n }\n\n remove () {\n this.parent.removeChild(this.el)\n }\n\n show () {\n setTimeout(() => this.el.style.opacity = this.instance.options.bgOpacity, 30)\n }\n\n hide () {\n this.el.style.opacity = 0\n }\n}\n","/**\n * A list of options.\n *\n * @type {Object}\n * @example\n * // Default options\n * var options = {\n * defaultZoomable: 'img[data-action=\"zoom\"]',\n * enableGrab: true,\n * preloadImage: true,\n * transitionDuration: 0.4,\n * transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)',\n * bgColor: 'rgb(255, 255, 255)',\n * bgOpacity: 1,\n * scaleBase: 1.0,\n * scaleExtra: 0.5,\n * scrollThreshold: 40,\n * customSize: null,\n * onOpen: null,\n * onClose: null,\n * onRelease: null,\n * onBeforeOpen: null,\n * onBeforeClose: null,\n * onBeforeGrab: null,\n * onBeforeMove: null,\n * onBeforeRelease: null\n * }\n */\nconst OPTIONS = {\n /**\n * Zoomable elements by default. It can be a css selector or an element.\n * @type {string|Element}\n */\n defaultZoomable: 'img[data-action=\"zoom\"]',\n\n /**\n * To be able to grab and drag the image for extra zoom-in.\n * @type {boolean}\n */\n enableGrab: true,\n\n /**\n * Preload images with attribute \"data-original\".\n * @type {boolean}\n */\n preloadImage: true,\n\n /**\n * Transition duration in seconds.\n * @type {number}\n */\n transitionDuration: 0.4,\n\n /**\n * Transition timing function.\n * @type {string}\n */\n transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)',\n\n /**\n * Overlay background color.\n * @type {string}\n */\n bgColor: 'rgb(255, 255, 255)',\n\n /**\n * Overlay background opacity.\n * @type {number}\n */\n bgOpacity: 1,\n\n /**\n * The base scale factor for zooming. By default scale to fit the window.\n * @type {number}\n */\n scaleBase: 1.0,\n\n /**\n * The extra scale factor when grabbing the image.\n * @type {number}\n */\n scaleExtra: 0.5,\n\n /**\n * How much scrolling it takes before closing out.\n * @type {number}\n */\n scrollThreshold: 40,\n\n /**\n * Scale (zoom in) to given width and height. Ignore scaleBase if set.\n * @type {Object}\n * @example\n * customSize: { width: 800, height: 400 }\n */\n customSize: null,\n\n /**\n * A callback function that will be called when a target is opened and\n * transition has ended. It will get the target element as the argument.\n * @type {Function}\n */\n onOpen: null,\n\n /**\n * Same as above, except fired when closed.\n * @type {Function}\n */\n onClose: null,\n\n /**\n * Same as above, except fired when released.\n * @type {Function}\n */\n onRelease: null,\n\n /**\n * A callback function that will be called before open.\n * @type {Function}\n */\n onBeforeOpen: null,\n\n /**\n * A callback function that will be called before close.\n * @type {Function}\n */\n onBeforeClose: null,\n\n /**\n * A callback function that will be called before grab.\n * @type {Function}\n */\n onBeforeGrab: null,\n\n /**\n * A callback function that will be called before move.\n * @type {Function}\n */\n onBeforeMove: null,\n\n /**\n * A callback function that will be called before release.\n * @type {Function}\n */\n onBeforeRelease: null\n}\n\n/**\n * Duration (ms) longer than or equal to this value will be recognized as grab,\n * otherwise click.\n * @type {number}\n */\nconst PRESS_DELAY = 200\n\n/**\n * Event types related to grab.\n * @type {Array}\n */\nconst EVENT_TYPES_GRAB = [\n 'mousedown', 'mousemove', 'mouseup',\n 'touchstart', 'touchmove', 'touchend'\n]\n\n/**\n * Scale factor for multi-touch.\n * @type {number}\n */\nconst MULTITOUCH_SCALE_FACTOR = 2\n\nexport {\n OPTIONS,\n PRESS_DELAY,\n EVENT_TYPES_GRAB,\n MULTITOUCH_SCALE_FACTOR\n}\n","import { scrollTop, bind } from './_helpers'\nimport { PRESS_DELAY, MULTITOUCH_SCALE_FACTOR } from './_defaults'\n\nexport default class EventHandler {\n\n constructor (instance) {\n bind(this, instance)\n }\n\n click (e) {\n e.preventDefault()\n\n if (this.shown) {\n if (this.released) this.close()\n else this.release()\n } else {\n this.open(e.currentTarget)\n }\n }\n\n scroll () {\n const st = scrollTop()\n\n if (this.lastScrollPosition === null) {\n this.lastScrollPosition = st\n }\n\n const deltaY = this.lastScrollPosition - st\n\n if (Math.abs(deltaY) >= this.options.scrollThreshold) {\n this.lastScrollPosition = null\n this.close()\n }\n }\n\n keydown (e) {\n const code = e.key || e.code\n if (code === 'Escape' || e.keyCode === 27) {\n if (this.released) this.close()\n else this.release(() => this.close())\n }\n }\n\n mousedown (e) {\n if (e.button !== 0) return\n e.preventDefault()\n\n this.pressTimer = setTimeout(() => {\n this.grab(e.clientX, e.clientY)\n }, PRESS_DELAY)\n }\n\n mousemove (e) {\n if (this.released) return\n this.move(e.clientX, e.clientY)\n }\n\n mouseup (e) {\n if (e.button !== 0) return\n clearTimeout(this.pressTimer)\n\n if (this.released) this.close()\n else this.release()\n }\n\n touchstart (e) {\n e.preventDefault()\n\n this.pressTimer = setTimeout(() => {\n processTouches(e.touches, this.options.scaleExtra,\n (x, y, scaleExtra) => {\n this.grab(x, y, scaleExtra)\n })\n }, PRESS_DELAY)\n }\n\n touchmove (e) {\n if (this.released) return\n\n processTouches(e.touches, this.options.scaleExtra,\n (x, y, scaleExtra) => {\n this.move(x, y, scaleExtra)\n })\n }\n\n touchend (e) {\n if (e.targetTouches.length > 0) return\n clearTimeout(this.pressTimer)\n\n if (this.released) this.close()\n else this.release()\n }\n}\n\nfunction processTouches (touches, currScaleExtra, cb) {\n const total = touches.length\n const firstTouch = touches[0]\n const multitouch = total > 1\n\n let scaleExtra = currScaleExtra\n let i = touches.length\n let [xs, ys] = [0, 0]\n\n // keep track of the min and max of touch positions\n let min = { x: firstTouch.clientX, y: firstTouch.clientY }\n let max = { x: firstTouch.clientX, y: firstTouch.clientY }\n\n while (i--) {\n const t = touches[i]\n const [x, y] = [t.clientX, t.clientY]\n xs += x\n ys += y\n\n if (!multitouch) continue\n\n if (x < min.x) {\n min.x = x\n } else if (x > max.x) {\n max.x = x\n }\n\n if (y < min.y) {\n min.y = y\n } else if (y > max.y) {\n max.y = y\n }\n }\n\n if (multitouch) {\n // change scaleExtra dynamically\n const [distX, distY] = [max.x - min.x, max.y - min.y]\n\n if (distX > distY) {\n scaleExtra = (distX / window.innerWidth) * MULTITOUCH_SCALE_FACTOR\n } else {\n scaleExtra = (distY / window.innerHeight) * MULTITOUCH_SCALE_FACTOR\n }\n }\n\n cb(xs / total, ys / total, scaleExtra)\n}\n","import Target from './Target'\nimport Overlay from './Overlay'\nimport EventHandler from './EventHandler'\nimport { OPTIONS, EVENT_TYPES_GRAB } from './_defaults'\nimport { loadImage, toggleListeners, transEndEvent, cursor } from './_helpers'\n\n/**\n * Zooming instance.\n * @param {Object} [options] Update default options if provided.\n */\nexport default class Zooming {\n\n constructor (options) {\n // elements\n this.body = document.body\n this.overlay = new Overlay(document.createElement('div'), this)\n this.target = null\n\n // state\n this.shown = false // target is open\n this.lock = false // target is in transform\n this.released = true // mouse/finger is not pressing down\n this.lastScrollPosition = null\n this.pressTimer = null\n\n this.options = Object.assign({}, OPTIONS)\n if (options) this.config(options)\n\n this.eventHandler = new EventHandler(this)\n this.overlay.init()\n }\n\n /**\n * Make element(s) zoomable.\n * @param {string|Element} el A css selector or an Element.\n * @return {this}\n */\n listen (el) {\n if (typeof el === 'string') {\n let els = document.querySelectorAll(el), i = els.length\n\n while (i--) {\n this.listen(els[i])\n }\n\n return this\n }\n\n if (el.tagName !== 'IMG') return\n\n el.style.cursor = cursor.zoomIn\n el.addEventListener('click', this.eventHandler.click)\n\n if (this.options.preloadImage && el.hasAttribute('data-original')) {\n loadImage(el.getAttribute('data-original'))\n }\n\n return this\n }\n\n /**\n * Open (zoom in) the Element.\n * @param {Element} el The Element to open.\n * @param {Function} [cb=this.options.onOpen] A callback function that will\n * be called when a target is opened and transition has ended. It will get\n * the target element as the argument.\n * @return {this}\n */\n open (el, cb = this.options.onOpen) {\n if (this.shown || this.lock) return\n\n const target = typeof el === 'string'\n ? document.querySelector(el)\n : el\n\n if (target.tagName !== 'IMG') return\n\n this.target = new Target(target, this)\n\n // onBeforeOpen event\n if (this.options.onBeforeOpen) this.options.onBeforeOpen(target)\n\n this.shown = true\n this.lock = true\n\n this.target.open()\n this.overlay.setParent(target.parentNode)\n this.overlay.insert()\n this.overlay.show()\n\n document.addEventListener('scroll', this.eventHandler.scroll)\n document.addEventListener('keydown', this.eventHandler.keydown)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.lock = false\n\n if (this.options.enableGrab) {\n toggleListeners(document, EVENT_TYPES_GRAB, this.eventHandler, true)\n }\n\n if (target.hasAttribute('data-original')) {\n this.target.upgradeSource()\n }\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Close (zoom out) the Element currently opened.\n * @param {Function} [cb=this.options.onClose] A callback function that will\n * be called when a target is closed and transition has ended. It will get\n * the target element as the argument.\n * @return {this}\n */\n close (cb = this.options.onClose) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeClose event\n if (this.options.onBeforeClose) this.options.onBeforeClose(target)\n\n this.lock = true\n\n this.body.style.cursor = cursor.default\n this.overlay.hide()\n this.target.close()\n\n document.removeEventListener('scroll', this.eventHandler.scroll)\n document.removeEventListener('keydown', this.eventHandler.keydown)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.shown = false\n this.lock = false\n\n if (this.options.enableGrab) {\n toggleListeners(document, EVENT_TYPES_GRAB, this.eventHandler, false)\n }\n\n if (target.hasAttribute('data-original')) {\n this.target.downgradeSource()\n }\n\n this.target.restoreCloseStyle()\n this.overlay.remove()\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Grab the Element currently opened given a position and apply extra zoom-in.\n * @param {number} x The X-axis of where the press happened.\n * @param {number} y The Y-axis of where the press happened.\n * @param {number} scaleExtra Extra zoom-in to apply.\n * @param {Function} [cb=this.options.scaleExtra] A callback function that\n * will be called when a target is grabbed and transition has ended. It\n * will get the target element as the argument.\n * @return {this}\n */\n grab (x, y, scaleExtra = this.options.scaleExtra, cb) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeGrab event\n if (this.options.onBeforeGrab) this.options.onBeforeGrab(target)\n\n this.released = false\n this.target.grab(x, y, scaleExtra)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n }\n\n /**\n * Move the Element currently grabbed given a position and apply extra zoom-in.\n * @param {number} x The X-axis of where the press happened.\n * @param {number} y The Y-axis of where the press happened.\n * @param {number} scaleExtra Extra zoom-in to apply.\n * @param {Function} [cb=this.options.scaleExtra] A callback function that\n * will be called when a target is moved and transition has ended. It will\n * get the target element as the argument.\n * @return {this}\n */\n move (x, y, scaleExtra = this.options.scaleExtra, cb) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeMove event\n if (this.options.onBeforeMove) this.options.onBeforeMove(target)\n\n this.released = false\n\n this.target.move(x, y, scaleExtra)\n this.body.style.cursor = cursor.move\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n }\n\n /**\n * Release the Element currently grabbed.\n * @param {Function} [cb=this.options.onRelease] A callback function that\n * will be called when a target is released and transition has ended. It\n * will get the target element as the argument.\n * @return {this}\n */\n release (cb = this.options.onRelease) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeRelease event\n if (this.options.onBeforeRelease) this.options.onBeforeRelease(target)\n\n this.lock = true\n\n this.target.restoreOpenStyle()\n this.body.style.cursor = cursor.default\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.lock = false\n this.released = true\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Update options.\n * @param {Object} options An Object that contains this.options.\n * @return {this}\n */\n config (options) {\n if (!options) return this.options\n\n for (let key in options) {\n this.options[key] = options[key]\n }\n\n this.overlay.updateStyle()\n\n return this\n }\n}\n","import Zooming from './Zooming'\nimport { OPTIONS } from './_defaults'\n\ndocument.addEventListener('DOMContentLoaded', () => {\n new Zooming().listen(OPTIONS.defaultZoomable)\n})\n\nexport default Zooming\n"],"names":["body","document","docElm","documentElement","webkitPrefix","style","divide","denominator","numerator","half","loadImage","url","cb","img","Image","onload","src","scrollTop","window","pageYOffset","parentNode","getWindowCenter","docWidth","clientWidth","docHeight","clientHeight","toggleListeners","el","types","handler","add","forEach","addEventListener","t","removeEventListener","sniffTransition","ret","trans","tform","end","some","prop","undefined","transitionProp","transEndEvent","transformProp","transformCssProp","replace","createElement","setStyle","styles","remember","value","transition","transform","s","original","key","cursor","bind","_this","that","methods","Object","getOwnPropertyNames","getPrototypeOf","m","Target","instance","translate","scale","srcThumbnail","options","preloadImage","hasAttribute","getAttribute","rect","getBoundingClientRect","calculateTranslate","calculateScale","scaleBase","customSize","offsetWidth","open","enableGrab","grab","zoomOut","transitionDuration","transitionTimingFunction","x","y","close","scaleExtra","windowCenter","dx","dy","move","dataOriginal","temp","cloneNode","setAttribute","position","visibility","appendChild","removeChild","targetCenter","left","width","top","height","targetHalfWidth","targetHalfHeight","targetEdgeToWindowEdge","scaleHorizontally","scaleVertically","Math","min","Overlay","parent","bgColor","opacity","bgOpacity","OPTIONS","PRESS_DELAY","EVENT_TYPES_GRAB","MULTITOUCH_SCALE_FACTOR","EventHandler","e","preventDefault","shown","released","release","currentTarget","st","lastScrollPosition","deltaY","abs","scrollThreshold","code","keyCode","button","pressTimer","setTimeout","clientX","clientY","touches","targetTouches","length","processTouches","currScaleExtra","total","firstTouch","multitouch","i","xs","ys","max","distX","distY","innerWidth","innerHeight","Zooming","overlay","target","lock","assign","config","eventHandler","init","els","querySelectorAll","listen","tagName","zoomIn","click","onOpen","querySelector","onBeforeOpen","setParent","insert","show","scroll","keydown","onEnd","upgradeSource","onClose","onBeforeClose","default","hide","downgradeSource","restoreCloseStyle","remove","onBeforeGrab","onBeforeMove","onRelease","onBeforeRelease","restoreOpenStyle","updateStyle","defaultZoomable"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":null,"sources":["../src/_helpers.js","../src/Target.js","../src/Overlay.js","../src/EventHandler.js","../src/_options.js","../src/Zooming.js","../src/main.js"],"sourcesContent":["const body = document.body\nconst docElm = document.documentElement\nconst webkitPrefix = 'WebkitAppearance' in document.documentElement.style\n ? '-webkit-'\n : ''\n\n const cursor = {\n default: 'auto',\n zoomIn: `${webkitPrefix}zoom-in`,\n zoomOut: `${webkitPrefix}zoom-out`,\n grab: `${webkitPrefix}grab`,\n move: 'move'\n }\n\nconst EVENT_TYPES_GRAB = [\n 'mousedown', 'mousemove', 'mouseup',\n 'touchstart', 'touchmove', 'touchend'\n]\n\nconst divide = (denominator) => {\n return (numerator) => {\n return numerator / denominator\n }\n}\n\nconst half = divide(2)\n\nconst loadImage = (url, cb) => {\n const img = new Image()\n img.onload = () => {\n if (cb) cb(img)\n }\n img.src = url\n}\n\nconst scrollTop = () => {\n return window.pageYOffset ||\n (docElm || body.parentNode || body).scrollTop\n}\n\nconst getWindowCenter = () => {\n const docWidth = docElm.clientWidth || body.clientWidth\n const docHeight = docElm.clientHeight || body.clientHeight\n\n return {\n x: half(docWidth),\n y: half(docHeight)\n }\n}\n\nconst toggleListeners = (el, types, handler, add = true) => {\n types.forEach(t => {\n if (add) {\n el.addEventListener(t, handler[t])\n } else {\n el.removeEventListener(t, handler[t])\n }\n })\n}\n\nconst toggleGrabListeners = (el, handler, add) => {\n return toggleListeners(el, EVENT_TYPES_GRAB, handler, add)\n}\n\nconst sniffTransition = (el) => {\n let ret = {}\n const trans = ['webkitTransition', 'transition', 'mozTransition']\n const tform = ['webkitTransform', 'transform', 'mozTransform']\n const end = {\n 'transition' : 'transitionend',\n 'mozTransition' : 'transitionend',\n 'webkitTransition' : 'webkitTransitionEnd'\n }\n\n trans.some(prop => {\n if (el.style[prop] !== undefined) {\n ret.transitionProp = prop\n ret.transEndEvent = end[prop]\n return true\n }\n })\n\n tform.some(prop => {\n if (el.style[prop] !== undefined) {\n ret.transformProp = prop\n ret.transformCssProp = prop.replace(/(.*)Transform/, '-$1-transform')\n return true\n }\n })\n\n return ret\n}\n\nconst trans = sniffTransition(document.createElement('div'))\nconst transitionProp = trans.transitionProp\nconst transformProp = trans.transformProp\nconst transformCssProp = trans.transformCssProp\nconst transEndEvent = trans.transEndEvent\n\nconst setStyle = (el, styles, remember) => {\n let value\n if (styles.transition) {\n value = styles.transition\n delete styles.transition\n styles[transitionProp] = value\n }\n if (styles.transform) {\n value = styles.transform\n delete styles.transform\n styles[transformProp] = value\n }\n\n let s = el.style\n let original = {}\n\n for (let key in styles) {\n if (remember) original[key] = s[key] || ''\n s[key] = styles[key]\n }\n\n return original\n}\n\nconst bind = (_this, that) => {\n const methods = (\n Object.getOwnPropertyNames(\n Object.getPrototypeOf(_this)\n )\n )\n\n methods.forEach(m => {\n _this[m] = _this[m].bind(that)\n })\n}\n\nexport {\n webkitPrefix,\n half,\n loadImage,\n scrollTop,\n getWindowCenter,\n toggleGrabListeners,\n transformCssProp,\n transEndEvent,\n setStyle,\n cursor,\n bind\n}\n","import { transformCssProp, setStyle, half, getWindowCenter, loadImage, cursor } from './_helpers'\n\nexport default class Target {\n\n constructor (el, instance) {\n this.el = el\n this.instance = instance\n this.body = document.body\n this.translate = null\n this.scale = null\n this.srcThumbnail = null\n this.style = {\n open: null,\n close: null\n }\n }\n\n open () {\n const options = this.instance.options\n\n // load hi-res image if preloadImage option is disabled\n if (!options.preloadImage && this.el.hasAttribute('data-original')) {\n loadImage(this.el.getAttribute('data-original'))\n }\n\n const rect = this.el.getBoundingClientRect()\n this.translate = calculateTranslate(rect)\n this.scale = calculateScale(rect, options.scaleBase, options.customSize)\n\n // force layout update\n this.el.offsetWidth\n\n this.style.open = {\n position: 'relative',\n zIndex: 999,\n cursor: options.enableGrab\n ? cursor.grab\n : cursor.zoomOut,\n transition: `${transformCssProp}\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`,\n transform: `translate(${this.translate.x}px, ${this.translate.y}px)\n scale(${this.scale.x},${this.scale.y})`\n }\n\n // trigger transition\n this.style.close = setStyle(this.el, this.style.open, true)\n }\n\n close () {\n // force layout update\n this.el.offsetWidth\n\n setStyle(this.el, { transform: 'none' })\n }\n\n grab (x, y, scaleExtra) {\n const windowCenter = getWindowCenter()\n const [dx, dy] = [windowCenter.x - x, windowCenter.y - y]\n\n setStyle(this.el, {\n cursor: cursor.move,\n transform: `translate(\n ${this.translate.x + dx}px, ${this.translate.y + dy}px)\n scale(${this.scale.x + scaleExtra},${this.scale.y + scaleExtra})`\n })\n }\n\n move (x, y, scaleExtra) {\n const windowCenter = getWindowCenter()\n const [dx, dy] = [windowCenter.x - x, windowCenter.y - y]\n\n setStyle(this.el, {\n transition: transformCssProp,\n transform: `translate(\n ${this.translate.x + dx}px, ${this.translate.y + dy}px)\n scale(${this.scale.x + scaleExtra},${this.scale.y + scaleExtra})`\n })\n }\n\n restoreCloseStyle () {\n setStyle(this.el, this.style.close)\n }\n\n restoreOpenStyle () {\n setStyle(this.el, this.style.open)\n }\n\n upgradeSource () {\n this.srcThumbnail = this.el.getAttribute('src')\n const dataOriginal = this.el.getAttribute('data-original')\n const temp = this.el.cloneNode(false)\n\n // force compute the hi-res image in DOM to prevent\n // image flickering while updating src\n temp.setAttribute('src', dataOriginal)\n temp.style.position = 'fixed'\n temp.style.visibility = 'hidden'\n this.body.appendChild(temp)\n\n setTimeout(() => {\n this.el.setAttribute('src', dataOriginal)\n this.body.removeChild(temp)\n }, 10)\n }\n\n downgradeSource () {\n this.el.setAttribute('src', this.srcThumbnail)\n }\n}\n\nfunction calculateTranslate (rect) {\n const windowCenter = getWindowCenter()\n const targetCenter = {\n x: rect.left + half(rect.width),\n y: rect.top + half(rect.height)\n }\n\n // The vector to translate image to the window center\n return {\n x: windowCenter.x - targetCenter.x,\n y: windowCenter.y - targetCenter.y\n }\n}\n\nfunction calculateScale (rect, scaleBase, customSize) {\n if (customSize) {\n return {\n x: customSize.width / rect.width,\n y: customSize.height / rect.height\n }\n } else {\n const targetHalfWidth = half(rect.width)\n const targetHalfHeight = half(rect.height)\n const windowCenter = getWindowCenter()\n\n // The distance between target edge and window edge\n const targetEdgeToWindowEdge = {\n x: windowCenter.x - targetHalfWidth,\n y: windowCenter.y - targetHalfHeight\n }\n\n const scaleHorizontally = targetEdgeToWindowEdge.x / targetHalfWidth\n const scaleVertically = targetEdgeToWindowEdge.y / targetHalfHeight\n\n // The additional scale is based on the smaller value of\n // scaling horizontally and scaling vertically\n const scale = scaleBase + Math.min(scaleHorizontally, scaleVertically)\n\n return {\n x: scale,\n y: scale\n }\n }\n}\n","import { setStyle } from './_helpers'\n\nexport default class Overlay {\n\n constructor (el, instance) {\n this.el = el\n this.instance = instance\n this.parent = null\n }\n\n init () {\n const options = this.instance.options\n\n setStyle(this.el, {\n zIndex: 998,\n backgroundColor: options.bgColor,\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n opacity: 0,\n transition: `opacity\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`\n })\n\n this.el.addEventListener('click', () => this.instance.close())\n }\n\n updateStyle () {\n const options = this.instance.options\n\n setStyle(this.el, {\n backgroundColor: options.bgColor,\n transition: `opacity\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`\n })\n }\n\n setParent (parent) {\n this.parent = parent\n }\n\n insert () {\n this.parent.appendChild(this.el)\n }\n\n remove () {\n this.parent.removeChild(this.el)\n }\n\n show () {\n setTimeout(() => this.el.style.opacity = this.instance.options.bgOpacity, 30)\n }\n\n hide () {\n this.el.style.opacity = 0\n }\n}\n","import { scrollTop, bind } from './_helpers'\n\n/**\n * Press duration (ms) longer than or equal to this value will be recognized\n * as grab, otherwise click.\n * @type {number}\n */\nconst PRESS_DELAY = 200\n\n/**\n * Scale factor for multi-touch.\n * @type {number}\n */\nconst MULTITOUCH_SCALE_FACTOR = 2\n\nexport default class EventHandler {\n\n constructor (instance) {\n bind(this, instance)\n }\n\n click (e) {\n e.preventDefault()\n\n if (this.shown) {\n if (this.released) this.close()\n else this.release()\n } else {\n this.open(e.currentTarget)\n }\n }\n\n scroll () {\n const st = scrollTop()\n\n if (this.lastScrollPosition === null) {\n this.lastScrollPosition = st\n }\n\n const deltaY = this.lastScrollPosition - st\n\n if (Math.abs(deltaY) >= this.options.scrollThreshold) {\n this.lastScrollPosition = null\n this.close()\n }\n }\n\n keydown (e) {\n const code = e.key || e.code\n if (code === 'Escape' || e.keyCode === 27) {\n if (this.released) this.close()\n else this.release(() => this.close())\n }\n }\n\n mousedown (e) {\n if (e.button !== 0) return\n e.preventDefault()\n\n this.pressTimer = setTimeout(() => {\n this.grab(e.clientX, e.clientY)\n }, PRESS_DELAY)\n }\n\n mousemove (e) {\n if (this.released) return\n this.move(e.clientX, e.clientY)\n }\n\n mouseup (e) {\n if (e.button !== 0) return\n clearTimeout(this.pressTimer)\n\n if (this.released) this.close()\n else this.release()\n }\n\n touchstart (e) {\n e.preventDefault()\n\n this.pressTimer = setTimeout(() => {\n processTouches(e.touches, this.options.scaleExtra,\n (x, y, scaleExtra) => {\n this.grab(x, y, scaleExtra)\n })\n }, PRESS_DELAY)\n }\n\n touchmove (e) {\n if (this.released) return\n\n processTouches(e.touches, this.options.scaleExtra,\n (x, y, scaleExtra) => {\n this.move(x, y, scaleExtra)\n })\n }\n\n touchend (e) {\n if (e.targetTouches.length > 0) return\n clearTimeout(this.pressTimer)\n\n if (this.released) this.close()\n else this.release()\n }\n}\n\nfunction processTouches (touches, currScaleExtra, cb) {\n const total = touches.length\n const firstTouch = touches[0]\n const multitouch = total > 1\n\n let scaleExtra = currScaleExtra\n let i = touches.length\n let [xs, ys] = [0, 0]\n\n // keep track of the min and max of touch positions\n let min = { x: firstTouch.clientX, y: firstTouch.clientY }\n let max = { x: firstTouch.clientX, y: firstTouch.clientY }\n\n while (i--) {\n const t = touches[i]\n const [x, y] = [t.clientX, t.clientY]\n xs += x\n ys += y\n\n if (!multitouch) continue\n\n if (x < min.x) {\n min.x = x\n } else if (x > max.x) {\n max.x = x\n }\n\n if (y < min.y) {\n min.y = y\n } else if (y > max.y) {\n max.y = y\n }\n }\n\n if (multitouch) {\n // change scaleExtra dynamically\n const [distX, distY] = [max.x - min.x, max.y - min.y]\n\n if (distX > distY) {\n scaleExtra = (distX / window.innerWidth) * MULTITOUCH_SCALE_FACTOR\n } else {\n scaleExtra = (distY / window.innerHeight) * MULTITOUCH_SCALE_FACTOR\n }\n }\n\n cb(xs / total, ys / total, scaleExtra)\n}\n","/**\n * A list of options.\n *\n * @type {Object}\n * @example\n * // Default options\n * var options = {\n * defaultZoomable: 'img[data-action=\"zoom\"]',\n * enableGrab: true,\n * preloadImage: true,\n * transitionDuration: 0.4,\n * transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)',\n * bgColor: 'rgb(255, 255, 255)',\n * bgOpacity: 1,\n * scaleBase: 1.0,\n * scaleExtra: 0.5,\n * scrollThreshold: 40,\n * customSize: null,\n * onOpen: null,\n * onClose: null,\n * onRelease: null,\n * onBeforeOpen: null,\n * onBeforeClose: null,\n * onBeforeGrab: null,\n * onBeforeMove: null,\n * onBeforeRelease: null\n * }\n */\nexport default {\n /**\n * Zoomable elements by default. It can be a css selector or an element.\n * @type {string|Element}\n */\n defaultZoomable: 'img[data-action=\"zoom\"]',\n\n /**\n * To be able to grab and drag the image for extra zoom-in.\n * @type {boolean}\n */\n enableGrab: true,\n\n /**\n * Preload images with attribute \"data-original\".\n * @type {boolean}\n */\n preloadImage: true,\n\n /**\n * Transition duration in seconds.\n * @type {number}\n */\n transitionDuration: 0.4,\n\n /**\n * Transition timing function.\n * @type {string}\n */\n transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)',\n\n /**\n * Overlay background color.\n * @type {string}\n */\n bgColor: 'rgb(255, 255, 255)',\n\n /**\n * Overlay background opacity.\n * @type {number}\n */\n bgOpacity: 1,\n\n /**\n * The base scale factor for zooming. By default scale to fit the window.\n * @type {number}\n */\n scaleBase: 1.0,\n\n /**\n * The extra scale factor when grabbing the image.\n * @type {number}\n */\n scaleExtra: 0.5,\n\n /**\n * How much scrolling it takes before closing out.\n * @type {number}\n */\n scrollThreshold: 40,\n\n /**\n * Scale (zoom in) to given width and height. Ignore scaleBase if set.\n * @type {Object}\n * @example\n * customSize: { width: 800, height: 400 }\n */\n customSize: null,\n\n /**\n * A callback function that will be called when a target is opened and\n * transition has ended. It will get the target element as the argument.\n * @type {Function}\n */\n onOpen: null,\n\n /**\n * Same as above, except fired when closed.\n * @type {Function}\n */\n onClose: null,\n\n /**\n * Same as above, except fired when released.\n * @type {Function}\n */\n onRelease: null,\n\n /**\n * A callback function that will be called before open.\n * @type {Function}\n */\n onBeforeOpen: null,\n\n /**\n * A callback function that will be called before close.\n * @type {Function}\n */\n onBeforeClose: null,\n\n /**\n * A callback function that will be called before grab.\n * @type {Function}\n */\n onBeforeGrab: null,\n\n /**\n * A callback function that will be called before move.\n * @type {Function}\n */\n onBeforeMove: null,\n\n /**\n * A callback function that will be called before release.\n * @type {Function}\n */\n onBeforeRelease: null\n}\n","import Target from './Target'\nimport Overlay from './Overlay'\nimport EventHandler from './EventHandler'\nimport OPTIONS from './_options'\nimport { loadImage, toggleGrabListeners, transEndEvent, cursor } from './_helpers'\n\n/**\n * Zooming instance.\n * @param {Object} [options] Update default options if provided.\n */\nexport default class Zooming {\n\n constructor (options) {\n // elements\n this.body = document.body\n this.overlay = new Overlay(document.createElement('div'), this)\n this.target = null\n\n // state\n this.shown = false // target is open\n this.lock = false // target is in transform\n this.released = true // mouse/finger is not pressing down\n this.lastScrollPosition = null\n this.pressTimer = null\n\n this.options = Object.assign({}, OPTIONS)\n if (options) this.config(options)\n\n this.eventHandler = new EventHandler(this)\n this.overlay.init()\n }\n\n /**\n * Make element(s) zoomable.\n * @param {string|Element} el A css selector or an Element.\n * @return {this}\n */\n listen (el) {\n if (typeof el === 'string') {\n let els = document.querySelectorAll(el), i = els.length\n\n while (i--) {\n this.listen(els[i])\n }\n\n return this\n }\n\n if (el.tagName !== 'IMG') return\n\n el.style.cursor = cursor.zoomIn\n el.addEventListener('click', this.eventHandler.click)\n\n if (this.options.preloadImage && el.hasAttribute('data-original')) {\n loadImage(el.getAttribute('data-original'))\n }\n\n return this\n }\n\n /**\n * Open (zoom in) the Element.\n * @param {Element} el The Element to open.\n * @param {Function} [cb=this.options.onOpen] A callback function that will\n * be called when a target is opened and transition has ended. It will get\n * the target element as the argument.\n * @return {this}\n */\n open (el, cb = this.options.onOpen) {\n if (this.shown || this.lock) return\n\n const target = typeof el === 'string'\n ? document.querySelector(el)\n : el\n\n if (target.tagName !== 'IMG') return\n\n this.target = new Target(target, this)\n\n // onBeforeOpen event\n if (this.options.onBeforeOpen) this.options.onBeforeOpen(target)\n\n this.shown = true\n this.lock = true\n\n this.target.open()\n this.overlay.setParent(target.parentNode)\n this.overlay.insert()\n this.overlay.show()\n\n document.addEventListener('scroll', this.eventHandler.scroll)\n document.addEventListener('keydown', this.eventHandler.keydown)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.lock = false\n\n if (this.options.enableGrab) {\n toggleGrabListeners(document, this.eventHandler, true)\n }\n\n if (target.hasAttribute('data-original')) {\n this.target.upgradeSource()\n }\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Close (zoom out) the Element currently opened.\n * @param {Function} [cb=this.options.onClose] A callback function that will\n * be called when a target is closed and transition has ended. It will get\n * the target element as the argument.\n * @return {this}\n */\n close (cb = this.options.onClose) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeClose event\n if (this.options.onBeforeClose) this.options.onBeforeClose(target)\n\n this.lock = true\n\n this.body.style.cursor = cursor.default\n this.overlay.hide()\n this.target.close()\n\n document.removeEventListener('scroll', this.eventHandler.scroll)\n document.removeEventListener('keydown', this.eventHandler.keydown)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.shown = false\n this.lock = false\n\n if (this.options.enableGrab) {\n toggleGrabListeners(document, this.eventHandler, false)\n }\n\n if (target.hasAttribute('data-original')) {\n this.target.downgradeSource()\n }\n\n this.target.restoreCloseStyle()\n this.overlay.remove()\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Grab the Element currently opened given a position and apply extra zoom-in.\n * @param {number} x The X-axis of where the press happened.\n * @param {number} y The Y-axis of where the press happened.\n * @param {number} scaleExtra Extra zoom-in to apply.\n * @param {Function} [cb=this.options.scaleExtra] A callback function that\n * will be called when a target is grabbed and transition has ended. It\n * will get the target element as the argument.\n * @return {this}\n */\n grab (x, y, scaleExtra = this.options.scaleExtra, cb) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeGrab event\n if (this.options.onBeforeGrab) this.options.onBeforeGrab(target)\n\n this.released = false\n this.target.grab(x, y, scaleExtra)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n }\n\n /**\n * Move the Element currently grabbed given a position and apply extra zoom-in.\n * @param {number} x The X-axis of where the press happened.\n * @param {number} y The Y-axis of where the press happened.\n * @param {number} scaleExtra Extra zoom-in to apply.\n * @param {Function} [cb=this.options.scaleExtra] A callback function that\n * will be called when a target is moved and transition has ended. It will\n * get the target element as the argument.\n * @return {this}\n */\n move (x, y, scaleExtra = this.options.scaleExtra, cb) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeMove event\n if (this.options.onBeforeMove) this.options.onBeforeMove(target)\n\n this.released = false\n\n this.target.move(x, y, scaleExtra)\n this.body.style.cursor = cursor.move\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n }\n\n /**\n * Release the Element currently grabbed.\n * @param {Function} [cb=this.options.onRelease] A callback function that\n * will be called when a target is released and transition has ended. It\n * will get the target element as the argument.\n * @return {this}\n */\n release (cb = this.options.onRelease) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeRelease event\n if (this.options.onBeforeRelease) this.options.onBeforeRelease(target)\n\n this.lock = true\n\n this.target.restoreOpenStyle()\n this.body.style.cursor = cursor.default\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.lock = false\n this.released = true\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Update options.\n * @param {Object} options An Object that contains this.options.\n * @return {this}\n */\n config (options) {\n if (!options) return this.options\n\n for (let key in options) {\n this.options[key] = options[key]\n }\n\n this.overlay.updateStyle()\n\n return this\n }\n}\n","import Zooming from './Zooming'\nimport OPTIONS from './_options'\n\ndocument.addEventListener('DOMContentLoaded', () => {\n new Zooming().listen(OPTIONS.defaultZoomable)\n})\n\nexport default Zooming\n"],"names":["body","document","docElm","documentElement","webkitPrefix","style","cursor","EVENT_TYPES_GRAB","divide","denominator","numerator","half","loadImage","url","cb","img","Image","onload","src","scrollTop","window","pageYOffset","parentNode","getWindowCenter","docWidth","clientWidth","docHeight","clientHeight","toggleListeners","el","types","handler","add","forEach","addEventListener","t","removeEventListener","toggleGrabListeners","sniffTransition","ret","trans","tform","end","some","prop","undefined","transitionProp","transEndEvent","transformProp","transformCssProp","replace","createElement","setStyle","styles","remember","value","transition","transform","s","original","key","bind","_this","that","methods","Object","getOwnPropertyNames","getPrototypeOf","m","Target","instance","translate","scale","srcThumbnail","options","preloadImage","hasAttribute","getAttribute","rect","getBoundingClientRect","calculateTranslate","calculateScale","scaleBase","customSize","offsetWidth","open","enableGrab","grab","zoomOut","transitionDuration","transitionTimingFunction","x","y","close","scaleExtra","windowCenter","dx","dy","move","dataOriginal","temp","cloneNode","setAttribute","position","visibility","appendChild","removeChild","targetCenter","left","width","top","height","targetHalfWidth","targetHalfHeight","targetEdgeToWindowEdge","scaleHorizontally","scaleVertically","Math","min","Overlay","parent","bgColor","opacity","bgOpacity","PRESS_DELAY","MULTITOUCH_SCALE_FACTOR","EventHandler","e","preventDefault","shown","released","release","currentTarget","st","lastScrollPosition","deltaY","abs","scrollThreshold","code","keyCode","button","pressTimer","setTimeout","clientX","clientY","touches","targetTouches","length","processTouches","currScaleExtra","total","firstTouch","multitouch","i","xs","ys","max","distX","distY","innerWidth","innerHeight","Zooming","overlay","target","lock","assign","OPTIONS","config","eventHandler","init","els","querySelectorAll","listen","tagName","zoomIn","click","onOpen","querySelector","onBeforeOpen","setParent","insert","show","scroll","keydown","onEnd","upgradeSource","onClose","onBeforeClose","default","hide","downgradeSource","restoreCloseStyle","remove","onBeforeGrab","onBeforeMove","onRelease","onBeforeRelease","restoreOpenStyle","updateStyle","defaultZoomable"],"mappings":"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"} \ No newline at end of file diff --git a/build/zooming.min.js b/build/zooming.min.js index ebb9e9b5..6a8e320a 100644 --- a/build/zooming.min.js +++ b/build/zooming.min.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Zooming=e()}(this,function(){"use strict";function t(t){var e=h(),n={x:t.left+a(t.width),y:t.top+a(t.height)};return{x:e.x-n.x,y:e.y-n.y}}function e(t,e,n){if(n)return{x:n.width/t.width,y:n.height/t.height};var i=a(t.width),o=a(t.height),s=h(),r={x:s.x-i,y:s.y-o},l=r.x/i,u=r.y/o,c=e+Math.min(l,u);return{x:c,y:c}}function n(t,e,n){for(var i=t.length,o=t[0],s=i>1,r=e,a=t.length,l=0,u=0,h={x:o.clientX,y:o.clientY},c={x:o.clientX,y:o.clientY};a--;){var d=t[a],f=[d.clientX,d.clientY],v=f[0],y=f[1];l+=v,u+=y,s&&(vc.x&&(c.x=v),yc.y&&(c.y=y))}if(s){var m=c.x-h.x,p=c.y-h.y;r=m>p?m/window.innerWidth*S:p/window.innerHeight*S}n(l/i,u/i,r)}var i=document.body,o=document.documentElement,s="WebkitAppearance"in document.documentElement.style?"-webkit-":"",r=function(t){return function(e){return e/t}},a=r(2),l=function(t,e){var n=new Image;n.onload=function(){e&&e(n)},n.src=t},u=function(){return window.pageYOffset||(o||i.parentNode||i).scrollTop},h=function(){var t=o.clientWidth||i.clientWidth,e=o.clientHeight||i.clientHeight;return{x:a(t),y:a(e)}},c=function(t,e,n){var i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];e.forEach(function(e){i?t.addEventListener(e,n[e]):t.removeEventListener(e,n[e])})},d=function(t){var e={},n=["webkitTransition","transition","mozTransition"],i=["webkitTransform","transform","mozTransform"],o={transition:"transitionend",mozTransition:"transitionend",webkitTransition:"webkitTransitionEnd"};return n.some(function(n){if(void 0!==t.style[n])return e.transitionProp=n,e.transEndEvent=o[n],!0}),i.some(function(n){if(void 0!==t.style[n])return e.transformProp=n,e.transformCssProp=n.replace(/(.*)Transform/,"-$1-transform"),!0}),e},f=d(document.createElement("div")),v=f.transitionProp,y=f.transformProp,m=f.transformCssProp,p=f.transEndEvent,g=function(t,e,n){var i=void 0;e.transition&&(i=e.transition,delete e.transition,e[v]=i),e.transform&&(i=e.transform,delete e.transform,e[y]=i);var o=t.style,s={};for(var r in e)n&&(s[r]=o[r]||""),o[r]=e[r];return s},b={default:"auto",zoomIn:s+"zoom-in",zoomOut:s+"zoom-out",grab:s+"grab",move:"move"},k=function(t,e){var n=Object.getOwnPropertyNames(Object.getPrototypeOf(t));n.forEach(function(n){t[n]=t[n].bind(e)})},w=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},x=function(){function t(t,e){for(var n=0;n=this.options.scrollThreshold&&(this.lastScrollPosition=null,this.close())}},{key:"keydown",value:function(t){var e=this,n=t.key||t.code;"Escape"!==n&&27!==t.keyCode||(this.released?this.close():this.release(function(){return e.close()}))}},{key:"mousedown",value:function(t){var e=this;0===t.button&&(t.preventDefault(),this.pressTimer=setTimeout(function(){e.grab(t.clientX,t.clientY)},L))}},{key:"mousemove",value:function(t){this.released||this.move(t.clientX,t.clientY)}},{key:"mouseup",value:function(t){0===t.button&&(clearTimeout(this.pressTimer),this.released?this.close():this.release())}},{key:"touchstart",value:function(t){var e=this;t.preventDefault(),this.pressTimer=setTimeout(function(){n(t.touches,e.options.scaleExtra,function(t,n,i){e.grab(t,n,i)})},L)}},{key:"touchmove",value:function(t){var e=this;this.released||n(t.touches,this.options.scaleExtra,function(t,n,i){e.move(t,n,i)})}},{key:"touchend",value:function(t){t.targetTouches.length>0||(clearTimeout(this.pressTimer),this.released?this.close():this.release())}}]),t}(),P=function(){function t(e){w(this,t),this.body=document.body,this.overlay=new T(document.createElement("div"),this),this.target=null,this.shown=!1,this.lock=!1,this.released=!0,this.lastScrollPosition=null,this.pressTimer=null,this.options=Object.assign({},C),e&&this.config(e),this.eventHandler=new B(this),this.overlay.init()}return x(t,[{key:"listen",value:function(t){if("string"==typeof t){for(var e=document.querySelectorAll(t),n=e.length;n--;)this.listen(e[n]);return this}if("IMG"===t.tagName)return t.style.cursor=b.zoomIn,t.addEventListener("click",this.eventHandler.click),this.options.preloadImage&&t.hasAttribute("data-original")&&l(t.getAttribute("data-original")),this}},{key:"open",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.onOpen;if(!this.shown&&!this.lock){var i="string"==typeof t?document.querySelector(t):t;if("IMG"===i.tagName){this.target=new E(i,this),this.options.onBeforeOpen&&this.options.onBeforeOpen(i),this.shown=!0,this.lock=!0,this.target.open(),this.overlay.setParent(i.parentNode),this.overlay.insert(),this.overlay.show(),document.addEventListener("scroll",this.eventHandler.scroll),document.addEventListener("keydown",this.eventHandler.keydown);var o=function t(){i.removeEventListener(p,t),e.lock=!1,e.options.enableGrab&&c(document,O,e.eventHandler,!0),i.hasAttribute("data-original")&&e.target.upgradeSource(),n&&n(i)};return i.addEventListener(p,o),this}}}},{key:"close",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.onClose;if(this.shown&&!this.lock){var n=this.target.el;this.options.onBeforeClose&&this.options.onBeforeClose(n),this.lock=!0,this.body.style.cursor=b.default,this.overlay.hide(),this.target.close(),document.removeEventListener("scroll",this.eventHandler.scroll),document.removeEventListener("keydown",this.eventHandler.keydown);var i=function i(){n.removeEventListener(p,i),t.shown=!1,t.lock=!1,t.options.enableGrab&&c(document,O,t.eventHandler,!1),n.hasAttribute("data-original")&&t.target.downgradeSource(),t.target.restoreCloseStyle(),t.overlay.remove(),e&&e(n)};return n.addEventListener(p,i),this}}},{key:"grab",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.options.scaleExtra,i=arguments[3];if(this.shown&&!this.lock){var o=this.target.el;this.options.onBeforeGrab&&this.options.onBeforeGrab(o),this.released=!1,this.target.grab(t,e,n);var s=function t(){o.removeEventListener(p,t),i&&i(o)};o.addEventListener(p,s)}}},{key:"move",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.options.scaleExtra,i=arguments[3];if(this.shown&&!this.lock){var o=this.target.el;this.options.onBeforeMove&&this.options.onBeforeMove(o),this.released=!1,this.target.move(t,e,n),this.body.style.cursor=b.move;var s=function t(){o.removeEventListener(p,t),i&&i(o)};o.addEventListener(p,s)}}},{key:"release",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.onRelease;if(this.shown&&!this.lock){var n=this.target.el;this.options.onBeforeRelease&&this.options.onBeforeRelease(n),this.lock=!0,this.target.restoreOpenStyle(),this.body.style.cursor=b.default;var i=function i(){n.removeEventListener(p,i),t.lock=!1,t.released=!0,e&&e(n)};return n.addEventListener(p,i),this}}},{key:"config",value:function(t){if(!t)return this.options;for(var e in t)this.options[e]=t[e];return this.overlay.updateStyle(),this}}]),t}();return document.addEventListener("DOMContentLoaded",function(){(new P).listen(C.defaultZoomable)}),P}); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Zooming=e()}(this,function(){"use strict";function t(t){var e=d(),n={x:t.left+u(t.width),y:t.top+u(t.height)};return{x:e.x-n.x,y:e.y-n.y}}function e(t,e,n){if(n)return{x:n.width/t.width,y:n.height/t.height};var i=u(t.width),o=u(t.height),s=d(),r={x:s.x-i,y:s.y-o},a=r.x/i,l=r.y/o,h=e+Math.min(a,l);return{x:h,y:h}}function n(t,e,n){for(var i=t.length,o=t[0],s=i>1,r=e,a=t.length,l=0,u=0,h={x:o.clientX,y:o.clientY},c={x:o.clientX,y:o.clientY};a--;){var d=t[a],f=[d.clientX,d.clientY],v=f[0],y=f[1];l+=v,u+=y,s&&(vc.x&&(c.x=v),yc.y&&(c.y=y))}if(s){var m=c.x-h.x,p=c.y-h.y;r=m>p?m/window.innerWidth*S:p/window.innerHeight*S}n(l/i,u/i,r)}var i=document.body,o=document.documentElement,s="WebkitAppearance"in document.documentElement.style?"-webkit-":"",r={default:"auto",zoomIn:s+"zoom-in",zoomOut:s+"zoom-out",grab:s+"grab",move:"move"},a=["mousedown","mousemove","mouseup","touchstart","touchmove","touchend"],l=function(t){return function(e){return e/t}},u=l(2),h=function(t,e){var n=new Image;n.onload=function(){e&&e(n)},n.src=t},c=function(){return window.pageYOffset||(o||i.parentNode||i).scrollTop},d=function(){var t=o.clientWidth||i.clientWidth,e=o.clientHeight||i.clientHeight;return{x:u(t),y:u(e)}},f=function(t,e,n){var i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];e.forEach(function(e){i?t.addEventListener(e,n[e]):t.removeEventListener(e,n[e])})},v=function(t,e,n){return f(t,a,e,n)},y=function(t){var e={},n=["webkitTransition","transition","mozTransition"],i=["webkitTransform","transform","mozTransform"],o={transition:"transitionend",mozTransition:"transitionend",webkitTransition:"webkitTransitionEnd"};return n.some(function(n){if(void 0!==t.style[n])return e.transitionProp=n,e.transEndEvent=o[n],!0}),i.some(function(n){if(void 0!==t.style[n])return e.transformProp=n,e.transformCssProp=n.replace(/(.*)Transform/,"-$1-transform"),!0}),e},m=y(document.createElement("div")),p=m.transitionProp,g=m.transformProp,b=m.transformCssProp,k=m.transEndEvent,w=function(t,e,n){var i=void 0;e.transition&&(i=e.transition,delete e.transition,e[p]=i),e.transform&&(i=e.transform,delete e.transform,e[g]=i);var o=t.style,s={};for(var r in e)n&&(s[r]=o[r]||""),o[r]=e[r];return s},x=function(t,e){var n=Object.getOwnPropertyNames(Object.getPrototypeOf(t));n.forEach(function(n){t[n]=t[n].bind(e)})},E=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},T=function(){function t(t,e){for(var n=0;n=this.options.scrollThreshold&&(this.lastScrollPosition=null,this.close())}},{key:"keydown",value:function(t){var e=this,n=t.key||t.code;"Escape"!==n&&27!==t.keyCode||(this.released?this.close():this.release(function(){return e.close()}))}},{key:"mousedown",value:function(t){var e=this;0===t.button&&(t.preventDefault(),this.pressTimer=setTimeout(function(){e.grab(t.clientX,t.clientY)},O))}},{key:"mousemove",value:function(t){this.released||this.move(t.clientX,t.clientY)}},{key:"mouseup",value:function(t){0===t.button&&(clearTimeout(this.pressTimer),this.released?this.close():this.release())}},{key:"touchstart",value:function(t){var e=this;t.preventDefault(),this.pressTimer=setTimeout(function(){n(t.touches,e.options.scaleExtra,function(t,n,i){e.grab(t,n,i)})},O)}},{key:"touchmove",value:function(t){var e=this;this.released||n(t.touches,this.options.scaleExtra,function(t,n,i){e.move(t,n,i)})}},{key:"touchend",value:function(t){t.targetTouches.length>0||(clearTimeout(this.pressTimer),this.released?this.close():this.release())}}]),t}(),P={defaultZoomable:'img[data-action="zoom"]',enableGrab:!0,preloadImage:!0,transitionDuration:.4,transitionTimingFunction:"cubic-bezier(0.4, 0, 0, 1)",bgColor:"rgb(255, 255, 255)",bgOpacity:1,scaleBase:1,scaleExtra:.5,scrollThreshold:40,customSize:null,onOpen:null,onClose:null,onRelease:null,onBeforeOpen:null,onBeforeClose:null,onBeforeGrab:null,onBeforeMove:null,onBeforeRelease:null},z=function(){function t(e){E(this,t),this.body=document.body,this.overlay=new L(document.createElement("div"),this),this.target=null,this.shown=!1,this.lock=!1,this.released=!0,this.lastScrollPosition=null,this.pressTimer=null,this.options=Object.assign({},P),e&&this.config(e),this.eventHandler=new B(this),this.overlay.init()}return T(t,[{key:"listen",value:function(t){if("string"==typeof t){for(var e=document.querySelectorAll(t),n=e.length;n--;)this.listen(e[n]);return this}if("IMG"===t.tagName)return t.style.cursor=r.zoomIn,t.addEventListener("click",this.eventHandler.click),this.options.preloadImage&&t.hasAttribute("data-original")&&h(t.getAttribute("data-original")),this}},{key:"open",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.onOpen;if(!this.shown&&!this.lock){var i="string"==typeof t?document.querySelector(t):t;if("IMG"===i.tagName){this.target=new C(i,this),this.options.onBeforeOpen&&this.options.onBeforeOpen(i),this.shown=!0,this.lock=!0,this.target.open(),this.overlay.setParent(i.parentNode),this.overlay.insert(),this.overlay.show(),document.addEventListener("scroll",this.eventHandler.scroll),document.addEventListener("keydown",this.eventHandler.keydown);var o=function t(){i.removeEventListener(k,t),e.lock=!1,e.options.enableGrab&&v(document,e.eventHandler,!0),i.hasAttribute("data-original")&&e.target.upgradeSource(),n&&n(i)};return i.addEventListener(k,o),this}}}},{key:"close",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.onClose;if(this.shown&&!this.lock){var n=this.target.el;this.options.onBeforeClose&&this.options.onBeforeClose(n),this.lock=!0,this.body.style.cursor=r.default,this.overlay.hide(),this.target.close(),document.removeEventListener("scroll",this.eventHandler.scroll),document.removeEventListener("keydown",this.eventHandler.keydown);var i=function i(){n.removeEventListener(k,i),t.shown=!1,t.lock=!1,t.options.enableGrab&&v(document,t.eventHandler,!1),n.hasAttribute("data-original")&&t.target.downgradeSource(),t.target.restoreCloseStyle(),t.overlay.remove(),e&&e(n)};return n.addEventListener(k,i),this}}},{key:"grab",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.options.scaleExtra,i=arguments[3];if(this.shown&&!this.lock){var o=this.target.el;this.options.onBeforeGrab&&this.options.onBeforeGrab(o),this.released=!1,this.target.grab(t,e,n);var s=function t(){o.removeEventListener(k,t),i&&i(o)};o.addEventListener(k,s)}}},{key:"move",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.options.scaleExtra,i=arguments[3];if(this.shown&&!this.lock){var o=this.target.el;this.options.onBeforeMove&&this.options.onBeforeMove(o),this.released=!1,this.target.move(t,e,n),this.body.style.cursor=r.move;var s=function t(){o.removeEventListener(k,t),i&&i(o)};o.addEventListener(k,s)}}},{key:"release",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.onRelease;if(this.shown&&!this.lock){var n=this.target.el;this.options.onBeforeRelease&&this.options.onBeforeRelease(n),this.lock=!0,this.target.restoreOpenStyle(),this.body.style.cursor=r.default;var i=function i(){n.removeEventListener(k,i),t.lock=!1,t.released=!0,e&&e(n)};return n.addEventListener(k,i),this}}},{key:"config",value:function(t){if(!t)return this.options;for(var e in t)this.options[e]=t[e];return this.overlay.updateStyle(),this}}]),t}();return document.addEventListener("DOMContentLoaded",function(){(new z).listen(P.defaultZoomable)}),z}); //# sourceMappingURL=zooming.min.js.map diff --git a/build/zooming.min.js.map b/build/zooming.min.js.map index f136b1cb..40c31516 100644 --- a/build/zooming.min.js.map +++ b/build/zooming.min.js.map @@ -1 +1 @@ -{"version":3,"file":null,"sources":["../src/Target.js","../src/EventHandler.js","../src/_helpers.js","../src/Overlay.js","../src/_defaults.js","../src/Zooming.js","../src/main.js"],"sourcesContent":["import { transformCssProp, setStyle, half, getWindowCenter, loadImage, cursor } from './_helpers'\n\nexport default class Target {\n\n constructor (el, instance) {\n this.el = el\n this.instance = instance\n this.body = document.body\n this.translate = null\n this.scale = null\n this.srcThumbnail = null\n this.style = {\n open: null,\n close: null\n }\n }\n\n open () {\n const options = this.instance.options\n\n // load hi-res image if preloadImage option is disabled\n if (!options.preloadImage && this.el.hasAttribute('data-original')) {\n loadImage(this.el.getAttribute('data-original'))\n }\n\n const rect = this.el.getBoundingClientRect()\n this.translate = calculateTranslate(rect)\n this.scale = calculateScale(rect, options.scaleBase, options.customSize)\n\n // force layout update\n this.el.offsetWidth\n\n this.style.open = {\n position: 'relative',\n zIndex: 999,\n cursor: options.enableGrab\n ? cursor.grab\n : cursor.zoomOut,\n transition: `${transformCssProp}\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`,\n transform: `translate(${this.translate.x}px, ${this.translate.y}px)\n scale(${this.scale.x},${this.scale.y})`\n }\n\n // trigger transition\n this.style.close = setStyle(this.el, this.style.open, true)\n }\n\n close () {\n // force layout update\n this.el.offsetWidth\n\n setStyle(this.el, { transform: 'none' })\n }\n\n grab (x, y, scaleExtra) {\n const windowCenter = getWindowCenter()\n const [dx, dy] = [windowCenter.x - x, windowCenter.y - y]\n\n setStyle(this.el, {\n cursor: cursor.move,\n transform: `translate(\n ${this.translate.x + dx}px, ${this.translate.y + dy}px)\n scale(${this.scale.x + scaleExtra},${this.scale.y + scaleExtra})`\n })\n }\n\n move (x, y, scaleExtra) {\n const windowCenter = getWindowCenter()\n const [dx, dy] = [windowCenter.x - x, windowCenter.y - y]\n\n setStyle(this.el, {\n transition: transformCssProp,\n transform: `translate(\n ${this.translate.x + dx}px, ${this.translate.y + dy}px)\n scale(${this.scale.x + scaleExtra},${this.scale.y + scaleExtra})`\n })\n }\n\n restoreCloseStyle () {\n setStyle(this.el, this.style.close)\n }\n\n restoreOpenStyle () {\n setStyle(this.el, this.style.open)\n }\n\n upgradeSource () {\n this.srcThumbnail = this.el.getAttribute('src')\n const dataOriginal = this.el.getAttribute('data-original')\n const temp = this.el.cloneNode(false)\n\n // force compute the hi-res image in DOM to prevent\n // image flickering while updating src\n temp.setAttribute('src', dataOriginal)\n temp.style.position = 'fixed'\n temp.style.visibility = 'hidden'\n this.body.appendChild(temp)\n\n setTimeout(() => {\n this.el.setAttribute('src', dataOriginal)\n this.body.removeChild(temp)\n }, 10)\n }\n\n downgradeSource () {\n this.el.setAttribute('src', this.srcThumbnail)\n }\n}\n\nfunction calculateTranslate (rect) {\n const windowCenter = getWindowCenter()\n const targetCenter = {\n x: rect.left + half(rect.width),\n y: rect.top + half(rect.height)\n }\n\n // The vector to translate image to the window center\n return {\n x: windowCenter.x - targetCenter.x,\n y: windowCenter.y - targetCenter.y\n }\n}\n\nfunction calculateScale (rect, scaleBase, customSize) {\n if (customSize) {\n return {\n x: customSize.width / rect.width,\n y: customSize.height / rect.height\n }\n } else {\n const targetHalfWidth = half(rect.width)\n const targetHalfHeight = half(rect.height)\n const windowCenter = getWindowCenter()\n\n // The distance between target edge and window edge\n const targetEdgeToWindowEdge = {\n x: windowCenter.x - targetHalfWidth,\n y: windowCenter.y - targetHalfHeight\n }\n\n const scaleHorizontally = targetEdgeToWindowEdge.x / targetHalfWidth\n const scaleVertically = targetEdgeToWindowEdge.y / targetHalfHeight\n\n // The additional scale is based on the smaller value of\n // scaling horizontally and scaling vertically\n const scale = scaleBase + Math.min(scaleHorizontally, scaleVertically)\n\n return {\n x: scale,\n y: scale\n }\n }\n}\n","import { scrollTop, bind } from './_helpers'\nimport { PRESS_DELAY, MULTITOUCH_SCALE_FACTOR } from './_defaults'\n\nexport default class EventHandler {\n\n constructor (instance) {\n bind(this, instance)\n }\n\n click (e) {\n e.preventDefault()\n\n if (this.shown) {\n if (this.released) this.close()\n else this.release()\n } else {\n this.open(e.currentTarget)\n }\n }\n\n scroll () {\n const st = scrollTop()\n\n if (this.lastScrollPosition === null) {\n this.lastScrollPosition = st\n }\n\n const deltaY = this.lastScrollPosition - st\n\n if (Math.abs(deltaY) >= this.options.scrollThreshold) {\n this.lastScrollPosition = null\n this.close()\n }\n }\n\n keydown (e) {\n const code = e.key || e.code\n if (code === 'Escape' || e.keyCode === 27) {\n if (this.released) this.close()\n else this.release(() => this.close())\n }\n }\n\n mousedown (e) {\n if (e.button !== 0) return\n e.preventDefault()\n\n this.pressTimer = setTimeout(() => {\n this.grab(e.clientX, e.clientY)\n }, PRESS_DELAY)\n }\n\n mousemove (e) {\n if (this.released) return\n this.move(e.clientX, e.clientY)\n }\n\n mouseup (e) {\n if (e.button !== 0) return\n clearTimeout(this.pressTimer)\n\n if (this.released) this.close()\n else this.release()\n }\n\n touchstart (e) {\n e.preventDefault()\n\n this.pressTimer = setTimeout(() => {\n processTouches(e.touches, this.options.scaleExtra,\n (x, y, scaleExtra) => {\n this.grab(x, y, scaleExtra)\n })\n }, PRESS_DELAY)\n }\n\n touchmove (e) {\n if (this.released) return\n\n processTouches(e.touches, this.options.scaleExtra,\n (x, y, scaleExtra) => {\n this.move(x, y, scaleExtra)\n })\n }\n\n touchend (e) {\n if (e.targetTouches.length > 0) return\n clearTimeout(this.pressTimer)\n\n if (this.released) this.close()\n else this.release()\n }\n}\n\nfunction processTouches (touches, currScaleExtra, cb) {\n const total = touches.length\n const firstTouch = touches[0]\n const multitouch = total > 1\n\n let scaleExtra = currScaleExtra\n let i = touches.length\n let [xs, ys] = [0, 0]\n\n // keep track of the min and max of touch positions\n let min = { x: firstTouch.clientX, y: firstTouch.clientY }\n let max = { x: firstTouch.clientX, y: firstTouch.clientY }\n\n while (i--) {\n const t = touches[i]\n const [x, y] = [t.clientX, t.clientY]\n xs += x\n ys += y\n\n if (!multitouch) continue\n\n if (x < min.x) {\n min.x = x\n } else if (x > max.x) {\n max.x = x\n }\n\n if (y < min.y) {\n min.y = y\n } else if (y > max.y) {\n max.y = y\n }\n }\n\n if (multitouch) {\n // change scaleExtra dynamically\n const [distX, distY] = [max.x - min.x, max.y - min.y]\n\n if (distX > distY) {\n scaleExtra = (distX / window.innerWidth) * MULTITOUCH_SCALE_FACTOR\n } else {\n scaleExtra = (distY / window.innerHeight) * MULTITOUCH_SCALE_FACTOR\n }\n }\n\n cb(xs / total, ys / total, scaleExtra)\n}\n","const body = document.body\nconst docElm = document.documentElement\nconst webkitPrefix = 'WebkitAppearance' in document.documentElement.style\n ? '-webkit-'\n : ''\n\nconst divide = (denominator) => {\n return (numerator) => {\n return numerator / denominator\n }\n}\n\nconst half = divide(2)\n\nconst loadImage = (url, cb) => {\n const img = new Image()\n img.onload = () => {\n if (cb) cb(img)\n }\n img.src = url\n}\n\nconst scrollTop = () => {\n return window.pageYOffset ||\n (docElm || body.parentNode || body).scrollTop\n}\n\nconst getWindowCenter = () => {\n const docWidth = docElm.clientWidth || body.clientWidth\n const docHeight = docElm.clientHeight || body.clientHeight\n\n return {\n x: half(docWidth),\n y: half(docHeight)\n }\n}\n\nconst toggleListeners = (el, types, handler, add = true) => {\n types.forEach(t => {\n if (add) {\n el.addEventListener(t, handler[t])\n } else {\n el.removeEventListener(t, handler[t])\n }\n })\n}\n\nconst sniffTransition = (el) => {\n let ret = {}\n const trans = ['webkitTransition', 'transition', 'mozTransition']\n const tform = ['webkitTransform', 'transform', 'mozTransform']\n const end = {\n 'transition' : 'transitionend',\n 'mozTransition' : 'transitionend',\n 'webkitTransition' : 'webkitTransitionEnd'\n }\n\n trans.some(prop => {\n if (el.style[prop] !== undefined) {\n ret.transitionProp = prop\n ret.transEndEvent = end[prop]\n return true\n }\n })\n\n tform.some(prop => {\n if (el.style[prop] !== undefined) {\n ret.transformProp = prop\n ret.transformCssProp = prop.replace(/(.*)Transform/, '-$1-transform')\n return true\n }\n })\n\n return ret\n}\n\nconst trans = sniffTransition(document.createElement('div'))\nconst transitionProp = trans.transitionProp\nconst transformProp = trans.transformProp\nconst transformCssProp = trans.transformCssProp\nconst transEndEvent = trans.transEndEvent\n\nconst setStyle = (el, styles, remember) => {\n let value\n if (styles.transition) {\n value = styles.transition\n delete styles.transition\n styles[transitionProp] = value\n }\n if (styles.transform) {\n value = styles.transform\n delete styles.transform\n styles[transformProp] = value\n }\n\n let s = el.style\n let original = {}\n\n for (let key in styles) {\n if (remember) original[key] = s[key] || ''\n s[key] = styles[key]\n }\n\n return original\n}\n\nconst cursor = {\n default: 'auto',\n zoomIn: `${webkitPrefix}zoom-in`,\n zoomOut: `${webkitPrefix}zoom-out`,\n grab: `${webkitPrefix}grab`,\n move: 'move'\n}\n\nconst bind = (_this, that) => {\n const methods = (\n Object.getOwnPropertyNames(\n Object.getPrototypeOf(_this)\n )\n )\n\n methods.forEach(m => {\n _this[m] = _this[m].bind(that)\n })\n}\n\nexport {\n webkitPrefix,\n half,\n loadImage,\n scrollTop,\n getWindowCenter,\n toggleListeners,\n transformCssProp,\n transEndEvent,\n setStyle,\n cursor,\n bind\n}\n","import { setStyle } from './_helpers'\n\nexport default class Overlay {\n\n constructor (el, instance) {\n this.el = el\n this.instance = instance\n this.parent = null\n }\n\n init () {\n const options = this.instance.options\n\n setStyle(this.el, {\n zIndex: 998,\n backgroundColor: options.bgColor,\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n opacity: 0,\n transition: `opacity\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`\n })\n\n this.el.addEventListener('click', this.instance.close())\n }\n\n updateStyle () {\n const options = this.instance.options\n\n setStyle(this.el, {\n backgroundColor: options.bgColor,\n transition: `opacity\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`\n })\n }\n\n setParent (parent) {\n this.parent = parent\n }\n\n insert () {\n this.parent.appendChild(this.el)\n }\n\n remove () {\n this.parent.removeChild(this.el)\n }\n\n show () {\n setTimeout(() => this.el.style.opacity = this.instance.options.bgOpacity, 30)\n }\n\n hide () {\n this.el.style.opacity = 0\n }\n}\n","/**\n * A list of options.\n *\n * @type {Object}\n * @example\n * // Default options\n * var options = {\n * defaultZoomable: 'img[data-action=\"zoom\"]',\n * enableGrab: true,\n * preloadImage: true,\n * transitionDuration: 0.4,\n * transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)',\n * bgColor: 'rgb(255, 255, 255)',\n * bgOpacity: 1,\n * scaleBase: 1.0,\n * scaleExtra: 0.5,\n * scrollThreshold: 40,\n * customSize: null,\n * onOpen: null,\n * onClose: null,\n * onRelease: null,\n * onBeforeOpen: null,\n * onBeforeClose: null,\n * onBeforeGrab: null,\n * onBeforeMove: null,\n * onBeforeRelease: null\n * }\n */\nconst OPTIONS = {\n /**\n * Zoomable elements by default. It can be a css selector or an element.\n * @type {string|Element}\n */\n defaultZoomable: 'img[data-action=\"zoom\"]',\n\n /**\n * To be able to grab and drag the image for extra zoom-in.\n * @type {boolean}\n */\n enableGrab: true,\n\n /**\n * Preload images with attribute \"data-original\".\n * @type {boolean}\n */\n preloadImage: true,\n\n /**\n * Transition duration in seconds.\n * @type {number}\n */\n transitionDuration: 0.4,\n\n /**\n * Transition timing function.\n * @type {string}\n */\n transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)',\n\n /**\n * Overlay background color.\n * @type {string}\n */\n bgColor: 'rgb(255, 255, 255)',\n\n /**\n * Overlay background opacity.\n * @type {number}\n */\n bgOpacity: 1,\n\n /**\n * The base scale factor for zooming. By default scale to fit the window.\n * @type {number}\n */\n scaleBase: 1.0,\n\n /**\n * The extra scale factor when grabbing the image.\n * @type {number}\n */\n scaleExtra: 0.5,\n\n /**\n * How much scrolling it takes before closing out.\n * @type {number}\n */\n scrollThreshold: 40,\n\n /**\n * Scale (zoom in) to given width and height. Ignore scaleBase if set.\n * @type {Object}\n * @example\n * customSize: { width: 800, height: 400 }\n */\n customSize: null,\n\n /**\n * A callback function that will be called when a target is opened and\n * transition has ended. It will get the target element as the argument.\n * @type {Function}\n */\n onOpen: null,\n\n /**\n * Same as above, except fired when closed.\n * @type {Function}\n */\n onClose: null,\n\n /**\n * Same as above, except fired when released.\n * @type {Function}\n */\n onRelease: null,\n\n /**\n * A callback function that will be called before open.\n * @type {Function}\n */\n onBeforeOpen: null,\n\n /**\n * A callback function that will be called before close.\n * @type {Function}\n */\n onBeforeClose: null,\n\n /**\n * A callback function that will be called before grab.\n * @type {Function}\n */\n onBeforeGrab: null,\n\n /**\n * A callback function that will be called before move.\n * @type {Function}\n */\n onBeforeMove: null,\n\n /**\n * A callback function that will be called before release.\n * @type {Function}\n */\n onBeforeRelease: null\n}\n\n/**\n * Duration (ms) longer than or equal to this value will be recognized as grab,\n * otherwise click.\n * @type {number}\n */\nconst PRESS_DELAY = 200\n\n/**\n * Event types related to grab.\n * @type {Array}\n */\nconst EVENT_TYPES_GRAB = [\n 'mousedown', 'mousemove', 'mouseup',\n 'touchstart', 'touchmove', 'touchend'\n]\n\n/**\n * Scale factor for multi-touch.\n * @type {number}\n */\nconst MULTITOUCH_SCALE_FACTOR = 2\n\nexport {\n OPTIONS,\n PRESS_DELAY,\n EVENT_TYPES_GRAB,\n MULTITOUCH_SCALE_FACTOR\n}\n","import Target from './Target'\nimport Overlay from './Overlay'\nimport EventHandler from './EventHandler'\nimport { OPTIONS, EVENT_TYPES_GRAB } from './_defaults'\nimport { loadImage, toggleListeners, transEndEvent, cursor } from './_helpers'\n\n/**\n * Zooming instance.\n * @param {Object} [options] Update default options if provided.\n */\nexport default class Zooming {\n\n constructor (options) {\n // elements\n this.body = document.body\n this.overlay = new Overlay(document.createElement('div'), this)\n this.target = null\n\n // state\n this.shown = false // target is open\n this.lock = false // target is in transform\n this.released = true // mouse/finger is not pressing down\n this.lastScrollPosition = null\n this.pressTimer = null\n\n this.options = Object.assign({}, OPTIONS)\n if (options) this.config(options)\n\n this.eventHandler = new EventHandler(this)\n this.overlay.init()\n }\n\n /**\n * Make element(s) zoomable.\n * @param {string|Element} el A css selector or an Element.\n * @return {this}\n */\n listen (el) {\n if (typeof el === 'string') {\n let els = document.querySelectorAll(el), i = els.length\n\n while (i--) {\n this.listen(els[i])\n }\n\n return this\n }\n\n if (el.tagName !== 'IMG') return\n\n el.style.cursor = cursor.zoomIn\n el.addEventListener('click', this.eventHandler.click)\n\n if (this.options.preloadImage && el.hasAttribute('data-original')) {\n loadImage(el.getAttribute('data-original'))\n }\n\n return this\n }\n\n /**\n * Open (zoom in) the Element.\n * @param {Element} el The Element to open.\n * @param {Function} [cb=this.options.onOpen] A callback function that will\n * be called when a target is opened and transition has ended. It will get\n * the target element as the argument.\n * @return {this}\n */\n open (el, cb = this.options.onOpen) {\n if (this.shown || this.lock) return\n\n const target = typeof el === 'string'\n ? document.querySelector(el)\n : el\n\n if (target.tagName !== 'IMG') return\n\n this.target = new Target(target, this)\n\n // onBeforeOpen event\n if (this.options.onBeforeOpen) this.options.onBeforeOpen(target)\n\n this.shown = true\n this.lock = true\n\n this.target.open()\n this.overlay.setParent(target.parentNode)\n this.overlay.insert()\n this.overlay.show()\n\n document.addEventListener('scroll', this.eventHandler.scroll)\n document.addEventListener('keydown', this.eventHandler.keydown)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.lock = false\n\n if (this.options.enableGrab) {\n toggleListeners(document, EVENT_TYPES_GRAB, this.eventHandler, true)\n }\n\n if (target.hasAttribute('data-original')) {\n this.target.upgradeSource()\n }\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Close (zoom out) the Element currently opened.\n * @param {Function} [cb=this.options.onClose] A callback function that will\n * be called when a target is closed and transition has ended. It will get\n * the target element as the argument.\n * @return {this}\n */\n close (cb = this.options.onClose) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeClose event\n if (this.options.onBeforeClose) this.options.onBeforeClose(target)\n\n this.lock = true\n\n this.body.style.cursor = cursor.default\n this.overlay.hide()\n this.target.close()\n\n document.removeEventListener('scroll', this.eventHandler.scroll)\n document.removeEventListener('keydown', this.eventHandler.keydown)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.shown = false\n this.lock = false\n\n if (this.options.enableGrab) {\n toggleListeners(document, EVENT_TYPES_GRAB, this.eventHandler, false)\n }\n\n if (target.hasAttribute('data-original')) {\n this.target.downgradeSource()\n }\n\n this.target.restoreCloseStyle()\n this.overlay.remove()\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Grab the Element currently opened given a position and apply extra zoom-in.\n * @param {number} x The X-axis of where the press happened.\n * @param {number} y The Y-axis of where the press happened.\n * @param {number} scaleExtra Extra zoom-in to apply.\n * @param {Function} [cb=this.options.scaleExtra] A callback function that\n * will be called when a target is grabbed and transition has ended. It\n * will get the target element as the argument.\n * @return {this}\n */\n grab (x, y, scaleExtra = this.options.scaleExtra, cb) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeGrab event\n if (this.options.onBeforeGrab) this.options.onBeforeGrab(target)\n\n this.released = false\n this.target.grab(x, y, scaleExtra)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n }\n\n /**\n * Move the Element currently grabbed given a position and apply extra zoom-in.\n * @param {number} x The X-axis of where the press happened.\n * @param {number} y The Y-axis of where the press happened.\n * @param {number} scaleExtra Extra zoom-in to apply.\n * @param {Function} [cb=this.options.scaleExtra] A callback function that\n * will be called when a target is moved and transition has ended. It will\n * get the target element as the argument.\n * @return {this}\n */\n move (x, y, scaleExtra = this.options.scaleExtra, cb) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeMove event\n if (this.options.onBeforeMove) this.options.onBeforeMove(target)\n\n this.released = false\n\n this.target.move(x, y, scaleExtra)\n this.body.style.cursor = cursor.move\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n }\n\n /**\n * Release the Element currently grabbed.\n * @param {Function} [cb=this.options.onRelease] A callback function that\n * will be called when a target is released and transition has ended. It\n * will get the target element as the argument.\n * @return {this}\n */\n release (cb = this.options.onRelease) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeRelease event\n if (this.options.onBeforeRelease) this.options.onBeforeRelease(target)\n\n this.lock = true\n\n this.target.restoreOpenStyle()\n this.body.style.cursor = cursor.default\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.lock = false\n this.released = true\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Update options.\n * @param {Object} options An Object that contains this.options.\n * @return {this}\n */\n config (options) {\n if (!options) return this.options\n\n for (let key in options) {\n this.options[key] = options[key]\n }\n\n this.overlay.updateStyle()\n\n return this\n }\n}\n","import Zooming from './Zooming'\nimport { OPTIONS } from './_defaults'\n\ndocument.addEventListener('DOMContentLoaded', () => {\n new Zooming().listen(OPTIONS.defaultZoomable)\n})\n\nexport default Zooming\n"],"names":["calculateTranslate","rect","windowCenter","getWindowCenter","targetCenter","left","half","width","top","height","x","y","calculateScale","scaleBase","customSize","targetHalfWidth","targetHalfHeight","targetEdgeToWindowEdge","scaleHorizontally","scaleVertically","scale","Math","min","processTouches","touches","currScaleExtra","cb","total","length","firstTouch","multitouch","scaleExtra","i","xs","ys","clientX","clientY","max","t","distX","distY","window","innerWidth","MULTITOUCH_SCALE_FACTOR","innerHeight","body","document","docElm","documentElement","webkitPrefix","style","divide","denominator","numerator","loadImage","url","img","Image","onload","src","scrollTop","pageYOffset","parentNode","docWidth","clientWidth","docHeight","clientHeight","toggleListeners","el","types","handler","add","forEach","addEventListener","removeEventListener","sniffTransition","ret","trans","tform","end","some","undefined","prop","transitionProp","transEndEvent","transformProp","transformCssProp","replace","createElement","setStyle","styles","remember","value","transition","transform","s","original","key","cursor","bind","_this","that","methods","Object","getOwnPropertyNames","getPrototypeOf","m","Target","instance","translate","srcThumbnail","options","this","preloadImage","hasAttribute","getAttribute","getBoundingClientRect","offsetWidth","open","enableGrab","grab","zoomOut","transitionDuration","transitionTimingFunction","close","dx","dy","move","dataOriginal","temp","cloneNode","setAttribute","position","visibility","appendChild","removeChild","Overlay","parent","bgColor","opacity","bgOpacity","OPTIONS","PRESS_DELAY","EVENT_TYPES_GRAB","EventHandler","e","preventDefault","shown","released","release","currentTarget","st","lastScrollPosition","deltaY","abs","scrollThreshold","code","keyCode","button","pressTimer","setTimeout","_this3","targetTouches","Zooming","overlay","target","lock","assign","config","eventHandler","init","els","querySelectorAll","listen","tagName","zoomIn","click","onOpen","querySelector","onBeforeOpen","setParent","insert","show","scroll","keydown","onEnd","upgradeSource","onClose","onBeforeClose","default","hide","_this2","downgradeSource","restoreCloseStyle","remove","onBeforeGrab","onBeforeMove","onRelease","onBeforeRelease","restoreOpenStyle","updateStyle","defaultZoomable"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":null,"sources":["../src/Target.js","../src/EventHandler.js","../src/_helpers.js","../src/Overlay.js","../src/_options.js","../src/Zooming.js","../src/main.js"],"sourcesContent":["import { transformCssProp, setStyle, half, getWindowCenter, loadImage, cursor } from './_helpers'\n\nexport default class Target {\n\n constructor (el, instance) {\n this.el = el\n this.instance = instance\n this.body = document.body\n this.translate = null\n this.scale = null\n this.srcThumbnail = null\n this.style = {\n open: null,\n close: null\n }\n }\n\n open () {\n const options = this.instance.options\n\n // load hi-res image if preloadImage option is disabled\n if (!options.preloadImage && this.el.hasAttribute('data-original')) {\n loadImage(this.el.getAttribute('data-original'))\n }\n\n const rect = this.el.getBoundingClientRect()\n this.translate = calculateTranslate(rect)\n this.scale = calculateScale(rect, options.scaleBase, options.customSize)\n\n // force layout update\n this.el.offsetWidth\n\n this.style.open = {\n position: 'relative',\n zIndex: 999,\n cursor: options.enableGrab\n ? cursor.grab\n : cursor.zoomOut,\n transition: `${transformCssProp}\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`,\n transform: `translate(${this.translate.x}px, ${this.translate.y}px)\n scale(${this.scale.x},${this.scale.y})`\n }\n\n // trigger transition\n this.style.close = setStyle(this.el, this.style.open, true)\n }\n\n close () {\n // force layout update\n this.el.offsetWidth\n\n setStyle(this.el, { transform: 'none' })\n }\n\n grab (x, y, scaleExtra) {\n const windowCenter = getWindowCenter()\n const [dx, dy] = [windowCenter.x - x, windowCenter.y - y]\n\n setStyle(this.el, {\n cursor: cursor.move,\n transform: `translate(\n ${this.translate.x + dx}px, ${this.translate.y + dy}px)\n scale(${this.scale.x + scaleExtra},${this.scale.y + scaleExtra})`\n })\n }\n\n move (x, y, scaleExtra) {\n const windowCenter = getWindowCenter()\n const [dx, dy] = [windowCenter.x - x, windowCenter.y - y]\n\n setStyle(this.el, {\n transition: transformCssProp,\n transform: `translate(\n ${this.translate.x + dx}px, ${this.translate.y + dy}px)\n scale(${this.scale.x + scaleExtra},${this.scale.y + scaleExtra})`\n })\n }\n\n restoreCloseStyle () {\n setStyle(this.el, this.style.close)\n }\n\n restoreOpenStyle () {\n setStyle(this.el, this.style.open)\n }\n\n upgradeSource () {\n this.srcThumbnail = this.el.getAttribute('src')\n const dataOriginal = this.el.getAttribute('data-original')\n const temp = this.el.cloneNode(false)\n\n // force compute the hi-res image in DOM to prevent\n // image flickering while updating src\n temp.setAttribute('src', dataOriginal)\n temp.style.position = 'fixed'\n temp.style.visibility = 'hidden'\n this.body.appendChild(temp)\n\n setTimeout(() => {\n this.el.setAttribute('src', dataOriginal)\n this.body.removeChild(temp)\n }, 10)\n }\n\n downgradeSource () {\n this.el.setAttribute('src', this.srcThumbnail)\n }\n}\n\nfunction calculateTranslate (rect) {\n const windowCenter = getWindowCenter()\n const targetCenter = {\n x: rect.left + half(rect.width),\n y: rect.top + half(rect.height)\n }\n\n // The vector to translate image to the window center\n return {\n x: windowCenter.x - targetCenter.x,\n y: windowCenter.y - targetCenter.y\n }\n}\n\nfunction calculateScale (rect, scaleBase, customSize) {\n if (customSize) {\n return {\n x: customSize.width / rect.width,\n y: customSize.height / rect.height\n }\n } else {\n const targetHalfWidth = half(rect.width)\n const targetHalfHeight = half(rect.height)\n const windowCenter = getWindowCenter()\n\n // The distance between target edge and window edge\n const targetEdgeToWindowEdge = {\n x: windowCenter.x - targetHalfWidth,\n y: windowCenter.y - targetHalfHeight\n }\n\n const scaleHorizontally = targetEdgeToWindowEdge.x / targetHalfWidth\n const scaleVertically = targetEdgeToWindowEdge.y / targetHalfHeight\n\n // The additional scale is based on the smaller value of\n // scaling horizontally and scaling vertically\n const scale = scaleBase + Math.min(scaleHorizontally, scaleVertically)\n\n return {\n x: scale,\n y: scale\n }\n }\n}\n","import { scrollTop, bind } from './_helpers'\n\n/**\n * Press duration (ms) longer than or equal to this value will be recognized\n * as grab, otherwise click.\n * @type {number}\n */\nconst PRESS_DELAY = 200\n\n/**\n * Scale factor for multi-touch.\n * @type {number}\n */\nconst MULTITOUCH_SCALE_FACTOR = 2\n\nexport default class EventHandler {\n\n constructor (instance) {\n bind(this, instance)\n }\n\n click (e) {\n e.preventDefault()\n\n if (this.shown) {\n if (this.released) this.close()\n else this.release()\n } else {\n this.open(e.currentTarget)\n }\n }\n\n scroll () {\n const st = scrollTop()\n\n if (this.lastScrollPosition === null) {\n this.lastScrollPosition = st\n }\n\n const deltaY = this.lastScrollPosition - st\n\n if (Math.abs(deltaY) >= this.options.scrollThreshold) {\n this.lastScrollPosition = null\n this.close()\n }\n }\n\n keydown (e) {\n const code = e.key || e.code\n if (code === 'Escape' || e.keyCode === 27) {\n if (this.released) this.close()\n else this.release(() => this.close())\n }\n }\n\n mousedown (e) {\n if (e.button !== 0) return\n e.preventDefault()\n\n this.pressTimer = setTimeout(() => {\n this.grab(e.clientX, e.clientY)\n }, PRESS_DELAY)\n }\n\n mousemove (e) {\n if (this.released) return\n this.move(e.clientX, e.clientY)\n }\n\n mouseup (e) {\n if (e.button !== 0) return\n clearTimeout(this.pressTimer)\n\n if (this.released) this.close()\n else this.release()\n }\n\n touchstart (e) {\n e.preventDefault()\n\n this.pressTimer = setTimeout(() => {\n processTouches(e.touches, this.options.scaleExtra,\n (x, y, scaleExtra) => {\n this.grab(x, y, scaleExtra)\n })\n }, PRESS_DELAY)\n }\n\n touchmove (e) {\n if (this.released) return\n\n processTouches(e.touches, this.options.scaleExtra,\n (x, y, scaleExtra) => {\n this.move(x, y, scaleExtra)\n })\n }\n\n touchend (e) {\n if (e.targetTouches.length > 0) return\n clearTimeout(this.pressTimer)\n\n if (this.released) this.close()\n else this.release()\n }\n}\n\nfunction processTouches (touches, currScaleExtra, cb) {\n const total = touches.length\n const firstTouch = touches[0]\n const multitouch = total > 1\n\n let scaleExtra = currScaleExtra\n let i = touches.length\n let [xs, ys] = [0, 0]\n\n // keep track of the min and max of touch positions\n let min = { x: firstTouch.clientX, y: firstTouch.clientY }\n let max = { x: firstTouch.clientX, y: firstTouch.clientY }\n\n while (i--) {\n const t = touches[i]\n const [x, y] = [t.clientX, t.clientY]\n xs += x\n ys += y\n\n if (!multitouch) continue\n\n if (x < min.x) {\n min.x = x\n } else if (x > max.x) {\n max.x = x\n }\n\n if (y < min.y) {\n min.y = y\n } else if (y > max.y) {\n max.y = y\n }\n }\n\n if (multitouch) {\n // change scaleExtra dynamically\n const [distX, distY] = [max.x - min.x, max.y - min.y]\n\n if (distX > distY) {\n scaleExtra = (distX / window.innerWidth) * MULTITOUCH_SCALE_FACTOR\n } else {\n scaleExtra = (distY / window.innerHeight) * MULTITOUCH_SCALE_FACTOR\n }\n }\n\n cb(xs / total, ys / total, scaleExtra)\n}\n","const body = document.body\nconst docElm = document.documentElement\nconst webkitPrefix = 'WebkitAppearance' in document.documentElement.style\n ? '-webkit-'\n : ''\n\n const cursor = {\n default: 'auto',\n zoomIn: `${webkitPrefix}zoom-in`,\n zoomOut: `${webkitPrefix}zoom-out`,\n grab: `${webkitPrefix}grab`,\n move: 'move'\n }\n\nconst EVENT_TYPES_GRAB = [\n 'mousedown', 'mousemove', 'mouseup',\n 'touchstart', 'touchmove', 'touchend'\n]\n\nconst divide = (denominator) => {\n return (numerator) => {\n return numerator / denominator\n }\n}\n\nconst half = divide(2)\n\nconst loadImage = (url, cb) => {\n const img = new Image()\n img.onload = () => {\n if (cb) cb(img)\n }\n img.src = url\n}\n\nconst scrollTop = () => {\n return window.pageYOffset ||\n (docElm || body.parentNode || body).scrollTop\n}\n\nconst getWindowCenter = () => {\n const docWidth = docElm.clientWidth || body.clientWidth\n const docHeight = docElm.clientHeight || body.clientHeight\n\n return {\n x: half(docWidth),\n y: half(docHeight)\n }\n}\n\nconst toggleListeners = (el, types, handler, add = true) => {\n types.forEach(t => {\n if (add) {\n el.addEventListener(t, handler[t])\n } else {\n el.removeEventListener(t, handler[t])\n }\n })\n}\n\nconst toggleGrabListeners = (el, handler, add) => {\n return toggleListeners(el, EVENT_TYPES_GRAB, handler, add)\n}\n\nconst sniffTransition = (el) => {\n let ret = {}\n const trans = ['webkitTransition', 'transition', 'mozTransition']\n const tform = ['webkitTransform', 'transform', 'mozTransform']\n const end = {\n 'transition' : 'transitionend',\n 'mozTransition' : 'transitionend',\n 'webkitTransition' : 'webkitTransitionEnd'\n }\n\n trans.some(prop => {\n if (el.style[prop] !== undefined) {\n ret.transitionProp = prop\n ret.transEndEvent = end[prop]\n return true\n }\n })\n\n tform.some(prop => {\n if (el.style[prop] !== undefined) {\n ret.transformProp = prop\n ret.transformCssProp = prop.replace(/(.*)Transform/, '-$1-transform')\n return true\n }\n })\n\n return ret\n}\n\nconst trans = sniffTransition(document.createElement('div'))\nconst transitionProp = trans.transitionProp\nconst transformProp = trans.transformProp\nconst transformCssProp = trans.transformCssProp\nconst transEndEvent = trans.transEndEvent\n\nconst setStyle = (el, styles, remember) => {\n let value\n if (styles.transition) {\n value = styles.transition\n delete styles.transition\n styles[transitionProp] = value\n }\n if (styles.transform) {\n value = styles.transform\n delete styles.transform\n styles[transformProp] = value\n }\n\n let s = el.style\n let original = {}\n\n for (let key in styles) {\n if (remember) original[key] = s[key] || ''\n s[key] = styles[key]\n }\n\n return original\n}\n\nconst bind = (_this, that) => {\n const methods = (\n Object.getOwnPropertyNames(\n Object.getPrototypeOf(_this)\n )\n )\n\n methods.forEach(m => {\n _this[m] = _this[m].bind(that)\n })\n}\n\nexport {\n webkitPrefix,\n half,\n loadImage,\n scrollTop,\n getWindowCenter,\n toggleGrabListeners,\n transformCssProp,\n transEndEvent,\n setStyle,\n cursor,\n bind\n}\n","import { setStyle } from './_helpers'\n\nexport default class Overlay {\n\n constructor (el, instance) {\n this.el = el\n this.instance = instance\n this.parent = null\n }\n\n init () {\n const options = this.instance.options\n\n setStyle(this.el, {\n zIndex: 998,\n backgroundColor: options.bgColor,\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n opacity: 0,\n transition: `opacity\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`\n })\n\n this.el.addEventListener('click', () => this.instance.close())\n }\n\n updateStyle () {\n const options = this.instance.options\n\n setStyle(this.el, {\n backgroundColor: options.bgColor,\n transition: `opacity\n ${options.transitionDuration}s\n ${options.transitionTimingFunction}`\n })\n }\n\n setParent (parent) {\n this.parent = parent\n }\n\n insert () {\n this.parent.appendChild(this.el)\n }\n\n remove () {\n this.parent.removeChild(this.el)\n }\n\n show () {\n setTimeout(() => this.el.style.opacity = this.instance.options.bgOpacity, 30)\n }\n\n hide () {\n this.el.style.opacity = 0\n }\n}\n","/**\n * A list of options.\n *\n * @type {Object}\n * @example\n * // Default options\n * var options = {\n * defaultZoomable: 'img[data-action=\"zoom\"]',\n * enableGrab: true,\n * preloadImage: true,\n * transitionDuration: 0.4,\n * transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)',\n * bgColor: 'rgb(255, 255, 255)',\n * bgOpacity: 1,\n * scaleBase: 1.0,\n * scaleExtra: 0.5,\n * scrollThreshold: 40,\n * customSize: null,\n * onOpen: null,\n * onClose: null,\n * onRelease: null,\n * onBeforeOpen: null,\n * onBeforeClose: null,\n * onBeforeGrab: null,\n * onBeforeMove: null,\n * onBeforeRelease: null\n * }\n */\nexport default {\n /**\n * Zoomable elements by default. It can be a css selector or an element.\n * @type {string|Element}\n */\n defaultZoomable: 'img[data-action=\"zoom\"]',\n\n /**\n * To be able to grab and drag the image for extra zoom-in.\n * @type {boolean}\n */\n enableGrab: true,\n\n /**\n * Preload images with attribute \"data-original\".\n * @type {boolean}\n */\n preloadImage: true,\n\n /**\n * Transition duration in seconds.\n * @type {number}\n */\n transitionDuration: 0.4,\n\n /**\n * Transition timing function.\n * @type {string}\n */\n transitionTimingFunction: 'cubic-bezier(0.4, 0, 0, 1)',\n\n /**\n * Overlay background color.\n * @type {string}\n */\n bgColor: 'rgb(255, 255, 255)',\n\n /**\n * Overlay background opacity.\n * @type {number}\n */\n bgOpacity: 1,\n\n /**\n * The base scale factor for zooming. By default scale to fit the window.\n * @type {number}\n */\n scaleBase: 1.0,\n\n /**\n * The extra scale factor when grabbing the image.\n * @type {number}\n */\n scaleExtra: 0.5,\n\n /**\n * How much scrolling it takes before closing out.\n * @type {number}\n */\n scrollThreshold: 40,\n\n /**\n * Scale (zoom in) to given width and height. Ignore scaleBase if set.\n * @type {Object}\n * @example\n * customSize: { width: 800, height: 400 }\n */\n customSize: null,\n\n /**\n * A callback function that will be called when a target is opened and\n * transition has ended. It will get the target element as the argument.\n * @type {Function}\n */\n onOpen: null,\n\n /**\n * Same as above, except fired when closed.\n * @type {Function}\n */\n onClose: null,\n\n /**\n * Same as above, except fired when released.\n * @type {Function}\n */\n onRelease: null,\n\n /**\n * A callback function that will be called before open.\n * @type {Function}\n */\n onBeforeOpen: null,\n\n /**\n * A callback function that will be called before close.\n * @type {Function}\n */\n onBeforeClose: null,\n\n /**\n * A callback function that will be called before grab.\n * @type {Function}\n */\n onBeforeGrab: null,\n\n /**\n * A callback function that will be called before move.\n * @type {Function}\n */\n onBeforeMove: null,\n\n /**\n * A callback function that will be called before release.\n * @type {Function}\n */\n onBeforeRelease: null\n}\n","import Target from './Target'\nimport Overlay from './Overlay'\nimport EventHandler from './EventHandler'\nimport OPTIONS from './_options'\nimport { loadImage, toggleGrabListeners, transEndEvent, cursor } from './_helpers'\n\n/**\n * Zooming instance.\n * @param {Object} [options] Update default options if provided.\n */\nexport default class Zooming {\n\n constructor (options) {\n // elements\n this.body = document.body\n this.overlay = new Overlay(document.createElement('div'), this)\n this.target = null\n\n // state\n this.shown = false // target is open\n this.lock = false // target is in transform\n this.released = true // mouse/finger is not pressing down\n this.lastScrollPosition = null\n this.pressTimer = null\n\n this.options = Object.assign({}, OPTIONS)\n if (options) this.config(options)\n\n this.eventHandler = new EventHandler(this)\n this.overlay.init()\n }\n\n /**\n * Make element(s) zoomable.\n * @param {string|Element} el A css selector or an Element.\n * @return {this}\n */\n listen (el) {\n if (typeof el === 'string') {\n let els = document.querySelectorAll(el), i = els.length\n\n while (i--) {\n this.listen(els[i])\n }\n\n return this\n }\n\n if (el.tagName !== 'IMG') return\n\n el.style.cursor = cursor.zoomIn\n el.addEventListener('click', this.eventHandler.click)\n\n if (this.options.preloadImage && el.hasAttribute('data-original')) {\n loadImage(el.getAttribute('data-original'))\n }\n\n return this\n }\n\n /**\n * Open (zoom in) the Element.\n * @param {Element} el The Element to open.\n * @param {Function} [cb=this.options.onOpen] A callback function that will\n * be called when a target is opened and transition has ended. It will get\n * the target element as the argument.\n * @return {this}\n */\n open (el, cb = this.options.onOpen) {\n if (this.shown || this.lock) return\n\n const target = typeof el === 'string'\n ? document.querySelector(el)\n : el\n\n if (target.tagName !== 'IMG') return\n\n this.target = new Target(target, this)\n\n // onBeforeOpen event\n if (this.options.onBeforeOpen) this.options.onBeforeOpen(target)\n\n this.shown = true\n this.lock = true\n\n this.target.open()\n this.overlay.setParent(target.parentNode)\n this.overlay.insert()\n this.overlay.show()\n\n document.addEventListener('scroll', this.eventHandler.scroll)\n document.addEventListener('keydown', this.eventHandler.keydown)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.lock = false\n\n if (this.options.enableGrab) {\n toggleGrabListeners(document, this.eventHandler, true)\n }\n\n if (target.hasAttribute('data-original')) {\n this.target.upgradeSource()\n }\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Close (zoom out) the Element currently opened.\n * @param {Function} [cb=this.options.onClose] A callback function that will\n * be called when a target is closed and transition has ended. It will get\n * the target element as the argument.\n * @return {this}\n */\n close (cb = this.options.onClose) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeClose event\n if (this.options.onBeforeClose) this.options.onBeforeClose(target)\n\n this.lock = true\n\n this.body.style.cursor = cursor.default\n this.overlay.hide()\n this.target.close()\n\n document.removeEventListener('scroll', this.eventHandler.scroll)\n document.removeEventListener('keydown', this.eventHandler.keydown)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.shown = false\n this.lock = false\n\n if (this.options.enableGrab) {\n toggleGrabListeners(document, this.eventHandler, false)\n }\n\n if (target.hasAttribute('data-original')) {\n this.target.downgradeSource()\n }\n\n this.target.restoreCloseStyle()\n this.overlay.remove()\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Grab the Element currently opened given a position and apply extra zoom-in.\n * @param {number} x The X-axis of where the press happened.\n * @param {number} y The Y-axis of where the press happened.\n * @param {number} scaleExtra Extra zoom-in to apply.\n * @param {Function} [cb=this.options.scaleExtra] A callback function that\n * will be called when a target is grabbed and transition has ended. It\n * will get the target element as the argument.\n * @return {this}\n */\n grab (x, y, scaleExtra = this.options.scaleExtra, cb) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeGrab event\n if (this.options.onBeforeGrab) this.options.onBeforeGrab(target)\n\n this.released = false\n this.target.grab(x, y, scaleExtra)\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n }\n\n /**\n * Move the Element currently grabbed given a position and apply extra zoom-in.\n * @param {number} x The X-axis of where the press happened.\n * @param {number} y The Y-axis of where the press happened.\n * @param {number} scaleExtra Extra zoom-in to apply.\n * @param {Function} [cb=this.options.scaleExtra] A callback function that\n * will be called when a target is moved and transition has ended. It will\n * get the target element as the argument.\n * @return {this}\n */\n move (x, y, scaleExtra = this.options.scaleExtra, cb) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeMove event\n if (this.options.onBeforeMove) this.options.onBeforeMove(target)\n\n this.released = false\n\n this.target.move(x, y, scaleExtra)\n this.body.style.cursor = cursor.move\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n }\n\n /**\n * Release the Element currently grabbed.\n * @param {Function} [cb=this.options.onRelease] A callback function that\n * will be called when a target is released and transition has ended. It\n * will get the target element as the argument.\n * @return {this}\n */\n release (cb = this.options.onRelease) {\n if (!this.shown || this.lock) return\n\n const target = this.target.el\n\n // onBeforeRelease event\n if (this.options.onBeforeRelease) this.options.onBeforeRelease(target)\n\n this.lock = true\n\n this.target.restoreOpenStyle()\n this.body.style.cursor = cursor.default\n\n const onEnd = () => {\n target.removeEventListener(transEndEvent, onEnd)\n\n this.lock = false\n this.released = true\n\n if (cb) cb(target)\n }\n\n target.addEventListener(transEndEvent, onEnd)\n\n return this\n }\n\n /**\n * Update options.\n * @param {Object} options An Object that contains this.options.\n * @return {this}\n */\n config (options) {\n if (!options) return this.options\n\n for (let key in options) {\n this.options[key] = options[key]\n }\n\n this.overlay.updateStyle()\n\n return this\n }\n}\n","import Zooming from './Zooming'\nimport OPTIONS from './_options'\n\ndocument.addEventListener('DOMContentLoaded', () => {\n new Zooming().listen(OPTIONS.defaultZoomable)\n})\n\nexport default Zooming\n"],"names":["calculateTranslate","rect","windowCenter","getWindowCenter","targetCenter","left","half","width","top","height","x","y","calculateScale","scaleBase","customSize","targetHalfWidth","targetHalfHeight","targetEdgeToWindowEdge","scaleHorizontally","scaleVertically","scale","Math","min","processTouches","touches","currScaleExtra","cb","total","length","firstTouch","multitouch","scaleExtra","i","xs","ys","clientX","clientY","max","t","distX","distY","window","innerWidth","MULTITOUCH_SCALE_FACTOR","innerHeight","body","document","docElm","documentElement","webkitPrefix","style","cursor","EVENT_TYPES_GRAB","divide","denominator","numerator","loadImage","url","img","Image","onload","src","scrollTop","pageYOffset","parentNode","docWidth","clientWidth","docHeight","clientHeight","toggleListeners","el","types","handler","add","forEach","addEventListener","removeEventListener","toggleGrabListeners","sniffTransition","ret","trans","tform","end","some","undefined","prop","transitionProp","transEndEvent","transformProp","transformCssProp","replace","createElement","setStyle","styles","remember","value","transition","transform","s","original","key","bind","_this","that","methods","Object","getOwnPropertyNames","getPrototypeOf","m","Target","instance","translate","srcThumbnail","options","this","preloadImage","hasAttribute","getAttribute","getBoundingClientRect","offsetWidth","open","enableGrab","grab","zoomOut","transitionDuration","transitionTimingFunction","close","dx","dy","move","dataOriginal","temp","cloneNode","setAttribute","position","visibility","appendChild","removeChild","Overlay","parent","bgColor","_this2","opacity","bgOpacity","PRESS_DELAY","EventHandler","e","preventDefault","shown","released","release","currentTarget","st","lastScrollPosition","deltaY","abs","scrollThreshold","code","keyCode","button","pressTimer","setTimeout","_this3","targetTouches","Zooming","overlay","target","lock","assign","OPTIONS","config","eventHandler","init","els","querySelectorAll","listen","tagName","zoomIn","click","onOpen","querySelector","onBeforeOpen","setParent","insert","show","scroll","keydown","onEnd","upgradeSource","onClose","onBeforeClose","default","hide","downgradeSource","restoreCloseStyle","remove","onBeforeGrab","onBeforeMove","onRelease","onBeforeRelease","restoreOpenStyle","updateStyle","defaultZoomable"],"mappings":"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"} \ No newline at end of file diff --git a/package.json b/package.json index f1d0dc43..aef2e499 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zooming", - "version": "1.0.5", + "version": "1.0.6", "description": "Image zoom that makes sense.", "main": "src/main.js", "repository": { diff --git a/src/EventHandler.js b/src/EventHandler.js index 407c9052..dc28a8d7 100644 --- a/src/EventHandler.js +++ b/src/EventHandler.js @@ -1,5 +1,17 @@ import { scrollTop, bind } from './_helpers' -import { PRESS_DELAY, MULTITOUCH_SCALE_FACTOR } from './_defaults' + +/** + * Press duration (ms) longer than or equal to this value will be recognized + * as grab, otherwise click. + * @type {number} + */ +const PRESS_DELAY = 200 + +/** + * Scale factor for multi-touch. + * @type {number} + */ +const MULTITOUCH_SCALE_FACTOR = 2 export default class EventHandler { diff --git a/src/Overlay.js b/src/Overlay.js index 6bf834a8..4782e92c 100644 --- a/src/Overlay.js +++ b/src/Overlay.js @@ -25,7 +25,7 @@ export default class Overlay { ${options.transitionTimingFunction}` }) - this.el.addEventListener('click', this.instance.close()) + this.el.addEventListener('click', () => this.instance.close()) } updateStyle () { diff --git a/src/Zooming.js b/src/Zooming.js index a04d5917..5ecea504 100644 --- a/src/Zooming.js +++ b/src/Zooming.js @@ -1,8 +1,8 @@ import Target from './Target' import Overlay from './Overlay' import EventHandler from './EventHandler' -import { OPTIONS, EVENT_TYPES_GRAB } from './_defaults' -import { loadImage, toggleListeners, transEndEvent, cursor } from './_helpers' +import OPTIONS from './_options' +import { loadImage, toggleGrabListeners, transEndEvent, cursor } from './_helpers' /** * Zooming instance. @@ -97,7 +97,7 @@ export default class Zooming { this.lock = false if (this.options.enableGrab) { - toggleListeners(document, EVENT_TYPES_GRAB, this.eventHandler, true) + toggleGrabListeners(document, this.eventHandler, true) } if (target.hasAttribute('data-original')) { @@ -143,7 +143,7 @@ export default class Zooming { this.lock = false if (this.options.enableGrab) { - toggleListeners(document, EVENT_TYPES_GRAB, this.eventHandler, false) + toggleGrabListeners(document, this.eventHandler, false) } if (target.hasAttribute('data-original')) { diff --git a/src/_helpers.js b/src/_helpers.js index 061ffbe0..5f8793b1 100644 --- a/src/_helpers.js +++ b/src/_helpers.js @@ -4,6 +4,19 @@ const webkitPrefix = 'WebkitAppearance' in document.documentElement.style ? '-webkit-' : '' + const cursor = { + default: 'auto', + zoomIn: `${webkitPrefix}zoom-in`, + zoomOut: `${webkitPrefix}zoom-out`, + grab: `${webkitPrefix}grab`, + move: 'move' + } + +const EVENT_TYPES_GRAB = [ + 'mousedown', 'mousemove', 'mouseup', + 'touchstart', 'touchmove', 'touchend' +] + const divide = (denominator) => { return (numerator) => { return numerator / denominator @@ -45,6 +58,10 @@ const toggleListeners = (el, types, handler, add = true) => { }) } +const toggleGrabListeners = (el, handler, add) => { + return toggleListeners(el, EVENT_TYPES_GRAB, handler, add) +} + const sniffTransition = (el) => { let ret = {} const trans = ['webkitTransition', 'transition', 'mozTransition'] @@ -104,14 +121,6 @@ const setStyle = (el, styles, remember) => { return original } -const cursor = { - default: 'auto', - zoomIn: `${webkitPrefix}zoom-in`, - zoomOut: `${webkitPrefix}zoom-out`, - grab: `${webkitPrefix}grab`, - move: 'move' -} - const bind = (_this, that) => { const methods = ( Object.getOwnPropertyNames( @@ -130,7 +139,7 @@ export { loadImage, scrollTop, getWindowCenter, - toggleListeners, + toggleGrabListeners, transformCssProp, transEndEvent, setStyle, diff --git a/src/_defaults.js b/src/_options.js similarity index 85% rename from src/_defaults.js rename to src/_options.js index 47f1cfa1..eea8a1fe 100644 --- a/src/_defaults.js +++ b/src/_options.js @@ -26,7 +26,7 @@ * onBeforeRelease: null * } */ -const OPTIONS = { +export default { /** * Zoomable elements by default. It can be a css selector or an element. * @type {string|Element} @@ -144,32 +144,3 @@ const OPTIONS = { */ onBeforeRelease: null } - -/** - * Duration (ms) longer than or equal to this value will be recognized as grab, - * otherwise click. - * @type {number} - */ -const PRESS_DELAY = 200 - -/** - * Event types related to grab. - * @type {Array} - */ -const EVENT_TYPES_GRAB = [ - 'mousedown', 'mousemove', 'mouseup', - 'touchstart', 'touchmove', 'touchend' -] - -/** - * Scale factor for multi-touch. - * @type {number} - */ -const MULTITOUCH_SCALE_FACTOR = 2 - -export { - OPTIONS, - PRESS_DELAY, - EVENT_TYPES_GRAB, - MULTITOUCH_SCALE_FACTOR -} diff --git a/src/main.js b/src/main.js index b5736351..4cb49f31 100644 --- a/src/main.js +++ b/src/main.js @@ -1,5 +1,5 @@ import Zooming from './Zooming' -import { OPTIONS } from './_defaults' +import OPTIONS from './_options' document.addEventListener('DOMContentLoaded', () => { new Zooming().listen(OPTIONS.defaultZoomable)