<!DOCTYPE html>
<html>
<head>
<script
src="https://code.jquery.com/jquery-3.2.1.js"
integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE="
crossorigin="anonymous"></script>
<!-- <script src="//cdnjs.cloudflare.com/ajax/libs/interact.js/1.2.9/interact.min.js"></script> -->
<link rel="stylesheet" href="style.css" />
<script src="interact.js"></script>
</head>
<body>
<div id="scroll-container">
<div id="resize-container">
<div class="resizable" id="firstResizable">resize me<div class="resize-handle"></div></div>
<div class="resizable" style="left: 200px">resize me<div class="resize-handle"></div></div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
interact('.resizable')
.draggable({})
.resizable({
preserveAspectRatio: false,
edges: {
left: true,
right: '.resize-handle',
bottom: '.resize-handle',
top: true
}
})
.on('dragstart', function (event) {
event.preventDefault();
})
.on('dragmove', dragMoveListener)
.on('resizestart', function(event) {
console.info('resizestart = ', event);
})
.on('resizemove', function(event) {
console.info('resizemove = ', event);
var target = event.target,
x = (parseFloat(target.getAttribute('data-x')) || 0),
y = (parseFloat(target.getAttribute('data-y')) || 0);
// update the element's style
target.style.width = event.rect.width + 'px';
target.style.height = event.rect.height + 'px';
// translate when resizing from top or left edges
x += event.deltaRect.left;
y += event.deltaRect.top;
target.style.webkitTransform = target.style.transform =
'translate(' + x + 'px,' + y + 'px)';
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
});
function dragMoveListener(event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
.resizable {
position: absolute;
width: 100px;
height: 100px;
background-color: #aaf;
padding: 1em;
border-radius: 5px;
margin: 3em;
box-sizing: border-box;
user-select: none;
}
.resize-handle {
position: absolute;
width: 30px;
height: 30px;
background-color: blue;
right: 0;
bottom: 0;
}
#resize-container {
position: relative;
top: 0;
left: 0;
width: 1500px;
height: 1400px;
background-color: #eee;
touch-action: manipulation;
}
#scroll-container {
position: absolute;
top: 0;
left: 0;
width: 500px;
height: 400px;
overflow: scroll;
background-color: #eee;
touch-action: manipulation;
}
/**
* interact.js v1.3.0-alpha.4+sha.7970416-dirty
*
* Copyright (c) 2012-2017 Taye Adeyemi <dev@taye.me>
* Open source 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<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
/*
* In a (windowless) server environment this file exports a factory function
* that takes the window to use.
*
* var interact = require('interact.js')(windowObject);
*
* See https://github.com/taye/interact.js/issues/187
*/
if (typeof window === 'undefined') {
module.exports = function (window) {
require('./src/utils/window').init(window);
return require('./src/index');
};
} else {
module.exports = require('./src/index');
}
},{"./src/index":19,"./src/utils/window":52}],2:[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 _require = require('./utils/arr'),
indexOf = _require.indexOf;
var extend = require('./utils/extend.js');
function fireUntilImmediateStopped(event, listeners) {
for (var i = 0, len = listeners.length; i < len && !event.immediatePropagationStopped; i++) {
listeners[i](event);
}
}
var Eventable = function () {
function Eventable(options) {
_classCallCheck(this, Eventable);
this.options = extend({}, options || {});
}
Eventable.prototype.fire = function fire(event) {
var listeners = void 0;
var onEvent = 'on' + event.type;
var global = this.global;
// Interactable#on() listeners
if (listeners = this[event.type]) {
fireUntilImmediateStopped(event, listeners);
}
// interactable.onevent listener
if (this[onEvent]) {
this[onEvent](event);
}
// interact.on() listeners
if (!event.propagationStopped && global && (listeners = global[event.type])) {
fireUntilImmediateStopped(event, listeners);
}
};
Eventable.prototype.on = function on(eventType, listener) {
// if this type of event was never bound
if (this[eventType]) {
this[eventType].push(listener);
} else {
this[eventType] = [listener];
}
};
Eventable.prototype.off = function off(eventType, listener) {
// if it is an action event type
var eventList = this[eventType];
var index = eventList ? indexOf(eventList, listener) : -1;
if (index !== -1) {
eventList.splice(index, 1);
}
if (eventList && eventList.length === 0 || !listener) {
this[eventType] = listener;
}
};
return Eventable;
}();
module.exports = Eventable;
},{"./utils/arr":36,"./utils/extend.js":41}],3:[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 extend = require('./utils/extend');
var getOriginXY = require('./utils/getOriginXY');
var defaults = require('./defaultOptions');
var signals = require('./utils/Signals').new();
var InteractEvent = function () {
function InteractEvent(interaction, event, action, phase, element, related) {
var preEnd = arguments.length > 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":35,"./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 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;
var _require2 = require('./utils/window'),
getWindow = _require2.getWindow;
var _require3 = require('./utils/arr'),
indexOf = _require3.indexOf,
contains = _require3.contains;
var _require4 = require('./utils/browser'),
wheelEvent = _require4.wheelEvent;
// all set interactables
scope.interactables = [];
/*\
* Interactable
[ property ]
**
* Object type returned by @interact
\*/
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
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];
}
}
}
};
/*\
* Interactable.getRect
[ method ]
*
* The default function to get an Interactables bounding rect. Can be
* overridden using @Interactable.rectChecker.
*
- element (Element) #optional The element to measure.
= (object) The object's bounding rectangle.
o {
o top : 0,
o left : 0,
o bottom: 0,
o right : 0,
o width : 0,
o height: 0
o }
\*/
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);
};
/*\
* Interactable.rectChecker
[ method ]
*
* Returns or sets the function used to calculate the interactable's
* element's rectangle
*
- checker (function) #optional A function which returns this Interactable's bounding rectangle. See @Interactable.getRect
= (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 _iterator = actions.names, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var action = _ref;
this.options[action][optionName] = newValue;
}
return this;
}
return this.options[optionName];
};
/*\
* Interactable.origin
[ method ]
*
* Gets or sets the origin of the Interactable's element. The x and y
* of the origin will be subtracted from action event coordinates.
*
- origin (object | string) #optional An object eg. { x: 0, y: 0 } or string 'parent', 'self' or any CSS selector
* OR
- origin (Element) #optional An HTML or SVG Element whose rect will be used
**
= (object) The current origin or this Interactable
\*/
Interactable.prototype.origin = function origin(newValue) {
return this._backCompatOption('origin', newValue);
};
/*\
* Interactable.deltaSource
[ method ]
*
* Returns or sets the mouse coordinate types used to calculate the
* movement of the pointer.
*
- newValue (string) #optional Use 'client' if you will be scrolling while interacting; Use 'page' if you want autoScroll to work
= (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;
};
/*\
* Interactable.context
[ method ]
*
* Gets the selector context Node of the Interactable. The default is `window.document`.
*
= (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);
};
/*\
* Interactable.fire
[ method ]
*
* Calls listeners for the given InteractEvent type bound globally
* and directly to this Interactable
*
- iEvent (InteractEvent) The InteractEvent object to be fired on this Interactable
= (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 i = 0; i < eventType.length; i++) {
this[method](eventType[i], listener, options);
}
return true;
}
if (is.object(eventType)) {
for (var prop in eventType) {
this[method](prop, eventType[prop], listener);
}
return true;
}
};
/*\
* Interactable.on
[ method ]
*
* Binds a listener for an InteractEvent, pointerEvent or DOM event.
*
- eventType (string | array | object) The types of events to listen for
- listener (function) The function event (s)
- options (object | boolean) #optional options object or useCapture flag for addEventListener
= (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;
};
/*\
* Interactable.off
[ method ]
*
* Removes an InteractEvent, pointerEvent or DOM event listener
*
- eventType (string | array | object) The types of events that were listened for
- listener (function) The listener function to be removed
- options (object | boolean) #optional options object or useCapture flag for removeEventListener
= (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;
};
/*\
* Interactable.set
[ method ]
*
* Reset the options of this Interactable
- options (object) The new settings to apply
= (object) This Interactable
\*/
Interactable.prototype.set = function set(options) {
if (!is.object(options)) {
options = {};
}
this.options = extend({}, defaults.base);
var perActions = extend({}, defaults.perAction);
for (var actionName in actions.methodDict) {
var methodName = actions.methodDict[actionName];
this.options[actionName] = extend({}, defaults[actionName]);
this.setPerAction(actionName, perActions);
this[methodName](options[actionName]);
}
for (var _iterator2 = Interactable.settingsMethods, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref2;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref2 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref2 = _i2.value;
}
var setting = _ref2;
this.options[setting] = defaults.base[setting];
if (setting in options) {
this[setting](options[setting]);
}
}
signals.fire('set', {
options: options,
interactable: this
});
return this;
};
/*\
* Interactable.unset
[ method ]
*
* Remove this interactable from the list of interactables and remove
* it's action capabilities and event listeners
*
= (object) @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(indexOf(scope.interactables, this), 1);
// Stop related interactions when an Interactable is unset
for (var _iterator3 = scope.interactions || [], _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
var _ref3;
if (_isArray3) {
if (_i3 >= _iterator3.length) break;
_ref3 = _iterator3[_i3++];
} else {
_i3 = _iterator3.next();
if (_i3.done) break;
_ref3 = _i3.value;
}
var interaction = _ref3;
if (interaction.target === this && interaction.interacting()) {
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.forEachSelector = function (callback, element) {
for (var i = 0; i < this.length; i++) {
var interactable = this[i];
// skip non CSS selector targets and out of context elements
if (!is.string(interactable.target) || element && !interactable.inContext(element)) {
continue;
}
var ret = callback(interactable, interactable.target, interactable._context, i, this);
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":34,"./utils/Signals":35,"./utils/arr":36,"./utils/browser":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.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
});
};
/*\
* Interaction.start
[ method ]
*
* 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.<action>able({ manualStart: false })` to always
* [start actions manually](https://github.com/taye/interact.js/issues/114)
*
- action (object) The action to be performed - drag, resize, etc.
- target (Interactable) The Interactable to target
- element (Element) The DOM Element to target
= (object) interact
**
| 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);
| }
| });
\*/
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 (utils.indexOf(scope.interactions, 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);
}
}
};
/*\
* Interaction.doMove
[ method ]
*
* 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.
*
**
| 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();
| }
| });
\*/
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);
};
/*\
* Interaction.end
[ method ]
*
* Stop the current action and fire an end event. Inertial movement does
* not happen.
*
- event (PointerEvent) #optional
**
| 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();
| }
| });
\*/
Interaction.prototype.end = function end(event) {
event = event || this.prevEvent;
if (this.interacting()) {
signals.fire('action-end', {
event: event,
interaction: this
});
}
this.stop();
};
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 utils.indexOf(this.pointerIds, 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, len = methodNames.length; i < len; 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 _i = 0; _i < event.changedTouches.length; _i++) {
var pointer = event.changedTouches[_i];
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 _i2 = 0; _i2 < scope.interactions.length && !invalidPointer; _i2++) {
invalidPointer = scope.interactions[_i2].pointerType !== 'mouse' && scope.interactions[_i2].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 _iterator = matches, _isArray = Array.isArray(_iterator), _i3 = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref2;
if (_isArray) {
if (_i3 >= _iterator.length) break;
_ref2 = _iterator[_i3++];
} else {
_i3 = _iterator.next();
if (_i3.done) break;
_ref2 = _i3.value;
}
var _ref3 = _ref2,
_pointer = _ref3[0],
_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 interaction = scope.interactions[_i4];
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(_ref4, signalName) {
var doc = _ref4.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 (_ref5) {
var interaction = _ref5.interaction,
pointer = _ref5.pointer,
pointerId = _ref5.pointerId,
pointerIndex = _ref5.pointerIndex,
event = _ref5.event,
eventTarget = _ref5.eventTarget,
down = _ref5.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":34,"./utils":44,"./utils/Signals":35,"./utils/browser":37,"./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');
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;
}
});
/*\
* Interactable.draggable
[ method ]
*
* Gets or sets whether drag actions can be performed on the
* Interactable
*
= (boolean) Indicates if this can be the target of drag events
| var isDraggable = interact('ul li').draggable();
* or
- options (boolean | object) #optional true/false or An object with event listeners to be fired on drag events (object makes the Interactable draggable)
= (object) This Interactable
| 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
| });
\*/
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');
var interact = require('../interact');
var InteractEvent = require('../InteractEvent');
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, interaction.element);
}
var dragEvent = interaction.prevEvent;
var dropEvents = getDropEvents(interaction, event, dragEvent);
if (dropEvents.activate) {
fireActiveDrops(interaction, 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 = interaction.activeDrops.elements = interaction.activeDrops.rects = interaction.dropEvents = null;
});
function collectDrops(interaction, element) {
var drops = [];
var elements = [];
element = element || interaction.element;
// collect all dropzones and their elements which qualify for a drop
for (var _iterator = scope.interactables, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref6;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref6 = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref6 = _i.value;
}
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 i = 0; i < dropElements.length; i++) {
var currentElement = dropElements[i];
if (currentElement !== element) {
drops.push(current);
elements.push(currentElement);
}
}
}
return {
elements: elements,
dropzones: drops
};
}
function fireActiveDrops(interaction, event) {
var prevElement = void 0;
// loop through all active dropzones and trigger event
for (var i = 0; i < interaction.activeDrops.dropzones.length; i++) {
var current = interaction.activeDrops.dropzones[i];
var currentElement = interaction.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(interaction, dragElement) {
// get dropzones and their elements that could receive the draggable
var possibleDrops = collectDrops(interaction, dragElement, true);
interaction.activeDrops.dropzones = possibleDrops.dropzones;
interaction.activeDrops.elements = possibleDrops.elements;
interaction.activeDrops.rects = [];
for (var i = 0; i < interaction.activeDrops.dropzones.length; i++) {
interaction.activeDrops.rects[i] = interaction.activeDrops.dropzones[i].getRect(interaction.activeDrops.elements[i]);
}
}
function getDrop(dragEvent, event, dragElement) {
var interaction = dragEvent.interaction;
var validDrops = [];
if (dynamicDrop) {
setActiveDrops(interaction, 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) {
if (dropEvents.leave) {
interaction.prevDropTarget.fire(dropEvents.leave);
}
if (dropEvents.move) {
interaction.dropTarget.fire(dropEvents.move);
}
if (dropEvents.enter) {
interaction.dropTarget.fire(dropEvents.enter);
}
if (dropEvents.drop) {
interaction.dropTarget.fire(dropEvents.drop);
}
if (dropEvents.deactivate) {
fireActiveDrops(interaction, dropEvents.deactivate);
}
interaction.prevDropTarget = interaction.dropTarget;
interaction.prevDropElement = interaction.dropElement;
}
/*\
* Interactable.dropzone
[ method ]
*
* Returns or sets whether elements can be dropped onto this
* Interactable 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.
*
| 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');
| }
*
*
- options (boolean | object | null) #optional The new value to be set.
| interact('.drop').dropzone({
| accept: '.can-drop' || document.getElementById('single-drop'),
| overlap: 'pointer' || 'center' || zeroToOne
| }
= (boolean | object) 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 (_ref7) {
var interactable = _ref7.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 (_ref8) {
var interaction = _ref8.interaction;
interaction.dropTarget = interaction.dropElement = interaction.prevDropTarget = interaction.prevDropElement = null;
});
/*\
* interact.dynamicDrop
[ method ]
*
* Returns or sets whether the dimensions of dropzone elements are
* calculated on every dragmove or only on dragstart for the default
* dropChecker
*
- newValue (boolean) #optional True to check on each move. False to check only before start
= (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":34,"../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;
}
});
/*\
* Interactable.gesturable
[ method ]
*
* Gets or sets whether multitouch gestures can be performed on the
* Interactable's element
*
= (boolean) Indicates if this can be the target of gesture events
| var isGestureable = interact(element).gesturable();
* or
- options (boolean | object) #optional true/false or An object with event listeners to be fired on gesture events (makes the Interactable gesturable)
= (object) this Interactable
| interact(element).gesturable({
| onstart: function (event) {},
| onmove : function (event) {},
| onend : function (event) {},
|
| // limit multiple gestures.
| // See the explanation in @Interactable.draggable example
| max: Infinity,
| maxPerElement: 1,
| });
\*/
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');
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.isIe9OrOlder ? {
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;
});
/*\
* Interactable.resizable
[ method ]
*
* Gets or sets whether resize actions can be performed on the
* Interactable
*
= (boolean) Indicates if this can be the target of resize elements
| var isResizeable = interact('input[type=text]').resizable();
* or
- options (boolean | object) #optional true/false or An object with event listeners to be fired on resize events (object makes the Interactable resizable)
= (object) This Interactable
| 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 @Interactable.draggable example
| max: Infinity,
| maxPerElement: 1,
| });
\*/
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":37,"./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';
var Interactable = require('../Interactable');
var actions = require('../actions/base');
var is = require('../utils/is');
var domUtils = require('../utils/domUtils');
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;
};
/*\
* Interactable.ignoreFrom
[ method ]
*
* 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.
*
- newValue (string | Element | null) #optional a CSS selector string, an Element or `null` to not ignore any elements
= (string | Element | object) The current ignoreFrom value or this Interactable
**
| interact(element, { ignoreFrom: document.getElementById('no-action') });
| // or
| interact(element).ignoreFrom('input, textarea, a');
\*/
Interactable.prototype.ignoreFrom = function (newValue) {
return this._backCompatOption('ignoreFrom', newValue);
};
/*\
* Interactable.allowFrom
[ method ]
*
* 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.
*
- newValue (string | Element | null) #optional a CSS selector string, an Element or `null` to allow from any element
= (string | Element | object) The current allowFrom value or this Interactable
**
| interact(element, { allowFrom: document.getElementById('drag-handle') });
| // or
| interact(element).allowFrom('.handle');
\*/
Interactable.prototype.allowFrom = function (newValue) {
return this._backCompatOption('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);
};
/*\
* Interactable.actionChecker
[ method ]
*
* Gets or sets the function used to check action to be performed on
* pointerDown
*
- checker (function | null) #optional 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.
= (Function | Interactable) The checker function or this Interactable
*
| 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;
| });
\*/
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;
};
/*\
* Interactable.styleCursor
[ method ]
*
* 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.
*
- newValue (boolean) #optional
= (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 action = null;
for (var _iterator = actions.names, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var actionName = _ref;
// check mouseButton setting if the pointer is down
if (interaction.pointerIsDown && interaction.mouse && (event.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/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 browser = require('../utils/browser');
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
}
},
setActionDefaults: function setActionDefaults(action) {
utils.extend(action.defaults, autoStart.defaults.perAction);
}
};
// 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.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;
var action = null;
function pushMatches(interactable, selector, context) {
var elements = browser.useMatchesSelectorPolyfill ? context.querySelectorAll(selector) : undefined;
if (utils.matchesSelector(element, selector, elements)) {
matches.push(interactable);
matchElements.push(element);
}
}
while (utils.is.element(element)) {
matches = [];
matchElements = [];
var elementInteractable = scope.interactables.get(element);
if (elementInteractable && (action = validateAction(elementInteractable.getAction(pointer, event, interaction, element, eventTarget), elementInteractable, element, eventTarget)) && !elementInteractable.options[action.name].manualStart) {
return {
element: element,
action: action,
target: elementInteractable
};
} else {
scope.interactables.forEachSelector(pushMatches, element);
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 = '';
}
});
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;
};
/*\
* Interactable.actionChecker
[ method ]
*
* Gets or sets the function used to check action to be performed on
* pointerDown
*
- checker (function | null) #optional 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.
= (Function | Interactable) The checker function or this Interactable
*
| 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;
| });
\*/
Interactable.prototype.actionChecker = function (checker) {
if (utils.is.function(checker)) {
this.options.actionChecker = checker;
return this;
}
if (checker === null) {
delete this.options.actionChecker;
return this;
}
return this.options.actionChecker;
};
/*\
* Interactable.styleCursor
[ method ]
*
* 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.
*
- newValue (boolean) #optional
= (boolean | Interactable) The current setting or this Interactable
\*/
Interactable.prototype.styleCursor = function (newValue) {
if (utils.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 _iterator = actions.names, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref5;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref5 = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref5 = _i.value;
}
var actionName = _ref5;
// check mouseButton setting if the pointer is down
if (interaction.pointerIsDown && interaction.mouse && (buttons & this.options[actionName].mouseButtons) === 0) {
continue;
}
action = actions[actionName].checker(pointer, event, this, element, interaction, rect);
if (action) {
return action;
}
}
};
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, len = scope.interactions.length; i < len; i++) {
var interaction = scope.interactions[i];
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;
}
/*\
* interact.maxInteractions
[ method ]
**
* 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.
**
- newValue (number) #optional Any number. newValue <= 0 means no interactions.
\*/
interact.maxInteractions = function (newValue) {
if (utils.is.number(newValue)) {
autoStart.maxInteractions = newValue;
return this;
}
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":34,"../utils":44,"../utils/Signals":35,"../utils/browser":37,"./InteractableMethods":12}],14:[function(require,module,exports){
'use strict';
var autoStart = require('./base');
var Interaction = require('../Interaction');
Interaction.signals.on('new', function (interaction) {
interaction.delayTimer = null;
});
autoStart.signals.on('prepared', function (_ref) {
var interaction = _ref.interaction;
var actionName = interaction.prepared.name;
if (!actionName) {
return;
}
var delay = interaction.target.options[actionName].delay;
if (delay > 0) {
interaction.delayTimer = setTimeout(function () {
interaction.start(interaction.prepared, interaction.target, interaction.element);
}, delay);
}
});
Interaction.signals.on('move', function (_ref2) {
var interaction = _ref2.interaction,
duplicate = _ref2.duplicate;
if (interaction.pointerWasMoved && !duplicate) {
clearTimeout(interaction.delayTimer);
}
});
// prevent regular down->move autoStart
autoStart.signals.on('before-start', function (_ref3) {
var interaction = _ref3.interaction;
var actionName = interaction.prepared.name;
if (!actionName) {
return;
}
var delay = interaction.target.options[actionName].delay;
if (delay > 0) {
interaction.prepared.name = null;
}
});
},{"../Interaction":5,"./base":13}],15:[function(require,module,exports){
'use strict';
var autoStart = require('./base');
var scope = require('../scope');
var browser = require('../utils/browser');
var is = require('../utils/is');
var _require = require('../utils/domUtils'),
matchesSelector = _require.matchesSelector,
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 options = interaction.target.options.drag;
var startAxis = options.startAxis;
var currentAxis = absX > absY ? 'x' : absX < absY ? 'y' : 'xy';
interaction.prepared.axis = options.lockAxis === 'start' ? currentAxis[0] // always lock to one axis even if currentAxis === 'xy'
: options.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
if (!interaction.prepared.name) {
var element = eventTarget;
var getDraggable = function getDraggable(interactable, selector, context) {
var elements = browser.useMatchesSelectorPolyfill ? context.querySelectorAll(selector) : undefined;
if (interactable === interaction.target) {
return;
}
if (!options.manualStart && !interactable.testIgnoreAllow(options, element, eventTarget) && matchesSelector(element, selector, elements)) {
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;
}
}
};
var action = null;
// check all interactables
while (is.element(element)) {
var elementInteractable = scope.interactables.get(element);
if (elementInteractable && elementInteractable !== interaction.target && !elementInteractable.options.drag.manualStart) {
action = elementInteractable.getAction(interaction.downPointer, interaction.downEvent, interaction, element);
}
if (action && action.name === 'drag' && checkStartAxis(currentAxis, elementInteractable)) {
interaction.prepared.name = 'drag';
interaction.target = elementInteractable;
interaction.element = element;
break;
}
var selectorInteractable = scope.interactables.forEachSelector(getDraggable, element);
if (selectorInteractable) {
interaction.prepared.name = 'drag';
interaction.target = selectorInteractable;
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":34,"../utils/browser":37,"../utils/domUtils":39,"../utils/is":46,"./base":13}],16:[function(require,module,exports){
'use strict';
require('./base').setActionDefaults(require('../actions/gesture'));
},{"../actions/gesture":9,"./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 },
// only allow left button by default
// see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons#Return_value
mouseButtons: 1,
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 */
// Legacy browser support
require('./legacyBrowsers');
// inertia
require('./inertia');
// modifiers
require('./modifiers/snap');
require('./modifiers/restrict');
// pointerEvents
require('./pointerEvents/base');
require('./pointerEvents/holdRepeat');
require('./pointerEvents/interactableTargets');
// delay
require('./autoStart/delay');
// 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/delay":14,"./autoStart/drag":15,"./autoStart/gesture":16,"./autoStart/resize":17,"./inertia":20,"./interact":21,"./interactablePreventDefault.js":22,"./legacyBrowsers":23,"./modifiers/restrict":25,"./modifiers/restrictEdges":26,"./modifiers/restrictSize":27,"./modifiers/snap":28,"./modifiers/snapSize":29,"./pointerEvents/base":31,"./pointerEvents/holdRepeat":32,"./pointerEvents/interactableTargets":33}],20:[function(require,module,exports){
'use strict';
var InteractEvent = require('./InteractEvent');
var Interaction = require('./Interaction');
var modifiers = require('./modifiers');
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":24,"./utils":44,"./utils/raf":50}],21:[function(require,module,exports){
'use strict';
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 = {};
/*\
* interact
[ method ]
*
* 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.
*
- element (Element | string) The HTML or SVG Element to interact with or CSS selector
= (object) An @Interactable
*
> Usage
| interact('#draggable').draggable(true);
|
| var rectables = interact('rect');
| rectables
| .gesturable(true)
| .on('gesturemove', function (event) {
| // ...
| });
\*/
function interact(element, options) {
var interactable = scope.interactables.get(element, options);
if (!interactable) {
interactable = new Interactable(element, options);
interactable.events.global = globalEvents;
}
return interactable;
}
/*\
* interact.isSet
[ method ]
*
* Check if an element has been set
- element (Element) The Element being searched for
= (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;
};
/*\
* interact.on
[ method ]
*
* Adds a global listener for an InteractEvent or adds a DOM event to
* `document`
*
- type (string | array | object) The types of events to listen for
- listener (function) The function event (s)
- options (object | boolean) #optional options object or useCapture flag for addEventListener
= (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 _iterator = type, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
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;
};
/*\
* interact.off
[ method ]
*
* Removes a global InteractEvent listener or DOM event from `document`
*
- type (string | array | object) The types of events that were listened for
- listener (function) The listener function to be removed
- options (object | boolean) #optional options object or useCapture flag for removeEventListener
= (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 _iterator2 = type, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref2;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref2 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref2 = _i2.value;
}
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 = utils.indexOf(globalEvents[type], listener)) !== -1) {
globalEvents[type].splice(index, 1);
}
}
return interact;
};
/*\
* interact.debug
[ method ]
*
* Returns an object which exposes internal data
= (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;
/*\
* interact.supportsTouch
[ method ]
*
= (boolean) Whether or not the browser supports touch input
\*/
interact.supportsTouch = function () {
return browser.supportsTouch;
};
/*\
* interact.supportsPointerEvent
[ method ]
*
= (boolean) Whether or not the browser supports PointerEvents
\*/
interact.supportsPointerEvent = function () {
return browser.supportsPointerEvent;
};
/*\
* interact.stop
[ method ]
*
* Cancels all interactions (end events are not fired)
*
- event (Event) An event on which to call preventDefault()
= (object) interact
\*/
interact.stop = function (event) {
for (var i = scope.interactions.length - 1; i >= 0; i--) {
scope.interactions[i].stop(event);
}
return interact;
};
/*\
* interact.pointerMoveTolerance
[ method ]
* Returns or sets the distance the pointer must be moved before an action
* sequence occurs. This also affects tolerance for tap events.
*
- newValue (number) #optional The movement from the start position must be greater than this value
= (number | Interactable) The current setting or interact
\*/
interact.pointerMoveTolerance = function (newValue) {
if (utils.is.number(newValue)) {
Interaction.pointerMoveTolerance = newValue;
return this;
}
return Interaction.pointerMoveTolerance;
};
interact.addDocument = scope.addDocument;
interact.removeDocument = scope.removeDocument;
scope.interact = interact;
module.exports = interact;
},{"./Interactable":4,"./Interaction":5,"./scope":34,"./utils":44,"./utils/browser":37,"./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 _require = require('./utils/domUtils'),
nodeContains = _require.nodeContains,
matchesSelector = _require.matchesSelector;
/*\
* Interactable.preventDefault
[ method ]
*
* 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
*
- newValue (string) #optional `true`, `false` or `'auto'`
= (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 if the browser supports passiveEvents
// CSS touch-action and user-selecct should be used instead
if (events.supportsOptions) {
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 _iterator = scope.interactions, _isArray = Array.isArray(_iterator), _i2 = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref2;
if (_isArray) {
if (_i2 >= _iterator.length) break;
_ref2 = _iterator[_i2++];
} else {
_i2 = _iterator.next();
if (_i2.done) break;
_ref2 = _i2.value;
}
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":34,"./utils/domUtils":39,"./utils/events":40,"./utils/is":46}],23:[function(require,module,exports){
'use strict';
var scope = require('./scope');
var events = require('./utils/events');
var browser = require('./utils/browser');
var iFinder = require('./utils/interactionFinder');
var pointerEvents = require('./pointerEvents/base');
var _require = require('./utils/window'),
window = _require.window;
var toString = Object.prototype.toString;
if (!window.Array.isArray) {
window.Array.isArray = function (obj) {
return toString.call(obj) === '[object Array]';
};
}
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
};
}
// http://www.quirksmode.org/dom/events/click.html
// >Events leading to dblclick
//
// IE8 doesn't fire down event before dblclick.
// This workaround tries to fire a tap and doubletap after dblclick
function onIE8Dblclick(event) {
var eventTarget = event.target;
var interaction = iFinder.search(event, event.type, eventTarget);
if (!interaction) {
return;
}
if (interaction.prevTap && event.clientX === interaction.prevTap.clientX && event.clientY === interaction.prevTap.clientY && eventTarget === interaction.prevTap.target) {
interaction.downTargets[0] = eventTarget;
interaction.downTimes[0] = new Date().getTime();
pointerEvents.fire({
interaction: interaction,
event: event,
eventTarget: eventTarget,
pointer: event,
type: 'tap'
});
}
}
if (browser.isIE8) {
var selectFix = function selectFix(event) {
for (var _iterator = scope.interactions, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var interaction = _ref;
if (interaction.interacting()) {
interaction.target.checkAndPreventDefault(event);
}
}
};
var onDocIE8 = function onDocIE8(_ref2, signalName) {
var doc = _ref2.doc,
win = _ref2.win;
var eventMethod = signalName.indexOf('listen') === 0 ? events.add : events.remove;
// For IE's lack of Event#preventDefault
eventMethod(doc, 'selectstart', selectFix);
if (pointerEvents) {
eventMethod(doc, 'dblclick', onIE8Dblclick);
}
};
scope.signals.on('add-document', onDocIE8);
scope.signals.on('remove-document', onDocIE8);
}
module.exports = null;
},{"./pointerEvents/base":31,"./scope":34,"./utils/browser":37,"./utils/events":40,"./utils/interactionFinder":45,"./utils/window":52}],24:[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 modifierName = modifiers.names[i];
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 coords = extend({}, arg.pageCoords);
var result = {
dx: 0,
dy: 0,
changed: false,
locked: false,
shouldMove: true
};
for (var _iterator = modifiers.names, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var modifierName = _ref;
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) {
coords.x += arg.status.dx;
coords.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 _iterator2 = modifiers.names, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref2;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref2 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref2 = _i2.value;
}
var modifierName = _ref2;
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(_ref3, signalName) {
var interaction = _ref3.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);
}
};
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', function (_ref4) {
var interaction = _ref4.interaction,
preEnd = _ref4.preEnd,
interactingBeforeMove = _ref4.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;
});
Interaction.signals.on('action-end', function (_ref5) {
var interaction = _ref5.interaction,
event = _ref5.event;
for (var i = 0; i < modifiers.names.length; i++) {
var options = interaction.target.options[interaction.prepared.name][modifiers.names[i]];
// 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;
}
}
});
InteractEvent.signals.on('set-xy', function (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);
}
});
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}],25:[function(require,module,exports){
'use strict';
var modifiers = require('./index');
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 pageCoords = _ref2.pageCoords,
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({}, pageCoords);
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,"./index":24}],26:[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('./index');
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 pageCoords = _ref2.pageCoords,
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({}, pageCoords);
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,"./index":24,"./restrict":25}],27:[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('./index');
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,"./index":24,"./restrictEdges":26}],28:[function(require,module,exports){
'use strict';
var modifiers = require('./index');
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 _iterator = options.relativePoints, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref2;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref2 = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref2 = _i.value;
}
var _ref3 = _ref2,
relativeX = _ref3.x,
relativeY = _ref3.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,
pageCoords = _ref4.pageCoords,
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({}, pageCoords);
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 _iterator2 = offsets, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref5;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref5 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref5 = _i2.value;
}
var _ref6 = _ref5,
offsetX = _ref6.x,
offsetY = _ref6.y;
var relativeX = page.x - offsetX;
var relativeY = page.y - offsetY;
for (var _iterator3 = options.targets, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
var _ref7;
if (_isArray3) {
if (_i3 >= _iterator3.length) break;
_ref7 = _iterator3[_i3++];
} else {
_i3 = _iterator3.next();
if (_i3.done) break;
_ref7 = _i3.value;
}
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,"./index":24}],29:[function(require,module,exports){
'use strict';
// This module allows snapping of the size of targets during resize
// interactions.
var modifiers = require('./index');
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,
pageCoords = arg.pageCoords;
var page = utils.extend({}, pageCoords);
var relativeX = page.x - offset[0].x;
var relativeY = page.y - offset[0].y;
arg.options = utils.extend({}, options);
arg.options.targets = [];
for (var _iterator = options.targets, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
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,"./index":24,"./snap":28}],30:[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}],31:[function(require,module,exports){
'use strict';
var PointerEvent = require('./PointerEvent');
var Interaction = require('../Interaction');
var utils = require('../utils');
var browser = require('../utils/browser');
var defaults = require('../defaultOptions');
var signals = require('../utils/Signals').new();
var _require = require('../utils/arr'),
filter = _require.filter;
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 _iterator = path, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref2;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref2 = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref2 = _i.value;
}
var element = _ref2;
signalArg.element = element;
signals.fire('collect-targets', signalArg);
}
if (type === 'hold') {
signalArg.targets = filter(signalArg.targets, 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;
// copy event to be used in timeout for IE8
var eventCopy = browser.isIE8 ? utils.extend({}, event) : event;
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 _iterator2 = path, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref7;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref7 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref7 = _i2.value;
}
var element = _ref7;
signalArg.element = element;
signals.fire('collect-targets', signalArg);
}
if (!signalArg.targets.length) {
return;
}
var minDuration = Infinity;
for (var i = 0; i < signalArg.targets.length; i++) {
var target = signalArg.targets[i];
var holdDuration = target.eventable.options.holdDuration;
if (holdDuration < minDuration) {
minDuration = holdDuration;
}
}
timer.duration = minDuration;
timer.timeout = setTimeout(function () {
fire({
interaction: interaction,
eventTarget: eventTarget,
pointer: browser.isIE8 ? eventCopy : pointer,
event: eventCopy,
type: 'hold'
});
}, minDuration);
});
Interaction.signals.on('up', function (_ref8) {
var interaction = _ref8.interaction,
pointer = _ref8.pointer,
event = _ref8.event,
eventTarget = _ref8.eventTarget;
if (!interaction.pointerWasMoved) {
fire({ interaction: interaction, eventTarget: eventTarget, pointer: pointer, event: event, type: 'tap' });
}
});
['up', 'cancel'].forEach(function (signalName) {
Interaction.signals.on(signalName, function (_ref9) {
var interaction = _ref9.interaction,
pointerIndex = _ref9.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":35,"../utils/arr":36,"../utils/browser":37,"./PointerEvent":30}],32:[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":31}],33:[function(require,module,exports){
'use strict';
var pointerEvents = require('./base');
var Interactable = require('../Interactable');
var browser = require('../utils/browser');
var is = require('../utils/is');
var domUtils = require('../utils/domUtils');
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;
function collectSelectors(interactable, selector, context) {
var els = browser.useMatchesSelectorPolyfill ? context.querySelectorAll(selector) : undefined;
var eventable = interactable.events;
var options = eventable.options;
if (eventable[type] && is.element(element) && domUtils.matchesSelector(element, selector, els) && interactable.testIgnoreAllow(options, element, eventTarget)) {
targets.push({
element: element,
eventable: eventable,
props: { interactable: interactable }
});
}
}
var interactable = scope.interactables.get(element);
if (interactable) {
var eventable = interactable.events;
var options = eventable.options;
if (eventable[type] && interactable.testIgnoreAllow(options, element, eventTarget)) {
targets.push({
element: element,
eventable: eventable,
props: { interactable: interactable }
});
}
}
scope.interactables.forEachSelector(collectSelectors, element);
});
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":34,"../utils/arr":36,"../utils/browser":37,"../utils/domUtils":39,"../utils/extend":41,"../utils/is":46,"./base":31}],34:[function(require,module,exports){
'use strict';
var utils = require('./utils');
var events = require('./utils/events');
var signals = require('./utils/Signals').new();
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 || scope.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 = utils.indexOf(scope.documents, doc);
win = win || scope.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":35,"./utils/domObjects":38,"./utils/events":40}],35:[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 _require = require('./arr'),
indexOf = _require.indexOf;
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 = indexOf(this.listeners[name], 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++) {
if (targetListeners[i](arg, name) === false) {
return;
}
}
};
return Signals;
}();
Signals.new = function () {
return new Signals();
};
module.exports = Signals;
},{"./arr":36}],36:[function(require,module,exports){
"use strict";
function indexOf(array, target) {
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === target) {
return i;
}
}
return -1;
}
function contains(array, target) {
return indexOf(array, target) !== -1;
}
function merge(target, source) {
for (var i = 0; i < source.length; i++) {
target.push(source[i]);
}
return target;
}
function filter(array, test) {
var result = [];
for (var i = 0; i < array.length; i++) {
if (test(array[i])) {
result.push(array[i]);
}
}
return result;
}
module.exports = {
indexOf: indexOf,
contains: contains,
merge: merge,
filter: filter
};
},{}],37:[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,
isIE8: 'attachEvent' in window && !('addEventListener' in window),
// Opera Mobile must be handled differently
isOperaMobile: navigator.appName === 'Opera' && browser.supportsTouch && navigator.userAgent.match('Presto'),
// 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),
isIe9OrOlder: /MSIE (8|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',
useMatchesSelectorPolyfill: false,
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'
};
browser.useMatchesSelectorPolyfill = !is.function(Element.prototype[browser.prefixedMatchesSelector]);
module.exports = browser;
},{"./domObjects":38,"./is":46,"./window":52}],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;
},
// taken from http://tanalin.com/en/blog/2012/12/matches-selector-ie8/ and modified
matchesSelectorPolyfill: browser.useMatchesSelectorPolyfill ? function (element, selector, elems) {
elems = elems || element.parentNode.querySelectorAll(selector);
for (var i = 0, len = elems.length; i < len; i++) {
if (elems[i] === element) {
return true;
}
}
return false;
} : null,
matchesSelector: function matchesSelector(element, selector, nodeList) {
if (browser.useMatchesSelectorPolyfill) {
return domUtils.matchesSelectorPolyfill(element, selector, nodeList);
}
// 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":37,"./domObjects":38,"./is":46,"./window":52}],40:[function(require,module,exports){
'use strict';
var is = require('./is');
var domUtils = require('./domUtils');
var pExtend = require('./pointerExtend');
var _require = require('./window'),
window = _require.window,
getWindow = _require.getWindow;
var _require2 = require('./arr'),
indexOf = _require2.indexOf,
contains = _require2.contains;
var useAttachEvent = 'attachEvent' in window && !('addEventListener' in window);
var addEvent = useAttachEvent ? 'attachEvent' : 'addEventListener';
var removeEvent = useAttachEvent ? 'detachEvent' : 'removeEventListener';
var on = useAttachEvent ? 'on' : '';
var elements = [];
var targets = [];
var attachedListeners = [];
// {
// type: {
// selectors: ['selector', ...],
// contexts : [document, ...],
// listeners: [[listener, capture, passive], ...]
// }
// }
var delegatedEvents = {};
var documents = [];
var supportsOptions = !useAttachEvent && 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 = indexOf(elements, element);
var target = targets[elementIndex];
if (!target) {
target = {
events: {},
typeCount: 0
};
elementIndex = elements.push(element) - 1;
targets.push(target);
attachedListeners.push(useAttachEvent ? {
supplied: [],
wrapped: [],
useCount: []
} : null);
}
if (!target.events[type]) {
target.events[type] = [];
target.typeCount++;
}
if (!contains(target.events[type], listener)) {
var ret = void 0;
if (useAttachEvent) {
var _attachedListeners$el = attachedListeners[elementIndex],
supplied = _attachedListeners$el.supplied,
wrapped = _attachedListeners$el.wrapped,
useCount = _attachedListeners$el.useCount;
var listenerIndex = indexOf(supplied, listener);
var wrappedListener = wrapped[listenerIndex] || function (event) {
if (!event.immediatePropagationStopped) {
event.target = event.srcElement;
event.currentTarget = element;
event.preventDefault = event.preventDefault || preventDef;
event.stopPropagation = event.stopPropagation || stopProp;
event.stopImmediatePropagation = event.stopImmediatePropagation || stopImmProp;
if (/mouse|click/.test(event.type)) {
event.pageX = event.clientX + getWindow(element).document.documentElement.scrollLeft;
event.pageY = event.clientY + getWindow(element).document.documentElement.scrollTop;
}
listener(event);
}
};
ret = element[addEvent](on + type, wrappedListener, !!options.capture);
if (listenerIndex === -1) {
supplied.push(listener);
wrapped.push(wrappedListener);
useCount.push(1);
} else {
useCount[listenerIndex]++;
}
} else {
ret = element[addEvent](type, listener, supportsOptions ? options : !!options.capture);
}
target.events[type].push(listener);
return ret;
}
}
function remove(element, type, listener, optionalArg) {
var options = getOptions(optionalArg);
var elementIndex = indexOf(elements, element);
var target = targets[elementIndex];
if (!target || !target.events) {
return;
}
var wrappedListener = listener;
var listeners = void 0;
var listenerIndex = void 0;
if (useAttachEvent) {
listeners = attachedListeners[elementIndex];
listenerIndex = indexOf(listeners.supplied, listener);
wrappedListener = listeners.wrapped[listenerIndex];
}
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[removeEvent](on + type, wrappedListener, supportsOptions ? options : !!options.capture);
target.events[type].splice(_i, 1);
if (useAttachEvent && listeners) {
listeners.useCount[listenerIndex]--;
if (listeners.useCount[listenerIndex] === 0) {
listeners.supplied.splice(listenerIndex, 1);
listeners.wrapped.splice(listenerIndex, 1);
listeners.useCount.splice(listenerIndex, 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);
attachedListeners.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 i = 0; i < documents.length; i++) {
add(documents[i], type, delegateListener);
add(documents[i], 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 eventTarget = domUtils.getActualElement(event.path ? event.path[0] : event.target);
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 preventDef() {
this.returnValue = false;
}
function preventOriginalDefault() {
this.originalEvent.preventDefault();
}
function stopProp() {
this.cancelBubble = true;
}
function stopImmProp() {
this.cancelBubble = true;
this.immediatePropagationStopped = true;
}
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,
useAttachEvent: useAttachEvent,
supportsOptions: supportsOptions,
_elements: elements,
_targets: targets,
_attachedListeners: attachedListeners
};
},{"./arr":36,"./domUtils":39,"./is":46,"./pointerExtend":48,"./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":36,"./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 _iterator = finder.methodOrder, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
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 _iterator2 = scope.interactions, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref3;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref3 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref3 = _i2.value;
}
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 _iterator3 = scope.interactions, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
var _ref5;
if (_isArray3) {
if (_i3 >= _iterator3.length) break;
_ref5 = _iterator3[_i3++];
} else {
_i3 = _iterator3.next();
if (_i3.done) break;
_ref5 = _i3.value;
}
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 _iterator4 = scope.interactions, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
var _ref6;
if (_isArray4) {
if (_i4 >= _iterator4.length) break;
_ref6 = _iterator4[_i4++];
} else {
_i4 = _iterator4.next();
if (_i4.done) break;
_ref6 = _i4.value;
}
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 _iterator5 = scope.interactions, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {
var _ref8;
if (_isArray5) {
if (_i5 >= _iterator5.length) break;
_ref8 = _iterator5[_i5++];
} else {
_i5 = _iterator5.next();
if (_i5.done) break;
_ref8 = _i5.value;
}
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 _iterator6 = scope.interactions, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {
var _ref10;
if (_isArray6) {
if (_i6 >= _iterator6.length) break;
_ref10 = _iterator6[_i6++];
} else {
_i6 = _iterator6.next();
if (_i6.done) break;
_ref10 = _i6.value;
}
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":34,"./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'
);
}
};
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 _iterator = pointers, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
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) {
return [domUtils.getActualElement(event.path ? event.path[0] : event.target), domUtils.getActualElement(event.currentTarget)];
}
};
module.exports = pointerUtils;
},{"./browser":37,"./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