/** * interact.js v1.3.3 * * Copyright (c) 2012-2018 Taye Adeyemi * Released under the MIT License. * https://raw.github.com/taye/interact.js/master/LICENSE */ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.interact = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 6 && arguments[6] !== undefined ? arguments[6] : false; _classCallCheck(this, InteractEvent); var target = interaction.target; var deltaSource = (target && target.options || defaults).deltaSource; var origin = getOriginXY(target, element, action); var starting = phase === 'start'; var ending = phase === 'end'; var coords = starting ? interaction.startCoords : interaction.curCoords; var prevEvent = interaction.prevEvent; element = element || interaction.element; var page = extend({}, coords.page); var client = extend({}, coords.client); page.x -= origin.x; page.y -= origin.y; client.x -= origin.x; client.y -= origin.y; this.ctrlKey = event.ctrlKey; this.altKey = event.altKey; this.shiftKey = event.shiftKey; this.metaKey = event.metaKey; this.button = event.button; this.buttons = event.buttons; this.target = element; this.currentTarget = element; this.relatedTarget = related || null; this.preEnd = preEnd; this.type = action + (phase || ''); this.interaction = interaction; this.interactable = target; this.t0 = starting ? interaction.downTimes[interaction.downTimes.length - 1] : prevEvent.t0; var signalArg = { interaction: interaction, event: event, action: action, phase: phase, element: element, related: related, page: page, client: client, coords: coords, starting: starting, ending: ending, deltaSource: deltaSource, iEvent: this }; signals.fire('set-xy', signalArg); if (ending) { // use previous coords when ending this.pageX = prevEvent.pageX; this.pageY = prevEvent.pageY; this.clientX = prevEvent.clientX; this.clientY = prevEvent.clientY; } else { this.pageX = page.x; this.pageY = page.y; this.clientX = client.x; this.clientY = client.y; } this.x0 = interaction.startCoords.page.x - origin.x; this.y0 = interaction.startCoords.page.y - origin.y; this.clientX0 = interaction.startCoords.client.x - origin.x; this.clientY0 = interaction.startCoords.client.y - origin.y; signals.fire('set-delta', signalArg); this.timeStamp = coords.timeStamp; this.dt = interaction.pointerDelta.timeStamp; this.duration = this.timeStamp - this.t0; // speed and velocity in pixels per second this.speed = interaction.pointerDelta[deltaSource].speed; this.velocityX = interaction.pointerDelta[deltaSource].vx; this.velocityY = interaction.pointerDelta[deltaSource].vy; this.swipe = ending || phase === 'inertiastart' ? this.getSwipe() : null; signals.fire('new', signalArg); } InteractEvent.prototype.getSwipe = function getSwipe() { var interaction = this.interaction; if (interaction.prevEvent.speed < 600 || this.timeStamp - interaction.prevEvent.timeStamp > 150) { return null; } var angle = 180 * Math.atan2(interaction.prevEvent.velocityY, interaction.prevEvent.velocityX) / Math.PI; var overlap = 22.5; if (angle < 0) { angle += 360; } var left = 135 - overlap <= angle && angle < 225 + overlap; var up = 225 - overlap <= angle && angle < 315 + overlap; var right = !left && (315 - overlap <= angle || angle < 45 + overlap); var down = !up && 45 - overlap <= angle && angle < 135 + overlap; return { up: up, down: down, left: left, right: right, angle: angle, speed: interaction.prevEvent.speed, velocity: { x: interaction.prevEvent.velocityX, y: interaction.prevEvent.velocityY } }; }; InteractEvent.prototype.preventDefault = function preventDefault() {}; /** */ InteractEvent.prototype.stopImmediatePropagation = function stopImmediatePropagation() { this.immediatePropagationStopped = this.propagationStopped = true; }; /** */ InteractEvent.prototype.stopPropagation = function stopPropagation() { this.propagationStopped = true; }; return InteractEvent; }(); signals.on('set-delta', function (_ref) { var iEvent = _ref.iEvent, interaction = _ref.interaction, starting = _ref.starting, deltaSource = _ref.deltaSource; var prevEvent = starting ? iEvent : interaction.prevEvent; if (deltaSource === 'client') { iEvent.dx = iEvent.clientX - prevEvent.clientX; iEvent.dy = iEvent.clientY - prevEvent.clientY; } else { iEvent.dx = iEvent.pageX - prevEvent.pageX; iEvent.dy = iEvent.pageY - prevEvent.pageY; } }); InteractEvent.signals = signals; module.exports = InteractEvent; },{"./defaultOptions":18,"./utils/Signals":34,"./utils/extend":41,"./utils/getOriginXY":42}],4:[function(require,module,exports){ 'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var clone = require('./utils/clone'); var is = require('./utils/is'); var events = require('./utils/events'); var extend = require('./utils/extend'); var actions = require('./actions/base'); var scope = require('./scope'); var Eventable = require('./Eventable'); var defaults = require('./defaultOptions'); var signals = require('./utils/Signals').new(); var _require = require('./utils/domUtils'), getElementRect = _require.getElementRect, nodeContains = _require.nodeContains, trySelector = _require.trySelector, matchesSelector = _require.matchesSelector; var _require2 = require('./utils/window'), getWindow = _require2.getWindow; var _require3 = require('./utils/arr'), contains = _require3.contains; var _require4 = require('./utils/browser'), wheelEvent = _require4.wheelEvent; // all set interactables scope.interactables = []; var Interactable = function () { /** */ function Interactable(target, options) { _classCallCheck(this, Interactable); options = options || {}; this.target = target; this.events = new Eventable(); this._context = options.context || scope.document; this._win = getWindow(trySelector(target) ? this._context : target); this._doc = this._win.document; signals.fire('new', { target: target, options: options, interactable: this, win: this._win }); scope.addDocument(this._doc, this._win); scope.interactables.push(this); this.set(options); } Interactable.prototype.setOnEvents = function setOnEvents(action, phases) { var onAction = 'on' + action; if (is.function(phases.onstart)) { this.events[onAction + 'start'] = phases.onstart; } if (is.function(phases.onmove)) { this.events[onAction + 'move'] = phases.onmove; } if (is.function(phases.onend)) { this.events[onAction + 'end'] = phases.onend; } if (is.function(phases.oninertiastart)) { this.events[onAction + 'inertiastart'] = phases.oninertiastart; } return this; }; Interactable.prototype.setPerAction = function setPerAction(action, options) { // for all the default per-action options for (var option in options) { // if this option exists for this action if (option in defaults[action]) { // if the option in the options arg is an object value if (is.object(options[option])) { // duplicate the object and merge this.options[action][option] = clone(this.options[action][option] || {}); extend(this.options[action][option], options[option]); if (is.object(defaults.perAction[option]) && 'enabled' in defaults.perAction[option]) { this.options[action][option].enabled = options[option].enabled === false ? false : true; } } else if (is.bool(options[option]) && is.object(defaults.perAction[option])) { this.options[action][option].enabled = options[option]; } else if (options[option] !== undefined) { // or if it's not undefined, do a plain assignment this.options[action][option] = options[option]; } } } }; /** * The default function to get an Interactables bounding rect. Can be * overridden using {@link Interactable.rectChecker}. * * @param {Element} [element] The element to measure. * @return {object} The object's bounding rectangle. */ Interactable.prototype.getRect = function getRect(element) { element = element || this.target; if (is.string(this.target) && !is.element(element)) { element = this._context.querySelector(this.target); } return getElementRect(element); }; /** * Returns or sets the function used to calculate the interactable's * element's rectangle * * @param {function} [checker] A function which returns this Interactable's * bounding rectangle. See {@link Interactable.getRect} * @return {function | object} The checker function or this Interactable */ Interactable.prototype.rectChecker = function rectChecker(checker) { if (is.function(checker)) { this.getRect = checker; return this; } if (checker === null) { delete this.options.getRect; return this; } return this.getRect; }; Interactable.prototype._backCompatOption = function _backCompatOption(optionName, newValue) { if (trySelector(newValue) || is.object(newValue)) { this.options[optionName] = newValue; for (var _i = 0; _i < actions.names.length; _i++) { var _ref; _ref = actions.names[_i]; var action = _ref; this.options[action][optionName] = newValue; } return this; } return this.options[optionName]; }; /** * Gets or sets the origin of the Interactable's element. The x and y * of the origin will be subtracted from action event coordinates. * * @param {Element | object | string} [origin] An HTML or SVG Element whose * rect will be used, an object eg. { x: 0, y: 0 } or string 'parent', 'self' * or any CSS selector * * @return {object} The current origin or this Interactable */ Interactable.prototype.origin = function origin(newValue) { return this._backCompatOption('origin', newValue); }; /** * Returns or sets the mouse coordinate types used to calculate the * movement of the pointer. * * @param {string} [newValue] Use 'client' if you will be scrolling while * interacting; Use 'page' if you want autoScroll to work * @return {string | object} The current deltaSource or this Interactable */ Interactable.prototype.deltaSource = function deltaSource(newValue) { if (newValue === 'page' || newValue === 'client') { this.options.deltaSource = newValue; return this; } return this.options.deltaSource; }; /** * Gets the selector context Node of the Interactable. The default is * `window.document`. * * @return {Node} The context Node of this Interactable */ Interactable.prototype.context = function context() { return this._context; }; Interactable.prototype.inContext = function inContext(element) { return this._context === element.ownerDocument || nodeContains(this._context, element); }; /** * Calls listeners for the given InteractEvent type bound globally * and directly to this Interactable * * @param {InteractEvent} iEvent The InteractEvent object to be fired on this * Interactable * @return {Interactable} this Interactable */ Interactable.prototype.fire = function fire(iEvent) { this.events.fire(iEvent); return this; }; Interactable.prototype._onOffMultiple = function _onOffMultiple(method, eventType, listener, options) { if (is.string(eventType) && eventType.search(' ') !== -1) { eventType = eventType.trim().split(/ +/); } if (is.array(eventType)) { for (var _i2 = 0; _i2 < eventType.length; _i2++) { var _ref2; _ref2 = eventType[_i2]; var type = _ref2; this[method](type, listener, options); } return true; } if (is.object(eventType)) { for (var prop in eventType) { this[method](prop, eventType[prop], listener); } return true; } }; /** * Binds a listener for an InteractEvent, pointerEvent or DOM event. * * @param {string | array | object} eventType The types of events to listen * for * @param {function} listener The function event (s) * @param {object | boolean} [options] options object or useCapture flag * for addEventListener * @return {object} This Interactable */ Interactable.prototype.on = function on(eventType, listener, options) { if (this._onOffMultiple('on', eventType, listener, options)) { return this; } if (eventType === 'wheel') { eventType = wheelEvent; } if (contains(Interactable.eventTypes, eventType)) { this.events.on(eventType, listener); } // delegated event for selector else if (is.string(this.target)) { events.addDelegate(this.target, this._context, eventType, listener, options); } else { events.add(this.target, eventType, listener, options); } return this; }; /** * Removes an InteractEvent, pointerEvent or DOM event listener * * @param {string | array | object} eventType The types of events that were * listened for * @param {function} listener The listener function to be removed * @param {object | boolean} [options] options object or useCapture flag for * removeEventListener * @return {object} This Interactable */ Interactable.prototype.off = function off(eventType, listener, options) { if (this._onOffMultiple('off', eventType, listener, options)) { return this; } if (eventType === 'wheel') { eventType = wheelEvent; } // if it is an action event type if (contains(Interactable.eventTypes, eventType)) { this.events.off(eventType, listener); } // delegated event else if (is.string(this.target)) { events.removeDelegate(this.target, this._context, eventType, listener, options); } // remove listener from this Interatable's element else { events.remove(this.target, eventType, listener, options); } return this; }; /** * Reset the options of this Interactable * * @param {object} options The new settings to apply * @return {object} This Interactable */ Interactable.prototype.set = function set(options) { if (!is.object(options)) { options = {}; } this.options = clone(defaults.base); var perActions = clone(defaults.perAction); for (var actionName in actions.methodDict) { var methodName = actions.methodDict[actionName]; this.options[actionName] = clone(defaults[actionName]); this.setPerAction(actionName, perActions); this[methodName](options[actionName]); } for (var _i3 = 0; _i3 < Interactable.settingsMethods.length; _i3++) { var _ref3; _ref3 = Interactable.settingsMethods[_i3]; var setting = _ref3; this.options[setting] = defaults.base[setting]; if (setting in options) { this[setting](options[setting]); } } signals.fire('set', { options: options, interactable: this }); return this; }; /** * Remove this interactable from the list of interactables and remove it's * action capabilities and event listeners * * @return {interact} */ Interactable.prototype.unset = function unset() { events.remove(this.target, 'all'); if (is.string(this.target)) { // remove delegated events for (var type in events.delegatedEvents) { var delegated = events.delegatedEvents[type]; if (delegated.selectors[0] === this.target && delegated.contexts[0] === this._context) { delegated.selectors.splice(0, 1); delegated.contexts.splice(0, 1); delegated.listeners.splice(0, 1); // remove the arrays if they are empty if (!delegated.selectors.length) { delegated[type] = null; } } events.remove(this._context, type, events.delegateListener); events.remove(this._context, type, events.delegateUseCapture, true); } } else { events.remove(this, 'all'); } signals.fire('unset', { interactable: this }); scope.interactables.splice(scope.interactables.indexOf(this), 1); // Stop related interactions when an Interactable is unset for (var _i4 = 0; _i4 < (scope.interactions || []).length; _i4++) { var _ref4; _ref4 = (scope.interactions || [])[_i4]; var interaction = _ref4; if (interaction.target === this && interaction.interacting() && !interaction._ending) { interaction.stop(); } } return scope.interact; }; return Interactable; }(); scope.interactables.indexOfElement = function indexOfElement(target, context) { context = context || scope.document; for (var i = 0; i < this.length; i++) { var interactable = this[i]; if (interactable.target === target && interactable._context === context) { return i; } } return -1; }; scope.interactables.get = function interactableGet(element, options, dontCheckInContext) { var ret = this[this.indexOfElement(element, options && options.context)]; return ret && (is.string(element) || dontCheckInContext || ret.inContext(element)) ? ret : null; }; scope.interactables.forEachMatch = function (element, callback) { for (var _i5 = 0; _i5 < this.length; _i5++) { var _ref5; _ref5 = this[_i5]; var interactable = _ref5; var ret = void 0; if ((is.string(interactable.target) // target is a selector and the element matches ? is.element(element) && matchesSelector(element, interactable.target) : // target is the element element === interactable.target) && // the element is in context interactable.inContext(element)) { ret = callback(interactable); } if (ret !== undefined) { return ret; } } }; // all interact.js eventTypes Interactable.eventTypes = scope.eventTypes = []; Interactable.signals = signals; Interactable.settingsMethods = ['deltaSource', 'origin', 'preventDefault', 'rectChecker']; module.exports = Interactable; },{"./Eventable":2,"./actions/base":6,"./defaultOptions":18,"./scope":33,"./utils/Signals":34,"./utils/arr":35,"./utils/browser":36,"./utils/clone":37,"./utils/domUtils":39,"./utils/events":40,"./utils/extend":41,"./utils/is":46,"./utils/window":52}],5:[function(require,module,exports){ 'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var scope = require('./scope'); var utils = require('./utils'); var events = require('./utils/events'); var browser = require('./utils/browser'); var domObjects = require('./utils/domObjects'); var finder = require('./utils/interactionFinder'); var signals = require('./utils/Signals').new(); var listeners = {}; var methodNames = ['pointerDown', 'pointerMove', 'pointerUp', 'updatePointer', 'removePointer']; // for ignoring browser's simulated mouse events var prevTouchTime = 0; // all active and idle interactions scope.interactions = []; var Interaction = function () { /** */ function Interaction(_ref) { var pointerType = _ref.pointerType; _classCallCheck(this, Interaction); this.target = null; // current interactable being interacted with this.element = null; // the target element of the interactable this.prepared = { // action that's ready to be fired on next move event name: null, axis: null, edges: null }; // keep track of added pointers this.pointers = []; this.pointerIds = []; this.downTargets = []; this.downTimes = []; // Previous native pointer move event coordinates this.prevCoords = { page: { x: 0, y: 0 }, client: { x: 0, y: 0 }, timeStamp: 0 }; // current native pointer move event coordinates this.curCoords = { page: { x: 0, y: 0 }, client: { x: 0, y: 0 }, timeStamp: 0 }; // Starting InteractEvent pointer coordinates this.startCoords = { page: { x: 0, y: 0 }, client: { x: 0, y: 0 }, timeStamp: 0 }; // Change in coordinates and time of the pointer this.pointerDelta = { page: { x: 0, y: 0, vx: 0, vy: 0, speed: 0 }, client: { x: 0, y: 0, vx: 0, vy: 0, speed: 0 }, timeStamp: 0 }; this.downEvent = null; // pointerdown/mousedown/touchstart event this.downPointer = {}; this._eventTarget = null; this._curEventTarget = null; this.prevEvent = null; // previous action event this.pointerIsDown = false; this.pointerWasMoved = false; this._interacting = false; this._ending = false; this.pointerType = pointerType; signals.fire('new', this); scope.interactions.push(this); } Interaction.prototype.pointerDown = function pointerDown(pointer, event, eventTarget) { var pointerIndex = this.updatePointer(pointer, event, true); signals.fire('down', { pointer: pointer, event: event, eventTarget: eventTarget, pointerIndex: pointerIndex, interaction: this }); }; /** * ```js * interact(target) * .draggable({ * // disable the default drag start by down->move * manualStart: true * }) * // start dragging after the user holds the pointer down * .on('hold', function (event) { * var interaction = event.interaction; * * if (!interaction.interacting()) { * interaction.start({ name: 'drag' }, * event.interactable, * event.currentTarget); * } * }); * ``` * * Start an action with the given Interactable and Element as tartgets. The * action must be enabled for the target Interactable and an appropriate * number of pointers must be held down - 1 for drag/resize, 2 for gesture. * * Use it with `interactable.able({ manualStart: false })` to always * [start actions manually](https://github.com/taye/interact.js/issues/114) * * @param {object} action The action to be performed - drag, resize, etc. * @param {Interactable} target The Interactable to target * @param {Element} element The DOM Element to target * @return {object} interact */ Interaction.prototype.start = function start(action, target, element) { if (this.interacting() || !this.pointerIsDown || this.pointerIds.length < (action.name === 'gesture' ? 2 : 1)) { return; } // if this interaction had been removed after stopping // add it back if (scope.interactions.indexOf(this) === -1) { scope.interactions.push(this); } utils.copyAction(this.prepared, action); this.target = target; this.element = element; signals.fire('action-start', { interaction: this, event: this.downEvent }); }; Interaction.prototype.pointerMove = function pointerMove(pointer, event, eventTarget) { if (!this.simulation) { this.updatePointer(pointer); utils.setCoords(this.curCoords, this.pointers); } var duplicateMove = this.curCoords.page.x === this.prevCoords.page.x && this.curCoords.page.y === this.prevCoords.page.y && this.curCoords.client.x === this.prevCoords.client.x && this.curCoords.client.y === this.prevCoords.client.y; var dx = void 0; var dy = void 0; // register movement greater than pointerMoveTolerance if (this.pointerIsDown && !this.pointerWasMoved) { dx = this.curCoords.client.x - this.startCoords.client.x; dy = this.curCoords.client.y - this.startCoords.client.y; this.pointerWasMoved = utils.hypot(dx, dy) > Interaction.pointerMoveTolerance; } var signalArg = { pointer: pointer, pointerIndex: this.getPointerIndex(pointer), event: event, eventTarget: eventTarget, dx: dx, dy: dy, duplicate: duplicateMove, interaction: this, interactingBeforeMove: this.interacting() }; if (!duplicateMove) { // set pointer coordinate, time changes and speeds utils.setCoordDeltas(this.pointerDelta, this.prevCoords, this.curCoords); } signals.fire('move', signalArg); if (!duplicateMove) { // if interacting, fire an 'action-move' signal etc if (this.interacting()) { this.doMove(signalArg); } if (this.pointerWasMoved) { utils.copyCoords(this.prevCoords, this.curCoords); } } }; /** * ```js * interact(target) * .draggable(true) * .on('dragmove', function (event) { * if (someCondition) { * // change the snap settings * event.interactable.draggable({ snap: { targets: [] }}); * // fire another move event with re-calculated snap * event.interaction.doMove(); * } * }); * ``` * * Force a move of the current action at the same coordinates. Useful if * snap/restrict has been changed and you want a movement with the new * settings. */ Interaction.prototype.doMove = function doMove(signalArg) { signalArg = utils.extend({ pointer: this.pointers[0], event: this.prevEvent, eventTarget: this._eventTarget, interaction: this }, signalArg || {}); signals.fire('before-action-move', signalArg); if (!this._dontFireMove) { signals.fire('action-move', signalArg); } this._dontFireMove = false; }; // End interact move events and stop auto-scroll unless simulation is running Interaction.prototype.pointerUp = function pointerUp(pointer, event, eventTarget, curEventTarget) { var pointerIndex = this.getPointerIndex(pointer); signals.fire(/cancel$/i.test(event.type) ? 'cancel' : 'up', { pointer: pointer, pointerIndex: pointerIndex, event: event, eventTarget: eventTarget, curEventTarget: curEventTarget, interaction: this }); if (!this.simulation) { this.end(event); } this.pointerIsDown = false; this.removePointer(pointer, event); }; /** * ```js * interact(target) * .draggable(true) * .on('move', function (event) { * if (event.pageX > 1000) { * // end the current action * event.interaction.end(); * // stop all further listeners from being called * event.stopImmediatePropagation(); * } * }); * ``` * * Stop the current action and fire an end event. Inertial movement does * not happen. * * @param {PointerEvent} [event] */ Interaction.prototype.end = function end(event) { this._ending = true; event = event || this.prevEvent; if (this.interacting()) { signals.fire('action-end', { event: event, interaction: this }); } this.stop(); this._ending = false; }; Interaction.prototype.currentAction = function currentAction() { return this._interacting ? this.prepared.name : null; }; Interaction.prototype.interacting = function interacting() { return this._interacting; }; /** */ Interaction.prototype.stop = function stop() { signals.fire('stop', { interaction: this }); if (this._interacting) { signals.fire('stop-active', { interaction: this }); signals.fire('stop-' + this.prepared.name, { interaction: this }); } this.target = this.element = null; this._interacting = false; this.prepared.name = this.prevEvent = null; }; Interaction.prototype.getPointerIndex = function getPointerIndex(pointer) { // mouse and pen interactions may have only one pointer if (this.pointerType === 'mouse' || this.pointerType === 'pen') { return 0; } return this.pointerIds.indexOf(utils.getPointerId(pointer)); }; Interaction.prototype.updatePointer = function updatePointer(pointer, event) { var down = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : event && /(down|start)$/i.test(event.type); var id = utils.getPointerId(pointer); var index = this.getPointerIndex(pointer); if (index === -1) { index = this.pointerIds.length; this.pointerIds[index] = id; } if (down) { signals.fire('update-pointer-down', { pointer: pointer, event: event, down: down, pointerId: id, pointerIndex: index, interaction: this }); } this.pointers[index] = pointer; return index; }; Interaction.prototype.removePointer = function removePointer(pointer, event) { var index = this.getPointerIndex(pointer); if (index === -1) { return; } signals.fire('remove-pointer', { pointer: pointer, event: event, pointerIndex: index, interaction: this }); this.pointers.splice(index, 1); this.pointerIds.splice(index, 1); this.downTargets.splice(index, 1); this.downTimes.splice(index, 1); }; Interaction.prototype._updateEventTargets = function _updateEventTargets(target, currentTarget) { this._eventTarget = target; this._curEventTarget = currentTarget; }; return Interaction; }(); for (var _i = 0; _i < methodNames.length; _i++) { var method = methodNames[_i]; listeners[method] = doOnInteractions(method); } function doOnInteractions(method) { return function (event) { var pointerType = utils.getPointerType(event); var _utils$getEventTarget = utils.getEventTargets(event), eventTarget = _utils$getEventTarget[0], curEventTarget = _utils$getEventTarget[1]; var matches = []; // [ [pointer, interaction], ...] if (browser.supportsTouch && /touch/.test(event.type)) { prevTouchTime = new Date().getTime(); for (var _i2 = 0; _i2 < event.changedTouches.length; _i2++) { var _ref2; _ref2 = event.changedTouches[_i2]; var changedTouch = _ref2; var pointer = changedTouch; var interaction = finder.search(pointer, event.type, eventTarget); matches.push([pointer, interaction || new Interaction({ pointerType: pointerType })]); } } else { var invalidPointer = false; if (!browser.supportsPointerEvent && /mouse/.test(event.type)) { // ignore mouse events while touch interactions are active for (var i = 0; i < scope.interactions.length && !invalidPointer; i++) { invalidPointer = scope.interactions[i].pointerType !== 'mouse' && scope.interactions[i].pointerIsDown; } // try to ignore mouse events that are simulated by the browser // after a touch event invalidPointer = invalidPointer || new Date().getTime() - prevTouchTime < 500 // on iOS and Firefox Mobile, MouseEvent.timeStamp is zero if simulated || event.timeStamp === 0; } if (!invalidPointer) { var _interaction = finder.search(event, event.type, eventTarget); if (!_interaction) { _interaction = new Interaction({ pointerType: pointerType }); } matches.push([event, _interaction]); } } for (var _i3 = 0; _i3 < matches.length; _i3++) { var _ref3 = matches[_i3]; var _pointer = _ref3[0]; var _interaction2 = _ref3[1]; _interaction2._updateEventTargets(eventTarget, curEventTarget); _interaction2[method](_pointer, event, eventTarget, curEventTarget); } }; } function endAll(event) { for (var _i4 = 0; _i4 < scope.interactions.length; _i4++) { var _ref4; _ref4 = scope.interactions[_i4]; var interaction = _ref4; interaction.end(event); signals.fire('endall', { event: event, interaction: interaction }); } } var docEvents = {/* 'eventType': listenerFunc */}; var pEventTypes = browser.pEventTypes; if (domObjects.PointerEvent) { docEvents[pEventTypes.down] = listeners.pointerDown; docEvents[pEventTypes.move] = listeners.pointerMove; docEvents[pEventTypes.up] = listeners.pointerUp; docEvents[pEventTypes.cancel] = listeners.pointerUp; } else { docEvents.mousedown = listeners.pointerDown; docEvents.mousemove = listeners.pointerMove; docEvents.mouseup = listeners.pointerUp; docEvents.touchstart = listeners.pointerDown; docEvents.touchmove = listeners.pointerMove; docEvents.touchend = listeners.pointerUp; docEvents.touchcancel = listeners.pointerUp; } docEvents.blur = endAll; function onDocSignal(_ref5, signalName) { var doc = _ref5.doc; var eventMethod = signalName.indexOf('add') === 0 ? events.add : events.remove; // delegate event listener for (var eventType in scope.delegatedEvents) { eventMethod(doc, eventType, events.delegateListener); eventMethod(doc, eventType, events.delegateUseCapture, true); } for (var _eventType in docEvents) { eventMethod(doc, _eventType, docEvents[_eventType]); } } signals.on('update-pointer-down', function (_ref6) { var interaction = _ref6.interaction, pointer = _ref6.pointer, pointerId = _ref6.pointerId, pointerIndex = _ref6.pointerIndex, event = _ref6.event, eventTarget = _ref6.eventTarget, down = _ref6.down; interaction.pointerIds[pointerIndex] = pointerId; interaction.pointers[pointerIndex] = pointer; if (down) { interaction.pointerIsDown = true; } if (!interaction.interacting()) { utils.setCoords(interaction.startCoords, interaction.pointers); utils.copyCoords(interaction.curCoords, interaction.startCoords); utils.copyCoords(interaction.prevCoords, interaction.startCoords); interaction.downEvent = event; interaction.downTimes[pointerIndex] = interaction.curCoords.timeStamp; interaction.downTargets[pointerIndex] = eventTarget || event && utils.getEventTargets(event)[0]; interaction.pointerWasMoved = false; utils.pointerExtend(interaction.downPointer, pointer); } }); scope.signals.on('add-document', onDocSignal); scope.signals.on('remove-document', onDocSignal); Interaction.pointerMoveTolerance = 1; Interaction.doOnInteractions = doOnInteractions; Interaction.endAll = endAll; Interaction.signals = signals; Interaction.docEvents = docEvents; scope.endAllInteractions = endAll; module.exports = Interaction; },{"./scope":33,"./utils":44,"./utils/Signals":34,"./utils/browser":36,"./utils/domObjects":38,"./utils/events":40,"./utils/interactionFinder":45}],6:[function(require,module,exports){ 'use strict'; var Interaction = require('../Interaction'); var InteractEvent = require('../InteractEvent'); var actions = { firePrepared: firePrepared, names: [], methodDict: {} }; Interaction.signals.on('action-start', function (_ref) { var interaction = _ref.interaction, event = _ref.event; interaction._interacting = true; firePrepared(interaction, event, 'start'); }); Interaction.signals.on('action-move', function (_ref2) { var interaction = _ref2.interaction, event = _ref2.event, preEnd = _ref2.preEnd; firePrepared(interaction, event, 'move', preEnd); // if the action was ended in a listener if (!interaction.interacting()) { return false; } }); Interaction.signals.on('action-end', function (_ref3) { var interaction = _ref3.interaction, event = _ref3.event; firePrepared(interaction, event, 'end'); }); function firePrepared(interaction, event, phase, preEnd) { var actionName = interaction.prepared.name; var newEvent = new InteractEvent(interaction, event, actionName, phase, interaction.element, null, preEnd); interaction.target.fire(newEvent); interaction.prevEvent = newEvent; } module.exports = actions; },{"../InteractEvent":3,"../Interaction":5}],7:[function(require,module,exports){ 'use strict'; var actions = require('./base'); var utils = require('../utils'); var InteractEvent = require('../InteractEvent'); /** @lends Interactable */ var Interactable = require('../Interactable'); var Interaction = require('../Interaction'); var defaultOptions = require('../defaultOptions'); var drag = { defaults: { enabled: false, mouseButtons: null, origin: null, snap: null, restrict: null, inertia: null, autoScroll: null, startAxis: 'xy', lockAxis: 'xy' }, checker: function checker(pointer, event, interactable) { var dragOptions = interactable.options.drag; return dragOptions.enabled ? { name: 'drag', axis: dragOptions.lockAxis === 'start' ? dragOptions.startAxis : dragOptions.lockAxis } : null; }, getCursor: function getCursor() { return 'move'; } }; Interaction.signals.on('before-action-move', function (_ref) { var interaction = _ref.interaction; if (interaction.prepared.name !== 'drag') { return; } var axis = interaction.prepared.axis; if (axis === 'x') { interaction.curCoords.page.y = interaction.startCoords.page.y; interaction.curCoords.client.y = interaction.startCoords.client.y; interaction.pointerDelta.page.speed = Math.abs(interaction.pointerDelta.page.vx); interaction.pointerDelta.client.speed = Math.abs(interaction.pointerDelta.client.vx); interaction.pointerDelta.client.vy = 0; interaction.pointerDelta.page.vy = 0; } else if (axis === 'y') { interaction.curCoords.page.x = interaction.startCoords.page.x; interaction.curCoords.client.x = interaction.startCoords.client.x; interaction.pointerDelta.page.speed = Math.abs(interaction.pointerDelta.page.vy); interaction.pointerDelta.client.speed = Math.abs(interaction.pointerDelta.client.vy); interaction.pointerDelta.client.vx = 0; interaction.pointerDelta.page.vx = 0; } }); // dragmove InteractEvent.signals.on('new', function (_ref2) { var iEvent = _ref2.iEvent, interaction = _ref2.interaction; if (iEvent.type !== 'dragmove') { return; } var axis = interaction.prepared.axis; if (axis === 'x') { iEvent.pageY = interaction.startCoords.page.y; iEvent.clientY = interaction.startCoords.client.y; iEvent.dy = 0; } else if (axis === 'y') { iEvent.pageX = interaction.startCoords.page.x; iEvent.clientX = interaction.startCoords.client.x; iEvent.dx = 0; } }); /** * ```js * interact(element).draggable({ * onstart: function (event) {}, * onmove : function (event) {}, * onend : function (event) {}, * * // the axis in which the first movement must be * // for the drag sequence to start * // 'xy' by default - any direction * startAxis: 'x' || 'y' || 'xy', * * // 'xy' by default - don't restrict to one axis (move in any direction) * // 'x' or 'y' to restrict movement to either axis * // 'start' to restrict movement to the axis the drag started in * lockAxis: 'x' || 'y' || 'xy' || 'start', * * // max number of drags that can happen concurrently * // with elements of this Interactable. Infinity by default * max: Infinity, * * // max number of drags that can target the same element+Interactable * // 1 by default * maxPerElement: 2 * }); * * var isDraggable = interact('element').draggable(); // true * ``` * * Get or set whether drag actions can be performed on the target * * @param {boolean | object} [options] true/false or An object with event * listeners to be fired on drag events (object makes the Interactable * draggable) * @return {boolean | Interactable} boolean indicating if this can be the * target of drag events, or this Interctable */ Interactable.prototype.draggable = function (options) { if (utils.is.object(options)) { this.options.drag.enabled = options.enabled === false ? false : true; this.setPerAction('drag', options); this.setOnEvents('drag', options); if (/^(xy|x|y|start)$/.test(options.lockAxis)) { this.options.drag.lockAxis = options.lockAxis; } if (/^(xy|x|y)$/.test(options.startAxis)) { this.options.drag.startAxis = options.startAxis; } return this; } if (utils.is.bool(options)) { this.options.drag.enabled = options; if (!options) { this.ondragstart = this.ondragstart = this.ondragend = null; } return this; } return this.options.drag; }; actions.drag = drag; actions.names.push('drag'); utils.merge(Interactable.eventTypes, ['dragstart', 'dragmove', 'draginertiastart', 'draginertiaresume', 'dragend']); actions.methodDict.drag = 'draggable'; defaultOptions.drag = drag.defaults; module.exports = drag; },{"../InteractEvent":3,"../Interactable":4,"../Interaction":5,"../defaultOptions":18,"../utils":44,"./base":6}],8:[function(require,module,exports){ 'use strict'; var actions = require('./base'); var utils = require('../utils'); var scope = require('../scope'); /** @lends module:interact */ var interact = require('../interact'); var InteractEvent = require('../InteractEvent'); /** @lends Interactable */ var Interactable = require('../Interactable'); var Interaction = require('../Interaction'); var defaultOptions = require('../defaultOptions'); var drop = { defaults: { enabled: false, accept: null, overlap: 'pointer' } }; var dynamicDrop = false; Interaction.signals.on('action-start', function (_ref) { var interaction = _ref.interaction, event = _ref.event; if (interaction.prepared.name !== 'drag') { return; } // reset active dropzones interaction.activeDrops.dropzones = []; interaction.activeDrops.elements = []; interaction.activeDrops.rects = []; interaction.dropEvents = null; if (!interaction.dynamicDrop) { setActiveDrops(interaction.activeDrops, interaction.element); } var dragEvent = interaction.prevEvent; var dropEvents = getDropEvents(interaction, event, dragEvent); if (dropEvents.activate) { fireActiveDrops(interaction.activeDrops, dropEvents.activate); } }); InteractEvent.signals.on('new', function (_ref2) { var interaction = _ref2.interaction, iEvent = _ref2.iEvent, event = _ref2.event; if (iEvent.type !== 'dragmove' && iEvent.type !== 'dragend') { return; } var draggableElement = interaction.element; var dragEvent = iEvent; var dropResult = getDrop(dragEvent, event, draggableElement); interaction.dropTarget = dropResult.dropzone; interaction.dropElement = dropResult.element; interaction.dropEvents = getDropEvents(interaction, event, dragEvent); }); Interaction.signals.on('action-move', function (_ref3) { var interaction = _ref3.interaction; if (interaction.prepared.name !== 'drag') { return; } fireDropEvents(interaction, interaction.dropEvents); }); Interaction.signals.on('action-end', function (_ref4) { var interaction = _ref4.interaction; if (interaction.prepared.name === 'drag') { fireDropEvents(interaction, interaction.dropEvents); } }); Interaction.signals.on('stop-drag', function (_ref5) { var interaction = _ref5.interaction; interaction.activeDrops = { dropzones: null, elements: null, rects: null }; interaction.dropEvents = null; }); function collectDrops(activeDrops, element) { var drops = []; var elements = []; // collect all dropzones and their elements which qualify for a drop for (var _i = 0; _i < scope.interactables.length; _i++) { var _ref6; _ref6 = scope.interactables[_i]; var current = _ref6; if (!current.options.drop.enabled) { continue; } var accept = current.options.drop.accept; // test the draggable element against the dropzone's accept setting if (utils.is.element(accept) && accept !== element || utils.is.string(accept) && !utils.matchesSelector(element, accept)) { continue; } // query for new elements if necessary var dropElements = utils.is.string(current.target) ? current._context.querySelectorAll(current.target) : [current.target]; for (var _i2 = 0; _i2 < dropElements.length; _i2++) { var _ref7; _ref7 = dropElements[_i2]; var currentElement = _ref7; if (currentElement !== element) { drops.push(current); elements.push(currentElement); } } } return { elements: elements, dropzones: drops }; } function fireActiveDrops(activeDrops, event) { var prevElement = void 0; // loop through all active dropzones and trigger event for (var i = 0; i < activeDrops.dropzones.length; i++) { var current = activeDrops.dropzones[i]; var currentElement = activeDrops.elements[i]; // prevent trigger of duplicate events on same element if (currentElement !== prevElement) { // set current element as event target event.target = currentElement; current.fire(event); } prevElement = currentElement; } } // Collect a new set of possible drops and save them in activeDrops. // setActiveDrops should always be called when a drag has just started or a // drag event happens while dynamicDrop is true function setActiveDrops(activeDrops, dragElement) { // get dropzones and their elements that could receive the draggable var possibleDrops = collectDrops(activeDrops, dragElement); activeDrops.dropzones = possibleDrops.dropzones; activeDrops.elements = possibleDrops.elements; activeDrops.rects = []; for (var i = 0; i < activeDrops.dropzones.length; i++) { activeDrops.rects[i] = activeDrops.dropzones[i].getRect(activeDrops.elements[i]); } } function getDrop(dragEvent, event, dragElement) { var interaction = dragEvent.interaction; var validDrops = []; if (dynamicDrop) { setActiveDrops(interaction.activeDrops, dragElement); } // collect all dropzones and their elements which qualify for a drop for (var j = 0; j < interaction.activeDrops.dropzones.length; j++) { var current = interaction.activeDrops.dropzones[j]; var currentElement = interaction.activeDrops.elements[j]; var rect = interaction.activeDrops.rects[j]; validDrops.push(current.dropCheck(dragEvent, event, interaction.target, dragElement, currentElement, rect) ? currentElement : null); } // get the most appropriate dropzone based on DOM depth and order var dropIndex = utils.indexOfDeepestElement(validDrops); return { dropzone: interaction.activeDrops.dropzones[dropIndex] || null, element: interaction.activeDrops.elements[dropIndex] || null }; } function getDropEvents(interaction, pointerEvent, dragEvent) { var dropEvents = { enter: null, leave: null, activate: null, deactivate: null, move: null, drop: null }; var tmpl = { dragEvent: dragEvent, interaction: interaction, target: interaction.dropElement, dropzone: interaction.dropTarget, relatedTarget: dragEvent.target, draggable: dragEvent.interactable, timeStamp: dragEvent.timeStamp }; if (interaction.dropElement !== interaction.prevDropElement) { // if there was a prevDropTarget, create a dragleave event if (interaction.prevDropTarget) { dropEvents.leave = utils.extend({ type: 'dragleave' }, tmpl); dragEvent.dragLeave = dropEvents.leave.target = interaction.prevDropElement; dragEvent.prevDropzone = dropEvents.leave.dropzone = interaction.prevDropTarget; } // if the dropTarget is not null, create a dragenter event if (interaction.dropTarget) { dropEvents.enter = { dragEvent: dragEvent, interaction: interaction, target: interaction.dropElement, dropzone: interaction.dropTarget, relatedTarget: dragEvent.target, draggable: dragEvent.interactable, timeStamp: dragEvent.timeStamp, type: 'dragenter' }; dragEvent.dragEnter = interaction.dropElement; dragEvent.dropzone = interaction.dropTarget; } } if (dragEvent.type === 'dragend' && interaction.dropTarget) { dropEvents.drop = utils.extend({ type: 'drop' }, tmpl); dragEvent.dropzone = interaction.dropTarget; dragEvent.relatedTarget = interaction.dropElement; } if (dragEvent.type === 'dragstart') { dropEvents.activate = utils.extend({ type: 'dropactivate' }, tmpl); dropEvents.activate.target = null; dropEvents.activate.dropzone = null; } if (dragEvent.type === 'dragend') { dropEvents.deactivate = utils.extend({ type: 'dropdeactivate' }, tmpl); dropEvents.deactivate.target = null; dropEvents.deactivate.dropzone = null; } if (dragEvent.type === 'dragmove' && interaction.dropTarget) { dropEvents.move = utils.extend({ dragmove: dragEvent, type: 'dropmove' }, tmpl); dragEvent.dropzone = interaction.dropTarget; } return dropEvents; } function fireDropEvents(interaction, dropEvents) { var activeDrops = interaction.activeDrops, prevDropTarget = interaction.prevDropTarget, dropTarget = interaction.dropTarget, dropElement = interaction.dropElement; if (dropEvents.leave) { prevDropTarget.fire(dropEvents.leave); } if (dropEvents.move) { dropTarget.fire(dropEvents.move); } if (dropEvents.enter) { dropTarget.fire(dropEvents.enter); } if (dropEvents.drop) { dropTarget.fire(dropEvents.drop); } if (dropEvents.deactivate) { fireActiveDrops(activeDrops, dropEvents.deactivate); } interaction.prevDropTarget = dropTarget; interaction.prevDropElement = dropElement; } /** * ```js * interact(target) * .dropChecker(function(dragEvent, // related dragmove or dragend event * event, // TouchEvent/PointerEvent/MouseEvent * dropped, // bool result of the default checker * dropzone, // dropzone Interactable * dropElement, // dropzone elemnt * draggable, // draggable Interactable * draggableElement) {// draggable element * * return dropped && event.target.hasAttribute('allow-drop'); * } * ``` * * ```js * interact('.drop').dropzone({ * accept: '.can-drop' || document.getElementById('single-drop'), * overlap: 'pointer' || 'center' || zeroToOne * } * ``` * * Returns or sets whether draggables can be dropped onto this target to * trigger drop events * * Dropzones can receive the following events: * - `dropactivate` and `dropdeactivate` when an acceptable drag starts and ends * - `dragenter` and `dragleave` when a draggable enters and leaves the dropzone * - `dragmove` when a draggable that has entered the dropzone is moved * - `drop` when a draggable is dropped into this dropzone * * Use the `accept` option to allow only elements that match the given CSS * selector or element. The value can be: * * - **an Element** - only that element can be dropped into this dropzone. * - **a string**, - the element being dragged must match it as a CSS selector. * - **`null`** - accept options is cleared - it accepts any element. * * Use the `overlap` option to set how drops are checked for. The allowed * values are: * * - `'pointer'`, the pointer must be over the dropzone (default) * - `'center'`, the draggable element's center must be over the dropzone * - a number from 0-1 which is the `(intersection area) / (draggable area)`. * e.g. `0.5` for drop to happen when half of the area of the draggable is * over the dropzone * * Use the `checker` option to specify a function to check if a dragged element * is over this Interactable. * * @param {boolean | object | null} [options] The new options to be set. * @return {boolean | Interactable} The current setting or this Interactable */ Interactable.prototype.dropzone = function (options) { if (utils.is.object(options)) { this.options.drop.enabled = options.enabled === false ? false : true; if (utils.is.function(options.ondrop)) { this.events.ondrop = options.ondrop; } if (utils.is.function(options.ondropactivate)) { this.events.ondropactivate = options.ondropactivate; } if (utils.is.function(options.ondropdeactivate)) { this.events.ondropdeactivate = options.ondropdeactivate; } if (utils.is.function(options.ondragenter)) { this.events.ondragenter = options.ondragenter; } if (utils.is.function(options.ondragleave)) { this.events.ondragleave = options.ondragleave; } if (utils.is.function(options.ondropmove)) { this.events.ondropmove = options.ondropmove; } if (/^(pointer|center)$/.test(options.overlap)) { this.options.drop.overlap = options.overlap; } else if (utils.is.number(options.overlap)) { this.options.drop.overlap = Math.max(Math.min(1, options.overlap), 0); } if ('accept' in options) { this.options.drop.accept = options.accept; } if ('checker' in options) { this.options.drop.checker = options.checker; } return this; } if (utils.is.bool(options)) { this.options.drop.enabled = options; if (!options) { this.ondragenter = this.ondragleave = this.ondrop = this.ondropactivate = this.ondropdeactivate = null; } return this; } return this.options.drop; }; Interactable.prototype.dropCheck = function (dragEvent, event, draggable, draggableElement, dropElement, rect) { var dropped = false; // if the dropzone has no rect (eg. display: none) // call the custom dropChecker or just return false if (!(rect = rect || this.getRect(dropElement))) { return this.options.drop.checker ? this.options.drop.checker(dragEvent, event, dropped, this, dropElement, draggable, draggableElement) : false; } var dropOverlap = this.options.drop.overlap; if (dropOverlap === 'pointer') { var origin = utils.getOriginXY(draggable, draggableElement, 'drag'); var page = utils.getPageXY(dragEvent); page.x += origin.x; page.y += origin.y; var horizontal = page.x > rect.left && page.x < rect.right; var vertical = page.y > rect.top && page.y < rect.bottom; dropped = horizontal && vertical; } var dragRect = draggable.getRect(draggableElement); if (dragRect && dropOverlap === 'center') { var cx = dragRect.left + dragRect.width / 2; var cy = dragRect.top + dragRect.height / 2; dropped = cx >= rect.left && cx <= rect.right && cy >= rect.top && cy <= rect.bottom; } if (dragRect && utils.is.number(dropOverlap)) { var overlapArea = Math.max(0, Math.min(rect.right, dragRect.right) - Math.max(rect.left, dragRect.left)) * Math.max(0, Math.min(rect.bottom, dragRect.bottom) - Math.max(rect.top, dragRect.top)); var overlapRatio = overlapArea / (dragRect.width * dragRect.height); dropped = overlapRatio >= dropOverlap; } if (this.options.drop.checker) { dropped = this.options.drop.checker(dragEvent, event, dropped, this, dropElement, draggable, draggableElement); } return dropped; }; Interactable.signals.on('unset', function (_ref8) { var interactable = _ref8.interactable; interactable.dropzone(false); }); Interactable.settingsMethods.push('dropChecker'); Interaction.signals.on('new', function (interaction) { interaction.dropTarget = null; // the dropzone a drag target might be dropped into interaction.dropElement = null; // the element at the time of checking interaction.prevDropTarget = null; // the dropzone that was recently dragged away from interaction.prevDropElement = null; // the element at the time of checking interaction.dropEvents = null; // the dropEvents related to the current drag event interaction.activeDrops = { dropzones: [], // the dropzones that are mentioned below elements: [], // elements of dropzones that accept the target draggable rects: [] // the rects of the elements mentioned above }; }); Interaction.signals.on('stop', function (_ref9) { var interaction = _ref9.interaction; interaction.dropTarget = interaction.dropElement = interaction.prevDropTarget = interaction.prevDropElement = null; }); /** * Returns or sets whether the dimensions of dropzone elements are calculated * on every dragmove or only on dragstart for the default dropChecker * * @param {boolean} [newValue] True to check on each move. False to check only * before start * @return {boolean | interact} The current setting or interact */ interact.dynamicDrop = function (newValue) { if (utils.is.bool(newValue)) { //if (dragging && dynamicDrop !== newValue && !newValue) { //calcRects(dropzones); //} dynamicDrop = newValue; return interact; } return dynamicDrop; }; utils.merge(Interactable.eventTypes, ['dragenter', 'dragleave', 'dropactivate', 'dropdeactivate', 'dropmove', 'drop']); actions.methodDict.drop = 'dropzone'; defaultOptions.drop = drop.defaults; module.exports = drop; },{"../InteractEvent":3,"../Interactable":4,"../Interaction":5,"../defaultOptions":18,"../interact":21,"../scope":33,"../utils":44,"./base":6}],9:[function(require,module,exports){ 'use strict'; var actions = require('./base'); var utils = require('../utils'); var InteractEvent = require('../InteractEvent'); var Interactable = require('../Interactable'); var Interaction = require('../Interaction'); var defaultOptions = require('../defaultOptions'); var gesture = { defaults: { enabled: false, origin: null, restrict: null }, checker: function checker(pointer, event, interactable, element, interaction) { if (interaction.pointerIds.length >= 2) { return { name: 'gesture' }; } return null; }, getCursor: function getCursor() { return ''; } }; InteractEvent.signals.on('new', function (_ref) { var iEvent = _ref.iEvent, interaction = _ref.interaction; if (iEvent.type !== 'gesturestart') { return; } iEvent.ds = 0; interaction.gesture.startDistance = interaction.gesture.prevDistance = iEvent.distance; interaction.gesture.startAngle = interaction.gesture.prevAngle = iEvent.angle; interaction.gesture.scale = 1; }); InteractEvent.signals.on('new', function (_ref2) { var iEvent = _ref2.iEvent, interaction = _ref2.interaction; if (iEvent.type !== 'gesturemove') { return; } iEvent.ds = iEvent.scale - interaction.gesture.scale; interaction.target.fire(iEvent); interaction.gesture.prevAngle = iEvent.angle; interaction.gesture.prevDistance = iEvent.distance; if (iEvent.scale !== Infinity && iEvent.scale !== null && iEvent.scale !== undefined && !isNaN(iEvent.scale)) { interaction.gesture.scale = iEvent.scale; } }); /** * ```js * interact(element).gesturable({ * onstart: function (event) {}, * onmove : function (event) {}, * onend : function (event) {}, * * // limit multiple gestures. * // See the explanation in {@link Interactable.draggable} example * max: Infinity, * maxPerElement: 1, * }); * * var isGestureable = interact(element).gesturable(); * ``` * * Gets or sets whether multitouch gestures can be performed on the target * * @param {boolean | object} [options] true/false or An object with event * listeners to be fired on gesture events (makes the Interactable gesturable) * @return {boolean | Interactable} A boolean indicating if this can be the * target of gesture events, or this Interactable */ Interactable.prototype.gesturable = function (options) { if (utils.is.object(options)) { this.options.gesture.enabled = options.enabled === false ? false : true; this.setPerAction('gesture', options); this.setOnEvents('gesture', options); return this; } if (utils.is.bool(options)) { this.options.gesture.enabled = options; if (!options) { this.ongesturestart = this.ongesturestart = this.ongestureend = null; } return this; } return this.options.gesture; }; InteractEvent.signals.on('set-delta', function (_ref3) { var interaction = _ref3.interaction, iEvent = _ref3.iEvent, action = _ref3.action, event = _ref3.event, starting = _ref3.starting, ending = _ref3.ending, deltaSource = _ref3.deltaSource; if (action !== 'gesture') { return; } var pointers = interaction.pointers; iEvent.touches = [pointers[0], pointers[1]]; if (starting) { iEvent.distance = utils.touchDistance(pointers, deltaSource); iEvent.box = utils.touchBBox(pointers); iEvent.scale = 1; iEvent.ds = 0; iEvent.angle = utils.touchAngle(pointers, undefined, deltaSource); iEvent.da = 0; } else if (ending || event instanceof InteractEvent) { iEvent.distance = interaction.prevEvent.distance; iEvent.box = interaction.prevEvent.box; iEvent.scale = interaction.prevEvent.scale; iEvent.ds = iEvent.scale - 1; iEvent.angle = interaction.prevEvent.angle; iEvent.da = iEvent.angle - interaction.gesture.startAngle; } else { iEvent.distance = utils.touchDistance(pointers, deltaSource); iEvent.box = utils.touchBBox(pointers); iEvent.scale = iEvent.distance / interaction.gesture.startDistance; iEvent.angle = utils.touchAngle(pointers, interaction.gesture.prevAngle, deltaSource); iEvent.ds = iEvent.scale - interaction.gesture.prevScale; iEvent.da = iEvent.angle - interaction.gesture.prevAngle; } }); Interaction.signals.on('new', function (interaction) { interaction.gesture = { start: { x: 0, y: 0 }, startDistance: 0, // distance between two touches of touchStart prevDistance: 0, distance: 0, scale: 1, // gesture.distance / gesture.startDistance startAngle: 0, // angle of line joining two touches prevAngle: 0 // angle of the previous gesture event }; }); actions.gesture = gesture; actions.names.push('gesture'); utils.merge(Interactable.eventTypes, ['gesturestart', 'gesturemove', 'gestureend']); actions.methodDict.gesture = 'gesturable'; defaultOptions.gesture = gesture.defaults; module.exports = gesture; },{"../InteractEvent":3,"../Interactable":4,"../Interaction":5,"../defaultOptions":18,"../utils":44,"./base":6}],10:[function(require,module,exports){ 'use strict'; var actions = require('./base'); var utils = require('../utils'); var browser = require('../utils/browser'); var InteractEvent = require('../InteractEvent'); /** @lends Interactable */ var Interactable = require('../Interactable'); var Interaction = require('../Interaction'); var defaultOptions = require('../defaultOptions'); // Less Precision with touch input var defaultMargin = browser.supportsTouch || browser.supportsPointerEvent ? 20 : 10; var resize = { defaults: { enabled: false, mouseButtons: null, origin: null, snap: null, restrict: null, inertia: null, autoScroll: null, square: false, preserveAspectRatio: false, axis: 'xy', // use default margin margin: NaN, // object with props left, right, top, bottom which are // true/false values to resize when the pointer is over that edge, // CSS selectors to match the handles for each direction // or the Elements for each handle edges: null, // a value of 'none' will limit the resize rect to a minimum of 0x0 // 'negate' will alow the rect to have negative width/height // 'reposition' will keep the width/height positive by swapping // the top and bottom edges and/or swapping the left and right edges invert: 'none' }, checker: function checker(pointer, event, interactable, element, interaction, rect) { if (!rect) { return null; } var page = utils.extend({}, interaction.curCoords.page); var options = interactable.options; if (options.resize.enabled) { var resizeOptions = options.resize; var resizeEdges = { left: false, right: false, top: false, bottom: false }; // if using resize.edges if (utils.is.object(resizeOptions.edges)) { for (var edge in resizeEdges) { resizeEdges[edge] = checkResizeEdge(edge, resizeOptions.edges[edge], page, interaction._eventTarget, element, rect, resizeOptions.margin || defaultMargin); } resizeEdges.left = resizeEdges.left && !resizeEdges.right; resizeEdges.top = resizeEdges.top && !resizeEdges.bottom; if (resizeEdges.left || resizeEdges.right || resizeEdges.top || resizeEdges.bottom) { return { name: 'resize', edges: resizeEdges }; } } else { var right = options.resize.axis !== 'y' && page.x > rect.right - defaultMargin; var bottom = options.resize.axis !== 'x' && page.y > rect.bottom - defaultMargin; if (right || bottom) { return { name: 'resize', axes: (right ? 'x' : '') + (bottom ? 'y' : '') }; } } } return null; }, cursors: browser.isIe9 ? { x: 'e-resize', y: 's-resize', xy: 'se-resize', top: 'n-resize', left: 'w-resize', bottom: 's-resize', right: 'e-resize', topleft: 'se-resize', bottomright: 'se-resize', topright: 'ne-resize', bottomleft: 'ne-resize' } : { x: 'ew-resize', y: 'ns-resize', xy: 'nwse-resize', top: 'ns-resize', left: 'ew-resize', bottom: 'ns-resize', right: 'ew-resize', topleft: 'nwse-resize', bottomright: 'nwse-resize', topright: 'nesw-resize', bottomleft: 'nesw-resize' }, getCursor: function getCursor(action) { if (action.axis) { return resize.cursors[action.name + action.axis]; } else if (action.edges) { var cursorKey = ''; var edgeNames = ['top', 'bottom', 'left', 'right']; for (var i = 0; i < 4; i++) { if (action.edges[edgeNames[i]]) { cursorKey += edgeNames[i]; } } return resize.cursors[cursorKey]; } } }; // resizestart InteractEvent.signals.on('new', function (_ref) { var iEvent = _ref.iEvent, interaction = _ref.interaction; if (iEvent.type !== 'resizestart' || !interaction.prepared.edges) { return; } var startRect = interaction.target.getRect(interaction.element); var resizeOptions = interaction.target.options.resize; /* * When using the `resizable.square` or `resizable.preserveAspectRatio` options, resizing from one edge * will affect another. E.g. with `resizable.square`, resizing to make the right edge larger will make * the bottom edge larger by the same amount. We call these 'linked' edges. Any linked edges will depend * on the active edges and the edge being interacted with. */ if (resizeOptions.square || resizeOptions.preserveAspectRatio) { var linkedEdges = utils.extend({}, interaction.prepared.edges); linkedEdges.top = linkedEdges.top || linkedEdges.left && !linkedEdges.bottom; linkedEdges.left = linkedEdges.left || linkedEdges.top && !linkedEdges.right; linkedEdges.bottom = linkedEdges.bottom || linkedEdges.right && !linkedEdges.top; linkedEdges.right = linkedEdges.right || linkedEdges.bottom && !linkedEdges.left; interaction.prepared._linkedEdges = linkedEdges; } else { interaction.prepared._linkedEdges = null; } // if using `resizable.preserveAspectRatio` option, record aspect ratio at the start of the resize if (resizeOptions.preserveAspectRatio) { interaction.resizeStartAspectRatio = startRect.width / startRect.height; } interaction.resizeRects = { start: startRect, current: utils.extend({}, startRect), inverted: utils.extend({}, startRect), previous: utils.extend({}, startRect), delta: { left: 0, right: 0, width: 0, top: 0, bottom: 0, height: 0 } }; iEvent.rect = interaction.resizeRects.inverted; iEvent.deltaRect = interaction.resizeRects.delta; }); // resizemove InteractEvent.signals.on('new', function (_ref2) { var iEvent = _ref2.iEvent, phase = _ref2.phase, interaction = _ref2.interaction; if (phase !== 'move' || !interaction.prepared.edges) { return; } var resizeOptions = interaction.target.options.resize; var invert = resizeOptions.invert; var invertible = invert === 'reposition' || invert === 'negate'; var edges = interaction.prepared.edges; var start = interaction.resizeRects.start; var current = interaction.resizeRects.current; var inverted = interaction.resizeRects.inverted; var delta = interaction.resizeRects.delta; var previous = utils.extend(interaction.resizeRects.previous, inverted); var originalEdges = edges; var dx = iEvent.dx; var dy = iEvent.dy; if (resizeOptions.preserveAspectRatio || resizeOptions.square) { // `resize.preserveAspectRatio` takes precedence over `resize.square` var startAspectRatio = resizeOptions.preserveAspectRatio ? interaction.resizeStartAspectRatio : 1; edges = interaction.prepared._linkedEdges; if (originalEdges.left && originalEdges.bottom || originalEdges.right && originalEdges.top) { dy = -dx / startAspectRatio; } else if (originalEdges.left || originalEdges.right) { dy = dx / startAspectRatio; } else if (originalEdges.top || originalEdges.bottom) { dx = dy * startAspectRatio; } } // update the 'current' rect without modifications if (edges.top) { current.top += dy; } if (edges.bottom) { current.bottom += dy; } if (edges.left) { current.left += dx; } if (edges.right) { current.right += dx; } if (invertible) { // if invertible, copy the current rect utils.extend(inverted, current); if (invert === 'reposition') { // swap edge values if necessary to keep width/height positive var swap = void 0; if (inverted.top > inverted.bottom) { swap = inverted.top; inverted.top = inverted.bottom; inverted.bottom = swap; } if (inverted.left > inverted.right) { swap = inverted.left; inverted.left = inverted.right; inverted.right = swap; } } } else { // if not invertible, restrict to minimum of 0x0 rect inverted.top = Math.min(current.top, start.bottom); inverted.bottom = Math.max(current.bottom, start.top); inverted.left = Math.min(current.left, start.right); inverted.right = Math.max(current.right, start.left); } inverted.width = inverted.right - inverted.left; inverted.height = inverted.bottom - inverted.top; for (var edge in inverted) { delta[edge] = inverted[edge] - previous[edge]; } iEvent.edges = interaction.prepared.edges; iEvent.rect = inverted; iEvent.deltaRect = delta; }); /** * ```js * interact(element).resizable({ * onstart: function (event) {}, * onmove : function (event) {}, * onend : function (event) {}, * * edges: { * top : true, // Use pointer coords to check for resize. * left : false, // Disable resizing from left edge. * bottom: '.resize-s',// Resize if pointer target matches selector * right : handleEl // Resize if pointer target is the given Element * }, * * // Width and height can be adjusted independently. When `true`, width and * // height are adjusted at a 1:1 ratio. * square: false, * * // Width and height can be adjusted independently. When `true`, width and * // height maintain the aspect ratio they had when resizing started. * preserveAspectRatio: false, * * // a value of 'none' will limit the resize rect to a minimum of 0x0 * // 'negate' will allow the rect to have negative width/height * // 'reposition' will keep the width/height positive by swapping * // the top and bottom edges and/or swapping the left and right edges * invert: 'none' || 'negate' || 'reposition' * * // limit multiple resizes. * // See the explanation in the {@link Interactable.draggable} example * max: Infinity, * maxPerElement: 1, * }); * * var isResizeable = interact(element).resizable(); * ``` * * Gets or sets whether resize actions can be performed on the target * * @param {boolean | object} [options] true/false or An object with event * listeners to be fired on resize events (object makes the Interactable * resizable) * @return {boolean | Interactable} A boolean indicating if this can be the * target of resize elements, or this Interactable */ Interactable.prototype.resizable = function (options) { if (utils.is.object(options)) { this.options.resize.enabled = options.enabled === false ? false : true; this.setPerAction('resize', options); this.setOnEvents('resize', options); if (/^x$|^y$|^xy$/.test(options.axis)) { this.options.resize.axis = options.axis; } else if (options.axis === null) { this.options.resize.axis = defaultOptions.resize.axis; } if (utils.is.bool(options.preserveAspectRatio)) { this.options.resize.preserveAspectRatio = options.preserveAspectRatio; } else if (utils.is.bool(options.square)) { this.options.resize.square = options.square; } return this; } if (utils.is.bool(options)) { this.options.resize.enabled = options; if (!options) { this.onresizestart = this.onresizestart = this.onresizeend = null; } return this; } return this.options.resize; }; function checkResizeEdge(name, value, page, element, interactableElement, rect, margin) { // false, '', undefined, null if (!value) { return false; } // true value, use pointer coords and element rect if (value === true) { // if dimensions are negative, "switch" edges var width = utils.is.number(rect.width) ? rect.width : rect.right - rect.left; var height = utils.is.number(rect.height) ? rect.height : rect.bottom - rect.top; if (width < 0) { if (name === 'left') { name = 'right'; } else if (name === 'right') { name = 'left'; } } if (height < 0) { if (name === 'top') { name = 'bottom'; } else if (name === 'bottom') { name = 'top'; } } if (name === 'left') { return page.x < (width >= 0 ? rect.left : rect.right) + margin; } if (name === 'top') { return page.y < (height >= 0 ? rect.top : rect.bottom) + margin; } if (name === 'right') { return page.x > (width >= 0 ? rect.right : rect.left) - margin; } if (name === 'bottom') { return page.y > (height >= 0 ? rect.bottom : rect.top) - margin; } } // the remaining checks require an element if (!utils.is.element(element)) { return false; } return utils.is.element(value) // the value is an element to use as a resize handle ? value === element // otherwise check if element matches value as selector : utils.matchesUpTo(element, value, interactableElement); } Interaction.signals.on('new', function (interaction) { interaction.resizeAxes = 'xy'; }); InteractEvent.signals.on('set-delta', function (_ref3) { var interaction = _ref3.interaction, iEvent = _ref3.iEvent, action = _ref3.action; if (action !== 'resize' || !interaction.resizeAxes) { return; } var options = interaction.target.options; if (options.resize.square) { if (interaction.resizeAxes === 'y') { iEvent.dx = iEvent.dy; } else { iEvent.dy = iEvent.dx; } iEvent.axes = 'xy'; } else { iEvent.axes = interaction.resizeAxes; if (interaction.resizeAxes === 'x') { iEvent.dy = 0; } else if (interaction.resizeAxes === 'y') { iEvent.dx = 0; } } }); actions.resize = resize; actions.names.push('resize'); utils.merge(Interactable.eventTypes, ['resizestart', 'resizemove', 'resizeinertiastart', 'resizeinertiaresume', 'resizeend']); actions.methodDict.resize = 'resizable'; defaultOptions.resize = resize.defaults; module.exports = resize; },{"../InteractEvent":3,"../Interactable":4,"../Interaction":5,"../defaultOptions":18,"../utils":44,"../utils/browser":36,"./base":6}],11:[function(require,module,exports){ 'use strict'; var raf = require('./utils/raf'); var getWindow = require('./utils/window').getWindow; var is = require('./utils/is'); var domUtils = require('./utils/domUtils'); var Interaction = require('./Interaction'); var defaultOptions = require('./defaultOptions'); var autoScroll = { defaults: { enabled: false, container: null, // the item that is scrolled (Window or HTMLElement) margin: 60, speed: 300 // the scroll speed in pixels per second }, interaction: null, i: null, // the handle returned by window.setInterval x: 0, y: 0, // Direction each pulse is to scroll in isScrolling: false, prevTime: 0, start: function start(interaction) { autoScroll.isScrolling = true; raf.cancel(autoScroll.i); autoScroll.interaction = interaction; autoScroll.prevTime = new Date().getTime(); autoScroll.i = raf.request(autoScroll.scroll); }, stop: function stop() { autoScroll.isScrolling = false; raf.cancel(autoScroll.i); }, // scroll the window by the values in scroll.x/y scroll: function scroll() { var options = autoScroll.interaction.target.options[autoScroll.interaction.prepared.name].autoScroll; var container = options.container || getWindow(autoScroll.interaction.element); var now = new Date().getTime(); // change in time in seconds var dt = (now - autoScroll.prevTime) / 1000; // displacement var s = options.speed * dt; if (s >= 1) { if (is.window(container)) { container.scrollBy(autoScroll.x * s, autoScroll.y * s); } else if (container) { container.scrollLeft += autoScroll.x * s; container.scrollTop += autoScroll.y * s; } autoScroll.prevTime = now; } if (autoScroll.isScrolling) { raf.cancel(autoScroll.i); autoScroll.i = raf.request(autoScroll.scroll); } }, check: function check(interactable, actionName) { var options = interactable.options; return options[actionName].autoScroll && options[actionName].autoScroll.enabled; }, onInteractionMove: function onInteractionMove(_ref) { var interaction = _ref.interaction, pointer = _ref.pointer; if (!(interaction.interacting() && autoScroll.check(interaction.target, interaction.prepared.name))) { return; } if (interaction.simulation) { autoScroll.x = autoScroll.y = 0; return; } var top = void 0; var right = void 0; var bottom = void 0; var left = void 0; var options = interaction.target.options[interaction.prepared.name].autoScroll; var container = options.container || getWindow(interaction.element); if (is.window(container)) { left = pointer.clientX < autoScroll.margin; top = pointer.clientY < autoScroll.margin; right = pointer.clientX > container.innerWidth - autoScroll.margin; bottom = pointer.clientY > container.innerHeight - autoScroll.margin; } else { var rect = domUtils.getElementClientRect(container); left = pointer.clientX < rect.left + autoScroll.margin; top = pointer.clientY < rect.top + autoScroll.margin; right = pointer.clientX > rect.right - autoScroll.margin; bottom = pointer.clientY > rect.bottom - autoScroll.margin; } autoScroll.x = right ? 1 : left ? -1 : 0; autoScroll.y = bottom ? 1 : top ? -1 : 0; if (!autoScroll.isScrolling) { // set the autoScroll properties to those of the target autoScroll.margin = options.margin; autoScroll.speed = options.speed; autoScroll.start(interaction); } } }; Interaction.signals.on('stop-active', function () { autoScroll.stop(); }); Interaction.signals.on('action-move', autoScroll.onInteractionMove); defaultOptions.perAction.autoScroll = autoScroll.defaults; module.exports = autoScroll; },{"./Interaction":5,"./defaultOptions":18,"./utils/domUtils":39,"./utils/is":46,"./utils/raf":50,"./utils/window":52}],12:[function(require,module,exports){ 'use strict'; /** @lends Interactable */ var Interactable = require('../Interactable'); var actions = require('../actions/base'); var is = require('../utils/is'); var domUtils = require('../utils/domUtils'); var _require = require('../utils'), warnOnce = _require.warnOnce; Interactable.prototype.getAction = function (pointer, event, interaction, element) { var action = this.defaultActionChecker(pointer, event, interaction, element); if (this.options.actionChecker) { return this.options.actionChecker(pointer, event, action, this, element, interaction); } return action; }; /** * ```js * interact(element, { ignoreFrom: document.getElementById('no-action') }); * // or * interact(element).ignoreFrom('input, textarea, a'); * ``` * @deprecated * If the target of the `mousedown`, `pointerdown` or `touchstart` event or any * of it's parents match the given CSS selector or Element, no * drag/resize/gesture is started. * * Don't use this method. Instead set the `ignoreFrom` option for each action * or for `pointerEvents` * * @example * interact(targett) * .draggable({ * ignoreFrom: 'input, textarea, a[href]'', * }) * .pointerEvents({ * ignoreFrom: '[no-pointer]', * }); * * @param {string | Element | null} [newValue] a CSS selector string, an * Element or `null` to not ignore any elements * @return {string | Element | object} The current ignoreFrom value or this * Interactable */ Interactable.prototype.ignoreFrom = warnOnce(function (newValue) { return this._backCompatOption('ignoreFrom', newValue); }, 'Interactable.ignoreForm() has been deprecated. Use Interactble.draggable({ignoreFrom: newValue}).'); /** * ```js * * @deprecated * A drag/resize/gesture is started only If the target of the `mousedown`, * `pointerdown` or `touchstart` event or any of it's parents match the given * CSS selector or Element. * * Don't use this method. Instead set the `allowFrom` option for each action * or for `pointerEvents` * * @example * interact(targett) * .resizable({ * allowFrom: '.resize-handle', * .pointerEvents({ * allowFrom: '.handle',, * }); * * @param {string | Element | null} [newValue] a CSS selector string, an * Element or `null` to allow from any element * @return {string | Element | object} The current allowFrom value or this * Interactable */ Interactable.prototype.allowFrom = warnOnce(function (newValue) { return this._backCompatOption('allowFrom', newValue); }, 'Interactable.allowForm() has been deprecated. Use Interactble.draggable({allowFrom: newValue}).'); Interactable.prototype.testIgnore = function (ignoreFrom, interactableElement, element) { if (!ignoreFrom || !is.element(element)) { return false; } if (is.string(ignoreFrom)) { return domUtils.matchesUpTo(element, ignoreFrom, interactableElement); } else if (is.element(ignoreFrom)) { return domUtils.nodeContains(ignoreFrom, element); } return false; }; Interactable.prototype.testAllow = function (allowFrom, interactableElement, element) { if (!allowFrom) { return true; } if (!is.element(element)) { return false; } if (is.string(allowFrom)) { return domUtils.matchesUpTo(element, allowFrom, interactableElement); } else if (is.element(allowFrom)) { return domUtils.nodeContains(allowFrom, element); } return false; }; Interactable.prototype.testIgnoreAllow = function (options, interactableElement, eventTarget) { return !this.testIgnore(options.ignoreFrom, interactableElement, eventTarget) && this.testAllow(options.allowFrom, interactableElement, eventTarget); }; /** * ```js * interact('.resize-drag') * .resizable(true) * .draggable(true) * .actionChecker(function (pointer, event, action, interactable, element, interaction) { * * if (interact.matchesSelector(event.target, '.drag-handle') { * // force drag with handle target * action.name = drag; * } * else { * // resize from the top and right edges * action.name = 'resize'; * action.edges = { top: true, right: true }; * } * * return action; * }); * ``` * * Gets or sets the function used to check action to be performed on * pointerDown * * @param {function | null} [checker] A function which takes a pointer event, * defaultAction string, interactable, element and interaction as parameters * and returns an object with name property 'drag' 'resize' or 'gesture' and * optionally an `edges` object with boolean 'top', 'left', 'bottom' and right * props. * @return {Function | Interactable} The checker function or this Interactable */ Interactable.prototype.actionChecker = function (checker) { if (is.function(checker)) { this.options.actionChecker = checker; return this; } if (checker === null) { delete this.options.actionChecker; return this; } return this.options.actionChecker; }; /** * Returns or sets whether the the cursor should be changed depending on the * action that would be performed if the mouse were pressed and dragged. * * @param {boolean} [newValue] * @return {boolean | Interactable} The current setting or this Interactable */ Interactable.prototype.styleCursor = function (newValue) { if (is.bool(newValue)) { this.options.styleCursor = newValue; return this; } if (newValue === null) { delete this.options.styleCursor; return this; } return this.options.styleCursor; }; Interactable.prototype.defaultActionChecker = function (pointer, event, interaction, element) { var rect = this.getRect(element); var buttons = event.buttons || { 0: 1, 1: 4, 3: 8, 4: 16 }[event.button]; var action = null; for (var _i = 0; _i < actions.names.length; _i++) { var _ref; _ref = actions.names[_i]; var actionName = _ref; // check mouseButton setting if the pointer is down if (interaction.pointerIsDown && /mouse|pointer/.test(interaction.pointerType) && (buttons & this.options[actionName].mouseButtons) === 0) { continue; } action = actions[actionName].checker(pointer, event, this, element, interaction, rect); if (action) { return action; } } }; },{"../Interactable":4,"../actions/base":6,"../utils":44,"../utils/domUtils":39,"../utils/is":46}],13:[function(require,module,exports){ 'use strict'; var interact = require('../interact'); var Interactable = require('../Interactable'); var Interaction = require('../Interaction'); var actions = require('../actions/base'); var defaultOptions = require('../defaultOptions'); var scope = require('../scope'); var utils = require('../utils'); var signals = require('../utils/Signals').new(); require('./InteractableMethods'); var autoStart = { signals: signals, withinInteractionLimit: withinInteractionLimit, // Allow this many interactions to happen simultaneously maxInteractions: Infinity, defaults: { perAction: { manualStart: false, max: Infinity, maxPerElement: 1, allowFrom: null, ignoreFrom: null, // only allow left button by default // see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons#Return_value mouseButtons: 1 } }, setActionDefaults: function setActionDefaults(action) { utils.extend(action.defaults, autoStart.defaults.perAction); }, validateAction: validateAction }; // set cursor style on mousedown Interaction.signals.on('down', function (_ref) { var interaction = _ref.interaction, pointer = _ref.pointer, event = _ref.event, eventTarget = _ref.eventTarget; if (interaction.interacting()) { return; } var actionInfo = getActionInfo(interaction, pointer, event, eventTarget); prepare(interaction, actionInfo); }); // set cursor style on mousemove Interaction.signals.on('move', function (_ref2) { var interaction = _ref2.interaction, pointer = _ref2.pointer, event = _ref2.event, eventTarget = _ref2.eventTarget; if (interaction.pointerType !== 'mouse' || interaction.pointerIsDown || interaction.interacting()) { return; } var actionInfo = getActionInfo(interaction, pointer, event, eventTarget); prepare(interaction, actionInfo); }); Interaction.signals.on('move', function (arg) { var interaction = arg.interaction, event = arg.event; if (!interaction.pointerIsDown || interaction.interacting() || !interaction.pointerWasMoved || !interaction.prepared.name) { return; } signals.fire('before-start', arg); var target = interaction.target; if (interaction.prepared.name && target) { // check manualStart and interaction limit if (target.options[interaction.prepared.name].manualStart || !withinInteractionLimit(target, interaction.element, interaction.prepared)) { interaction.stop(event); } else { interaction.start(interaction.prepared, target, interaction.element); } } }); // Check if the current target supports the action. // If so, return the validated action. Otherwise, return null function validateAction(action, interactable, element, eventTarget) { if (utils.is.object(action) && interactable.testIgnoreAllow(interactable.options[action.name], element, eventTarget) && interactable.options[action.name].enabled && withinInteractionLimit(interactable, element, action)) { return action; } return null; } function validateSelector(interaction, pointer, event, matches, matchElements, eventTarget) { for (var i = 0, len = matches.length; i < len; i++) { var match = matches[i]; var matchElement = matchElements[i]; var action = validateAction(match.getAction(pointer, event, interaction, matchElement), match, matchElement, eventTarget); if (action) { return { action: action, target: match, element: matchElement }; } } return {}; } function getActionInfo(interaction, pointer, event, eventTarget) { var matches = []; var matchElements = []; var element = eventTarget; function pushMatches(interactable) { matches.push(interactable); matchElements.push(element); } while (utils.is.element(element)) { matches = []; matchElements = []; scope.interactables.forEachMatch(element, pushMatches); var actionInfo = validateSelector(interaction, pointer, event, matches, matchElements, eventTarget); if (actionInfo.action && !actionInfo.target.options[actionInfo.action.name].manualStart) { return actionInfo; } element = utils.parentNode(element); } return {}; } function prepare(interaction, _ref3) { var action = _ref3.action, target = _ref3.target, element = _ref3.element; action = action || {}; if (interaction.target && interaction.target.options.styleCursor) { interaction.target._doc.documentElement.style.cursor = ''; } interaction.target = target; interaction.element = element; utils.copyAction(interaction.prepared, action); if (target && target.options.styleCursor) { var cursor = action ? actions[action.name].getCursor(action) : ''; interaction.target._doc.documentElement.style.cursor = cursor; } signals.fire('prepared', { interaction: interaction }); } Interaction.signals.on('stop', function (_ref4) { var interaction = _ref4.interaction; var target = interaction.target; if (target && target.options.styleCursor) { target._doc.documentElement.style.cursor = ''; } }); function withinInteractionLimit(interactable, element, action) { var options = interactable.options; var maxActions = options[action.name].max; var maxPerElement = options[action.name].maxPerElement; var activeInteractions = 0; var targetCount = 0; var targetElementCount = 0; // no actions if any of these values == 0 if (!(maxActions && maxPerElement && autoStart.maxInteractions)) { return; } for (var _i = 0; _i < scope.interactions.length; _i++) { var _ref5; _ref5 = scope.interactions[_i]; var interaction = _ref5; var otherAction = interaction.prepared.name; if (!interaction.interacting()) { continue; } activeInteractions++; if (activeInteractions >= autoStart.maxInteractions) { return false; } if (interaction.target !== interactable) { continue; } targetCount += otherAction === action.name | 0; if (targetCount >= maxActions) { return false; } if (interaction.element === element) { targetElementCount++; if (otherAction !== action.name || targetElementCount >= maxPerElement) { return false; } } } return autoStart.maxInteractions > 0; } /** * Returns or sets the maximum number of concurrent interactions allowed. By * default only 1 interaction is allowed at a time (for backwards * compatibility). To allow multiple interactions on the same Interactables and * elements, you need to enable it in the draggable, resizable and gesturable * `'max'` and `'maxPerElement'` options. * * @alias module:interact.maxInteractions * * @param {number} [newValue] Any number. newValue <= 0 means no interactions. */ interact.maxInteractions = function (newValue) { if (utils.is.number(newValue)) { autoStart.maxInteractions = newValue; return interact; } return autoStart.maxInteractions; }; Interactable.settingsMethods.push('styleCursor'); Interactable.settingsMethods.push('actionChecker'); Interactable.settingsMethods.push('ignoreFrom'); Interactable.settingsMethods.push('allowFrom'); defaultOptions.base.actionChecker = null; defaultOptions.base.styleCursor = true; utils.extend(defaultOptions.perAction, autoStart.defaults.perAction); module.exports = autoStart; },{"../Interactable":4,"../Interaction":5,"../actions/base":6,"../defaultOptions":18,"../interact":21,"../scope":33,"../utils":44,"../utils/Signals":34,"./InteractableMethods":12}],14:[function(require,module,exports){ 'use strict'; var autoStart = require('./base'); var scope = require('../scope'); var is = require('../utils/is'); var _require = require('../utils/domUtils'), parentNode = _require.parentNode; autoStart.setActionDefaults(require('../actions/drag')); autoStart.signals.on('before-start', function (_ref) { var interaction = _ref.interaction, eventTarget = _ref.eventTarget, dx = _ref.dx, dy = _ref.dy; if (interaction.prepared.name !== 'drag') { return; } // check if a drag is in the correct axis var absX = Math.abs(dx); var absY = Math.abs(dy); var targetOptions = interaction.target.options.drag; var startAxis = targetOptions.startAxis; var currentAxis = absX > absY ? 'x' : absX < absY ? 'y' : 'xy'; interaction.prepared.axis = targetOptions.lockAxis === 'start' ? currentAxis[0] // always lock to one axis even if currentAxis === 'xy' : targetOptions.lockAxis; // if the movement isn't in the startAxis of the interactable if (currentAxis !== 'xy' && startAxis !== 'xy' && startAxis !== currentAxis) { // cancel the prepared action interaction.prepared.name = null; // then try to get a drag from another ineractable var element = eventTarget; var getDraggable = function getDraggable(interactable) { if (interactable === interaction.target) { return; } var options = interaction.target.options.drag; if (!options.manualStart && interactable.testIgnoreAllow(options, element, eventTarget)) { var action = interactable.getAction(interaction.downPointer, interaction.downEvent, interaction, element); if (action && action.name === 'drag' && checkStartAxis(currentAxis, interactable) && autoStart.validateAction(action, interactable, element, eventTarget)) { return interactable; } } }; // check all interactables while (is.element(element)) { var interactable = scope.interactables.forEachMatch(element, getDraggable); if (interactable) { interaction.prepared.name = 'drag'; interaction.target = interactable; interaction.element = element; break; } element = parentNode(element); } } }); function checkStartAxis(startAxis, interactable) { if (!interactable) { return false; } var thisAxis = interactable.options.drag.startAxis; return startAxis === 'xy' || thisAxis === 'xy' || thisAxis === startAxis; } },{"../actions/drag":7,"../scope":33,"../utils/domUtils":39,"../utils/is":46,"./base":13}],15:[function(require,module,exports){ 'use strict'; require('./base').setActionDefaults(require('../actions/gesture')); },{"../actions/gesture":9,"./base":13}],16:[function(require,module,exports){ 'use strict'; var autoStart = require('./base'); var Interaction = require('../Interaction'); autoStart.defaults.perAction.hold = 0; autoStart.defaults.perAction.delay = 0; Interaction.signals.on('new', function (interaction) { interaction.autoStartHoldTimer = null; }); autoStart.signals.on('prepared', function (_ref) { var interaction = _ref.interaction; var hold = getHoldDuration(interaction); if (hold > 0) { interaction.autoStartHoldTimer = setTimeout(function () { interaction.start(interaction.prepared, interaction.target, interaction.element); }, hold); } }); Interaction.signals.on('move', function (_ref2) { var interaction = _ref2.interaction, duplicate = _ref2.duplicate; if (interaction.pointerWasMoved && !duplicate) { clearTimeout(interaction.autoStartHoldTimer); } }); // prevent regular down->move autoStart autoStart.signals.on('before-start', function (_ref3) { var interaction = _ref3.interaction; var hold = getHoldDuration(interaction); if (hold > 0) { interaction.prepared.name = null; } }); function getHoldDuration(interaction) { var actionName = interaction.prepared && interaction.prepared.name; if (!actionName) { return null; } var options = interaction.target.options; return options[actionName].hold || options[actionName].delay; } module.exports = { getHoldDuration: getHoldDuration }; },{"../Interaction":5,"./base":13}],17:[function(require,module,exports){ 'use strict'; require('./base').setActionDefaults(require('../actions/resize')); },{"../actions/resize":10,"./base":13}],18:[function(require,module,exports){ 'use strict'; module.exports = { base: { accept: null, preventDefault: 'auto', deltaSource: 'page' }, perAction: { origin: { x: 0, y: 0 }, inertia: { enabled: false, resistance: 10, // the lambda in exponential decay minSpeed: 100, // target speed must be above this for inertia to start endSpeed: 10, // the speed at which inertia is slow enough to stop allowResume: true, // allow resuming an action in inertia phase smoothEndDuration: 300 // animate to snap/restrict endOnly if there's no inertia } } }; },{}],19:[function(require,module,exports){ 'use strict'; /* browser entry point */ // inertia require('./inertia'); // modifiers require('./modifiers/snap'); require('./modifiers/restrict'); // pointerEvents require('./pointerEvents/base'); require('./pointerEvents/holdRepeat'); require('./pointerEvents/interactableTargets'); // autoStart hold require('./autoStart/hold'); // actions require('./actions/gesture'); require('./actions/resize'); require('./actions/drag'); require('./actions/drop'); // load these modifiers after resize is loaded require('./modifiers/snapSize'); require('./modifiers/restrictEdges'); require('./modifiers/restrictSize'); // autoStart actions require('./autoStart/gesture'); require('./autoStart/resize'); require('./autoStart/drag'); // Interactable preventDefault setting require('./interactablePreventDefault.js'); // autoScroll require('./autoScroll'); // export interact module.exports = require('./interact'); },{"./actions/drag":7,"./actions/drop":8,"./actions/gesture":9,"./actions/resize":10,"./autoScroll":11,"./autoStart/drag":14,"./autoStart/gesture":15,"./autoStart/hold":16,"./autoStart/resize":17,"./inertia":20,"./interact":21,"./interactablePreventDefault.js":22,"./modifiers/restrict":24,"./modifiers/restrictEdges":25,"./modifiers/restrictSize":26,"./modifiers/snap":27,"./modifiers/snapSize":28,"./pointerEvents/base":30,"./pointerEvents/holdRepeat":31,"./pointerEvents/interactableTargets":32}],20:[function(require,module,exports){ 'use strict'; var InteractEvent = require('./InteractEvent'); var Interaction = require('./Interaction'); var modifiers = require('./modifiers/base'); var utils = require('./utils'); var animationFrame = require('./utils/raf'); Interaction.signals.on('new', function (interaction) { interaction.inertiaStatus = { active: false, smoothEnd: false, allowResume: false, startEvent: null, upCoords: {}, xe: 0, ye: 0, sx: 0, sy: 0, t0: 0, vx0: 0, vys: 0, duration: 0, lambda_v0: 0, one_ve_v0: 0, i: null }; interaction.boundInertiaFrame = function () { return inertiaFrame.apply(interaction); }; interaction.boundSmoothEndFrame = function () { return smoothEndFrame.apply(interaction); }; }); Interaction.signals.on('down', function (_ref) { var interaction = _ref.interaction, event = _ref.event, pointer = _ref.pointer, eventTarget = _ref.eventTarget; var status = interaction.inertiaStatus; // Check if the down event hits the current inertia target if (status.active) { var element = eventTarget; // climb up the DOM tree from the event target while (utils.is.element(element)) { // if interaction element is the current inertia target element if (element === interaction.element) { // stop inertia animationFrame.cancel(status.i); status.active = false; interaction.simulation = null; // update pointers to the down event's coordinates interaction.updatePointer(pointer); utils.setCoords(interaction.curCoords, interaction.pointers); // fire appropriate signals var signalArg = { interaction: interaction }; Interaction.signals.fire('before-action-move', signalArg); Interaction.signals.fire('action-resume', signalArg); // fire a reume event var resumeEvent = new InteractEvent(interaction, event, interaction.prepared.name, 'inertiaresume', interaction.element); interaction.target.fire(resumeEvent); interaction.prevEvent = resumeEvent; modifiers.resetStatuses(interaction.modifierStatuses); utils.copyCoords(interaction.prevCoords, interaction.curCoords); break; } element = utils.parentNode(element); } } }); Interaction.signals.on('up', function (_ref2) { var interaction = _ref2.interaction, event = _ref2.event; var status = interaction.inertiaStatus; if (!interaction.interacting() || status.active) { return; } var target = interaction.target; var options = target && target.options; var inertiaOptions = options && interaction.prepared.name && options[interaction.prepared.name].inertia; var now = new Date().getTime(); var statuses = {}; var page = utils.extend({}, interaction.curCoords.page); var pointerSpeed = interaction.pointerDelta.client.speed; var smoothEnd = false; var modifierResult = void 0; // check if inertia should be started var inertiaPossible = inertiaOptions && inertiaOptions.enabled && interaction.prepared.name !== 'gesture' && event !== status.startEvent; var inertia = inertiaPossible && now - interaction.curCoords.timeStamp < 50 && pointerSpeed > inertiaOptions.minSpeed && pointerSpeed > inertiaOptions.endSpeed; var modifierArg = { interaction: interaction, pageCoords: page, statuses: statuses, preEnd: true, requireEndOnly: true }; // smoothEnd if (inertiaPossible && !inertia) { modifiers.resetStatuses(statuses); modifierResult = modifiers.setAll(modifierArg); if (modifierResult.shouldMove && modifierResult.locked) { smoothEnd = true; } } if (!(inertia || smoothEnd)) { return; } utils.copyCoords(status.upCoords, interaction.curCoords); interaction.pointers[0] = status.startEvent = new InteractEvent(interaction, event, interaction.prepared.name, 'inertiastart', interaction.element); status.t0 = now; status.active = true; status.allowResume = inertiaOptions.allowResume; interaction.simulation = status; target.fire(status.startEvent); if (inertia) { status.vx0 = interaction.pointerDelta.client.vx; status.vy0 = interaction.pointerDelta.client.vy; status.v0 = pointerSpeed; calcInertia(interaction, status); utils.extend(page, interaction.curCoords.page); page.x += status.xe; page.y += status.ye; modifiers.resetStatuses(statuses); modifierResult = modifiers.setAll(modifierArg); status.modifiedXe += modifierResult.dx; status.modifiedYe += modifierResult.dy; status.i = animationFrame.request(interaction.boundInertiaFrame); } else { status.smoothEnd = true; status.xe = modifierResult.dx; status.ye = modifierResult.dy; status.sx = status.sy = 0; status.i = animationFrame.request(interaction.boundSmoothEndFrame); } }); Interaction.signals.on('stop-active', function (_ref3) { var interaction = _ref3.interaction; var status = interaction.inertiaStatus; if (status.active) { animationFrame.cancel(status.i); status.active = false; interaction.simulation = null; } }); function calcInertia(interaction, status) { var inertiaOptions = interaction.target.options[interaction.prepared.name].inertia; var lambda = inertiaOptions.resistance; var inertiaDur = -Math.log(inertiaOptions.endSpeed / status.v0) / lambda; status.x0 = interaction.prevEvent.pageX; status.y0 = interaction.prevEvent.pageY; status.t0 = status.startEvent.timeStamp / 1000; status.sx = status.sy = 0; status.modifiedXe = status.xe = (status.vx0 - inertiaDur) / lambda; status.modifiedYe = status.ye = (status.vy0 - inertiaDur) / lambda; status.te = inertiaDur; status.lambda_v0 = lambda / status.v0; status.one_ve_v0 = 1 - inertiaOptions.endSpeed / status.v0; } function inertiaFrame() { updateInertiaCoords(this); utils.setCoordDeltas(this.pointerDelta, this.prevCoords, this.curCoords); var status = this.inertiaStatus; var options = this.target.options[this.prepared.name].inertia; var lambda = options.resistance; var t = new Date().getTime() / 1000 - status.t0; if (t < status.te) { var progress = 1 - (Math.exp(-lambda * t) - status.lambda_v0) / status.one_ve_v0; if (status.modifiedXe === status.xe && status.modifiedYe === status.ye) { status.sx = status.xe * progress; status.sy = status.ye * progress; } else { var quadPoint = utils.getQuadraticCurvePoint(0, 0, status.xe, status.ye, status.modifiedXe, status.modifiedYe, progress); status.sx = quadPoint.x; status.sy = quadPoint.y; } this.doMove(); status.i = animationFrame.request(this.boundInertiaFrame); } else { status.sx = status.modifiedXe; status.sy = status.modifiedYe; this.doMove(); this.end(status.startEvent); status.active = false; this.simulation = null; } utils.copyCoords(this.prevCoords, this.curCoords); } function smoothEndFrame() { updateInertiaCoords(this); var status = this.inertiaStatus; var t = new Date().getTime() - status.t0; var duration = this.target.options[this.prepared.name].inertia.smoothEndDuration; if (t < duration) { status.sx = utils.easeOutQuad(t, 0, status.xe, duration); status.sy = utils.easeOutQuad(t, 0, status.ye, duration); this.pointerMove(status.startEvent, status.startEvent); status.i = animationFrame.request(this.boundSmoothEndFrame); } else { status.sx = status.xe; status.sy = status.ye; this.pointerMove(status.startEvent, status.startEvent); this.end(status.startEvent); status.smoothEnd = status.active = false; this.simulation = null; } } function updateInertiaCoords(interaction) { var status = interaction.inertiaStatus; // return if inertia isn't running if (!status.active) { return; } var pageUp = status.upCoords.page; var clientUp = status.upCoords.client; utils.setCoords(interaction.curCoords, [{ pageX: pageUp.x + status.sx, pageY: pageUp.y + status.sy, clientX: clientUp.x + status.sx, clientY: clientUp.y + status.sy }]); } },{"./InteractEvent":3,"./Interaction":5,"./modifiers/base":23,"./utils":44,"./utils/raf":50}],21:[function(require,module,exports){ 'use strict'; /** @module interact */ var browser = require('./utils/browser'); var events = require('./utils/events'); var utils = require('./utils'); var scope = require('./scope'); var Interactable = require('./Interactable'); var Interaction = require('./Interaction'); var globalEvents = {}; /** * ```js * interact('#draggable').draggable(true); * * var rectables = interact('rect'); * rectables * .gesturable(true) * .on('gesturemove', function (event) { * // ... * }); * ``` * * The methods of this variable can be used to set elements as interactables * and also to change various default settings. * * Calling it as a function and passing an element or a valid CSS selector * string returns an Interactable object which has various methods to configure * it. * * @global * * @param {Element | string} element The HTML or SVG Element to interact with * or CSS selector * @return {Interactable} */ function interact(element, options) { var interactable = scope.interactables.get(element, options); if (!interactable) { interactable = new Interactable(element, options); interactable.events.global = globalEvents; } return interactable; } /** * Check if an element or selector has been set with the {@link interact} * function * * @alias module:interact.isSet * * @param {Element} element The Element being searched for * @return {boolean} Indicates if the element or CSS selector was previously * passed to interact */ interact.isSet = function (element, options) { return scope.interactables.indexOfElement(element, options && options.context) !== -1; }; /** * Add a global listener for an InteractEvent or adds a DOM event to `document` * * @alias module:interact.on * * @param {string | array | object} type The types of events to listen for * @param {function} listener The function event (s) * @param {object | boolean} [options] object or useCapture flag for * addEventListener * @return {object} interact */ interact.on = function (type, listener, options) { if (utils.is.string(type) && type.search(' ') !== -1) { type = type.trim().split(/ +/); } if (utils.is.array(type)) { for (var _i = 0; _i < type.length; _i++) { var _ref; _ref = type[_i]; var eventType = _ref; interact.on(eventType, listener, options); } return interact; } if (utils.is.object(type)) { for (var prop in type) { interact.on(prop, type[prop], listener); } return interact; } // if it is an InteractEvent type, add listener to globalEvents if (utils.contains(Interactable.eventTypes, type)) { // if this type of event was never bound if (!globalEvents[type]) { globalEvents[type] = [listener]; } else { globalEvents[type].push(listener); } } // If non InteractEvent type, addEventListener to document else { events.add(scope.document, type, listener, { options: options }); } return interact; }; /** * Removes a global InteractEvent listener or DOM event from `document` * * @alias module:interact.off * * @param {string | array | object} type The types of events that were listened * for * @param {function} listener The listener function to be removed * @param {object | boolean} options [options] object or useCapture flag for * removeEventListener * @return {object} interact */ interact.off = function (type, listener, options) { if (utils.is.string(type) && type.search(' ') !== -1) { type = type.trim().split(/ +/); } if (utils.is.array(type)) { for (var _i2 = 0; _i2 < type.length; _i2++) { var _ref2; _ref2 = type[_i2]; var eventType = _ref2; interact.off(eventType, listener, options); } return interact; } if (utils.is.object(type)) { for (var prop in type) { interact.off(prop, type[prop], listener); } return interact; } if (!utils.contains(Interactable.eventTypes, type)) { events.remove(scope.document, type, listener, options); } else { var index = void 0; if (type in globalEvents && (index = globalEvents[type].indexOf(listener)) !== -1) { globalEvents[type].splice(index, 1); } } return interact; }; /** * Returns an object which exposes internal data * @alias module:interact.debug * * @return {object} An object with properties that outline the current state * and expose internal functions and variables */ interact.debug = function () { return scope; }; // expose the functions used to calculate multi-touch properties interact.getPointerAverage = utils.pointerAverage; interact.getTouchBBox = utils.touchBBox; interact.getTouchDistance = utils.touchDistance; interact.getTouchAngle = utils.touchAngle; interact.getElementRect = utils.getElementRect; interact.getElementClientRect = utils.getElementClientRect; interact.matchesSelector = utils.matchesSelector; interact.closest = utils.closest; /** * @alias module:interact.supportsTouch * * @return {boolean} Whether or not the browser supports touch input */ interact.supportsTouch = function () { return browser.supportsTouch; }; /** * @alias module:interact.supportsPointerEvent * * @return {boolean} Whether or not the browser supports PointerEvents */ interact.supportsPointerEvent = function () { return browser.supportsPointerEvent; }; /** * Cancels all interactions (end events are not fired) * * @alias module:interact.stop * * @param {Event} event An event on which to call preventDefault() * @return {object} interact */ interact.stop = function (event) { for (var i = scope.interactions.length - 1; i >= 0; i--) { scope.interactions[i].stop(event); } return interact; }; /** * Returns or sets the distance the pointer must be moved before an action * sequence occurs. This also affects tolerance for tap events. * * @alias module:interact.pointerMoveTolerance * * @param {number} [newValue] The movement from the start position must be greater than this value * @return {interact | number} */ interact.pointerMoveTolerance = function (newValue) { if (utils.is.number(newValue)) { Interaction.pointerMoveTolerance = newValue; return interact; } return Interaction.pointerMoveTolerance; }; interact.addDocument = scope.addDocument; interact.removeDocument = scope.removeDocument; scope.interact = interact; module.exports = interact; },{"./Interactable":4,"./Interaction":5,"./scope":33,"./utils":44,"./utils/browser":36,"./utils/events":40}],22:[function(require,module,exports){ 'use strict'; var Interactable = require('./Interactable'); var Interaction = require('./Interaction'); var scope = require('./scope'); var is = require('./utils/is'); var events = require('./utils/events'); var browser = require('./utils/browser'); var _require = require('./utils/domUtils'), nodeContains = _require.nodeContains, matchesSelector = _require.matchesSelector; /** * Returns or sets whether to prevent the browser's default behaviour in * response to pointer events. Can be set to: * - `'always'` to always prevent * - `'never'` to never prevent * - `'auto'` to let interact.js try to determine what would be best * * @param {string} [newValue] `true`, `false` or `'auto'` * @return {string | Interactable} The current setting or this Interactable */ Interactable.prototype.preventDefault = function (newValue) { if (/^(always|never|auto)$/.test(newValue)) { this.options.preventDefault = newValue; return this; } if (is.bool(newValue)) { this.options.preventDefault = newValue ? 'always' : 'never'; return this; } return this.options.preventDefault; }; Interactable.prototype.checkAndPreventDefault = function (event) { var setting = this.options.preventDefault; if (setting === 'never') { return; } if (setting === 'always') { event.preventDefault(); return; } // setting === 'auto' // don't preventDefault of touch{start,move} events if the browser supports passive // events listeners. CSS touch-action and user-selecct should be used instead if (events.supportsPassive && /^touch(start|move)$/.test(event.type) && !browser.isIOS) { return; } // don't preventDefault of pointerdown events if (/^(mouse|pointer|touch)*(down|start)/i.test(event.type)) { return; } // don't preventDefault on editable elements if (is.element(event.target) && matchesSelector(event.target, 'input,select,textarea,[contenteditable=true],[contenteditable=true] *')) { return; } event.preventDefault(); }; function onInteractionEvent(_ref) { var interaction = _ref.interaction, event = _ref.event; if (interaction.target) { interaction.target.checkAndPreventDefault(event); } } var _arr = ['down', 'move', 'up', 'cancel']; for (var _i = 0; _i < _arr.length; _i++) { var eventSignal = _arr[_i]; Interaction.signals.on(eventSignal, onInteractionEvent); } // prevent native HTML5 drag on interact.js target elements Interaction.docEvents.dragstart = function preventNativeDrag(event) { for (var _i2 = 0; _i2 < scope.interactions.length; _i2++) { var _ref2; _ref2 = scope.interactions[_i2]; var interaction = _ref2; if (interaction.element && (interaction.element === event.target || nodeContains(interaction.element, event.target))) { interaction.target.checkAndPreventDefault(event); return; } } }; },{"./Interactable":4,"./Interaction":5,"./scope":33,"./utils/browser":36,"./utils/domUtils":39,"./utils/events":40,"./utils/is":46}],23:[function(require,module,exports){ 'use strict'; var InteractEvent = require('../InteractEvent'); var Interaction = require('../Interaction'); var extend = require('../utils/extend'); var modifiers = { names: [], setOffsets: function setOffsets(arg) { var interaction = arg.interaction, page = arg.pageCoords; var target = interaction.target, element = interaction.element, startOffset = interaction.startOffset; var rect = target.getRect(element); if (rect) { startOffset.left = page.x - rect.left; startOffset.top = page.y - rect.top; startOffset.right = rect.right - page.x; startOffset.bottom = rect.bottom - page.y; if (!('width' in rect)) { rect.width = rect.right - rect.left; } if (!('height' in rect)) { rect.height = rect.bottom - rect.top; } } else { startOffset.left = startOffset.top = startOffset.right = startOffset.bottom = 0; } arg.rect = rect; arg.interactable = target; arg.element = element; for (var _i = 0; _i < modifiers.names.length; _i++) { var _ref; _ref = modifiers.names[_i]; var modifierName = _ref; arg.options = target.options[interaction.prepared.name][modifierName]; if (!arg.options) { continue; } interaction.modifierOffsets[modifierName] = modifiers[modifierName].setOffset(arg); } }, setAll: function setAll(arg) { var interaction = arg.interaction, statuses = arg.statuses, preEnd = arg.preEnd, requireEndOnly = arg.requireEndOnly; var result = { dx: 0, dy: 0, changed: false, locked: false, shouldMove: true }; arg.modifiedCoords = extend({}, arg.pageCoords); for (var _i2 = 0; _i2 < modifiers.names.length; _i2++) { var _ref2; _ref2 = modifiers.names[_i2]; var modifierName = _ref2; var modifier = modifiers[modifierName]; var options = interaction.target.options[interaction.prepared.name][modifierName]; if (!shouldDo(options, preEnd, requireEndOnly)) { continue; } arg.status = arg.status = statuses[modifierName]; arg.options = options; arg.offset = arg.interaction.modifierOffsets[modifierName]; modifier.set(arg); if (arg.status.locked) { arg.modifiedCoords.x += arg.status.dx; arg.modifiedCoords.y += arg.status.dy; result.dx += arg.status.dx; result.dy += arg.status.dy; result.locked = true; } } // a move should be fired if: // - there are no modifiers enabled, // - no modifiers are "locked" i.e. have changed the pointer's coordinates, or // - the locked coords have changed since the last pointer move result.shouldMove = !arg.status || !result.locked || arg.status.changed; return result; }, resetStatuses: function resetStatuses(statuses) { for (var _i3 = 0; _i3 < modifiers.names.length; _i3++) { var _ref3; _ref3 = modifiers.names[_i3]; var modifierName = _ref3; var status = statuses[modifierName] || {}; status.dx = status.dy = 0; status.modifiedX = status.modifiedY = NaN; status.locked = false; status.changed = true; statuses[modifierName] = status; } return statuses; }, start: function start(_ref4, signalName) { var interaction = _ref4.interaction; var arg = { interaction: interaction, pageCoords: (signalName === 'action-resume' ? interaction.curCoords : interaction.startCoords).page, startOffset: interaction.startOffset, statuses: interaction.modifierStatuses, preEnd: false, requireEndOnly: false }; modifiers.setOffsets(arg); modifiers.resetStatuses(arg.statuses); arg.pageCoords = extend({}, interaction.startCoords.page); interaction.modifierResult = modifiers.setAll(arg); }, beforeMove: function beforeMove(_ref5) { var interaction = _ref5.interaction, preEnd = _ref5.preEnd, interactingBeforeMove = _ref5.interactingBeforeMove; var modifierResult = modifiers.setAll({ interaction: interaction, preEnd: preEnd, pageCoords: interaction.curCoords.page, statuses: interaction.modifierStatuses, requireEndOnly: false }); // don't fire an action move if a modifier would keep the event in the same // cordinates as before if (!modifierResult.shouldMove && interactingBeforeMove) { interaction._dontFireMove = true; } interaction.modifierResult = modifierResult; }, end: function end(_ref6) { var interaction = _ref6.interaction, event = _ref6.event; for (var _i4 = 0; _i4 < modifiers.names.length; _i4++) { var _ref7; _ref7 = modifiers.names[_i4]; var modifierName = _ref7; var options = interaction.target.options[interaction.prepared.name][modifierName]; // if the endOnly option is true for any modifier if (shouldDo(options, true, true)) { // fire a move event at the modified coordinates interaction.doMove({ event: event, preEnd: true }); break; } } }, setXY: function setXY(arg) { var iEvent = arg.iEvent, interaction = arg.interaction; var modifierArg = extend({}, arg); for (var i = 0; i < modifiers.names.length; i++) { var modifierName = modifiers.names[i]; modifierArg.options = interaction.target.options[interaction.prepared.name][modifierName]; if (!modifierArg.options) { continue; } var modifier = modifiers[modifierName]; modifierArg.status = interaction.modifierStatuses[modifierName]; iEvent[modifierName] = modifier.modifyCoords(modifierArg); } } }; Interaction.signals.on('new', function (interaction) { interaction.startOffset = { left: 0, right: 0, top: 0, bottom: 0 }; interaction.modifierOffsets = {}; interaction.modifierStatuses = modifiers.resetStatuses({}); interaction.modifierResult = null; }); Interaction.signals.on('action-start', modifiers.start); Interaction.signals.on('action-resume', modifiers.start); Interaction.signals.on('before-action-move', modifiers.beforeMove); Interaction.signals.on('action-end', modifiers.end); InteractEvent.signals.on('set-xy', modifiers.setXY); function shouldDo(options, preEnd, requireEndOnly) { return options && options.enabled && (preEnd || !options.endOnly) && (!requireEndOnly || options.endOnly); } module.exports = modifiers; },{"../InteractEvent":3,"../Interaction":5,"../utils/extend":41}],24:[function(require,module,exports){ 'use strict'; var modifiers = require('./base'); var utils = require('../utils'); var defaultOptions = require('../defaultOptions'); var restrict = { defaults: { enabled: false, endOnly: false, restriction: null, elementRect: null }, setOffset: function setOffset(_ref) { var rect = _ref.rect, startOffset = _ref.startOffset, options = _ref.options; var elementRect = options && options.elementRect; var offset = {}; if (rect && elementRect) { offset.left = startOffset.left - rect.width * elementRect.left; offset.top = startOffset.top - rect.height * elementRect.top; offset.right = startOffset.right - rect.width * (1 - elementRect.right); offset.bottom = startOffset.bottom - rect.height * (1 - elementRect.bottom); } else { offset.left = offset.top = offset.right = offset.bottom = 0; } return offset; }, set: function set(_ref2) { var modifiedCoords = _ref2.modifiedCoords, interaction = _ref2.interaction, status = _ref2.status, options = _ref2.options; if (!options) { return status; } var page = status.useStatusXY ? { x: status.x, y: status.y } : utils.extend({}, modifiedCoords); var restriction = getRestrictionRect(options.restriction, interaction, page); if (!restriction) { return status; } status.dx = 0; status.dy = 0; status.locked = false; var rect = restriction; var modifiedX = page.x; var modifiedY = page.y; var offset = interaction.modifierOffsets.restrict; // object is assumed to have // x, y, width, height or // left, top, right, bottom if ('x' in restriction && 'y' in restriction) { modifiedX = Math.max(Math.min(rect.x + rect.width - offset.right, page.x), rect.x + offset.left); modifiedY = Math.max(Math.min(rect.y + rect.height - offset.bottom, page.y), rect.y + offset.top); } else { modifiedX = Math.max(Math.min(rect.right - offset.right, page.x), rect.left + offset.left); modifiedY = Math.max(Math.min(rect.bottom - offset.bottom, page.y), rect.top + offset.top); } status.dx = modifiedX - page.x; status.dy = modifiedY - page.y; status.changed = status.modifiedX !== modifiedX || status.modifiedY !== modifiedY; status.locked = !!(status.dx || status.dy); status.modifiedX = modifiedX; status.modifiedY = modifiedY; }, modifyCoords: function modifyCoords(_ref3) { var page = _ref3.page, client = _ref3.client, status = _ref3.status, phase = _ref3.phase, options = _ref3.options; var elementRect = options && options.elementRect; if (options && options.enabled && !(phase === 'start' && elementRect && status.locked)) { if (status.locked) { page.x += status.dx; page.y += status.dy; client.x += status.dx; client.y += status.dy; return { dx: status.dx, dy: status.dy }; } } }, getRestrictionRect: getRestrictionRect }; function getRestrictionRect(value, interaction, page) { if (utils.is.function(value)) { return utils.resolveRectLike(value, interaction.target, interaction.element, [page.x, page.y, interaction]); } else { return utils.resolveRectLike(value, interaction.target, interaction.element); } } modifiers.restrict = restrict; modifiers.names.push('restrict'); defaultOptions.perAction.restrict = restrict.defaults; module.exports = restrict; },{"../defaultOptions":18,"../utils":44,"./base":23}],25:[function(require,module,exports){ 'use strict'; // This module adds the options.resize.restrictEdges setting which sets min and // max for the top, left, bottom and right edges of the target being resized. // // interact(target).resize({ // edges: { top: true, left: true }, // restrictEdges: { // inner: { top: 200, left: 200, right: 400, bottom: 400 }, // outer: { top: 0, left: 0, right: 600, bottom: 600 }, // }, // }); var modifiers = require('./base'); var utils = require('../utils'); var rectUtils = require('../utils/rect'); var defaultOptions = require('../defaultOptions'); var resize = require('../actions/resize'); var _require = require('./restrict'), getRestrictionRect = _require.getRestrictionRect; var noInner = { top: +Infinity, left: +Infinity, bottom: -Infinity, right: -Infinity }; var noOuter = { top: -Infinity, left: -Infinity, bottom: +Infinity, right: +Infinity }; var restrictEdges = { defaults: { enabled: false, endOnly: false, min: null, max: null, offset: null }, setOffset: function setOffset(_ref) { var interaction = _ref.interaction, startOffset = _ref.startOffset, options = _ref.options; if (!options) { return utils.extend({}, startOffset); } var offset = getRestrictionRect(options.offset, interaction, interaction.startCoords.page); if (offset) { return { top: startOffset.top + offset.y, left: startOffset.left + offset.x, bottom: startOffset.bottom + offset.y, right: startOffset.right + offset.x }; } return startOffset; }, set: function set(_ref2) { var modifiedCoords = _ref2.modifiedCoords, interaction = _ref2.interaction, status = _ref2.status, offset = _ref2.offset, options = _ref2.options; var edges = interaction.prepared.linkedEdges || interaction.prepared.edges; if (!interaction.interacting() || !edges) { return; } var page = status.useStatusXY ? { x: status.x, y: status.y } : utils.extend({}, modifiedCoords); var inner = rectUtils.xywhToTlbr(getRestrictionRect(options.inner, interaction, page)) || noInner; var outer = rectUtils.xywhToTlbr(getRestrictionRect(options.outer, interaction, page)) || noOuter; var modifiedX = page.x; var modifiedY = page.y; status.dx = 0; status.dy = 0; status.locked = false; if (edges.top) { modifiedY = Math.min(Math.max(outer.top + offset.top, page.y), inner.top + offset.top); } else if (edges.bottom) { modifiedY = Math.max(Math.min(outer.bottom - offset.bottom, page.y), inner.bottom - offset.bottom); } if (edges.left) { modifiedX = Math.min(Math.max(outer.left + offset.left, page.x), inner.left + offset.left); } else if (edges.right) { modifiedX = Math.max(Math.min(outer.right - offset.right, page.x), inner.right - offset.right); } status.dx = modifiedX - page.x; status.dy = modifiedY - page.y; status.changed = status.modifiedX !== modifiedX || status.modifiedY !== modifiedY; status.locked = !!(status.dx || status.dy); status.modifiedX = modifiedX; status.modifiedY = modifiedY; }, modifyCoords: function modifyCoords(_ref3) { var page = _ref3.page, client = _ref3.client, status = _ref3.status, phase = _ref3.phase, options = _ref3.options; if (options && options.enabled && !(phase === 'start' && status.locked)) { if (status.locked) { page.x += status.dx; page.y += status.dy; client.x += status.dx; client.y += status.dy; return { dx: status.dx, dy: status.dy }; } } }, noInner: noInner, noOuter: noOuter, getRestrictionRect: getRestrictionRect }; modifiers.restrictEdges = restrictEdges; modifiers.names.push('restrictEdges'); defaultOptions.perAction.restrictEdges = restrictEdges.defaults; resize.defaults.restrictEdges = restrictEdges.defaults; module.exports = restrictEdges; },{"../actions/resize":10,"../defaultOptions":18,"../utils":44,"../utils/rect":51,"./base":23,"./restrict":24}],26:[function(require,module,exports){ 'use strict'; // This module adds the options.resize.restrictSize setting which sets min and // max width and height for the target being resized. // // interact(target).resize({ // edges: { top: true, left: true }, // restrictSize: { // min: { width: -600, height: -600 }, // max: { width: 600, height: 600 }, // }, // }); var modifiers = require('./base'); var restrictEdges = require('./restrictEdges'); var utils = require('../utils'); var rectUtils = require('../utils/rect'); var defaultOptions = require('../defaultOptions'); var resize = require('../actions/resize'); var noMin = { width: -Infinity, height: -Infinity }; var noMax = { width: +Infinity, height: +Infinity }; var restrictSize = { defaults: { enabled: false, endOnly: false, min: null, max: null }, setOffset: function setOffset(_ref) { var interaction = _ref.interaction; return interaction.startOffset; }, set: function set(arg) { var interaction = arg.interaction, options = arg.options; var edges = interaction.prepared.linkedEdges || interaction.prepared.edges; if (!interaction.interacting() || !edges) { return; } var rect = rectUtils.xywhToTlbr(interaction.resizeRects.inverted); var minSize = rectUtils.tlbrToXywh(restrictEdges.getRestrictionRect(options.min, interaction)) || noMin; var maxSize = rectUtils.tlbrToXywh(restrictEdges.getRestrictionRect(options.max, interaction)) || noMax; arg.options = { enabled: options.enabled, endOnly: options.endOnly, inner: utils.extend({}, restrictEdges.noInner), outer: utils.extend({}, restrictEdges.noOuter) }; if (edges.top) { arg.options.inner.top = rect.bottom - minSize.height; arg.options.outer.top = rect.bottom - maxSize.height; } else if (edges.bottom) { arg.options.inner.bottom = rect.top + minSize.height; arg.options.outer.bottom = rect.top + maxSize.height; } if (edges.left) { arg.options.inner.left = rect.right - minSize.width; arg.options.outer.left = rect.right - maxSize.width; } else if (edges.right) { arg.options.inner.right = rect.left + minSize.width; arg.options.outer.right = rect.left + maxSize.width; } restrictEdges.set(arg); }, modifyCoords: restrictEdges.modifyCoords }; modifiers.restrictSize = restrictSize; modifiers.names.push('restrictSize'); defaultOptions.perAction.restrictSize = restrictSize.defaults; resize.defaults.restrictSize = restrictSize.defaults; module.exports = restrictSize; },{"../actions/resize":10,"../defaultOptions":18,"../utils":44,"../utils/rect":51,"./base":23,"./restrictEdges":25}],27:[function(require,module,exports){ 'use strict'; var modifiers = require('./base'); var interact = require('../interact'); var utils = require('../utils'); var defaultOptions = require('../defaultOptions'); var snap = { defaults: { enabled: false, endOnly: false, range: Infinity, targets: null, offsets: null, relativePoints: null }, setOffset: function setOffset(_ref) { var interaction = _ref.interaction, interactable = _ref.interactable, element = _ref.element, rect = _ref.rect, startOffset = _ref.startOffset, options = _ref.options; var offsets = []; var optionsOrigin = utils.rectToXY(utils.resolveRectLike(options.origin)); var origin = optionsOrigin || utils.getOriginXY(interactable, element, interaction.prepared.name); options = options || interactable.options[interaction.prepared.name].snap || {}; var snapOffset = void 0; if (options.offset === 'startCoords') { snapOffset = { x: interaction.startCoords.page.x - origin.x, y: interaction.startCoords.page.y - origin.y }; } else { var offsetRect = utils.resolveRectLike(options.offset, interactable, element, [interaction]); snapOffset = utils.rectToXY(offsetRect) || { x: 0, y: 0 }; } if (rect && options.relativePoints && options.relativePoints.length) { for (var _i = 0; _i < options.relativePoints.length; _i++) { var _ref3; _ref3 = options.relativePoints[_i]; var _ref2 = _ref3; var relativeX = _ref2.x; var relativeY = _ref2.y; offsets.push({ x: startOffset.left - rect.width * relativeX + snapOffset.x, y: startOffset.top - rect.height * relativeY + snapOffset.y }); } } else { offsets.push(snapOffset); } return offsets; }, set: function set(_ref4) { var interaction = _ref4.interaction, modifiedCoords = _ref4.modifiedCoords, status = _ref4.status, options = _ref4.options, offsets = _ref4.offset; var targets = []; var target = void 0; var page = void 0; var i = void 0; if (status.useStatusXY) { page = { x: status.x, y: status.y }; } else { var origin = utils.getOriginXY(interaction.target, interaction.element, interaction.prepared.name); page = utils.extend({}, modifiedCoords); page.x -= origin.x; page.y -= origin.y; } status.realX = page.x; status.realY = page.y; var len = options.targets ? options.targets.length : 0; for (var _i2 = 0; _i2 < offsets.length; _i2++) { var _ref6; _ref6 = offsets[_i2]; var _ref5 = _ref6; var offsetX = _ref5.x; var offsetY = _ref5.y; var relativeX = page.x - offsetX; var relativeY = page.y - offsetY; for (var _i3 = 0; _i3 < (options.targets || []).length; _i3++) { var _ref7; _ref7 = (options.targets || [])[_i3]; var snapTarget = _ref7; if (utils.is.function(snapTarget)) { target = snapTarget(relativeX, relativeY, interaction); } else { target = snapTarget; } if (!target) { continue; } targets.push({ x: utils.is.number(target.x) ? target.x + offsetX : relativeX, y: utils.is.number(target.y) ? target.y + offsetY : relativeY, range: utils.is.number(target.range) ? target.range : options.range }); } } var closest = { target: null, inRange: false, distance: 0, range: 0, dx: 0, dy: 0 }; for (i = 0, len = targets.length; i < len; i++) { target = targets[i]; var range = target.range; var dx = target.x - page.x; var dy = target.y - page.y; var distance = utils.hypot(dx, dy); var inRange = distance <= range; // Infinite targets count as being out of range // compared to non infinite ones that are in range if (range === Infinity && closest.inRange && closest.range !== Infinity) { inRange = false; } if (!closest.target || (inRange // is the closest target in range? ? closest.inRange && range !== Infinity // the pointer is relatively deeper in this target ? distance / range < closest.distance / closest.range // this target has Infinite range and the closest doesn't : range === Infinity && closest.range !== Infinity || // OR this target is closer that the previous closest distance < closest.distance : // The other is not in range and the pointer is closer to this target !closest.inRange && distance < closest.distance)) { closest.target = target; closest.distance = distance; closest.range = range; closest.inRange = inRange; closest.dx = dx; closest.dy = dy; status.range = range; } } var snapChanged = void 0; if (closest.target) { snapChanged = status.modifiedX !== closest.target.x || status.modifiedY !== closest.target.y; status.modifiedX = closest.target.x; status.modifiedY = closest.target.y; } else { snapChanged = true; status.modifiedX = NaN; status.modifiedY = NaN; } status.dx = closest.dx; status.dy = closest.dy; status.changed = snapChanged || closest.inRange && !status.locked; status.locked = closest.inRange; }, modifyCoords: function modifyCoords(_ref8) { var page = _ref8.page, client = _ref8.client, status = _ref8.status, phase = _ref8.phase, options = _ref8.options; var relativePoints = options && options.relativePoints; if (options && options.enabled && !(phase === 'start' && relativePoints && relativePoints.length)) { if (status.locked) { page.x += status.dx; page.y += status.dy; client.x += status.dx; client.y += status.dy; } return { range: status.range, locked: status.locked, x: status.modifiedX, y: status.modifiedY, realX: status.realX, realY: status.realY, dx: status.dx, dy: status.dy }; } } }; interact.createSnapGrid = function (grid) { return function (x, y) { var limits = grid.limits || { left: -Infinity, right: Infinity, top: -Infinity, bottom: Infinity }; var offsetX = 0; var offsetY = 0; if (utils.is.object(grid.offset)) { offsetX = grid.offset.x; offsetY = grid.offset.y; } var gridx = Math.round((x - offsetX) / grid.x); var gridy = Math.round((y - offsetY) / grid.y); var newX = Math.max(limits.left, Math.min(limits.right, gridx * grid.x + offsetX)); var newY = Math.max(limits.top, Math.min(limits.bottom, gridy * grid.y + offsetY)); return { x: newX, y: newY, range: grid.range }; }; }; modifiers.snap = snap; modifiers.names.push('snap'); defaultOptions.perAction.snap = snap.defaults; module.exports = snap; },{"../defaultOptions":18,"../interact":21,"../utils":44,"./base":23}],28:[function(require,module,exports){ 'use strict'; // This module allows snapping of the size of targets during resize // interactions. var modifiers = require('./base'); var snap = require('./snap'); var defaultOptions = require('../defaultOptions'); var resize = require('../actions/resize'); var utils = require('../utils/'); var snapSize = { defaults: { enabled: false, endOnly: false, range: Infinity, targets: null, offsets: null }, setOffset: function setOffset(arg) { var interaction = arg.interaction, options = arg.options; var edges = interaction.prepared.edges; if (!edges) { return; } arg.options = { relativePoints: [{ x: edges.left ? 0 : 1, y: edges.top ? 0 : 1 }], origin: { x: 0, y: 0 }, offset: 'self', range: options.range }; var offsets = snap.setOffset(arg); arg.options = options; return offsets; }, set: function set(arg) { var interaction = arg.interaction, options = arg.options, offset = arg.offset, modifiedCoords = arg.modifiedCoords; var page = utils.extend({}, modifiedCoords); var relativeX = page.x - offset[0].x; var relativeY = page.y - offset[0].y; arg.options = utils.extend({}, options); arg.options.targets = []; for (var _i = 0; _i < (options.targets || []).length; _i++) { var _ref; _ref = (options.targets || [])[_i]; var snapTarget = _ref; var target = void 0; if (utils.is.function(snapTarget)) { target = snapTarget(relativeX, relativeY, interaction); } else { target = snapTarget; } if (!target) { continue; } if ('width' in target && 'height' in target) { target.x = target.width; target.y = target.height; } arg.options.targets.push(target); } snap.set(arg); }, modifyCoords: function modifyCoords(arg) { var options = arg.options; arg.options = utils.extend({}, options); arg.options.enabled = options.enabled; arg.options.relativePoints = [null]; snap.modifyCoords(arg); } }; modifiers.snapSize = snapSize; modifiers.names.push('snapSize'); defaultOptions.perAction.snapSize = snapSize.defaults; resize.defaults.snapSize = snapSize.defaults; module.exports = snapSize; },{"../actions/resize":10,"../defaultOptions":18,"../utils/":44,"./base":23,"./snap":27}],29:[function(require,module,exports){ 'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var pointerUtils = require('../utils/pointerUtils'); module.exports = function () { /** */ function PointerEvent(type, pointer, event, eventTarget, interaction) { _classCallCheck(this, PointerEvent); pointerUtils.pointerExtend(this, event); if (event !== pointer) { pointerUtils.pointerExtend(this, pointer); } this.interaction = interaction; this.timeStamp = new Date().getTime(); this.originalEvent = event; this.type = type; this.pointerId = pointerUtils.getPointerId(pointer); this.pointerType = pointerUtils.getPointerType(pointer); this.target = eventTarget; this.currentTarget = null; if (type === 'tap') { var pointerIndex = interaction.getPointerIndex(pointer); this.dt = this.timeStamp - interaction.downTimes[pointerIndex]; var interval = this.timeStamp - interaction.tapTime; this.double = !!(interaction.prevTap && interaction.prevTap.type !== 'doubletap' && interaction.prevTap.target === this.target && interval < 500); } else if (type === 'doubletap') { this.dt = pointer.timeStamp - interaction.tapTime; } } PointerEvent.prototype.subtractOrigin = function subtractOrigin(_ref) { var originX = _ref.x, originY = _ref.y; this.pageX -= originX; this.pageY -= originY; this.clientX -= originX; this.clientY -= originY; return this; }; PointerEvent.prototype.addOrigin = function addOrigin(_ref2) { var originX = _ref2.x, originY = _ref2.y; this.pageX += originX; this.pageY += originY; this.clientX += originX; this.clientY += originY; return this; }; /** */ PointerEvent.prototype.preventDefault = function preventDefault() { this.originalEvent.preventDefault(); }; /** */ PointerEvent.prototype.stopPropagation = function stopPropagation() { this.propagationStopped = true; }; /** */ PointerEvent.prototype.stopImmediatePropagation = function stopImmediatePropagation() { this.immediatePropagationStopped = this.propagationStopped = true; }; return PointerEvent; }(); },{"../utils/pointerUtils":49}],30:[function(require,module,exports){ 'use strict'; var PointerEvent = require('./PointerEvent'); var Interaction = require('../Interaction'); var utils = require('../utils'); var defaults = require('../defaultOptions'); var signals = require('../utils/Signals').new(); var simpleSignals = ['down', 'up', 'cancel']; var simpleEvents = ['down', 'up', 'cancel']; var pointerEvents = { PointerEvent: PointerEvent, fire: fire, collectEventTargets: collectEventTargets, signals: signals, defaults: { holdDuration: 600, ignoreFrom: null, allowFrom: null, origin: { x: 0, y: 0 } }, types: ['down', 'move', 'up', 'cancel', 'tap', 'doubletap', 'hold'] }; function fire(arg) { var interaction = arg.interaction, pointer = arg.pointer, event = arg.event, eventTarget = arg.eventTarget, _arg$type = arg.type, type = _arg$type === undefined ? arg.pointerEvent.type : _arg$type, _arg$targets = arg.targets, targets = _arg$targets === undefined ? collectEventTargets(arg) : _arg$targets, _arg$pointerEvent = arg.pointerEvent, pointerEvent = _arg$pointerEvent === undefined ? new PointerEvent(type, pointer, event, eventTarget, interaction) : _arg$pointerEvent; var signalArg = { interaction: interaction, pointer: pointer, event: event, eventTarget: eventTarget, targets: targets, type: type, pointerEvent: pointerEvent }; for (var i = 0; i < targets.length; i++) { var target = targets[i]; for (var prop in target.props || {}) { pointerEvent[prop] = target.props[prop]; } var origin = utils.getOriginXY(target.eventable, target.element); pointerEvent.subtractOrigin(origin); pointerEvent.eventable = target.eventable; pointerEvent.currentTarget = target.element; target.eventable.fire(pointerEvent); pointerEvent.addOrigin(origin); if (pointerEvent.immediatePropagationStopped || pointerEvent.propagationStopped && i + 1 < targets.length && targets[i + 1].element !== pointerEvent.currentTarget) { break; } } signals.fire('fired', signalArg); if (type === 'tap') { // if pointerEvent should make a double tap, create and fire a doubletap // PointerEvent and use that as the prevTap var prevTap = pointerEvent.double ? fire({ interaction: interaction, pointer: pointer, event: event, eventTarget: eventTarget, type: 'doubletap' }) : pointerEvent; interaction.prevTap = prevTap; interaction.tapTime = prevTap.timeStamp; } return pointerEvent; } function collectEventTargets(_ref) { var interaction = _ref.interaction, pointer = _ref.pointer, event = _ref.event, eventTarget = _ref.eventTarget, type = _ref.type; var pointerIndex = interaction.getPointerIndex(pointer); // do not fire a tap event if the pointer was moved before being lifted if (type === 'tap' && (interaction.pointerWasMoved // or if the pointerup target is different to the pointerdown target || !(interaction.downTargets[pointerIndex] && interaction.downTargets[pointerIndex] === eventTarget))) { return []; } var path = utils.getPath(eventTarget); var signalArg = { interaction: interaction, pointer: pointer, event: event, eventTarget: eventTarget, type: type, path: path, targets: [], element: null }; for (var _i = 0; _i < path.length; _i++) { var _ref2; _ref2 = path[_i]; var element = _ref2; signalArg.element = element; signals.fire('collect-targets', signalArg); } if (type === 'hold') { signalArg.targets = signalArg.targets.filter(function (target) { return target.eventable.options.holdDuration === interaction.holdTimers[pointerIndex].duration; }); } return signalArg.targets; } Interaction.signals.on('update-pointer-down', function (_ref3) { var interaction = _ref3.interaction, pointerIndex = _ref3.pointerIndex; interaction.holdTimers[pointerIndex] = { duration: Infinity, timeout: null }; }); Interaction.signals.on('remove-pointer', function (_ref4) { var interaction = _ref4.interaction, pointerIndex = _ref4.pointerIndex; interaction.holdTimers.splice(pointerIndex, 1); }); Interaction.signals.on('move', function (_ref5) { var interaction = _ref5.interaction, pointer = _ref5.pointer, event = _ref5.event, eventTarget = _ref5.eventTarget, duplicateMove = _ref5.duplicateMove; var pointerIndex = interaction.getPointerIndex(pointer); if (!duplicateMove && (!interaction.pointerIsDown || interaction.pointerWasMoved)) { if (interaction.pointerIsDown) { clearTimeout(interaction.holdTimers[pointerIndex].timeout); } fire({ interaction: interaction, pointer: pointer, event: event, eventTarget: eventTarget, type: 'move' }); } }); Interaction.signals.on('down', function (_ref6) { var interaction = _ref6.interaction, pointer = _ref6.pointer, event = _ref6.event, eventTarget = _ref6.eventTarget, pointerIndex = _ref6.pointerIndex; var timer = interaction.holdTimers[pointerIndex]; var path = utils.getPath(eventTarget); var signalArg = { interaction: interaction, pointer: pointer, event: event, eventTarget: eventTarget, type: 'hold', targets: [], path: path, element: null }; for (var _i2 = 0; _i2 < path.length; _i2++) { var _ref7; _ref7 = path[_i2]; var element = _ref7; signalArg.element = element; signals.fire('collect-targets', signalArg); } if (!signalArg.targets.length) { return; } var minDuration = Infinity; for (var _i3 = 0; _i3 < signalArg.targets.length; _i3++) { var _ref8; _ref8 = signalArg.targets[_i3]; var target = _ref8; var holdDuration = target.eventable.options.holdDuration; if (holdDuration < minDuration) { minDuration = holdDuration; } } timer.duration = minDuration; timer.timeout = setTimeout(function () { fire({ interaction: interaction, eventTarget: eventTarget, pointer: pointer, event: event, type: 'hold' }); }, minDuration); }); Interaction.signals.on('up', function (_ref9) { var interaction = _ref9.interaction, pointer = _ref9.pointer, event = _ref9.event, eventTarget = _ref9.eventTarget; if (!interaction.pointerWasMoved) { fire({ interaction: interaction, eventTarget: eventTarget, pointer: pointer, event: event, type: 'tap' }); } }); var _arr = ['up', 'cancel']; for (var _i4 = 0; _i4 < _arr.length; _i4++) { var signalName = _arr[_i4]; Interaction.signals.on(signalName, function (_ref11) { var interaction = _ref11.interaction, pointerIndex = _ref11.pointerIndex; if (interaction.holdTimers[pointerIndex]) { clearTimeout(interaction.holdTimers[pointerIndex].timeout); } }); } function createSignalListener(type) { return function (_ref10) { var interaction = _ref10.interaction, pointer = _ref10.pointer, event = _ref10.event, eventTarget = _ref10.eventTarget; fire({ interaction: interaction, eventTarget: eventTarget, pointer: pointer, event: event, type: type }); }; } for (var i = 0; i < simpleSignals.length; i++) { Interaction.signals.on(simpleSignals[i], createSignalListener(simpleEvents[i])); } Interaction.signals.on('new', function (interaction) { interaction.prevTap = null; // the most recent tap event on this interaction interaction.tapTime = 0; // time of the most recent tap event interaction.holdTimers = []; // [{ duration, timeout }] }); defaults.pointerEvents = pointerEvents.defaults; module.exports = pointerEvents; },{"../Interaction":5,"../defaultOptions":18,"../utils":44,"../utils/Signals":34,"./PointerEvent":29}],31:[function(require,module,exports){ 'use strict'; var pointerEvents = require('./base'); var Interaction = require('../Interaction'); pointerEvents.signals.on('new', onNew); pointerEvents.signals.on('fired', onFired); var _arr = ['move', 'up', 'cancel', 'endall']; for (var _i = 0; _i < _arr.length; _i++) { var signal = _arr[_i]; Interaction.signals.on(signal, endHoldRepeat); } function onNew(_ref) { var pointerEvent = _ref.pointerEvent; if (pointerEvent.type !== 'hold') { return; } pointerEvent.count = (pointerEvent.count || 0) + 1; } function onFired(_ref2) { var interaction = _ref2.interaction, pointerEvent = _ref2.pointerEvent, eventTarget = _ref2.eventTarget, targets = _ref2.targets; if (pointerEvent.type !== 'hold' || !targets.length) { return; } // get the repeat interval from the first eventable var interval = targets[0].eventable.options.holdRepeatInterval; // don't repeat if the interval is 0 or less if (interval <= 0) { return; } // set a timeout to fire the holdrepeat event interaction.holdIntervalHandle = setTimeout(function () { pointerEvents.fire({ interaction: interaction, eventTarget: eventTarget, type: 'hold', pointer: pointerEvent, event: pointerEvent }); }, interval); } function endHoldRepeat(_ref3) { var interaction = _ref3.interaction; // set the interaction's holdStopTime property // to stop further holdRepeat events if (interaction.holdIntervalHandle) { clearInterval(interaction.holdIntervalHandle); interaction.holdIntervalHandle = null; } } // don't repeat by default pointerEvents.defaults.holdRepeatInterval = 0; pointerEvents.types.push('holdrepeat'); module.exports = { onNew: onNew, onFired: onFired, endHoldRepeat: endHoldRepeat }; },{"../Interaction":5,"./base":30}],32:[function(require,module,exports){ 'use strict'; var pointerEvents = require('./base'); var Interactable = require('../Interactable'); var is = require('../utils/is'); var scope = require('../scope'); var extend = require('../utils/extend'); var _require = require('../utils/arr'), merge = _require.merge; pointerEvents.signals.on('collect-targets', function (_ref) { var targets = _ref.targets, element = _ref.element, type = _ref.type, eventTarget = _ref.eventTarget; scope.interactables.forEachMatch(element, function (interactable) { var eventable = interactable.events; var options = eventable.options; if (eventable[type] && is.element(element) && interactable.testIgnoreAllow(options, element, eventTarget)) { targets.push({ element: element, eventable: eventable, props: { interactable: interactable } }); } }); }); Interactable.signals.on('new', function (_ref2) { var interactable = _ref2.interactable; interactable.events.getRect = function (element) { return interactable.getRect(element); }; }); Interactable.signals.on('set', function (_ref3) { var interactable = _ref3.interactable, options = _ref3.options; extend(interactable.events.options, pointerEvents.defaults); extend(interactable.events.options, options); }); merge(Interactable.eventTypes, pointerEvents.types); Interactable.prototype.pointerEvents = function (options) { extend(this.events.options, options); return this; }; var __backCompatOption = Interactable.prototype._backCompatOption; Interactable.prototype._backCompatOption = function (optionName, newValue) { var ret = __backCompatOption.call(this, optionName, newValue); if (ret === this) { this.events.options[optionName] = newValue; } return ret; }; Interactable.settingsMethods.push('pointerEvents'); },{"../Interactable":4,"../scope":33,"../utils/arr":35,"../utils/extend":41,"../utils/is":46,"./base":30}],33:[function(require,module,exports){ 'use strict'; var utils = require('./utils'); var events = require('./utils/events'); var signals = require('./utils/Signals').new(); var _require = require('./utils/window'), getWindow = _require.getWindow; var scope = { signals: signals, events: events, utils: utils, // main document document: require('./utils/domObjects').document, // all documents being listened to documents: [], addDocument: function addDocument(doc, win) { // do nothing if document is already known if (utils.contains(scope.documents, doc)) { return false; } win = win || getWindow(doc); scope.documents.push(doc); events.documents.push(doc); // don't add an unload event for the main document // so that the page may be cached in browser history if (doc !== scope.document) { events.add(win, 'unload', scope.onWindowUnload); } signals.fire('add-document', { doc: doc, win: win }); }, removeDocument: function removeDocument(doc, win) { var index = scope.documents.indexOf(doc); win = win || getWindow(doc); events.remove(win, 'unload', scope.onWindowUnload); scope.documents.splice(index, 1); events.documents.splice(index, 1); signals.fire('remove-document', { win: win, doc: doc }); }, onWindowUnload: function onWindowUnload() { scope.removeDocument(this.document, this); } }; module.exports = scope; },{"./utils":44,"./utils/Signals":34,"./utils/domObjects":38,"./utils/events":40,"./utils/window":52}],34:[function(require,module,exports){ "use strict"; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Signals = function () { function Signals() { _classCallCheck(this, Signals); this.listeners = { // signalName: [listeners], }; } Signals.prototype.on = function on(name, listener) { if (!this.listeners[name]) { this.listeners[name] = [listener]; return; } this.listeners[name].push(listener); }; Signals.prototype.off = function off(name, listener) { if (!this.listeners[name]) { return; } var index = this.listeners[name].indexOf(listener); if (index !== -1) { this.listeners[name].splice(index, 1); } }; Signals.prototype.fire = function fire(name, arg) { var targetListeners = this.listeners[name]; if (!targetListeners) { return; } for (var _i = 0; _i < targetListeners.length; _i++) { var _ref; _ref = targetListeners[_i]; var listener = _ref; if (listener(arg, name) === false) { return; } } }; return Signals; }(); Signals.new = function () { return new Signals(); }; module.exports = Signals; },{}],35:[function(require,module,exports){ "use strict"; function contains(array, target) { return array.indexOf(target) !== -1; } function merge(target, source) { for (var _i = 0; _i < source.length; _i++) { var _ref; _ref = source[_i]; var item = _ref; target.push(item); } return target; } module.exports = { contains: contains, merge: merge }; },{}],36:[function(require,module,exports){ 'use strict'; var _require = require('./window'), window = _require.window; var is = require('./is'); var domObjects = require('./domObjects'); var Element = domObjects.Element; var navigator = window.navigator; var browser = { // Does the browser support touch input? supportsTouch: !!('ontouchstart' in window || is.function(window.DocumentTouch) && domObjects.document instanceof window.DocumentTouch), // Does the browser support PointerEvents supportsPointerEvent: !!domObjects.PointerEvent, isIOS: /iP(hone|od|ad)/.test(navigator.platform), // scrolling doesn't change the result of getClientRects on iOS 7 isIOS7: /iP(hone|od|ad)/.test(navigator.platform) && /OS 7[^\d]/.test(navigator.appVersion), isIe9: /MSIE 9/.test(navigator.userAgent), // prefix matchesSelector prefixedMatchesSelector: 'matches' in Element.prototype ? 'matches' : 'webkitMatchesSelector' in Element.prototype ? 'webkitMatchesSelector' : 'mozMatchesSelector' in Element.prototype ? 'mozMatchesSelector' : 'oMatchesSelector' in Element.prototype ? 'oMatchesSelector' : 'msMatchesSelector', pEventTypes: domObjects.PointerEvent ? domObjects.PointerEvent === window.MSPointerEvent ? { up: 'MSPointerUp', down: 'MSPointerDown', over: 'mouseover', out: 'mouseout', move: 'MSPointerMove', cancel: 'MSPointerCancel' } : { up: 'pointerup', down: 'pointerdown', over: 'pointerover', out: 'pointerout', move: 'pointermove', cancel: 'pointercancel' } : null, // because Webkit and Opera still use 'mousewheel' event type wheelEvent: 'onmousewheel' in domObjects.document ? 'mousewheel' : 'wheel' }; // Opera Mobile must be handled differently browser.isOperaMobile = navigator.appName === 'Opera' && browser.supportsTouch && navigator.userAgent.match('Presto'); module.exports = browser; },{"./domObjects":38,"./is":46,"./window":52}],37:[function(require,module,exports){ 'use strict'; var is = require('./is'); module.exports = function clone(source) { var dest = {}; for (var prop in source) { if (is.plainObject(source[prop])) { dest[prop] = clone(source[prop]); } else { dest[prop] = source[prop]; } } return dest; }; },{"./is":46}],38:[function(require,module,exports){ 'use strict'; var domObjects = {}; var win = require('./window').window; function blank() {} domObjects.document = win.document; domObjects.DocumentFragment = win.DocumentFragment || blank; domObjects.SVGElement = win.SVGElement || blank; domObjects.SVGSVGElement = win.SVGSVGElement || blank; domObjects.SVGElementInstance = win.SVGElementInstance || blank; domObjects.Element = win.Element || blank; domObjects.HTMLElement = win.HTMLElement || domObjects.Element; domObjects.Event = win.Event; domObjects.Touch = win.Touch || blank; domObjects.PointerEvent = win.PointerEvent || win.MSPointerEvent; module.exports = domObjects; },{"./window":52}],39:[function(require,module,exports){ 'use strict'; var win = require('./window'); var browser = require('./browser'); var is = require('./is'); var domObjects = require('./domObjects'); var domUtils = { nodeContains: function nodeContains(parent, child) { while (child) { if (child === parent) { return true; } child = child.parentNode; } return false; }, closest: function closest(element, selector) { while (is.element(element)) { if (domUtils.matchesSelector(element, selector)) { return element; } element = domUtils.parentNode(element); } return null; }, parentNode: function parentNode(node) { var parent = node.parentNode; if (is.docFrag(parent)) { // skip past #shado-root fragments while ((parent = parent.host) && is.docFrag(parent)) { continue; } return parent; } return parent; }, matchesSelector: function matchesSelector(element, selector) { // remove /deep/ from selectors if shadowDOM polyfill is used if (win.window !== win.realWindow) { selector = selector.replace(/\/deep\//g, ' '); } return element[browser.prefixedMatchesSelector](selector); }, // Test for the element that's "above" all other qualifiers indexOfDeepestElement: function indexOfDeepestElement(elements) { var deepestZoneParents = []; var dropzoneParents = []; var dropzone = void 0; var deepestZone = elements[0]; var index = deepestZone ? 0 : -1; var parent = void 0; var child = void 0; var i = void 0; var n = void 0; for (i = 1; i < elements.length; i++) { dropzone = elements[i]; // an element might belong to multiple selector dropzones if (!dropzone || dropzone === deepestZone) { continue; } if (!deepestZone) { deepestZone = dropzone; index = i; continue; } // check if the deepest or current are document.documentElement or document.rootElement // - if the current dropzone is, do nothing and continue if (dropzone.parentNode === dropzone.ownerDocument) { continue; } // - if deepest is, update with the current dropzone and continue to next else if (deepestZone.parentNode === dropzone.ownerDocument) { deepestZone = dropzone; index = i; continue; } if (!deepestZoneParents.length) { parent = deepestZone; while (parent.parentNode && parent.parentNode !== parent.ownerDocument) { deepestZoneParents.unshift(parent); parent = parent.parentNode; } } // if this element is an svg element and the current deepest is // an HTMLElement if (deepestZone instanceof domObjects.HTMLElement && dropzone instanceof domObjects.SVGElement && !(dropzone instanceof domObjects.SVGSVGElement)) { if (dropzone === deepestZone.parentNode) { continue; } parent = dropzone.ownerSVGElement; } else { parent = dropzone; } dropzoneParents = []; while (parent.parentNode !== parent.ownerDocument) { dropzoneParents.unshift(parent); parent = parent.parentNode; } n = 0; // get (position of last common ancestor) + 1 while (dropzoneParents[n] && dropzoneParents[n] === deepestZoneParents[n]) { n++; } var parents = [dropzoneParents[n - 1], dropzoneParents[n], deepestZoneParents[n]]; child = parents[0].lastChild; while (child) { if (child === parents[1]) { deepestZone = dropzone; index = i; deepestZoneParents = []; break; } else if (child === parents[2]) { break; } child = child.previousSibling; } } return index; }, matchesUpTo: function matchesUpTo(element, selector, limit) { while (is.element(element)) { if (domUtils.matchesSelector(element, selector)) { return true; } element = domUtils.parentNode(element); if (element === limit) { return domUtils.matchesSelector(element, selector); } } return false; }, getActualElement: function getActualElement(element) { return element instanceof domObjects.SVGElementInstance ? element.correspondingUseElement : element; }, getScrollXY: function getScrollXY(relevantWindow) { relevantWindow = relevantWindow || win.window; return { x: relevantWindow.scrollX || relevantWindow.document.documentElement.scrollLeft, y: relevantWindow.scrollY || relevantWindow.document.documentElement.scrollTop }; }, getElementClientRect: function getElementClientRect(element) { var clientRect = element instanceof domObjects.SVGElement ? element.getBoundingClientRect() : element.getClientRects()[0]; return clientRect && { left: clientRect.left, right: clientRect.right, top: clientRect.top, bottom: clientRect.bottom, width: clientRect.width || clientRect.right - clientRect.left, height: clientRect.height || clientRect.bottom - clientRect.top }; }, getElementRect: function getElementRect(element) { var clientRect = domUtils.getElementClientRect(element); if (!browser.isIOS7 && clientRect) { var scroll = domUtils.getScrollXY(win.getWindow(element)); clientRect.left += scroll.x; clientRect.right += scroll.x; clientRect.top += scroll.y; clientRect.bottom += scroll.y; } return clientRect; }, getPath: function getPath(element) { var path = []; while (element) { path.push(element); element = domUtils.parentNode(element); } return path; }, trySelector: function trySelector(value) { if (!is.string(value)) { return false; } // an exception will be raised if it is invalid domObjects.document.querySelector(value); return true; } }; module.exports = domUtils; },{"./browser":36,"./domObjects":38,"./is":46,"./window":52}],40:[function(require,module,exports){ 'use strict'; var is = require('./is'); var domUtils = require('./domUtils'); var pointerUtils = require('./pointerUtils'); var pExtend = require('./pointerExtend'); var _require = require('./window'), window = _require.window; var _require2 = require('./arr'), contains = _require2.contains; var elements = []; var targets = []; // { // type: { // selectors: ['selector', ...], // contexts : [document, ...], // listeners: [[listener, capture, passive], ...] // } // } var delegatedEvents = {}; var documents = []; var supportsOptions = function () { var supported = false; window.document.createElement('div').addEventListener('test', null, { get capture() { supported = true; } }); return supported; }(); function add(element, type, listener, optionalArg) { var options = getOptions(optionalArg); var elementIndex = elements.indexOf(element); var target = targets[elementIndex]; if (!target) { target = { events: {}, typeCount: 0 }; elementIndex = elements.push(element) - 1; targets.push(target); } if (!target.events[type]) { target.events[type] = []; target.typeCount++; } if (!contains(target.events[type], listener)) { element.addEventListener(type, listener, supportsOptions ? options : !!options.capture); target.events[type].push(listener); } } function remove(element, type, listener, optionalArg) { var options = getOptions(optionalArg); var elementIndex = elements.indexOf(element); var target = targets[elementIndex]; if (!target || !target.events) { return; } if (type === 'all') { for (type in target.events) { if (target.events.hasOwnProperty(type)) { remove(element, type, 'all'); } } return; } if (target.events[type]) { var len = target.events[type].length; if (listener === 'all') { for (var i = 0; i < len; i++) { remove(element, type, target.events[type][i], options); } return; } else { for (var _i = 0; _i < len; _i++) { if (target.events[type][_i] === listener) { element.removeEventListener('on' + type, listener, supportsOptions ? options : !!options.capture); target.events[type].splice(_i, 1); break; } } } if (target.events[type] && target.events[type].length === 0) { target.events[type] = null; target.typeCount--; } } if (!target.typeCount) { targets.splice(elementIndex, 1); elements.splice(elementIndex, 1); } } function addDelegate(selector, context, type, listener, optionalArg) { var options = getOptions(optionalArg); if (!delegatedEvents[type]) { delegatedEvents[type] = { selectors: [], contexts: [], listeners: [] }; // add delegate listener functions for (var _i2 = 0; _i2 < documents.length; _i2++) { var doc = documents[_i2]; add(doc, type, delegateListener); add(doc, type, delegateUseCapture, true); } } var delegated = delegatedEvents[type]; var index = void 0; for (index = delegated.selectors.length - 1; index >= 0; index--) { if (delegated.selectors[index] === selector && delegated.contexts[index] === context) { break; } } if (index === -1) { index = delegated.selectors.length; delegated.selectors.push(selector); delegated.contexts.push(context); delegated.listeners.push([]); } // keep listener and capture and passive flags delegated.listeners[index].push([listener, !!options.capture, options.passive]); } function removeDelegate(selector, context, type, listener, optionalArg) { var options = getOptions(optionalArg); var delegated = delegatedEvents[type]; var matchFound = false; var index = void 0; if (!delegated) { return; } // count from last index of delegated to 0 for (index = delegated.selectors.length - 1; index >= 0; index--) { // look for matching selector and context Node if (delegated.selectors[index] === selector && delegated.contexts[index] === context) { var listeners = delegated.listeners[index]; // each item of the listeners array is an array: [function, capture, passive] for (var i = listeners.length - 1; i >= 0; i--) { var _listeners$i = listeners[i], fn = _listeners$i[0], capture = _listeners$i[1], passive = _listeners$i[2]; // check if the listener functions and capture and passive flags match if (fn === listener && capture === !!options.capture && passive === options.passive) { // remove the listener from the array of listeners listeners.splice(i, 1); // if all listeners for this interactable have been removed // remove the interactable from the delegated arrays if (!listeners.length) { delegated.selectors.splice(index, 1); delegated.contexts.splice(index, 1); delegated.listeners.splice(index, 1); // remove delegate function from context remove(context, type, delegateListener); remove(context, type, delegateUseCapture, true); // remove the arrays if they are empty if (!delegated.selectors.length) { delegatedEvents[type] = null; } } // only remove one listener matchFound = true; break; } } if (matchFound) { break; } } } } // bound to the interactable context when a DOM event // listener is added to a selector interactable function delegateListener(event, optionalArg) { var options = getOptions(optionalArg); var fakeEvent = {}; var delegated = delegatedEvents[event.type]; var _pointerUtils$getEven = pointerUtils.getEventTargets(event), eventTarget = _pointerUtils$getEven[0]; var element = eventTarget; // duplicate the event so that currentTarget can be changed pExtend(fakeEvent, event); fakeEvent.originalEvent = event; fakeEvent.preventDefault = preventOriginalDefault; // climb up document tree looking for selector matches while (is.element(element)) { for (var i = 0; i < delegated.selectors.length; i++) { var selector = delegated.selectors[i]; var context = delegated.contexts[i]; if (domUtils.matchesSelector(element, selector) && domUtils.nodeContains(context, eventTarget) && domUtils.nodeContains(context, element)) { var listeners = delegated.listeners[i]; fakeEvent.currentTarget = element; for (var j = 0; j < listeners.length; j++) { var _listeners$j = listeners[j], fn = _listeners$j[0], capture = _listeners$j[1], passive = _listeners$j[2]; if (capture === !!options.capture && passive === options.passive) { fn(fakeEvent); } } } } element = domUtils.parentNode(element); } } function delegateUseCapture(event) { return delegateListener.call(this, event, true); } function preventOriginalDefault() { this.originalEvent.preventDefault(); } function getOptions(param) { return is.object(param) ? param : { capture: param }; } module.exports = { add: add, remove: remove, addDelegate: addDelegate, removeDelegate: removeDelegate, delegateListener: delegateListener, delegateUseCapture: delegateUseCapture, delegatedEvents: delegatedEvents, documents: documents, supportsOptions: supportsOptions, _elements: elements, _targets: targets }; },{"./arr":35,"./domUtils":39,"./is":46,"./pointerExtend":48,"./pointerUtils":49,"./window":52}],41:[function(require,module,exports){ "use strict"; module.exports = function extend(dest, source) { for (var prop in source) { dest[prop] = source[prop]; } return dest; }; },{}],42:[function(require,module,exports){ 'use strict'; var _require = require('./rect'), resolveRectLike = _require.resolveRectLike, rectToXY = _require.rectToXY; module.exports = function (target, element, action) { var actionOptions = target.options[action]; var actionOrigin = actionOptions && actionOptions.origin; var origin = actionOrigin || target.options.origin; var originRect = resolveRectLike(origin, target, element, [target && element]); return rectToXY(originRect) || { x: 0, y: 0 }; }; },{"./rect":51}],43:[function(require,module,exports){ "use strict"; module.exports = function (x, y) { return Math.sqrt(x * x + y * y); }; },{}],44:[function(require,module,exports){ 'use strict'; var extend = require('./extend'); var win = require('./window'); var utils = { warnOnce: function warnOnce(method, message) { var warned = false; return function () { if (!warned) { win.window.console.warn(message); warned = true; } return method.apply(this, arguments); }; }, // http://stackoverflow.com/a/5634528/2280888 _getQBezierValue: function _getQBezierValue(t, p1, p2, p3) { var iT = 1 - t; return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3; }, getQuadraticCurvePoint: function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) { return { x: utils._getQBezierValue(position, startX, cpX, endX), y: utils._getQBezierValue(position, startY, cpY, endY) }; }, // http://gizma.com/easing/ easeOutQuad: function easeOutQuad(t, b, c, d) { t /= d; return -c * t * (t - 2) + b; }, copyAction: function copyAction(dest, src) { dest.name = src.name; dest.axis = src.axis; dest.edges = src.edges; return dest; }, is: require('./is'), extend: extend, hypot: require('./hypot'), getOriginXY: require('./getOriginXY') }; extend(utils, require('./arr')); extend(utils, require('./domUtils')); extend(utils, require('./pointerUtils')); extend(utils, require('./rect')); module.exports = utils; },{"./arr":35,"./domUtils":39,"./extend":41,"./getOriginXY":42,"./hypot":43,"./is":46,"./pointerUtils":49,"./rect":51,"./window":52}],45:[function(require,module,exports){ 'use strict'; var scope = require('../scope'); var utils = require('./index'); var finder = { methodOrder: ['simulationResume', 'mouseOrPen', 'hasPointer', 'idle'], search: function search(pointer, eventType, eventTarget) { var pointerType = utils.getPointerType(pointer); var pointerId = utils.getPointerId(pointer); var details = { pointer: pointer, pointerId: pointerId, pointerType: pointerType, eventType: eventType, eventTarget: eventTarget }; for (var _i = 0; _i < finder.methodOrder.length; _i++) { var _ref; _ref = finder.methodOrder[_i]; var method = _ref; var interaction = finder[method](details); if (interaction) { return interaction; } } }, // try to resume simulation with a new pointer simulationResume: function simulationResume(_ref2) { var pointerType = _ref2.pointerType, eventType = _ref2.eventType, eventTarget = _ref2.eventTarget; if (!/down|start/i.test(eventType)) { return null; } for (var _i2 = 0; _i2 < scope.interactions.length; _i2++) { var _ref3; _ref3 = scope.interactions[_i2]; var interaction = _ref3; var element = eventTarget; if (interaction.simulation && interaction.simulation.allowResume && interaction.pointerType === pointerType) { while (element) { // if the element is the interaction element if (element === interaction.element) { return interaction; } element = utils.parentNode(element); } } } return null; }, // if it's a mouse or pen interaction mouseOrPen: function mouseOrPen(_ref4) { var pointerId = _ref4.pointerId, pointerType = _ref4.pointerType, eventType = _ref4.eventType; if (pointerType !== 'mouse' && pointerType !== 'pen') { return null; } var firstNonActive = void 0; for (var _i3 = 0; _i3 < scope.interactions.length; _i3++) { var _ref5; _ref5 = scope.interactions[_i3]; var interaction = _ref5; if (interaction.pointerType === pointerType) { // if it's a down event, skip interactions with running simulations if (interaction.simulation && !utils.contains(interaction.pointerIds, pointerId)) { continue; } // if the interaction is active, return it immediately if (interaction.interacting()) { return interaction; } // otherwise save it and look for another active interaction else if (!firstNonActive) { firstNonActive = interaction; } } } // if no active mouse interaction was found use the first inactive mouse // interaction if (firstNonActive) { return firstNonActive; } // find any mouse or pen interaction. // ignore the interaction if the eventType is a *down, and a simulation // is active for (var _i4 = 0; _i4 < scope.interactions.length; _i4++) { var _ref6; _ref6 = scope.interactions[_i4]; var _interaction = _ref6; if (_interaction.pointerType === pointerType && !(/down/i.test(eventType) && _interaction.simulation)) { return _interaction; } } return null; }, // get interaction that has this pointer hasPointer: function hasPointer(_ref7) { var pointerId = _ref7.pointerId; for (var _i5 = 0; _i5 < scope.interactions.length; _i5++) { var _ref8; _ref8 = scope.interactions[_i5]; var interaction = _ref8; if (utils.contains(interaction.pointerIds, pointerId)) { return interaction; } } }, // get first idle interaction with a matching pointerType idle: function idle(_ref9) { var pointerType = _ref9.pointerType; for (var _i6 = 0; _i6 < scope.interactions.length; _i6++) { var _ref10; _ref10 = scope.interactions[_i6]; var interaction = _ref10; // if there's already a pointer held down if (interaction.pointerIds.length === 1) { var target = interaction.target; // don't add this pointer if there is a target interactable and it // isn't gesturable if (target && !target.options.gesture.enabled) { continue; } } // maximum of 2 pointers per interaction else if (interaction.pointerIds.length >= 2) { continue; } if (!interaction.interacting() && pointerType === interaction.pointerType) { return interaction; } } return null; } }; module.exports = finder; },{"../scope":33,"./index":44}],46:[function(require,module,exports){ 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var win = require('./window'); var isWindow = require('./isWindow'); var is = { array: function array() {}, window: function window(thing) { return thing === win.window || isWindow(thing); }, docFrag: function docFrag(thing) { return is.object(thing) && thing.nodeType === 11; }, object: function object(thing) { return !!thing && (typeof thing === 'undefined' ? 'undefined' : _typeof(thing)) === 'object'; }, function: function _function(thing) { return typeof thing === 'function'; }, number: function number(thing) { return typeof thing === 'number'; }, bool: function bool(thing) { return typeof thing === 'boolean'; }, string: function string(thing) { return typeof thing === 'string'; }, element: function element(thing) { if (!thing || (typeof thing === 'undefined' ? 'undefined' : _typeof(thing)) !== 'object') { return false; } var _window = win.getWindow(thing) || win.window; return (/object|function/.test(_typeof(_window.Element)) ? thing instanceof _window.Element //DOM2 : thing.nodeType === 1 && typeof thing.nodeName === 'string' ); }, plainObject: function plainObject(thing) { return is.object(thing) && thing.constructor.name === 'Object'; } }; is.array = function (thing) { return is.object(thing) && typeof thing.length !== 'undefined' && is.function(thing.splice); }; module.exports = is; },{"./isWindow":47,"./window":52}],47:[function(require,module,exports){ "use strict"; module.exports = function (thing) { return !!(thing && thing.Window) && thing instanceof thing.Window; }; },{}],48:[function(require,module,exports){ 'use strict'; function pointerExtend(dest, source) { for (var prop in source) { var prefixedPropREs = module.exports.prefixedPropREs; var deprecated = false; // skip deprecated prefixed properties for (var vendor in prefixedPropREs) { if (prop.indexOf(vendor) === 0 && prefixedPropREs[vendor].test(prop)) { deprecated = true; break; } } if (!deprecated && typeof source[prop] !== 'function') { dest[prop] = source[prop]; } } return dest; } pointerExtend.prefixedPropREs = { webkit: /(Movement[XY]|Radius[XY]|RotationAngle|Force)$/ }; module.exports = pointerExtend; },{}],49:[function(require,module,exports){ 'use strict'; var hypot = require('./hypot'); var browser = require('./browser'); var dom = require('./domObjects'); var domUtils = require('./domUtils'); var domObjects = require('./domObjects'); var is = require('./is'); var pointerExtend = require('./pointerExtend'); var pointerUtils = { copyCoords: function copyCoords(dest, src) { dest.page = dest.page || {}; dest.page.x = src.page.x; dest.page.y = src.page.y; dest.client = dest.client || {}; dest.client.x = src.client.x; dest.client.y = src.client.y; dest.timeStamp = src.timeStamp; }, setCoordDeltas: function setCoordDeltas(targetObj, prev, cur) { targetObj.page.x = cur.page.x - prev.page.x; targetObj.page.y = cur.page.y - prev.page.y; targetObj.client.x = cur.client.x - prev.client.x; targetObj.client.y = cur.client.y - prev.client.y; targetObj.timeStamp = cur.timeStamp - prev.timeStamp; // set pointer velocity var dt = Math.max(targetObj.timeStamp / 1000, 0.001); targetObj.page.speed = hypot(targetObj.page.x, targetObj.page.y) / dt; targetObj.page.vx = targetObj.page.x / dt; targetObj.page.vy = targetObj.page.y / dt; targetObj.client.speed = hypot(targetObj.client.x, targetObj.page.y) / dt; targetObj.client.vx = targetObj.client.x / dt; targetObj.client.vy = targetObj.client.y / dt; }, isNativePointer: function isNativePointer(pointer) { return pointer instanceof dom.Event || pointer instanceof dom.Touch; }, // Get specified X/Y coords for mouse or event.touches[0] getXY: function getXY(type, pointer, xy) { xy = xy || {}; type = type || 'page'; xy.x = pointer[type + 'X']; xy.y = pointer[type + 'Y']; return xy; }, getPageXY: function getPageXY(pointer, page) { page = page || {}; // Opera Mobile handles the viewport and scrolling oddly if (browser.isOperaMobile && pointerUtils.isNativePointer(pointer)) { pointerUtils.getXY('screen', pointer, page); page.x += window.scrollX; page.y += window.scrollY; } else { pointerUtils.getXY('page', pointer, page); } return page; }, getClientXY: function getClientXY(pointer, client) { client = client || {}; if (browser.isOperaMobile && pointerUtils.isNativePointer(pointer)) { // Opera Mobile handles the viewport and scrolling oddly pointerUtils.getXY('screen', pointer, client); } else { pointerUtils.getXY('client', pointer, client); } return client; }, getPointerId: function getPointerId(pointer) { return is.number(pointer.pointerId) ? pointer.pointerId : pointer.identifier; }, setCoords: function setCoords(targetObj, pointers, timeStamp) { var pointer = pointers.length > 1 ? pointerUtils.pointerAverage(pointers) : pointers[0]; var tmpXY = {}; pointerUtils.getPageXY(pointer, tmpXY); targetObj.page.x = tmpXY.x; targetObj.page.y = tmpXY.y; pointerUtils.getClientXY(pointer, tmpXY); targetObj.client.x = tmpXY.x; targetObj.client.y = tmpXY.y; targetObj.timeStamp = is.number(timeStamp) ? timeStamp : new Date().getTime(); }, pointerExtend: pointerExtend, getTouchPair: function getTouchPair(event) { var touches = []; // array of touches is supplied if (is.array(event)) { touches[0] = event[0]; touches[1] = event[1]; } // an event else { if (event.type === 'touchend') { if (event.touches.length === 1) { touches[0] = event.touches[0]; touches[1] = event.changedTouches[0]; } else if (event.touches.length === 0) { touches[0] = event.changedTouches[0]; touches[1] = event.changedTouches[1]; } } else { touches[0] = event.touches[0]; touches[1] = event.touches[1]; } } return touches; }, pointerAverage: function pointerAverage(pointers) { var average = { pageX: 0, pageY: 0, clientX: 0, clientY: 0, screenX: 0, screenY: 0 }; for (var _i = 0; _i < pointers.length; _i++) { var _ref; _ref = pointers[_i]; var pointer = _ref; for (var _prop in average) { average[_prop] += pointer[_prop]; } } for (var prop in average) { average[prop] /= pointers.length; } return average; }, touchBBox: function touchBBox(event) { if (!event.length && !(event.touches && event.touches.length > 1)) { return; } var touches = pointerUtils.getTouchPair(event); var minX = Math.min(touches[0].pageX, touches[1].pageX); var minY = Math.min(touches[0].pageY, touches[1].pageY); var maxX = Math.max(touches[0].pageX, touches[1].pageX); var maxY = Math.max(touches[0].pageY, touches[1].pageY); return { x: minX, y: minY, left: minX, top: minY, width: maxX - minX, height: maxY - minY }; }, touchDistance: function touchDistance(event, deltaSource) { var sourceX = deltaSource + 'X'; var sourceY = deltaSource + 'Y'; var touches = pointerUtils.getTouchPair(event); var dx = touches[0][sourceX] - touches[1][sourceX]; var dy = touches[0][sourceY] - touches[1][sourceY]; return hypot(dx, dy); }, touchAngle: function touchAngle(event, prevAngle, deltaSource) { var sourceX = deltaSource + 'X'; var sourceY = deltaSource + 'Y'; var touches = pointerUtils.getTouchPair(event); var dx = touches[1][sourceX] - touches[0][sourceX]; var dy = touches[1][sourceY] - touches[0][sourceY]; var angle = 180 * Math.atan2(dy, dx) / Math.PI; return angle; }, getPointerType: function getPointerType(pointer) { return is.string(pointer.pointerType) ? pointer.pointerType : is.number(pointer.pointerType) ? [undefined, undefined, 'touch', 'pen', 'mouse'][pointer.pointerType] // if the PointerEvent API isn't available, then the "pointer" must // be either a MouseEvent, TouchEvent, or Touch object : /touch/.test(pointer.type) || pointer instanceof domObjects.Touch ? 'touch' : 'mouse'; }, // [ event.target, event.currentTarget ] getEventTargets: function getEventTargets(event) { var path = is.function(event.composedPath) ? event.composedPath() : event.path; return [domUtils.getActualElement(path ? path[0] : event.target), domUtils.getActualElement(event.currentTarget)]; } }; module.exports = pointerUtils; },{"./browser":36,"./domObjects":38,"./domUtils":39,"./hypot":43,"./is":46,"./pointerExtend":48}],50:[function(require,module,exports){ 'use strict'; var _require = require('./window'), window = _require.window; var vendors = ['ms', 'moz', 'webkit', 'o']; var lastTime = 0; var request = void 0; var cancel = void 0; for (var x = 0; x < vendors.length && !window.requestAnimationFrame; x++) { request = window[vendors[x] + 'RequestAnimationFrame']; cancel = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame']; } if (!request) { request = function request(callback) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = setTimeout(function () { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; } if (!cancel) { cancel = function cancel(id) { clearTimeout(id); }; } module.exports = { request: request, cancel: cancel }; },{"./window":52}],51:[function(require,module,exports){ 'use strict'; var extend = require('./extend'); var is = require('./is'); var _require = require('./domUtils'), closest = _require.closest, parentNode = _require.parentNode, getElementRect = _require.getElementRect; var rectUtils = { getStringOptionResult: function getStringOptionResult(value, interactable, element) { if (!is.string(value)) { return null; } if (value === 'parent') { value = parentNode(element); } else if (value === 'self') { value = interactable.getRect(element); } else { value = closest(element, value); } return value; }, resolveRectLike: function resolveRectLike(value, interactable, element, functionArgs) { value = rectUtils.getStringOptionResult(value, interactable, element) || value; if (is.function(value)) { value = value.apply(null, functionArgs); } if (is.element(value)) { value = getElementRect(value); } return value; }, rectToXY: function rectToXY(rect) { return rect && { x: 'x' in rect ? rect.x : rect.left, y: 'y' in rect ? rect.y : rect.top }; }, xywhToTlbr: function xywhToTlbr(rect) { if (rect && !('left' in rect && 'top' in rect)) { rect = extend({}, rect); rect.left = rect.x || 0; rect.top = rect.y || 0; rect.right = rect.right || rect.left + rect.width; rect.bottom = rect.bottom || rect.top + rect.height; } return rect; }, tlbrToXywh: function tlbrToXywh(rect) { if (rect && !('x' in rect && 'y' in rect)) { rect = extend({}, rect); rect.x = rect.left || 0; rect.top = rect.top || 0; rect.width = rect.width || rect.right - rect.x; rect.height = rect.height || rect.bottom - rect.y; } return rect; } }; module.exports = rectUtils; },{"./domUtils":39,"./extend":41,"./is":46}],52:[function(require,module,exports){ 'use strict'; var win = module.exports; var isWindow = require('./isWindow'); function init(window) { // get wrapped window if using Shadow DOM polyfill win.realWindow = window; // create a TextNode var el = window.document.createTextNode(''); // check if it's wrapped by a polyfill if (el.ownerDocument !== window.document && typeof window.wrap === 'function' && window.wrap(el) === el) { // use wrapped window window = window.wrap(window); } win.window = window; } if (typeof window === 'undefined') { win.window = undefined; win.realWindow = undefined; } else { init(window); } win.getWindow = function getWindow(node) { if (isWindow(node)) { return node; } var rootNode = node.ownerDocument || node; return rootNode.defaultView || rootNode.parentWindow || win.window; }; win.init = init; },{"./isWindow":47}]},{},[1])(1) }); //# sourceMappingURL=interact.js.map