react-draggable
Version:
React draggable component
336 lines (297 loc) • 8.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.matchesSelector = matchesSelector;
exports.matchesSelectorAndParentsTo = matchesSelectorAndParentsTo;
exports.addEvent = addEvent;
exports.removeEvent = removeEvent;
exports.outerHeight = outerHeight;
exports.outerWidth = outerWidth;
exports.innerHeight = innerHeight;
exports.innerWidth = innerWidth;
exports.offsetXYFromParent = offsetXYFromParent;
exports.createCSSTransform = createCSSTransform;
exports.createSVGTransform = createSVGTransform;
exports.getTranslation = getTranslation;
exports.getTouch = getTouch;
exports.getTouchIdentifier = getTouchIdentifier;
exports.addUserSelectStyles = addUserSelectStyles;
exports.removeUserSelectStyles = removeUserSelectStyles;
exports.styleHacks = styleHacks;
exports.addClassName = addClassName;
exports.removeClassName = removeClassName;
var _shims = require("./shims");
var _getPrefix = _interopRequireWildcard(require("./getPrefix"));
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
let matchesSelectorFunc = '';
function matchesSelector(el
/*: Node*/
, selector
/*: string*/
)
/*: boolean*/
{
if (!matchesSelectorFunc) {
matchesSelectorFunc = (0, _shims.findInArray)(['matches', 'webkitMatchesSelector', 'mozMatchesSelector', 'msMatchesSelector', 'oMatchesSelector'], function (method) {
// $FlowIgnore: Doesn't think elements are indexable
return (0, _shims.isFunction)(el[method]);
});
} // Might not be found entirely (not an Element?) - in that case, bail
// $FlowIgnore: Doesn't think elements are indexable
if (!(0, _shims.isFunction)(el[matchesSelectorFunc])) return false; // $FlowIgnore: Doesn't think elements are indexable
return el[matchesSelectorFunc](selector);
} // Works up the tree to the draggable itself attempting to match selector.
function matchesSelectorAndParentsTo(el
/*: Node*/
, selector
/*: string*/
, baseNode
/*: Node*/
)
/*: boolean*/
{
let node = el;
do {
if (matchesSelector(node, selector)) return true;
if (node === baseNode) return false;
node = node.parentNode;
} while (node);
return false;
}
function addEvent(el
/*: ?Node*/
, event
/*: string*/
, handler
/*: Function*/
)
/*: void*/
{
if (!el) {
return;
}
if (el.attachEvent) {
el.attachEvent('on' + event, handler);
} else if (el.addEventListener) {
el.addEventListener(event, handler, true);
} else {
// $FlowIgnore: Doesn't think elements are indexable
el['on' + event] = handler;
}
}
function removeEvent(el
/*: ?Node*/
, event
/*: string*/
, handler
/*: Function*/
)
/*: void*/
{
if (!el) {
return;
}
if (el.detachEvent) {
el.detachEvent('on' + event, handler);
} else if (el.removeEventListener) {
el.removeEventListener(event, handler, true);
} else {
// $FlowIgnore: Doesn't think elements are indexable
el['on' + event] = null;
}
}
function outerHeight(node
/*: HTMLElement*/
)
/*: number*/
{
// This is deliberately excluding margin for our calculations, since we are using
// offsetTop which is including margin. See getBoundPosition
let height = node.clientHeight;
const computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
height += (0, _shims.int)(computedStyle.borderTopWidth);
height += (0, _shims.int)(computedStyle.borderBottomWidth);
return height;
}
function outerWidth(node
/*: HTMLElement*/
)
/*: number*/
{
// This is deliberately excluding margin for our calculations, since we are using
// offsetLeft which is including margin. See getBoundPosition
let width = node.clientWidth;
const computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
width += (0, _shims.int)(computedStyle.borderLeftWidth);
width += (0, _shims.int)(computedStyle.borderRightWidth);
return width;
}
function innerHeight(node
/*: HTMLElement*/
)
/*: number*/
{
let height = node.clientHeight;
const computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
height -= (0, _shims.int)(computedStyle.paddingTop);
height -= (0, _shims.int)(computedStyle.paddingBottom);
return height;
}
function innerWidth(node
/*: HTMLElement*/
)
/*: number*/
{
let width = node.clientWidth;
const computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
width -= (0, _shims.int)(computedStyle.paddingLeft);
width -= (0, _shims.int)(computedStyle.paddingRight);
return width;
} // Get from offsetParent
function offsetXYFromParent(evt
/*: {clientX: number, clientY: number}*/
, offsetParent
/*: HTMLElement*/
)
/*: ControlPosition*/
{
const isBody = offsetParent === offsetParent.ownerDocument.body;
const offsetParentRect = isBody ? {
left: 0,
top: 0
} : offsetParent.getBoundingClientRect();
const x = evt.clientX + offsetParent.scrollLeft - offsetParentRect.left;
const y = evt.clientY + offsetParent.scrollTop - offsetParentRect.top;
return {
x,
y
};
}
function createCSSTransform(controlPos
/*: ControlPosition*/
, positionOffset
/*: PositionOffsetControlPosition*/
)
/*: Object*/
{
const translation = getTranslation(controlPos, positionOffset, 'px');
return {
[(0, _getPrefix.browserPrefixToKey)('transform', _getPrefix.default)]: translation
};
}
function createSVGTransform(controlPos
/*: ControlPosition*/
, positionOffset
/*: PositionOffsetControlPosition*/
)
/*: string*/
{
const translation = getTranslation(controlPos, positionOffset, '');
return translation;
}
function getTranslation({
x,
y
}
/*: ControlPosition*/
, positionOffset
/*: PositionOffsetControlPosition*/
, unitSuffix
/*: string*/
)
/*: string*/
{
let translation = `translate(${x}${unitSuffix},${y}${unitSuffix})`;
if (positionOffset) {
const defaultX = `${typeof positionOffset.x === 'string' ? positionOffset.x : positionOffset.x + unitSuffix}`;
const defaultY = `${typeof positionOffset.y === 'string' ? positionOffset.y : positionOffset.y + unitSuffix}`;
translation = `translate(${defaultX}, ${defaultY})` + translation;
}
return translation;
}
function getTouch(e
/*: MouseTouchEvent*/
, identifier
/*: number*/
)
/*: ?{clientX: number, clientY: number}*/
{
return e.targetTouches && (0, _shims.findInArray)(e.targetTouches, t => identifier === t.identifier) || e.changedTouches && (0, _shims.findInArray)(e.changedTouches, t => identifier === t.identifier);
}
function getTouchIdentifier(e
/*: MouseTouchEvent*/
)
/*: ?number*/
{
if (e.targetTouches && e.targetTouches[0]) return e.targetTouches[0].identifier;
if (e.changedTouches && e.changedTouches[0]) return e.changedTouches[0].identifier;
} // User-select Hacks:
//
// Useful for preventing blue highlights all over everything when dragging.
// Note we're passing `document` b/c we could be iframed
function addUserSelectStyles(doc
/*: ?Document*/
) {
if (!doc) return;
let styleEl = doc.getElementById('react-draggable-style-el');
if (!styleEl) {
styleEl = doc.createElement('style');
styleEl.type = 'text/css';
styleEl.id = 'react-draggable-style-el';
styleEl.innerHTML = '.react-draggable-transparent-selection *::-moz-selection {all: inherit;}\n';
styleEl.innerHTML += '.react-draggable-transparent-selection *::selection {all: inherit;}\n';
doc.getElementsByTagName('head')[0].appendChild(styleEl);
}
if (doc.body) addClassName(doc.body, 'react-draggable-transparent-selection');
}
function removeUserSelectStyles(doc
/*: ?Document*/
) {
try {
if (doc && doc.body) removeClassName(doc.body, 'react-draggable-transparent-selection'); // $FlowIgnore: IE
if (doc.selection) {
// $FlowIgnore: IE
doc.selection.empty();
} else {
window.getSelection().removeAllRanges(); // remove selection caused by scroll
}
} catch (e) {// probably IE
}
}
function styleHacks(childStyle
/*: Object*/
= {})
/*: Object*/
{
// Workaround IE pointer events; see #51
// https://github.com/mzabriskie/react-draggable/issues/51#issuecomment-103488278
return {
touchAction: 'none',
...childStyle
};
}
function addClassName(el
/*: HTMLElement*/
, className
/*: string*/
) {
if (el.classList) {
el.classList.add(className);
} else {
if (!el.className.match(new RegExp(`(?:^|\\s)${className}(?!\\S)`))) {
el.className += ` ${className}`;
}
}
}
function removeClassName(el
/*: HTMLElement*/
, className
/*: string*/
) {
if (el.classList) {
el.classList.remove(className);
} else {
el.className = el.className.replace(new RegExp(`(?:^|\\s)${className}(?!\\S)`, 'g'), '');
}
}