const is = require('../utils/is');
const arr = require('../utils/arr');
function init (scope) {
const {
actions,
InteractEvent,
Interactable,
Interaction,
defaults,
} = scope;
Interaction.signals.on('before-action-move', beforeMove);
Interaction.signals.on('action-resume', beforeMove);
// dragmove
InteractEvent.signals.on('new', newInteractEvent);
Interactable.prototype.draggable = module.exports.draggable;
actions.drag = module.exports;
actions.names.push('drag');
arr.merge(Interactable.eventTypes, [
'dragstart',
'dragmove',
'draginertiastart',
'draginertiaresume',
'dragend',
]);
actions.methodDict.drag = 'draggable';
defaults.drag = module.exports.defaults;
}
function beforeMove ({ interaction }) {
if (interaction.prepared.name !== 'drag') { return; }
const 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;
}
}
function newInteractEvent ({ iEvent, interaction }) {
if (iEvent.type !== 'dragmove') { return; }
const axis = interaction.prepared.axis;
if (axis === 'x') {
iEvent.pageY = interaction.startCoords.page.y;
iEvent.clientY = interaction.startCoords.client.y;
iEvent.dy = 0;
}
else if (axis === 'y') {
iEvent.pageX = interaction.startCoords.page.x;
iEvent.clientX = interaction.startCoords.client.x;
iEvent.dx = 0;
}
}
/**
* ```js
* interact(element).draggable({
* onstart: function (event) {},
* onmove : function (event) {},
* onend : function (event) {},
*
* // the axis in which the first movement must be
* // for the drag sequence to start
* // 'xy' by default - any direction
* startAxis: 'x' || 'y' || 'xy',
*
* // 'xy' by default - don't restrict to one axis (move in any direction)
* // 'x' or 'y' to restrict movement to either axis
* // 'start' to restrict movement to the axis the drag started in
* lockAxis: 'x' || 'y' || 'xy' || 'start',
*
* // max number of drags that can happen concurrently
* // with elements of this Interactable. Infinity by default
* max: Infinity,
*
* // max number of drags that can target the same element+Interactable
* // 1 by default
* maxPerElement: 2
* });
*
* var isDraggable = interact('element').draggable(); // true
* ```
*
* Get or set whether drag actions can be performed on the target
*
* @alias Interactable.prototype.draggable
*
* @param {boolean | object} [options] true/false or An object with event
* listeners to be fired on drag events (object makes the Interactable
* draggable)
* @return {boolean | Interactable} boolean indicating if this can be the
* target of drag events, or this Interctable
*/
function draggable (options) {
if (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 (is.bool(options)) {
this.options.drag.enabled = options;
if (!options) {
this.ondragstart = this.ondragstart = this.ondragend = null;
}
return this;
}
return this.options.drag;
}
module.exports = {
init,
draggable,
beforeMove,
newInteractEvent,
defaults: {
startAxis : 'xy',
lockAxis : 'xy',
},
checker (pointer, event, interactable) {
const dragOptions = interactable.options.drag;
return dragOptions.enabled
? {
name: 'drag',
axis: (dragOptions.lockAxis === 'start'
? dragOptions.startAxis
: dragOptions.lockAxis),
}
: null;
},
getCursor () {
return 'move';
},
};