/**
|
* interact.js v1.3.0-alpha.1+sha.3b5033b
|
*
|
* 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, useCapture) {
|
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, useCapture);
|
}
|
|
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)
|
- useCapture (boolean) #optional useCapture flag for addEventListener
|
= (object) This Interactable
|
\*/
|
|
|
Interactable.prototype.on = function on(eventType, listener, useCapture) {
|
// convert to boolean
|
useCapture = !!useCapture;
|
|
if (this._onOffMultiple('on', eventType, listener, useCapture)) {
|
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, useCapture);
|
} else {
|
events.add(this.target, eventType, listener, useCapture);
|
}
|
|
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
|
- useCapture (boolean) #optional useCapture flag for removeEventListener
|
= (object) This Interactable
|
\*/
|
|
|
Interactable.prototype.off = function off(eventType, listener, useCapture) {
|
// convert to boolean
|
useCapture = !!useCapture;
|
|
if (this._onOffMultiple('off', eventType, listener, useCapture)) {
|
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, useCapture);
|
}
|
// remove listener from this Interatable's element
|
else {
|
events.remove(this.target, eventType, listener, useCapture);
|
}
|
|
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 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() {
|
_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.mouse = false;
|
|
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) {
|
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 id = utils.getPointerId(pointer);
|
var index = this.mouse ? 0 : utils.indexOf(this.pointerIds, id);
|
|
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 _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()]);
|
}
|
} 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].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();
|
_interaction.mouse = /mouse/i.test(event.pointerType || event.type)
|
// MSPointerEvent.MSPOINTER_TYPE_MOUSE
|
|| event.pointerType === 4 || !event.pointerType;
|
}
|
|
matches.push([event, _interaction]);
|
}
|
}
|
|
for (var _iterator = matches, _isArray = Array.isArray(_iterator), _i3 = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
|
var _ref;
|
|
if (_isArray) {
|
if (_i3 >= _iterator.length) break;
|
_ref = _iterator[_i3++];
|
} else {
|
_i3 = _iterator.next();
|
if (_i3.done) break;
|
_ref = _i3.value;
|
}
|
|
var _ref2 = _ref,
|
_pointer = _ref2[0],
|
_interaction2 = _ref2[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 (scope.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(_ref3, signalName) {
|
var doc = _ref3.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 (_ref4) {
|
var interaction = _ref4.interaction,
|
pointer = _ref4.pointer,
|
pointerId = _ref4.pointerId,
|
pointerIndex = _ref4.pointerIndex,
|
event = _ref4.event,
|
eventTarget = _ref4.eventTarget,
|
down = _ref4.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/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.move) {
|
interaction.dropTarget.fire(dropEvents.move);
|
}
|
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: [] };
|
});
|
|
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 };
|
});
|
|
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 },
|
|
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 }
|
}
|
};
|
|
},{}],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 inertiaPossible = false;
|
var inertia = false;
|
var smoothEnd = false;
|
var modifierResult = void 0;
|
|
// check if inertia should be started
|
inertiaPossible = inertiaOptions && inertiaOptions.enabled && interaction.prepared.name !== 'gesture' && event !== status.startEvent;
|
|
inertia = inertiaPossible && now - interaction.curCoords.timeStamp < 50 && pointerSpeed > inertiaOptions.minSpeed && pointerSpeed > inertiaOptions.endSpeed;
|
|
var modifierArg = {
|
interaction: interaction,
|
page: 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)
|
- useCapture (boolean) #optional useCapture flag for addEventListener
|
= (object) interact
|
\*/
|
interact.on = function (type, listener, useCapture) {
|
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, useCapture);
|
}
|
|
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, useCapture);
|
}
|
|
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
|
- useCapture (boolean) #optional useCapture flag for removeEventListener
|
= (object) interact
|
\*/
|
interact.off = function (type, listener, useCapture) {
|
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, useCapture);
|
}
|
|
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, useCapture);
|
} 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 _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 of pointerdown events
|
if (/^(mouse|pointer|touch)*(down|start)/i.test(event.type)) {
|
return;
|
}
|
|
// don't preventDefault on editable elements
|
if (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/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) {
|
return utils.resolveRectLike(value, interaction.target, interaction.element, [page.x, page.y, interaction]);
|
}
|
|
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
|
};
|
|
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,
|
min: utils.extend({}, restrictEdges.noMin),
|
max: utils.extend({}, restrictEdges.noMax)
|
};
|
|
if (edges.top) {
|
arg.options.min.top = rect.bottom - maxSize.height;
|
arg.options.max.top = rect.bottom - minSize.height;
|
} else if (edges.bottom) {
|
arg.options.min.bottom = rect.top + minSize.height;
|
arg.options.max.bottom = rect.top + maxSize.height;
|
}
|
if (edges.left) {
|
arg.options.min.left = rect.right - maxSize.width;
|
arg.options.max.left = rect.right - minSize.width;
|
} else if (edges.right) {
|
arg.options.min.right = rect.left + minSize.width;
|
arg.options.max.right = rect.left + maxSize.width;
|
}
|
|
return 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, interaction);
|
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, eventCopy: eventCopy, eventTarget: eventTarget,
|
pointer: browser.isIE8 ? eventCopy : pointer,
|
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 browser = require('./browser');
|
|
var finder = {
|
methodOrder: ['simulationResume', 'mouse', 'hasPointer', 'idle'],
|
|
search: function search(pointer, eventType, eventTarget) {
|
var mouseEvent = /mouse/i.test(pointer.pointerType || eventType)
|
// MSPointerEvent.MSPOINTER_TYPE_MOUSE
|
|| pointer.pointerType === 4;
|
var pointerId = utils.getPointerId(pointer);
|
var details = { pointer: pointer, pointerId: pointerId, mouseEvent: mouseEvent, 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 mouseEvent = _ref2.mouseEvent,
|
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.mouse === mouseEvent) {
|
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 interaction
|
mouse: function mouse(_ref4) {
|
var pointerId = _ref4.pointerId,
|
mouseEvent = _ref4.mouseEvent,
|
eventType = _ref4.eventType;
|
|
if (!mouseEvent && (browser.supportsTouch || browser.supportsPointerEvent)) {
|
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.mouse) {
|
// 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 interaction specifically for mouse.
|
// ignore the interaction if the eventType is a mousedown, 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.mouse && !(/down/.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
|
idle: function idle(_ref9) {
|
var mouseEvent = _ref9.mouseEvent;
|
|
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() && mouseEvent === interaction.mouse) {
|
return interaction;
|
}
|
}
|
|
return null;
|
}
|
};
|
|
module.exports = finder;
|
|
},{"../scope":34,"./browser":37,"./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 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, interaction) {
|
// if the PointerEvent API isn't available, then the pointer must be ither
|
// a MouseEvent or TouchEvent
|
if (interaction.mouse) {
|
return 'mouse';
|
}
|
if (!browser.supportsPointerEvent) {
|
return 'touch';
|
}
|
|
return is.string(pointer.pointerType) ? pointer.pointerType : [undefined, undefined, 'touch', 'pen', 'mouse'][pointer.pointerType];
|
},
|
|
// [ 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
|