Repository URL to install this package:
|
Version:
2.5.0-rc.0 ▾
|
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
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 _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
exports.getEventNodeFromPoint = getEventNodeFromPoint;
exports.isEvent = isEvent;
exports.objectsCollide = objectsCollide;
exports.getBoundsForNode = getBoundsForNode;
var _contains = require('dom-helpers/query/contains');
var _contains2 = _interopRequireDefault(_contains);
var _closest = require('dom-helpers/query/closest');
var _closest2 = _interopRequireDefault(_closest);
var _events = require('dom-helpers/events');
var _events2 = _interopRequireDefault(_events);
var _constants = require('./utils/constants');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function addEventListener(type, handler) {
var target = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : document;
// events.on(target, type, handler, { passive: false });
target.addEventListener(type, handler, false);
return {
remove: function remove() {
_events2.default.off(target, type, handler);
}
};
}
function isOverContainer(container, x, y) {
return !container || (0, _contains2.default)(container, document.elementFromPoint(x, y));
}
function getEventNodeFromPoint(node, _ref) {
var clientX = _ref.clientX,
clientY = _ref.clientY;
var target = document.elementFromPoint(clientX, clientY);
return (0, _closest2.default)(target, '.rbc-event', node);
}
function isEvent(node, bounds) {
return !!getEventNodeFromPoint(node, bounds);
}
function getEventCoordinates(e) {
var target = e;
if (e.touches && e.touches.length) {
target = e.touches[0];
} else if (e.changedTouches && e.changedTouches.length) {
target = e.changedTouches[0];
}
return {
clientX: target.clientX,
clientY: target.clientY,
pageX: target.pageX,
pageY: target.pageY
};
}
var clickTolerance = 10;
var clickInterval = 250;
var Selection = function () {
function Selection(node) {
var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref2$global = _ref2.global,
global = _ref2$global === undefined ? false : _ref2$global,
_ref2$longPressThresh = _ref2.longPressThreshold,
longPressThreshold = _ref2$longPressThresh === undefined ? 250 : _ref2$longPressThresh;
_classCallCheck(this, Selection);
this.container = node;
this.globalMouse = !node || global;
this.longPressThreshold = longPressThreshold;
this._listeners = Object.create(null);
this._handleInitialEvent = this._handleInitialEvent.bind(this);
this._handleMoveEvent = this._handleMoveEvent.bind(this);
this._handleTouchMoveEvent = this._handleTouchMoveEvent.bind(this);
this._handleTerminatingEvent = this._handleTerminatingEvent.bind(this);
this._keyListener = this._keyListener.bind(this);
// Fixes an iOS 10 bug where scrolling could not be prevented on the window.
// https://github.com/metafizzy/flickity/issues/457#issuecomment-254501356
this._onTouchMoveWindowListener = addEventListener('touchmove', function () {}, window);
this._onKeyDownListener = addEventListener('keydown', this._keyListener);
this._onKeyUpListener = addEventListener('keyup', this._keyListener);
this._addInitialEventListener();
}
_createClass(Selection, [{
key: 'on',
value: function on(type, handler) {
var handlers = this._listeners[type] || (this._listeners[type] = []);
handlers.push(handler);
return {
remove: function remove() {
var idx = handlers.indexOf(handler);
if (idx !== -1) handlers.splice(idx, 1);
}
};
}
}, {
key: 'emit',
value: function emit(type) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var result = void 0;
var handlers = this._listeners[type] || [];
handlers.forEach(function (fn) {
if (result === undefined) result = fn.apply(undefined, args);
});
return result;
}
}, {
key: 'teardown',
value: function teardown() {
this.listeners = Object.create(null);
this._onTouchMoveWindowListener && this._onTouchMoveWindowListener.remove();
this._onInitialEventListener && this._onInitialEventListener.remove();
this._onEndListener && this._onEndListener.remove();
this._onMoveListener && this._onMoveListener.remove();
this._onKeyUpListener && this._onKeyUpListener.remove();
this._onKeyDownListener && this._onKeyDownListener.remove();
}
}, {
key: 'isSelected',
value: function isSelected(node) {
var box = this._selectRect;
if (!box || !this.selecting) return false;
return objectsCollide(box, getBoundsForNode(node));
}
}, {
key: 'filter',
value: function filter(items) {
var box = this._selectRect;
// not selecting
if (!box || !this.selecting) return [];
return items.filter(this.isSelected, this);
}
// Adds a listener that will call the handler only after the user has pressed on the screen
// without moving their finger for 250ms.
}, {
key: '_addLongPressListener',
value: function _addLongPressListener(handler, initialEvent) {
var _this = this;
var timer = null;
var touchMoveListener = null;
var touchEndListener = null;
var handleTouchStart = function handleTouchStart(initialEvent) {
timer = setTimeout(function () {
cleanup();
handler(initialEvent);
}, _this.longPressThreshold);
touchMoveListener = addEventListener('touchmove', function () {
return cleanup();
});
touchEndListener = addEventListener('touchend', function () {
return cleanup();
});
};
var touchStartListener = addEventListener('touchstart', handleTouchStart);
var cleanup = function cleanup() {
if (timer) {
clearTimeout(timer);
}
if (touchMoveListener) {
touchMoveListener.remove();
}
if (touchEndListener) {
touchEndListener.remove();
}
timer = null;
touchMoveListener = null;
touchEndListener = null;
};
if (initialEvent) {
handleTouchStart(initialEvent);
}
return {
remove: function remove() {
cleanup();
touchStartListener.remove();
}
};
}
// Listen for mousedown and touchstart events. When one is received, disable the other and setup
// future event handling based on the type of event.
}, {
key: '_addInitialEventListener',
value: function _addInitialEventListener() {
var _this2 = this;
var mouseDownListener = addEventListener('mousedown', function (e) {
_this2._onInitialEventListener.remove();
_this2._handleInitialEvent(e);
_this2._onInitialEventListener = addEventListener('mousedown', _this2._handleInitialEvent);
});
var touchStartListener = addEventListener('touchstart', function (e) {
_this2._onInitialEventListener.remove();
_this2._handleInitialEvent(e);
_this2._onInitialEventListener = addEventListener('touchstart', _this2._handleInitialEvent);
});
this._onInitialEventListener = {
remove: function remove() {
mouseDownListener.remove();
touchStartListener.remove();
}
};
}
}, {
key: '_handleInitialEvent',
value: function _handleInitialEvent(e) {
var _getEventCoordinates = getEventCoordinates(e),
clientX = _getEventCoordinates.clientX,
clientY = _getEventCoordinates.clientY,
pageX = _getEventCoordinates.pageX,
pageY = _getEventCoordinates.pageY;
// due to the fact that the IE does not appropriately delete eventlisteners
// should use this check
if (_constants.isIE || _constants.isEdge) {
if (!document.querySelector('.calendar')) return;
}
var node = this.container();
var collides = void 0;
var offsetData = void 0;
// Right clicks
if (e.which === 3 || e.button === 2 || !isOverContainer(node, clientX, clientY)) return;
if (!this.globalMouse && node && !(0, _contains2.default)(node, e.target)) {
var _normalizeDistance = normalizeDistance(0),
top = _normalizeDistance.top,
left = _normalizeDistance.left,
bottom = _normalizeDistance.bottom,
right = _normalizeDistance.right;
offsetData = getBoundsForNode(node);
collides = objectsCollide({
top: offsetData.top - top,
left: offsetData.left - left,
bottom: offsetData.bottom + bottom,
right: offsetData.right + right
}, { top: pageY, left: pageX });
if (!collides) return;
}
var result = this.emit('beforeSelect', this._initialEventData = {
isTouch: /^touch/.test(e.type),
x: pageX,
y: pageY,
clientX: clientX,
clientY: clientY
});
if (result === false) return;
switch (e.type) {
case 'mousedown':
this._onEndListener = addEventListener('mouseup', this._handleTerminatingEvent);
this._onMoveListener = addEventListener('mousemove', this._handleMoveEvent);
break;
case 'touchstart':
this.hoverSlotEnabled = false;
this._onEndListener = addEventListener('touchend', this._handleTerminatingEvent);
this._onMoveListener = addEventListener('touchmove', this._handleTouchMoveEvent);
break;
default:
break;
}
}
}, {
key: '_handleTerminatingEvent',
value: function _handleTerminatingEvent(e) {
var _getEventCoordinates2 = getEventCoordinates(e),
pageX = _getEventCoordinates2.pageX,
pageY = _getEventCoordinates2.pageY;
this.selecting = false;
this._onEndListener && this._onEndListener.remove();
this._onMoveListener && this._onMoveListener.remove();
if (!this._initialEventData) return;
var inRoot = !this.container || (0, _contains2.default)(this.container(), e.target);
var bounds = this._selectRect;
var click = this.isClick(pageX, pageY);
this._initialEventData = null;
if (click && !inRoot) {
return this.emit('reset');
}
if (click && inRoot) {
this.selecting = false;
return this._handleClickEvent(e);
}
// User drag-clicked in the Selectable area
if (!click) return this.emit('select', bounds);
}
}, {
key: '_handleClickEvent',
value: function _handleClickEvent(e) {
var _getEventCoordinates3 = getEventCoordinates(e),
pageX = _getEventCoordinates3.pageX,
pageY = _getEventCoordinates3.pageY,
clientX = _getEventCoordinates3.clientX,
clientY = _getEventCoordinates3.clientY;
var now = new Date().getTime();
var slotHoverCoords = getBoundsForNode(document.querySelector('#rbc-timeslot-hover'));
var clickY = this.hoverSlotEnabled && slotHoverCoords ? slotHoverCoords.top : pageY;
var clickClientY = this.hoverSlotEnabled && slotHoverCoords && slotHoverCoords.y ? slotHoverCoords.y : clientY;
this.hoverSlotEnabled = true;
if (this._lastClickData && now - this._lastClickData.timestamp < clickInterval) {
// Double click event
this._lastClickData = null;
return this.emit('doubleClick', {
event: e,
isTouch: /^touch/.test(e.type),
x: pageX,
y: clickY,
clientX: clientX,
clientY: clickClientY
});
}
// Click event
this._lastClickData = {
timestamp: now
};
return this.emit('click', {
event: e,
isTouch: /^touch/.test(e.type),
x: pageX,
y: clickY,
clientX: clientX,
clientY: clickClientY
});
}
}, {
key: '_handleMoveEvent',
value: function _handleMoveEvent(e) {
if (this._initialEventData === null) {
return;
}
var _initialEventData = this._initialEventData,
x = _initialEventData.x,
y = _initialEventData.y,
isTouch = _initialEventData.isTouch;
var _getEventCoordinates4 = getEventCoordinates(e),
pageX = _getEventCoordinates4.pageX,
pageY = _getEventCoordinates4.pageY;
var w = Math.abs(x - pageX);
var h = Math.abs(y - pageY);
var left = Math.min(pageX, x);
var top = Math.min(pageY, y);
var old = this.selecting;
// Prevent emitting selectStart event until mouse is moved.
// in Chrome on Windows, mouseMove event may be fired just after mouseDown event.
if (!old && !(w || h)) {
return;
}
this.selecting = true;
this._selectRect = {
top: top,
left: left,
isTouch: isTouch,
x: pageX,
y: pageY,
right: left + w,
bottom: top + h,
event: e
};
if (!old) {
this.emit('selectStart', this._initialEventData);
}
if (!this.isClick(pageX, pageY)) this.emit('selecting', this._selectRect);
if (e.cancelable) e.preventDefault();
}
}, {
key: '_handleTouchMoveEvent',
value: function _handleTouchMoveEvent(e) {
if (!this._initialEventData) {
return;
}
var _initialEventData2 = this._initialEventData,
x = _initialEventData2.x,
y = _initialEventData2.y,
isTouch = _initialEventData2.isTouch;
var _getEventCoordinates5 = getEventCoordinates(e),
pageX = _getEventCoordinates5.pageX,
pageY = _getEventCoordinates5.pageY;
var w = Math.abs(x - pageX);
var h = Math.abs(y - pageY);
var left = Math.min(pageX, x);
var top = Math.min(pageY, y);
var old = this.selecting;
// Prevent emitting selectStart event until mouse is moved.
// in Chrome on Windows, mouseMove event may be fired just after mouseDown event.
if (!old && !(w || h)) {
return;
}
this.selecting = true;
this._selectRect = {
top: top,
left: left,
isTouch: isTouch,
x: pageX,
y: pageY,
right: left + w,
bottom: top + h,
event: e
};
if (!old) {
this.emit('selectStart', this._initialEventData);
}
this.emit('selecting', this._selectRect);
}
}, {
key: '_keyListener',
value: function _keyListener(e) {
this.ctrl = e.metaKey || e.ctrlKey;
}
}, {
key: 'isClick',
value: function isClick(pageX, pageY) {
var _initialEventData3 = this._initialEventData,
x = _initialEventData3.x,
y = _initialEventData3.y;
return Math.abs(pageX - x) <= clickTolerance && Math.abs(pageY - y) <= clickTolerance;
}
}]);
return Selection;
}();
/**
* Resolve the disance prop from either an Int or an Object
* @return {Object}
*/
function normalizeDistance() {
var distance = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
if ((typeof distance === 'undefined' ? 'undefined' : _typeof(distance)) !== 'object') distance = {
top: distance,
left: distance,
right: distance,
bottom: distance
};
return distance;
}
/**
* Given two objects containing "top", "left", "offsetWidth" and "offsetHeight"
* properties, determine if they collide.
* @param {Object|HTMLElement} nodeA
* @param {Object|HTMLElement} nodeB
* @param {number} tolerance
* @return {bool}
*/
function objectsCollide(nodeA, nodeB) {
var tolerance = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var _getBoundsForNode = getBoundsForNode(nodeA),
aTop = _getBoundsForNode.top,
aLeft = _getBoundsForNode.left,
_getBoundsForNode$rig = _getBoundsForNode.right,
aRight = _getBoundsForNode$rig === undefined ? aLeft : _getBoundsForNode$rig,
_getBoundsForNode$bot = _getBoundsForNode.bottom,
aBottom = _getBoundsForNode$bot === undefined ? aTop : _getBoundsForNode$bot;
var _getBoundsForNode2 = getBoundsForNode(nodeB),
bTop = _getBoundsForNode2.top,
bLeft = _getBoundsForNode2.left,
_getBoundsForNode2$ri = _getBoundsForNode2.right,
bRight = _getBoundsForNode2$ri === undefined ? bLeft : _getBoundsForNode2$ri,
_getBoundsForNode2$bo = _getBoundsForNode2.bottom,
bBottom = _getBoundsForNode2$bo === undefined ? bTop : _getBoundsForNode2$bo;
return !( // 'a' bottom doesn't touch 'b' top
aBottom - tolerance < bTop ||
// 'a' top doesn't touch 'b' bottom
aTop + tolerance > bBottom ||
// 'a' right doesn't touch 'b' left
aRight - tolerance < bLeft ||
// 'a' left doesn't touch 'b' right
aLeft + tolerance > bRight);
}
/**
* Given a node, get everything needed to calculate its boundaries
* @param {HTMLElement} node
* @return {Object}
*/
function getBoundsForNode(node) {
if (!node || !node.getBoundingClientRect) return node;
var rect = node.getBoundingClientRect();
var left = rect.left + pageOffset('left');
var top = rect.top + pageOffset('top');
return {
x: rect.x,
y: rect.y,
top: top,
left: left,
right: (node.offsetWidth || 0) + left,
bottom: (node.offsetHeight || 0) + top
};
}
function pageOffset(dir) {
if (dir === 'left') return window.pageXOffset || document.body.scrollLeft || 0;
if (dir === 'top') return window.pageYOffset || document.body.scrollTop || 0;
}
exports.default = Selection;