@baleada/listenable-gestures
Version:
A collection of gesture recognizers that are compatible with Baleada Logic's Listenable class.
173 lines (154 loc) • 4.77 kB
JavaScript
import { emit, toEmitted, naiveDeepClone, getGetPoint, isDefined } from '../util';
/*
* clicks is defined as a single mouse that:
* - starts at a given point
* - does not move beyond a maximum distance
* - does not cancel
* - ends
* - repeats 2 times (or a minimum number of your choice), with each click ending less than or equal to 500ms (or a maximum interval of your choice) after the previous click ended
*/
var defaultOptions = {
minClicks: 1,
maxInterval: 500,
// Via https://ux.stackexchange.com/questions/40364/what-is-the-expected-timeframe-of-a-double-click
maxDistance: 5 // TODO: research standard maxDistance
};
export default function clicks() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var onDown = options.onDown,
onMove = options.onMove,
onLeave = options.onLeave,
onUp = options.onUp,
minClicks = isDefined(options.minClicks) ? options.minClicks : defaultOptions.minClicks,
maxInterval = isDefined(options.maxInterval) ? options.maxInterval : defaultOptions.maxInterval,
maxDistance = isDefined(options.maxDistance) ? options.maxDistance : defaultOptions.maxDistance;
function mousedown(handlerApi) {
var event = handlerApi.event,
setMetadata = handlerApi.setMetadata;
setMetadata({
path: 'mouseStatus',
value: 'down'
});
setMetadata({
path: 'lastClick.times.start',
value: event.timeStamp
});
var getPoint = getGetPoint('mouse');
setMetadata({
path: 'lastClick.points.start',
value: getPoint(event)
});
emit(onDown, toEmitted(handlerApi));
}
function mousemove(handlerApi) {
var getMetadata = handlerApi.getMetadata,
denied = handlerApi.denied;
if (getMetadata().mouseStatus !== 'down') {
denied();
}
emit(onMove, toEmitted(handlerApi));
}
function mouseleave(handlerApi) {
var getMetadata = handlerApi.getMetadata,
denied = handlerApi.denied;
if (getMetadata().mouseStatus === 'down') {
denied();
setMetadata({
path: 'mouseStatus',
value: 'leave'
});
}
emit(onLeave, toEmitted(handlerApi));
}
function mouseup(handlerApi) {
var event = handlerApi.event,
getMetadata = handlerApi.getMetadata,
toPolarCoordinates = handlerApi.toPolarCoordinates,
setMetadata = handlerApi.setMetadata,
pushMetadata = handlerApi.pushMetadata;
setMetadata({
path: 'mouseStatus',
value: 'up'
});
var _getMetadata$lastClic = getMetadata().lastClick.points.start,
xA = _getMetadata$lastClic.x,
yA = _getMetadata$lastClic.y,
xB = event.clientX,
yB = event.clientY,
_toPolarCoordinates = toPolarCoordinates({
xA: xA,
xB: xB,
yA: yA,
yB: yB
}),
distance = _toPolarCoordinates.distance,
endPoint = {
x: xB,
y: yB
},
endTime = event.timeStamp;
setMetadata({
path: 'lastClick.points.end',
value: endPoint
});
setMetadata({
path: 'lastClick.times.end',
value: endTime
});
setMetadata({
path: 'lastClick.distance',
value: distance
});
if (!Array.isArray(getMetadata().clicks)) {
setMetadata({
path: 'clicks',
value: []
});
}
var interval = getMetadata().clicks.length === 0 ? 0 : endTime - getMetadata().clicks[getMetadata().clicks.length - 1].times.end;
setMetadata({
path: 'lastClick.interval',
value: interval
});
var newClick = naiveDeepClone(getMetadata().lastClick);
pushMetadata({
path: 'clicks',
value: newClick
});
recognize(handlerApi);
emit(onUp, toEmitted(handlerApi));
}
function recognize(_ref) {
var getMetadata = _ref.getMetadata,
denied = _ref.denied,
setMetadata = _ref.setMetadata,
pushMetadata = _ref.pushMetadata,
recognized = _ref.recognized;
switch (true) {
case getMetadata().lastClick.interval > maxInterval || getMetadata().lastClick.distance > maxDistance:
// Deny after multiple touches and after clicks with intervals or movement distances that are too large
var lastClick = naiveDeepClone(getMetadata().lastClick);
denied();
setMetadata({
path: 'clicks',
value: []
});
pushMetadata({
path: 'clicks',
value: lastClick
});
break;
default:
if (getMetadata().clicks.length >= minClicks) {
recognized();
}
break;
}
}
return {
mousedown: mousedown,
mousemove: mousemove,
mouseleave: mouseleave,
mouseup: mouseup
};
}