209 lines
8.3 KiB
JavaScript
209 lines
8.3 KiB
JavaScript
import * as support from './_support';
|
|
import * as options from './_defaults';
|
|
import * as settings from './_settings';
|
|
import { percentage2number } from './_helpers';
|
|
import { extend } from '../helpers';
|
|
var DragEvents = /** @class */ (function () {
|
|
/**
|
|
* Create the gestures.
|
|
* @param {HTMLElement} surface The surface for the gesture.
|
|
* @param {object} area Restriction where on the surface the gesture can be started.
|
|
* @param {object} treshold Treshold for the gestures.
|
|
*/
|
|
function DragEvents(surface, area, treshold) {
|
|
this.surface = surface;
|
|
this.area = extend(area, options.area);
|
|
this.treshold = extend(treshold, options.treshold);
|
|
// Set the mouse/touch events.
|
|
if (!this.surface['mmHasDragEvents']) {
|
|
this.surface.addEventListener(support.touch ? 'touchstart' : 'mousedown', this.start.bind(this));
|
|
this.surface.addEventListener(support.touch ? 'touchend' : 'mouseup', this.stop.bind(this));
|
|
this.surface.addEventListener(support.touch ? 'touchleave' : 'mouseleave', this.stop.bind(this));
|
|
this.surface.addEventListener(support.touch ? 'touchmove' : 'mousemove', this.move.bind(this));
|
|
}
|
|
this.surface['mmHasDragEvents'] = true;
|
|
}
|
|
/**
|
|
* Starting the touch gesture.
|
|
* @param {Event} event The touch event.
|
|
*/
|
|
DragEvents.prototype.start = function (event) {
|
|
this.currentPosition = {
|
|
x: event.touches ? event.touches[0].pageX : event.pageX || 0,
|
|
y: event.touches ? event.touches[0].pageY : event.pageY || 0
|
|
};
|
|
/** The widht of the surface. */
|
|
var width = this.surface.clientWidth;
|
|
/** The height of the surface. */
|
|
var height = this.surface.clientHeight;
|
|
// Check if the gesture started below the area.top.
|
|
var top = percentage2number(this.area.top, height);
|
|
if (typeof top == 'number') {
|
|
if (this.currentPosition.y < top) {
|
|
return;
|
|
}
|
|
}
|
|
// Check if the gesture started before the area.right.
|
|
var right = percentage2number(this.area.right, width);
|
|
if (typeof right == 'number') {
|
|
right = width - right;
|
|
if (this.currentPosition.x > right) {
|
|
return;
|
|
}
|
|
}
|
|
// Check if the gesture started above the area.bottom.
|
|
var bottom = percentage2number(this.area.bottom, height);
|
|
if (typeof bottom == 'number') {
|
|
bottom = height - bottom;
|
|
if (this.currentPosition.y > bottom) {
|
|
return;
|
|
}
|
|
}
|
|
// Check if the gesture started after the area.left.
|
|
var left = percentage2number(this.area.left, width);
|
|
if (typeof left == 'number') {
|
|
if (this.currentPosition.x < left) {
|
|
return;
|
|
}
|
|
}
|
|
// Store the start x- and y-position.
|
|
this.startPosition = {
|
|
x: this.currentPosition.x,
|
|
y: this.currentPosition.y
|
|
};
|
|
// Set the state of the gesture to "watching".
|
|
this.state = settings.state.watching;
|
|
};
|
|
/**
|
|
* Stopping the touch gesture.
|
|
* @param {Event} event The touch event.
|
|
*/
|
|
DragEvents.prototype.stop = function (event) {
|
|
// Dispatch the "dragEnd" events.
|
|
if (this.state == settings.state.dragging) {
|
|
/** The direction. */
|
|
var dragDirection = this._dragDirection();
|
|
/** The event information. */
|
|
var detail = this._eventDetail(dragDirection);
|
|
this._dispatchEvents('drag*End', detail);
|
|
// Dispatch the "swipe" events.
|
|
if (Math.abs(this.movement[this.axis]) > this.treshold.swipe) {
|
|
/** The direction. */
|
|
var swipeDirection = this._swipeDirection();
|
|
detail.direction = swipeDirection;
|
|
this._dispatchEvents('swipe*', detail);
|
|
}
|
|
}
|
|
// Set the state of the gesture to "inactive".
|
|
this.state = settings.state.inactive;
|
|
};
|
|
/**
|
|
* Doing the touch gesture.
|
|
* @param {Event} event The touch event.
|
|
*/
|
|
DragEvents.prototype.move = function (event) {
|
|
switch (this.state) {
|
|
case settings.state.watching:
|
|
case settings.state.dragging:
|
|
var position = {
|
|
x: event.changedTouches
|
|
? event.touches[0].pageX
|
|
: event.pageX || 0,
|
|
y: event.changedTouches
|
|
? event.touches[0].pageY
|
|
: event.pageY || 0
|
|
};
|
|
this.movement = {
|
|
x: position.x - this.currentPosition.x,
|
|
y: position.y - this.currentPosition.y
|
|
};
|
|
this.distance = {
|
|
x: position.x - this.startPosition.x,
|
|
y: position.y - this.startPosition.y
|
|
};
|
|
this.currentPosition = {
|
|
x: position.x,
|
|
y: position.y
|
|
};
|
|
this.axis =
|
|
Math.abs(this.distance.x) > Math.abs(this.distance.y)
|
|
? 'x'
|
|
: 'y';
|
|
/** The direction. */
|
|
var dragDirection = this._dragDirection();
|
|
/** The event information. */
|
|
var detail = this._eventDetail(dragDirection);
|
|
// Watching for the gesture to go past the treshold.
|
|
if (this.state == settings.state.watching) {
|
|
if (Math.abs(this.distance[this.axis]) > this.treshold.start) {
|
|
this._dispatchEvents('drag*Start', detail);
|
|
// Set the state of the gesture to "inactive".
|
|
this.state = settings.state.dragging;
|
|
}
|
|
}
|
|
// Dispatch the "drag" events.
|
|
if (this.state == settings.state.dragging) {
|
|
this._dispatchEvents('drag*Move', detail);
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
/**
|
|
* Get the event details.
|
|
* @param {string} direction Direction for the event (up, right, down, left).
|
|
* @return {object} The event details.
|
|
*/
|
|
DragEvents.prototype._eventDetail = function (direction) {
|
|
var distX = this.distance.x;
|
|
var distY = this.distance.y;
|
|
if (this.axis == 'x') {
|
|
distX -= distX > 0 ? this.treshold.start : 0 - this.treshold.start;
|
|
}
|
|
if (this.axis == 'y') {
|
|
distY -= distY > 0 ? this.treshold.start : 0 - this.treshold.start;
|
|
}
|
|
return {
|
|
axis: this.axis,
|
|
direction: direction,
|
|
movementX: this.movement.x,
|
|
movementY: this.movement.y,
|
|
distanceX: distX,
|
|
distanceY: distY
|
|
};
|
|
};
|
|
/**
|
|
* Dispatch the events
|
|
* @param {string} eventName The name for the events to dispatch.
|
|
* @param {object} detail The event details.
|
|
*/
|
|
DragEvents.prototype._dispatchEvents = function (eventName, detail) {
|
|
/** General event, e.g. "drag" */
|
|
var event = new CustomEvent(eventName.replace('*', ''), { detail: detail });
|
|
this.surface.dispatchEvent(event);
|
|
/** Axis event, e.g. "dragX" */
|
|
var axis = new CustomEvent(eventName.replace('*', this.axis.toUpperCase()), { detail: detail });
|
|
this.surface.dispatchEvent(axis);
|
|
/** Direction event, e.g. "dragLeft" */
|
|
var direction = new CustomEvent(eventName.replace('*', detail.direction), {
|
|
detail: detail
|
|
});
|
|
this.surface.dispatchEvent(direction);
|
|
};
|
|
/**
|
|
* Get the dragging direction.
|
|
* @return {string} The direction in which the user is dragging.
|
|
*/
|
|
DragEvents.prototype._dragDirection = function () {
|
|
return settings.directionNames[this.axis][this.distance[this.axis] > 0 ? 0 : 1];
|
|
};
|
|
/**
|
|
* Get the dragging direction.
|
|
* @return {string} The direction in which the user is dragging.
|
|
*/
|
|
DragEvents.prototype._swipeDirection = function () {
|
|
return settings.directionNames[this.axis][this.movement[this.axis] > 0 ? 0 : 1];
|
|
};
|
|
return DragEvents;
|
|
}());
|
|
export default DragEvents;
|