@interactjs/utils
Advanced tools
Comparing version 1.4.0-alpha.17 to 1.4.0-alpha.18
51
arr.js
@@ -1,37 +0,30 @@ | ||
export function contains (array, target) { | ||
return array.indexOf(target) !== -1; | ||
export function contains(array, target) { | ||
return array.indexOf(target) !== -1; | ||
} | ||
export function remove (array, target) { | ||
return array.splice(array.indexOf(target), 1); | ||
export function remove(array, target) { | ||
return array.splice(array.indexOf(target), 1); | ||
} | ||
export function merge (target, source) { | ||
for (const item of source) { | ||
target.push(item); | ||
} | ||
return target; | ||
export function merge(target, source) { | ||
for (const item of source) { | ||
target.push(item); | ||
} | ||
return target; | ||
} | ||
export function from (source) { | ||
return merge([], source); | ||
export function from(source) { | ||
return merge([], source); | ||
} | ||
export function findIndex (array, func) { | ||
for (let i = 0; i < array.length; i++) { | ||
if (func(array[i], i, array)) { | ||
return i; | ||
export function findIndex(array, func) { | ||
for (let i = 0; i < array.length; i++) { | ||
if (func(array[i], i, array)) { | ||
return i; | ||
} | ||
} | ||
} | ||
return -1; | ||
return -1; | ||
} | ||
export function find (array, func) { | ||
return array[findIndex(array, func)]; | ||
export function find(array, func) { | ||
return array[findIndex(array, func)]; | ||
} | ||
export function some (array, func) { | ||
return findIndex(array, func) !== -1; | ||
export function some(array, func) { | ||
return findIndex(array, func) !== -1; | ||
} | ||
//# sourceMappingURL=arr.js.map |
122
browser.js
import win from './window'; | ||
import * as is from './is'; | ||
import domObjects from './domObjects'; | ||
const browser = { | ||
init, | ||
init, | ||
supportsTouch: null, | ||
supportsPointerEvent: null, | ||
isIOS7: null, | ||
isIOS: null, | ||
isIe9: null, | ||
isOperaMobile: null, | ||
prefixedMatchesSelector: null, | ||
pEventTypes: null, | ||
wheelEvent: null, | ||
}; | ||
function init(window) { | ||
const Element = domObjects.Element; | ||
const navigator = win.window.navigator; | ||
// Does the browser support touch input? | ||
browser.supportsTouch = !!(('ontouchstart' in window) || is.func(window.DocumentTouch) | ||
&& domObjects.document instanceof window.DocumentTouch); | ||
// Does the browser support PointerEvents | ||
browser.supportsPointerEvent = !!domObjects.PointerEvent; | ||
browser.isIOS = (/iP(hone|od|ad)/.test(navigator.platform)); | ||
// scrolling doesn't change the result of getClientRects on iOS 7 | ||
browser.isIOS7 = (/iP(hone|od|ad)/.test(navigator.platform) | ||
&& /OS 7[^\d]/.test(navigator.appVersion)); | ||
browser.isIe9 = /MSIE 9/.test(navigator.userAgent); | ||
// Opera Mobile must be handled differently | ||
browser.isOperaMobile = (navigator.appName === 'Opera' | ||
&& browser.supportsTouch | ||
&& navigator.userAgent.match('Presto')); | ||
// prefix matchesSelector | ||
browser.prefixedMatchesSelector = 'matches' in Element.prototype | ||
? 'matches' | ||
: 'webkitMatchesSelector' in Element.prototype | ||
? 'webkitMatchesSelector' | ||
: 'mozMatchesSelector' in Element.prototype | ||
? 'mozMatchesSelector' | ||
: 'oMatchesSelector' in Element.prototype | ||
? 'oMatchesSelector' | ||
: 'msMatchesSelector'; | ||
browser.pEventTypes = (domObjects.PointerEvent | ||
? (domObjects.PointerEvent === window.MSPointerEvent | ||
? { | ||
up: 'MSPointerUp', | ||
down: 'MSPointerDown', | ||
over: 'mouseover', | ||
out: 'mouseout', | ||
move: 'MSPointerMove', | ||
cancel: 'MSPointerCancel', | ||
} | ||
: { | ||
up: 'pointerup', | ||
down: 'pointerdown', | ||
over: 'pointerover', | ||
out: 'pointerout', | ||
move: 'pointermove', | ||
cancel: 'pointercancel', | ||
}) | ||
: null); | ||
// because Webkit and Opera still use 'mousewheel' event type | ||
browser.wheelEvent = 'onmousewheel' in domObjects.document ? 'mousewheel' : 'wheel'; | ||
} | ||
export default browser; | ||
function init (window) { | ||
const Element = domObjects.Element; | ||
const navigator = win.window.navigator; | ||
// Does the browser support touch input? | ||
browser.supportsTouch = !!(('ontouchstart' in window) || is.func(window.DocumentTouch) | ||
&& domObjects.document instanceof window.DocumentTouch); | ||
// Does the browser support PointerEvents | ||
browser.supportsPointerEvent = !!domObjects.PointerEvent; | ||
browser.isIOS = (/iP(hone|od|ad)/.test(navigator.platform)); | ||
// scrolling doesn't change the result of getClientRects on iOS 7 | ||
browser.isIOS7 = (/iP(hone|od|ad)/.test(navigator.platform) | ||
&& /OS 7[^\d]/.test(navigator.appVersion)); | ||
browser.isIe9 = /MSIE 9/.test(navigator.userAgent); | ||
// prefix matchesSelector | ||
browser.prefixedMatchesSelector = 'matches' in Element.prototype | ||
? 'matches' | ||
: 'webkitMatchesSelector' in Element.prototype | ||
? 'webkitMatchesSelector' | ||
: 'mozMatchesSelector' in Element.prototype | ||
? 'mozMatchesSelector' | ||
: 'oMatchesSelector' in Element.prototype | ||
? 'oMatchesSelector' | ||
: 'msMatchesSelector'; | ||
browser.pEventTypes = (domObjects.PointerEvent | ||
? (domObjects.PointerEvent === window.MSPointerEvent | ||
? { | ||
up: 'MSPointerUp', | ||
down: 'MSPointerDown', | ||
over: 'mouseover', | ||
out: 'mouseout', | ||
move: 'MSPointerMove', | ||
cancel: 'MSPointerCancel', | ||
} | ||
: { | ||
up: 'pointerup', | ||
down: 'pointerdown', | ||
over: 'pointerover', | ||
out: 'pointerout', | ||
move: 'pointermove', | ||
cancel: 'pointercancel', | ||
}) | ||
: null); | ||
// because Webkit and Opera still use 'mousewheel' event type | ||
browser.wheelEvent = 'onmousewheel' in domObjects.document? 'mousewheel': 'wheel'; | ||
// Opera Mobile must be handled differently | ||
browser.isOperaMobile = (navigator.appName === 'Opera' | ||
&& browser.supportsTouch | ||
&& navigator.userAgent.match('Presto')); | ||
} | ||
//# sourceMappingURL=browser.js.map |
35
clone.js
@@ -0,22 +1,19 @@ | ||
import * as arr from './arr'; | ||
import * as is from './is'; | ||
import * as arr from './arr'; | ||
export default function clone (source) { | ||
const dest = {}; | ||
for (const prop in source) { | ||
const value = source[prop]; | ||
if (is.plainObject(value)) { | ||
dest[prop] = clone(value); | ||
export default function clone(source) { | ||
const dest = {}; | ||
for (const prop in source) { | ||
const value = source[prop]; | ||
if (is.plainObject(value)) { | ||
dest[prop] = clone(value); | ||
} | ||
else if (is.array(value)) { | ||
dest[prop] = arr.from(value); | ||
} | ||
else { | ||
dest[prop] = value; | ||
} | ||
} | ||
else if (is.array(value)) { | ||
dest[prop] = arr.from(value); | ||
} | ||
else { | ||
dest[prop] = value; | ||
} | ||
} | ||
return dest; | ||
return dest; | ||
} | ||
//# sourceMappingURL=clone.js.map |
const domObjects = { | ||
init, | ||
init, | ||
document: null, | ||
DocumentFragment: null, | ||
SVGElement: null, | ||
SVGSVGElement: null, | ||
// eslint-disable-next-line no-undef | ||
SVGElementInstance: null, | ||
Element: null, | ||
HTMLElement: null, | ||
Event: null, | ||
Touch: null, | ||
PointerEvent: null, | ||
}; | ||
function blank () {} | ||
function blank() { } | ||
export default domObjects; | ||
function init (window) { | ||
domObjects.document = window.document; | ||
domObjects.DocumentFragment = window.DocumentFragment || blank; | ||
domObjects.SVGElement = window.SVGElement || blank; | ||
domObjects.SVGSVGElement = window.SVGSVGElement || blank; | ||
domObjects.SVGElementInstance = window.SVGElementInstance || blank; | ||
domObjects.Element = window.Element || blank; | ||
domObjects.HTMLElement = window.HTMLElement || domObjects.Element; | ||
domObjects.Event = window.Event; | ||
domObjects.Touch = window.Touch || blank; | ||
domObjects.PointerEvent = (window.PointerEvent || window.MSPointerEvent); | ||
function init(window) { | ||
const win = window; | ||
domObjects.document = win.document; | ||
domObjects.DocumentFragment = win.DocumentFragment || blank; | ||
domObjects.SVGElement = win.SVGElement || blank; | ||
domObjects.SVGSVGElement = win.SVGSVGElement || blank; | ||
domObjects.SVGElementInstance = win.SVGElementInstance || blank; | ||
domObjects.Element = win.Element || blank; | ||
domObjects.HTMLElement = win.HTMLElement || domObjects.Element; | ||
domObjects.Event = win.Event; | ||
domObjects.Touch = win.Touch || blank; | ||
domObjects.PointerEvent = (win.PointerEvent || win.MSPointerEvent); | ||
} | ||
//# sourceMappingURL=domObjects.js.map |
383
domUtils.js
@@ -1,232 +0,189 @@ | ||
import win from './window'; | ||
import browser from './browser'; | ||
import * as is from './is'; | ||
import win from './window'; | ||
import browser from './browser'; | ||
import * as is from './is'; | ||
import domObjects from './domObjects'; | ||
export function nodeContains (parent, child) { | ||
while (child) { | ||
if (child === parent) { | ||
return true; | ||
export function nodeContains(parent, child) { | ||
while (child) { | ||
if (child === parent) { | ||
return true; | ||
} | ||
child = child.parentNode; | ||
} | ||
child = child.parentNode; | ||
} | ||
return false; | ||
return false; | ||
} | ||
export function closest (element, selector) { | ||
while (is.element(element)) { | ||
if (matchesSelector(element, selector)) { return element; } | ||
element = parentNode(element); | ||
} | ||
return null; | ||
export function closest(element, selector) { | ||
while (is.element(element)) { | ||
if (matchesSelector(element, selector)) { | ||
return element; | ||
} | ||
element = parentNode(element); | ||
} | ||
return null; | ||
} | ||
export function parentNode (node) { | ||
let parent = node.parentNode; | ||
if (is.docFrag(parent)) { | ||
// skip past #shado-root fragments | ||
while ((parent = parent.host) && is.docFrag(parent)) { | ||
continue; | ||
export function parentNode(node) { | ||
let parent = node.parentNode; | ||
if (is.docFrag(parent)) { | ||
// skip past #shado-root fragments | ||
while ((parent = parent.host) && is.docFrag(parent)) { | ||
continue; | ||
} | ||
return parent; | ||
} | ||
return parent; | ||
} | ||
return parent; | ||
} | ||
export function matchesSelector (element, selector) { | ||
// remove /deep/ from selectors if shadowDOM polyfill is used | ||
if (win.window !== win.realWindow) { | ||
selector = selector.replace(/\/deep\//g, ' '); | ||
} | ||
return element[browser.prefixedMatchesSelector](selector); | ||
export function matchesSelector(element, selector) { | ||
// remove /deep/ from selectors if shadowDOM polyfill is used | ||
if (win.window !== win.realWindow) { | ||
selector = selector.replace(/\/deep\//g, ' '); | ||
} | ||
return element[browser.prefixedMatchesSelector](selector); | ||
} | ||
// Test for the element that's "above" all other qualifiers | ||
export function indexOfDeepestElement (elements) { | ||
let deepestZoneParents = []; | ||
let dropzoneParents = []; | ||
let dropzone; | ||
let deepestZone = elements[0]; | ||
let index = deepestZone? 0: -1; | ||
let parent; | ||
let child; | ||
let i; | ||
let n; | ||
for (i = 1; i < elements.length; i++) { | ||
dropzone = elements[i]; | ||
// an element might belong to multiple selector dropzones | ||
if (!dropzone || dropzone === deepestZone) { | ||
continue; | ||
export function indexOfDeepestElement(elements) { | ||
let deepestZoneParents = []; | ||
let dropzoneParents = []; | ||
let dropzone; | ||
let deepestZone = elements[0]; | ||
let index = deepestZone ? 0 : -1; | ||
let parent; | ||
let child; | ||
let i; | ||
let n; | ||
for (i = 1; i < elements.length; i++) { | ||
dropzone = elements[i]; | ||
// an element might belong to multiple selector dropzones | ||
if (!dropzone || dropzone === deepestZone) { | ||
continue; | ||
} | ||
if (!deepestZone) { | ||
deepestZone = dropzone; | ||
index = i; | ||
continue; | ||
} | ||
// check if the deepest or current are document.documentElement or document.rootElement | ||
// - if the current dropzone is, do nothing and continue | ||
if (dropzone.parentNode === dropzone.ownerDocument) { | ||
continue; | ||
} | ||
// - if deepest is, update with the current dropzone and continue to next | ||
else if (deepestZone.parentNode === dropzone.ownerDocument) { | ||
deepestZone = dropzone; | ||
index = i; | ||
continue; | ||
} | ||
if (!deepestZoneParents.length) { | ||
parent = deepestZone; | ||
while (parent.parentNode && parent.parentNode !== parent.ownerDocument) { | ||
deepestZoneParents.unshift(parent); | ||
parent = parent.parentNode; | ||
} | ||
} | ||
// if this element is an svg element and the current deepest is | ||
// an HTMLElement | ||
if (deepestZone instanceof domObjects.HTMLElement | ||
&& dropzone instanceof domObjects.SVGElement | ||
&& !(dropzone instanceof domObjects.SVGSVGElement)) { | ||
if (dropzone === deepestZone.parentNode) { | ||
continue; | ||
} | ||
parent = dropzone.ownerSVGElement; | ||
} | ||
else { | ||
parent = dropzone; | ||
} | ||
dropzoneParents = []; | ||
while (parent.parentNode !== parent.ownerDocument) { | ||
dropzoneParents.unshift(parent); | ||
parent = parent.parentNode; | ||
} | ||
n = 0; | ||
// get (position of last common ancestor) + 1 | ||
while (dropzoneParents[n] && dropzoneParents[n] === deepestZoneParents[n]) { | ||
n++; | ||
} | ||
const parents = [ | ||
dropzoneParents[n - 1], | ||
dropzoneParents[n], | ||
deepestZoneParents[n], | ||
]; | ||
child = parents[0].lastChild; | ||
while (child) { | ||
if (child === parents[1]) { | ||
deepestZone = dropzone; | ||
index = i; | ||
deepestZoneParents = []; | ||
break; | ||
} | ||
else if (child === parents[2]) { | ||
break; | ||
} | ||
child = child.previousSibling; | ||
} | ||
} | ||
if (!deepestZone) { | ||
deepestZone = dropzone; | ||
index = i; | ||
continue; | ||
} | ||
// check if the deepest or current are document.documentElement or document.rootElement | ||
// - if the current dropzone is, do nothing and continue | ||
if (dropzone.parentNode === dropzone.ownerDocument) { | ||
continue; | ||
} | ||
// - if deepest is, update with the current dropzone and continue to next | ||
else if (deepestZone.parentNode === dropzone.ownerDocument) { | ||
deepestZone = dropzone; | ||
index = i; | ||
continue; | ||
} | ||
if (!deepestZoneParents.length) { | ||
parent = deepestZone; | ||
while (parent.parentNode && parent.parentNode !== parent.ownerDocument) { | ||
deepestZoneParents.unshift(parent); | ||
parent = parent.parentNode; | ||
} | ||
} | ||
// if this element is an svg element and the current deepest is | ||
// an HTMLElement | ||
if (deepestZone instanceof domObjects.HTMLElement | ||
&& dropzone instanceof domObjects.SVGElement | ||
&& !(dropzone instanceof domObjects.SVGSVGElement)) { | ||
if (dropzone === deepestZone.parentNode) { | ||
continue; | ||
} | ||
parent = dropzone.ownerSVGElement; | ||
} | ||
else { | ||
parent = dropzone; | ||
} | ||
dropzoneParents = []; | ||
while (parent.parentNode !== parent.ownerDocument) { | ||
dropzoneParents.unshift(parent); | ||
parent = parent.parentNode; | ||
} | ||
n = 0; | ||
// get (position of last common ancestor) + 1 | ||
while (dropzoneParents[n] && dropzoneParents[n] === deepestZoneParents[n]) { | ||
n++; | ||
} | ||
const parents = [ | ||
dropzoneParents[n - 1], | ||
dropzoneParents[n], | ||
deepestZoneParents[n], | ||
]; | ||
child = parents[0].lastChild; | ||
while (child) { | ||
if (child === parents[1]) { | ||
deepestZone = dropzone; | ||
index = i; | ||
deepestZoneParents = []; | ||
break; | ||
} | ||
else if (child === parents[2]) { | ||
break; | ||
} | ||
child = child.previousSibling; | ||
} | ||
} | ||
return index; | ||
return index; | ||
} | ||
export function matchesUpTo (element, selector, limit) { | ||
while (is.element(element)) { | ||
if (matchesSelector(element, selector)) { | ||
return true; | ||
export function matchesUpTo(element, selector, limit) { | ||
while (is.element(element)) { | ||
if (matchesSelector(element, selector)) { | ||
return true; | ||
} | ||
element = parentNode(element); | ||
if (element === limit) { | ||
return matchesSelector(element, selector); | ||
} | ||
} | ||
element = parentNode(element); | ||
if (element === limit) { | ||
return matchesSelector(element, selector); | ||
} | ||
} | ||
return false; | ||
return false; | ||
} | ||
export function getActualElement (element) { | ||
return (element instanceof domObjects.SVGElementInstance | ||
? element.correspondingUseElement | ||
: element); | ||
export function getActualElement(element) { | ||
return (element instanceof domObjects.SVGElementInstance | ||
? element.correspondingUseElement | ||
: element); | ||
} | ||
export function getScrollXY (relevantWindow) { | ||
relevantWindow = relevantWindow || win.window; | ||
return { | ||
x: relevantWindow.scrollX || relevantWindow.document.documentElement.scrollLeft, | ||
y: relevantWindow.scrollY || relevantWindow.document.documentElement.scrollTop, | ||
}; | ||
export function getScrollXY(relevantWindow) { | ||
relevantWindow = relevantWindow || win.window; | ||
return { | ||
x: relevantWindow.scrollX || relevantWindow.document.documentElement.scrollLeft, | ||
y: relevantWindow.scrollY || relevantWindow.document.documentElement.scrollTop, | ||
}; | ||
} | ||
export function getElementClientRect (element) { | ||
const clientRect = (element instanceof domObjects.SVGElement | ||
? element.getBoundingClientRect() | ||
: element.getClientRects()[0]); | ||
return clientRect && { | ||
left : clientRect.left, | ||
right : clientRect.right, | ||
top : clientRect.top, | ||
bottom: clientRect.bottom, | ||
width : clientRect.width || clientRect.right - clientRect.left, | ||
height: clientRect.height || clientRect.bottom - clientRect.top, | ||
}; | ||
export function getElementClientRect(element) { | ||
const clientRect = (element instanceof domObjects.SVGElement | ||
? element.getBoundingClientRect() | ||
: element.getClientRects()[0]); | ||
return clientRect && { | ||
left: clientRect.left, | ||
right: clientRect.right, | ||
top: clientRect.top, | ||
bottom: clientRect.bottom, | ||
width: clientRect.width || clientRect.right - clientRect.left, | ||
height: clientRect.height || clientRect.bottom - clientRect.top, | ||
}; | ||
} | ||
export function getElementRect (element) { | ||
const clientRect = getElementClientRect(element); | ||
if (!browser.isIOS7 && clientRect) { | ||
const scroll = getScrollXY(win.getWindow(element)); | ||
clientRect.left += scroll.x; | ||
clientRect.right += scroll.x; | ||
clientRect.top += scroll.y; | ||
clientRect.bottom += scroll.y; | ||
} | ||
return clientRect; | ||
export function getElementRect(element) { | ||
const clientRect = getElementClientRect(element); | ||
if (!browser.isIOS7 && clientRect) { | ||
const scroll = getScrollXY(win.getWindow(element)); | ||
clientRect.left += scroll.x; | ||
clientRect.right += scroll.x; | ||
clientRect.top += scroll.y; | ||
clientRect.bottom += scroll.y; | ||
} | ||
return clientRect; | ||
} | ||
export function getPath (element) { | ||
const path = []; | ||
while (element) { | ||
path.push(element); | ||
element = parentNode(element); | ||
} | ||
return path; | ||
export function getPath(element) { | ||
const path = []; | ||
while (element) { | ||
path.push(element); | ||
element = parentNode(element); | ||
} | ||
return path; | ||
} | ||
export function trySelector (value) { | ||
if (!is.string(value)) { return false; } | ||
// an exception will be raised if it is invalid | ||
domObjects.document.querySelector(value); | ||
return true; | ||
export function trySelector(value) { | ||
if (!is.string(value)) { | ||
return false; | ||
} | ||
// an exception will be raised if it is invalid | ||
domObjects.document.querySelector(value); | ||
return true; | ||
} | ||
//# sourceMappingURL=domUtils.js.map |
419
events.js
@@ -1,11 +0,8 @@ | ||
import * as is from './is'; | ||
import { contains } from './arr'; | ||
import * as domUtils from './domUtils'; | ||
import pointerUtils from './pointerUtils'; | ||
import pExtend from './pointerExtend'; | ||
import { contains } from './arr'; | ||
import * as is from './is'; | ||
import pExtend from './pointerExtend'; | ||
import pointerUtils from './pointerUtils'; | ||
const elements = []; | ||
const targets = []; | ||
const targets = []; | ||
// { | ||
@@ -19,252 +16,206 @@ // type: { | ||
const delegatedEvents = {}; | ||
const documents = []; | ||
function add (element, type, listener, optionalArg) { | ||
const options = getOptions(optionalArg); | ||
let elementIndex = elements.indexOf(element); | ||
let target = targets[elementIndex]; | ||
if (!target) { | ||
target = { | ||
events: {}, | ||
typeCount: 0, | ||
}; | ||
elementIndex = elements.push(element) - 1; | ||
targets.push(target); | ||
} | ||
if (!target.events[type]) { | ||
target.events[type] = []; | ||
target.typeCount++; | ||
} | ||
if (!contains(target.events[type], listener)) { | ||
element.addEventListener(type, listener, events.supportsOptions? options : !!options.capture); | ||
target.events[type].push(listener); | ||
} | ||
const documents = []; | ||
function add(element, type, listener, optionalArg) { | ||
const options = getOptions(optionalArg); | ||
let elementIndex = elements.indexOf(element); | ||
let target = targets[elementIndex]; | ||
if (!target) { | ||
target = { | ||
events: {}, | ||
typeCount: 0, | ||
}; | ||
elementIndex = elements.push(element) - 1; | ||
targets.push(target); | ||
} | ||
if (!target.events[type]) { | ||
target.events[type] = []; | ||
target.typeCount++; | ||
} | ||
if (!contains(target.events[type], listener)) { | ||
element.addEventListener(type, listener, events.supportsOptions ? options : !!options.capture); | ||
target.events[type].push(listener); | ||
} | ||
} | ||
function remove (element, type, listener, optionalArg) { | ||
const options = getOptions(optionalArg); | ||
const elementIndex = elements.indexOf(element); | ||
const target = targets[elementIndex]; | ||
if (!target || !target.events) { | ||
return; | ||
} | ||
if (type === 'all') { | ||
for (type in target.events) { | ||
if (target.events.hasOwnProperty(type)) { | ||
remove(element, type, 'all'); | ||
} | ||
function remove(element, type, listener, optionalArg) { | ||
const options = getOptions(optionalArg); | ||
const elementIndex = elements.indexOf(element); | ||
const target = targets[elementIndex]; | ||
if (!target || !target.events) { | ||
return; | ||
} | ||
return; | ||
} | ||
if (target.events[type]) { | ||
const len = target.events[type].length; | ||
if (listener === 'all') { | ||
for (let i = 0; i < len; i++) { | ||
remove(element, type, target.events[type][i], options); | ||
} | ||
return; | ||
if (type === 'all') { | ||
for (type in target.events) { | ||
if (target.events.hasOwnProperty(type)) { | ||
remove(element, type, 'all'); | ||
} | ||
} | ||
return; | ||
} | ||
else { | ||
for (let i = 0; i < len; i++) { | ||
if (target.events[type][i] === listener) { | ||
element.removeEventListener(type, listener, events.supportsOptions? options : !!options.capture); | ||
target.events[type].splice(i, 1); | ||
break; | ||
if (target.events[type]) { | ||
const len = target.events[type].length; | ||
if (listener === 'all') { | ||
for (let i = 0; i < len; i++) { | ||
remove(element, type, target.events[type][i], options); | ||
} | ||
return; | ||
} | ||
} | ||
else { | ||
for (let i = 0; i < len; i++) { | ||
if (target.events[type][i] === listener) { | ||
element.removeEventListener(type, listener, events.supportsOptions ? options : !!options.capture); | ||
target.events[type].splice(i, 1); | ||
break; | ||
} | ||
} | ||
} | ||
if (target.events[type] && target.events[type].length === 0) { | ||
target.events[type] = null; | ||
target.typeCount--; | ||
} | ||
} | ||
if (target.events[type] && target.events[type].length === 0) { | ||
target.events[type] = null; | ||
target.typeCount--; | ||
if (!target.typeCount) { | ||
targets.splice(elementIndex, 1); | ||
elements.splice(elementIndex, 1); | ||
} | ||
} | ||
if (!target.typeCount) { | ||
targets.splice(elementIndex, 1); | ||
elements.splice(elementIndex, 1); | ||
} | ||
} | ||
function addDelegate (selector, context, type, listener, optionalArg) { | ||
const options = getOptions(optionalArg); | ||
if (!delegatedEvents[type]) { | ||
delegatedEvents[type] = { | ||
selectors: [], | ||
contexts : [], | ||
listeners: [], | ||
}; | ||
// add delegate listener functions | ||
for (const doc of documents) { | ||
add(doc, type, delegateListener); | ||
add(doc, type, delegateUseCapture, true); | ||
function addDelegate(selector, context, type, listener, optionalArg) { | ||
const options = getOptions(optionalArg); | ||
if (!delegatedEvents[type]) { | ||
delegatedEvents[type] = { | ||
selectors: [], | ||
contexts: [], | ||
listeners: [], | ||
}; | ||
// add delegate listener functions | ||
for (const doc of documents) { | ||
add(doc, type, delegateListener); | ||
add(doc, type, delegateUseCapture, true); | ||
} | ||
} | ||
} | ||
const delegated = delegatedEvents[type]; | ||
let index; | ||
for (index = delegated.selectors.length - 1; index >= 0; index--) { | ||
if (delegated.selectors[index] === selector | ||
&& delegated.contexts[index] === context) { | ||
break; | ||
const delegated = delegatedEvents[type]; | ||
let index; | ||
for (index = delegated.selectors.length - 1; index >= 0; index--) { | ||
if (delegated.selectors[index] === selector | ||
&& delegated.contexts[index] === context) { | ||
break; | ||
} | ||
} | ||
} | ||
if (index === -1) { | ||
index = delegated.selectors.length; | ||
delegated.selectors.push(selector); | ||
delegated.contexts .push(context); | ||
delegated.listeners.push([]); | ||
} | ||
// keep listener and capture and passive flags | ||
delegated.listeners[index].push([listener, !!options.capture, options.passive]); | ||
if (index === -1) { | ||
index = delegated.selectors.length; | ||
delegated.selectors.push(selector); | ||
delegated.contexts.push(context); | ||
delegated.listeners.push([]); | ||
} | ||
// keep listener and capture and passive flags | ||
delegated.listeners[index].push([listener, !!options.capture, options.passive]); | ||
} | ||
function removeDelegate (selector, context, type, listener, optionalArg) { | ||
const options = getOptions(optionalArg); | ||
const delegated = delegatedEvents[type]; | ||
let matchFound = false; | ||
let index; | ||
if (!delegated) { return; } | ||
// count from last index of delegated to 0 | ||
for (index = delegated.selectors.length - 1; index >= 0; index--) { | ||
// look for matching selector and context Node | ||
if (delegated.selectors[index] === selector | ||
&& delegated.contexts[index] === context) { | ||
const listeners = delegated.listeners[index]; | ||
// each item of the listeners array is an array: [function, capture, passive] | ||
for (let i = listeners.length - 1; i >= 0; i--) { | ||
const [fn, capture, passive] = listeners[i]; | ||
// check if the listener functions and capture and passive flags match | ||
if (fn === listener && capture === !!options.capture && passive === options.passive) { | ||
// remove the listener from the array of listeners | ||
listeners.splice(i, 1); | ||
// if all listeners for this interactable have been removed | ||
// remove the interactable from the delegated arrays | ||
if (!listeners.length) { | ||
delegated.selectors.splice(index, 1); | ||
delegated.contexts .splice(index, 1); | ||
delegated.listeners.splice(index, 1); | ||
// remove delegate function from context | ||
remove(context, type, delegateListener); | ||
remove(context, type, delegateUseCapture, true); | ||
// remove the arrays if they are empty | ||
if (!delegated.selectors.length) { | ||
delegatedEvents[type] = null; | ||
function removeDelegate(selector, context, type, listener, optionalArg) { | ||
const options = getOptions(optionalArg); | ||
const delegated = delegatedEvents[type]; | ||
let matchFound = false; | ||
let index; | ||
if (!delegated) { | ||
return; | ||
} | ||
// count from last index of delegated to 0 | ||
for (index = delegated.selectors.length - 1; index >= 0; index--) { | ||
// look for matching selector and context Node | ||
if (delegated.selectors[index] === selector | ||
&& delegated.contexts[index] === context) { | ||
const listeners = delegated.listeners[index]; | ||
// each item of the listeners array is an array: [function, capture, passive] | ||
for (let i = listeners.length - 1; i >= 0; i--) { | ||
const [fn, capture, passive] = listeners[i]; | ||
// check if the listener functions and capture and passive flags match | ||
if (fn === listener && capture === !!options.capture && passive === options.passive) { | ||
// remove the listener from the array of listeners | ||
listeners.splice(i, 1); | ||
// if all listeners for this interactable have been removed | ||
// remove the interactable from the delegated arrays | ||
if (!listeners.length) { | ||
delegated.selectors.splice(index, 1); | ||
delegated.contexts.splice(index, 1); | ||
delegated.listeners.splice(index, 1); | ||
// remove delegate function from context | ||
remove(context, type, delegateListener); | ||
remove(context, type, delegateUseCapture, true); | ||
// remove the arrays if they are empty | ||
if (!delegated.selectors.length) { | ||
delegatedEvents[type] = null; | ||
} | ||
} | ||
// only remove one listener | ||
matchFound = true; | ||
break; | ||
} | ||
} | ||
} | ||
// only remove one listener | ||
matchFound = true; | ||
break; | ||
if (matchFound) { | ||
break; | ||
} | ||
} | ||
} | ||
if (matchFound) { break; } | ||
} | ||
} | ||
} | ||
// bound to the interactable context when a DOM event | ||
// listener is added to a selector interactable | ||
function delegateListener (event, optionalArg) { | ||
const options = getOptions(optionalArg); | ||
const fakeEvent = {}; | ||
const delegated = delegatedEvents[event.type]; | ||
const [eventTarget] = (pointerUtils.getEventTargets(event)); | ||
let element = eventTarget; | ||
// duplicate the event so that currentTarget can be changed | ||
pExtend(fakeEvent, event); | ||
fakeEvent.originalEvent = event; | ||
fakeEvent.preventDefault = preventOriginalDefault; | ||
// climb up document tree looking for selector matches | ||
while (is.element(element)) { | ||
for (let i = 0; i < delegated.selectors.length; i++) { | ||
const selector = delegated.selectors[i]; | ||
const context = delegated.contexts[i]; | ||
if (domUtils.matchesSelector(element, selector) | ||
&& domUtils.nodeContains(context, eventTarget) | ||
&& domUtils.nodeContains(context, element)) { | ||
const listeners = delegated.listeners[i]; | ||
fakeEvent.currentTarget = element; | ||
for (let j = 0; j < listeners.length; j++) { | ||
const [fn, capture, passive] = listeners[j]; | ||
if (capture === !!options.capture && passive === options.passive) { | ||
fn(fakeEvent); | ||
} | ||
function delegateListener(event, optionalArg) { | ||
const options = getOptions(optionalArg); | ||
const fakeEvent = {}; | ||
const delegated = delegatedEvents[event.type]; | ||
const [eventTarget] = (pointerUtils.getEventTargets(event)); | ||
let element = eventTarget; | ||
// duplicate the event so that currentTarget can be changed | ||
pExtend(fakeEvent, event); | ||
fakeEvent.originalEvent = event; | ||
fakeEvent.preventDefault = preventOriginalDefault; | ||
// climb up document tree looking for selector matches | ||
while (is.element(element)) { | ||
for (let i = 0; i < delegated.selectors.length; i++) { | ||
const selector = delegated.selectors[i]; | ||
const context = delegated.contexts[i]; | ||
if (domUtils.matchesSelector(element, selector) | ||
&& domUtils.nodeContains(context, eventTarget) | ||
&& domUtils.nodeContains(context, element)) { | ||
const listeners = delegated.listeners[i]; | ||
fakeEvent.currentTarget = element; | ||
for (let j = 0; j < listeners.length; j++) { | ||
const [fn, capture, passive] = listeners[j]; | ||
if (capture === !!options.capture && passive === options.passive) { | ||
fn(fakeEvent); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
element = domUtils.parentNode(element); | ||
} | ||
element = domUtils.parentNode(element); | ||
} | ||
} | ||
function delegateUseCapture (event) { | ||
return delegateListener.call(this, event, true); | ||
function delegateUseCapture(event) { | ||
return delegateListener.call(this, event, true); | ||
} | ||
function preventOriginalDefault () { | ||
this.originalEvent.preventDefault(); | ||
function preventOriginalDefault() { | ||
this.originalEvent.preventDefault(); | ||
} | ||
function getOptions (param) { | ||
return is.object(param)? param : { capture: param }; | ||
function getOptions(param) { | ||
return is.object(param) ? param : { capture: param }; | ||
} | ||
const events = { | ||
add, | ||
remove, | ||
addDelegate, | ||
removeDelegate, | ||
delegateListener, | ||
delegateUseCapture, | ||
delegatedEvents, | ||
documents, | ||
supportsOptions: false, | ||
supportsPassive: false, | ||
_elements: elements, | ||
_targets: targets, | ||
init (window) { | ||
window.document.createElement('div').addEventListener('test', null, { | ||
get capture () { return (events.supportsOptions = true); }, | ||
get passive () { return (events.supportsPassive = true); }, | ||
}); | ||
}, | ||
add, | ||
remove, | ||
addDelegate, | ||
removeDelegate, | ||
delegateListener, | ||
delegateUseCapture, | ||
delegatedEvents, | ||
documents, | ||
supportsOptions: false, | ||
supportsPassive: false, | ||
_elements: elements, | ||
_targets: targets, | ||
init(window) { | ||
window.document.createElement('div').addEventListener('test', null, { | ||
get capture() { return (events.supportsOptions = true); }, | ||
get passive() { return (events.supportsPassive = true); }, | ||
}); | ||
}, | ||
}; | ||
export default events; | ||
//# sourceMappingURL=events.js.map |
@@ -1,6 +0,7 @@ | ||
export default function extend (dest, source) { | ||
for (const prop in source) { | ||
dest[prop] = source[prop]; | ||
} | ||
return dest; | ||
export default function extend(dest, source) { | ||
for (const prop in source) { | ||
dest[prop] = source[prop]; | ||
} | ||
return dest; | ||
} | ||
//# sourceMappingURL=extend.js.map |
@@ -1,14 +0,9 @@ | ||
import { | ||
resolveRectLike, | ||
rectToXY, | ||
} from './rect'; | ||
import { rectToXY, resolveRectLike } from './rect'; | ||
export default function (target, element, action) { | ||
const actionOptions = target.options[action]; | ||
const actionOrigin = actionOptions && actionOptions.origin; | ||
const origin = actionOrigin || target.options.origin; | ||
const originRect = resolveRectLike(origin, target, element, [target && element]); | ||
return rectToXY(originRect) || { x: 0, y: 0 }; | ||
const actionOptions = target.options[action]; | ||
const actionOrigin = actionOptions && actionOptions.origin; | ||
const origin = actionOrigin || target.options.origin; | ||
const originRect = resolveRectLike(origin, target, element, [target && element]); | ||
return rectToXY(originRect) || { x: 0, y: 0 }; | ||
} | ||
//# sourceMappingURL=getOriginXY.js.map |
@@ -1,1 +0,2 @@ | ||
export default (x, y) => Math.sqrt(x * x + y * y); | ||
export default (x, y) => Math.sqrt(x * x + y * y); | ||
//# sourceMappingURL=hypot.js.map |
95
index.js
@@ -0,64 +1,49 @@ | ||
import * as arr from './arr'; | ||
import * as dom from './domUtils'; | ||
import * as is from './is'; | ||
import win from './window'; | ||
export function warnOnce (method, message) { | ||
let warned = false; | ||
return function () { | ||
if (!warned) { | ||
win.window.console.warn(message); | ||
warned = true; | ||
} | ||
return method.apply(this, arguments); | ||
}; | ||
export function warnOnce(method, message) { | ||
let warned = false; | ||
return function () { | ||
if (!warned) { | ||
win.window.console.warn(message); | ||
warned = true; | ||
} | ||
return method.apply(this, arguments); | ||
}; | ||
} | ||
// http://stackoverflow.com/a/5634528/2280888 | ||
export function _getQBezierValue (t, p1, p2, p3) { | ||
const iT = 1 - t; | ||
return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3; | ||
export function _getQBezierValue(t, p1, p2, p3) { | ||
const iT = 1 - t; | ||
return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3; | ||
} | ||
export function getQuadraticCurvePoint (startX, startY, cpX, cpY, endX, endY, position) { | ||
return { | ||
x: _getQBezierValue(position, startX, cpX, endX), | ||
y: _getQBezierValue(position, startY, cpY, endY), | ||
}; | ||
export function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) { | ||
return { | ||
x: _getQBezierValue(position, startX, cpX, endX), | ||
y: _getQBezierValue(position, startY, cpY, endY), | ||
}; | ||
} | ||
// http://gizma.com/easing/ | ||
export function easeOutQuad (t, b, c, d) { | ||
t /= d; | ||
return -c * t*(t-2) + b; | ||
export function easeOutQuad(t, b, c, d) { | ||
t /= d; | ||
return -c * t * (t - 2) + b; | ||
} | ||
export function copyAction (dest, src) { | ||
dest.name = src.name; | ||
dest.axis = src.axis; | ||
dest.edges = src.edges; | ||
return dest; | ||
export function copyAction(dest, src) { | ||
dest.name = src.name; | ||
dest.axis = src.axis; | ||
dest.edges = src.edges; | ||
return dest; | ||
} | ||
import * as arr from './arr'; | ||
import * as dom from './domUtils'; | ||
import * as is from './is'; | ||
export { | ||
win, | ||
arr, | ||
dom, | ||
is, | ||
}; | ||
export { default as browser } from './browser'; | ||
export { default as Signals } from './Signals'; | ||
export { default as raf } from './raf'; | ||
export { default as extend } from './extend'; | ||
export { default as clone } from './clone'; | ||
export { default as getOriginXY } from './getOriginXY'; | ||
export { default as pointer } from './pointerUtils'; | ||
export { default as rect } from './rect'; | ||
export { default as events } from './events'; | ||
export { default as hypot } from './hypot'; | ||
export { default as browser } from './browser'; | ||
export { default as clone } from './clone'; | ||
export { default as events } from './events'; | ||
export { default as extend } from './extend'; | ||
export { default as getOriginXY } from './getOriginXY'; | ||
export { default as hypot } from './hypot'; | ||
export { default as normalizeListeners } from './normalizeListeners'; | ||
export { default as pointer } from './pointerUtils'; | ||
export { default as raf } from './raf'; | ||
export { default as rect } from './rect'; | ||
export { default as Signals } from './Signals'; | ||
export { win, arr, dom, is, }; | ||
//# sourceMappingURL=index.js.map |
import * as utils from './index'; | ||
const finder = { | ||
methodOrder: [ 'simulationResume', 'mouseOrPen', 'hasPointer', 'idle' ], | ||
search: function (details) { | ||
for (const method of finder.methodOrder) { | ||
const interaction = finder[method](details); | ||
if (interaction) { | ||
return interaction; | ||
} | ||
} | ||
}, | ||
// try to resume simulation with a new pointer | ||
simulationResume: function ({ pointerType, eventType, eventTarget, scope }) { | ||
if (!/down|start/i.test(eventType)) { | ||
return null; | ||
} | ||
for (const interaction of scope.interactions.list) { | ||
let element = eventTarget; | ||
if (interaction.simulation && interaction.simulation.allowResume | ||
&& (interaction.pointerType === pointerType)) { | ||
while (element) { | ||
// if the element is the interaction element | ||
if (element === interaction.element) { | ||
return interaction; | ||
} | ||
element = utils.dom.parentNode(element); | ||
methodOrder: ['simulationResume', 'mouseOrPen', 'hasPointer', 'idle'], | ||
search: function (details) { | ||
for (const method of finder.methodOrder) { | ||
const interaction = finder[method](details); | ||
if (interaction) { | ||
return interaction; | ||
} | ||
} | ||
} | ||
} | ||
return null; | ||
}, | ||
// if it's a mouse or pen interaction | ||
mouseOrPen: function ({ pointerId, pointerType, eventType, scope }) { | ||
if (pointerType !== 'mouse' && pointerType !== 'pen') { | ||
return null; | ||
} | ||
let firstNonActive; | ||
for (const interaction of scope.interactions.list) { | ||
if (interaction.pointerType === pointerType) { | ||
// if it's a down event, skip interactions with running simulations | ||
if (interaction.simulation && !hasPointerId(interaction, pointerId)) { continue; } | ||
// if the interaction is active, return it immediately | ||
if (interaction.interacting()) { | ||
return interaction; | ||
}, | ||
// try to resume simulation with a new pointer | ||
simulationResume: function ({ pointerType, eventType, eventTarget, scope }) { | ||
if (!/down|start/i.test(eventType)) { | ||
return null; | ||
} | ||
// otherwise save it and look for another active interaction | ||
else if (!firstNonActive) { | ||
firstNonActive = interaction; | ||
for (const interaction of scope.interactions.list) { | ||
let element = eventTarget; | ||
if (interaction.simulation && interaction.simulation.allowResume | ||
&& (interaction.pointerType === pointerType)) { | ||
while (element) { | ||
// if the element is the interaction element | ||
if (element === interaction.element) { | ||
return interaction; | ||
} | ||
element = utils.dom.parentNode(element); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// if no active mouse interaction was found use the first inactive mouse | ||
// interaction | ||
if (firstNonActive) { | ||
return firstNonActive; | ||
} | ||
// find any mouse or pen interaction. | ||
// ignore the interaction if the eventType is a *down, and a simulation | ||
// is active | ||
for (const interaction of scope.interactions.list) { | ||
if (interaction.pointerType === pointerType && !(/down/i.test(eventType) && interaction.simulation)) { | ||
return interaction; | ||
} | ||
} | ||
return null; | ||
}, | ||
// get interaction that has this pointer | ||
hasPointer: function ({ pointerId, scope }) { | ||
for (const interaction of scope.interactions.list) { | ||
if (hasPointerId(interaction, pointerId)) { | ||
return interaction; | ||
} | ||
} | ||
}, | ||
// get first idle interaction with a matching pointerType | ||
idle: function ({ pointerType, scope }) { | ||
for (const interaction of scope.interactions.list) { | ||
// if there's already a pointer held down | ||
if (interaction.pointers.length === 1) { | ||
const target = interaction.target; | ||
// don't add this pointer if there is a target interactable and it | ||
// isn't gesturable | ||
if (target && !target.options.gesture.enabled) { | ||
continue; | ||
return null; | ||
}, | ||
// if it's a mouse or pen interaction | ||
mouseOrPen: function ({ pointerId, pointerType, eventType, scope }) { | ||
if (pointerType !== 'mouse' && pointerType !== 'pen') { | ||
return null; | ||
} | ||
} | ||
// maximum of 2 pointers per interaction | ||
else if (interaction.pointers.length >= 2) { | ||
continue; | ||
} | ||
if (!interaction.interacting() && (pointerType === interaction.pointerType)) { | ||
return interaction; | ||
} | ||
} | ||
return null; | ||
}, | ||
let firstNonActive; | ||
for (const interaction of scope.interactions.list) { | ||
if (interaction.pointerType === pointerType) { | ||
// if it's a down event, skip interactions with running simulations | ||
if (interaction.simulation && !hasPointerId(interaction, pointerId)) { | ||
continue; | ||
} | ||
// if the interaction is active, return it immediately | ||
if (interaction.interacting()) { | ||
return interaction; | ||
} | ||
// otherwise save it and look for another active interaction | ||
else if (!firstNonActive) { | ||
firstNonActive = interaction; | ||
} | ||
} | ||
} | ||
// if no active mouse interaction was found use the first inactive mouse | ||
// interaction | ||
if (firstNonActive) { | ||
return firstNonActive; | ||
} | ||
// find any mouse or pen interaction. | ||
// ignore the interaction if the eventType is a *down, and a simulation | ||
// is active | ||
for (const interaction of scope.interactions.list) { | ||
if (interaction.pointerType === pointerType && !(/down/i.test(eventType) && interaction.simulation)) { | ||
return interaction; | ||
} | ||
} | ||
return null; | ||
}, | ||
// get interaction that has this pointer | ||
hasPointer: function ({ pointerId, scope }) { | ||
for (const interaction of scope.interactions.list) { | ||
if (hasPointerId(interaction, pointerId)) { | ||
return interaction; | ||
} | ||
} | ||
}, | ||
// get first idle interaction with a matching pointerType | ||
idle: function ({ pointerType, scope }) { | ||
for (const interaction of scope.interactions.list) { | ||
// if there's already a pointer held down | ||
if (interaction.pointers.length === 1) { | ||
const target = interaction.target; | ||
// don't add this pointer if there is a target interactable and it | ||
// isn't gesturable | ||
if (target && !target.options.gesture.enabled) { | ||
continue; | ||
} | ||
} | ||
// maximum of 2 pointers per interaction | ||
else if (interaction.pointers.length >= 2) { | ||
continue; | ||
} | ||
if (!interaction.interacting() && (pointerType === interaction.pointerType)) { | ||
return interaction; | ||
} | ||
} | ||
return null; | ||
}, | ||
}; | ||
function hasPointerId (interaction, pointerId) { | ||
return utils.arr.some(interaction.pointers, ({ id }) => id === pointerId); | ||
function hasPointerId(interaction, pointerId) { | ||
return utils.arr.some(interaction.pointers, ({ id }) => id === pointerId); | ||
} | ||
export default finder; | ||
//# sourceMappingURL=interactionFinder.js.map |
55
is.js
@@ -1,34 +0,25 @@ | ||
import win from './window'; | ||
import isWindow from './isWindow'; | ||
export const window = thing => thing === win.window || isWindow(thing); | ||
export const docFrag = thing => object(thing) && thing.nodeType === 11; | ||
export const object = thing => !!thing && (typeof thing === 'object'); | ||
export const func = thing => typeof thing === 'function'; | ||
export const number = thing => typeof thing === 'number' ; | ||
export const bool = thing => typeof thing === 'boolean' ; | ||
export const string = thing => typeof thing === 'string' ; | ||
export const element = thing => { | ||
if (!thing || (typeof thing !== 'object')) { return false; } | ||
const _window = win.getWindow(thing) || win.window; | ||
return (/object|function/.test(typeof _window.Element) | ||
? thing instanceof _window.Element //DOM2 | ||
: thing.nodeType === 1 && typeof thing.nodeName === 'string'); | ||
import win from './window'; | ||
export const window = (thing) => thing === win.window || isWindow(thing); | ||
export const docFrag = (thing) => object(thing) && thing.nodeType === 11; | ||
export const object = (thing) => !!thing && (typeof thing === 'object'); | ||
export const func = (thing) => typeof thing === 'function'; | ||
export const number = (thing) => typeof thing === 'number'; | ||
export const bool = (thing) => typeof thing === 'boolean'; | ||
export const string = (thing) => typeof thing === 'string'; | ||
export const element = (thing) => { | ||
if (!thing || (typeof thing !== 'object')) { | ||
return false; | ||
} | ||
const _window = win.getWindow(thing) || win.window; | ||
return (/object|function/.test(typeof _window.Element) | ||
? thing instanceof _window.Element //DOM2 | ||
: thing.nodeType === 1 && typeof thing.nodeName === 'string'); | ||
}; | ||
export const plainObject = thing => object(thing) && | ||
!!thing.constructor && | ||
thing.constructor.name === 'Object'; | ||
export const array = thing => (object(thing) | ||
&& (typeof thing.length !== 'undefined') | ||
&& func(thing.splice)); | ||
export const plainObject = (thing) => object(thing) && | ||
!!thing.constructor && | ||
/function Object\b/.test(thing.constructor.toString()); | ||
export const array = (thing) => (object(thing) | ||
&& (typeof thing.length !== 'undefined') | ||
&& func(thing.splice)); | ||
//# sourceMappingURL=is.js.map |
export default (thing) => !!(thing && thing.Window) && (thing instanceof thing.Window); | ||
//# sourceMappingURL=isWindow.js.map |
import * as is from './is'; | ||
import extend from './extend'; | ||
export default function normalize (type, listener, result) { | ||
result = result || {}; | ||
if (is.string(type) && type.search(' ') !== -1) { | ||
type = split(type); | ||
} | ||
if (is.array(type)) { | ||
return type.reduce((acc, t) => extend(acc, normalize(t, listener, result)), {}); | ||
} | ||
// ({ type: fn }) -> ('', { type: fn }) | ||
if (is.object(type)) { | ||
listener = type; | ||
type = ''; | ||
} | ||
if (is.func(listener)) { | ||
result[type] = result[type] || []; | ||
result[type].push(listener); | ||
} | ||
else if (is.array(listener)) { | ||
for (const l of listener) { | ||
normalize(type, l, result); | ||
import extend from './extend'; | ||
export default function normalize(type, listener, result) { | ||
result = result || {}; | ||
if (is.string(type) && type.search(' ') !== -1) { | ||
type = split(type); | ||
} | ||
} | ||
else if (is.object(listener)) { | ||
for (const prefix in listener) { | ||
const combinedTypes = split(prefix).map(p => `${type}${p}`); | ||
normalize(combinedTypes, listener[prefix], result); | ||
if (is.array(type)) { | ||
return type.reduce((acc, t) => extend(acc, normalize(t, listener, result)), {}); | ||
} | ||
} | ||
return result; | ||
// ({ type: fn }) -> ('', { type: fn }) | ||
if (is.object(type)) { | ||
listener = type; | ||
type = ''; | ||
} | ||
if (is.func(listener)) { | ||
result[type] = result[type] || []; | ||
result[type].push(listener); | ||
} | ||
else if (is.array(listener)) { | ||
for (const l of listener) { | ||
normalize(type, l, result); | ||
} | ||
} | ||
else if (is.object(listener)) { | ||
for (const prefix in listener) { | ||
const combinedTypes = split(prefix).map(p => `${type}${p}`); | ||
normalize(combinedTypes, listener[prefix], result); | ||
} | ||
} | ||
return result; | ||
} | ||
function split (type) { | ||
return type.trim().split(/ +/); | ||
function split(type) { | ||
return type.trim().split(/ +/); | ||
} | ||
//# sourceMappingURL=normalizeListeners.js.map |
{ | ||
"name": "@interactjs/utils", | ||
"version": "1.4.0-alpha.17+sha.793e5fa", | ||
"version": "1.4.0-alpha.18+sha.a8adfbf", | ||
"devDependencies": { | ||
"@interactjs/_dev": "1.4.0-alpha.17+sha.793e5fa" | ||
"@interactjs/_dev": "1.4.0-alpha.18+sha.a8adfbf" | ||
}, | ||
@@ -7,0 +7,0 @@ "publishConfig": { |
@@ -1,23 +0,21 @@ | ||
export default function pointerExtend (dest, source) { | ||
for (const prop in source) { | ||
const prefixedPropREs = pointerExtend.prefixedPropREs; | ||
let deprecated = false; | ||
// skip deprecated prefixed properties | ||
for (const vendor in prefixedPropREs) { | ||
if (prop.indexOf(vendor) === 0 && prefixedPropREs[vendor].test(prop)) { | ||
deprecated = true; | ||
break; | ||
} | ||
export default function pointerExtend(dest, source) { | ||
for (const prop in source) { | ||
const prefixedPropREs = pointerExtend.prefixedPropREs; | ||
let deprecated = false; | ||
// skip deprecated prefixed properties | ||
for (const vendor in prefixedPropREs) { | ||
if (prop.indexOf(vendor) === 0 && prefixedPropREs[vendor].test(prop)) { | ||
deprecated = true; | ||
break; | ||
} | ||
} | ||
if (!deprecated && typeof source[prop] !== 'function') { | ||
dest[prop] = source[prop]; | ||
} | ||
} | ||
if (!deprecated && typeof source[prop] !== 'function') { | ||
dest[prop] = source[prop]; | ||
} | ||
} | ||
return dest; | ||
return dest; | ||
} | ||
pointerExtend.prefixedPropREs = { | ||
webkit: /(Movement[XY]|Radius[XY]|RotationAngle|Force)$/, | ||
webkit: /(Movement[XY]|Radius[XY]|RotationAngle|Force)$/, | ||
}; | ||
//# sourceMappingURL=pointerExtend.js.map |
@@ -1,248 +0,205 @@ | ||
import hypot from './hypot'; | ||
import browser from './browser'; | ||
import dom from './domObjects'; | ||
import browser from './browser'; | ||
import { default as dom, default as domObjects } from './domObjects'; | ||
import * as domUtils from './domUtils'; | ||
import domObjects from './domObjects'; | ||
import * as is from './is'; | ||
import hypot from './hypot'; | ||
import * as is from './is'; | ||
import pointerExtend from './pointerExtend'; | ||
const pointerUtils = { | ||
copyCoords: function (dest, src) { | ||
dest.page = dest.page || {}; | ||
dest.page.x = src.page.x; | ||
dest.page.y = src.page.y; | ||
dest.client = dest.client || {}; | ||
dest.client.x = src.client.x; | ||
dest.client.y = src.client.y; | ||
dest.timeStamp = src.timeStamp; | ||
}, | ||
setCoordDeltas: function (targetObj, prev, cur) { | ||
targetObj.page.x = cur.page.x - prev.page.x; | ||
targetObj.page.y = cur.page.y - prev.page.y; | ||
targetObj.client.x = cur.client.x - prev.client.x; | ||
targetObj.client.y = cur.client.y - prev.client.y; | ||
targetObj.timeStamp = cur.timeStamp - prev.timeStamp; | ||
}, | ||
setCoordVelocity (targetObj, delta) { | ||
const dt = Math.max(delta.timeStamp / 1000, 0.001); | ||
targetObj.page.x = delta.page.x / dt; | ||
targetObj.page.y = delta.page.y / dt; | ||
targetObj.client.x = delta.client.x / dt; | ||
targetObj.client.y = delta.client.y / dt; | ||
targetObj.timeStamp = dt; | ||
}, | ||
isNativePointer: function (pointer) { | ||
return (pointer instanceof dom.Event || pointer instanceof dom.Touch); | ||
}, | ||
// Get specified X/Y coords for mouse or event.touches[0] | ||
getXY: function (type, pointer, xy) { | ||
xy = xy || {}; | ||
type = type || 'page'; | ||
xy.x = pointer[type + 'X']; | ||
xy.y = pointer[type + 'Y']; | ||
return xy; | ||
}, | ||
getPageXY: function (pointer, page) { | ||
page = page || {}; | ||
// Opera Mobile handles the viewport and scrolling oddly | ||
if (browser.isOperaMobile && pointerUtils.isNativePointer(pointer)) { | ||
pointerUtils.getXY('screen', pointer, page); | ||
page.x += window.scrollX; | ||
page.y += window.scrollY; | ||
} | ||
else { | ||
pointerUtils.getXY('page', pointer, page); | ||
} | ||
return page; | ||
}, | ||
getClientXY: function (pointer, client) { | ||
client = client || {}; | ||
if (browser.isOperaMobile && pointerUtils.isNativePointer(pointer)) { | ||
// Opera Mobile handles the viewport and scrolling oddly | ||
pointerUtils.getXY('screen', pointer, client); | ||
} | ||
else { | ||
pointerUtils.getXY('client', pointer, client); | ||
} | ||
return client; | ||
}, | ||
getPointerId: function (pointer) { | ||
return is.number(pointer.pointerId)? pointer.pointerId : pointer.identifier; | ||
}, | ||
setCoords: function (targetObj, pointers, timeStamp) { | ||
const pointer = (pointers.length > 1 | ||
? pointerUtils.pointerAverage(pointers) | ||
: pointers[0]); | ||
const tmpXY = {}; | ||
pointerUtils.getPageXY(pointer, tmpXY); | ||
targetObj.page.x = tmpXY.x; | ||
targetObj.page.y = tmpXY.y; | ||
pointerUtils.getClientXY(pointer, tmpXY); | ||
targetObj.client.x = tmpXY.x; | ||
targetObj.client.y = tmpXY.y; | ||
targetObj.timeStamp = is.number(timeStamp) ? timeStamp :new Date().getTime(); | ||
}, | ||
pointerExtend: pointerExtend, | ||
getTouchPair: function (event) { | ||
const touches = []; | ||
// array of touches is supplied | ||
if (is.array(event)) { | ||
touches[0] = event[0]; | ||
touches[1] = event[1]; | ||
} | ||
// an event | ||
else { | ||
if (event.type === 'touchend') { | ||
if (event.touches.length === 1) { | ||
touches[0] = event.touches[0]; | ||
touches[1] = event.changedTouches[0]; | ||
copyCoords: function (dest, src) { | ||
dest.page = dest.page || {}; | ||
dest.page.x = src.page.x; | ||
dest.page.y = src.page.y; | ||
dest.client = dest.client || {}; | ||
dest.client.x = src.client.x; | ||
dest.client.y = src.client.y; | ||
dest.timeStamp = src.timeStamp; | ||
}, | ||
setCoordDeltas: function (targetObj, prev, cur) { | ||
targetObj.page.x = cur.page.x - prev.page.x; | ||
targetObj.page.y = cur.page.y - prev.page.y; | ||
targetObj.client.x = cur.client.x - prev.client.x; | ||
targetObj.client.y = cur.client.y - prev.client.y; | ||
targetObj.timeStamp = cur.timeStamp - prev.timeStamp; | ||
}, | ||
setCoordVelocity(targetObj, delta) { | ||
const dt = Math.max(delta.timeStamp / 1000, 0.001); | ||
targetObj.page.x = delta.page.x / dt; | ||
targetObj.page.y = delta.page.y / dt; | ||
targetObj.client.x = delta.client.x / dt; | ||
targetObj.client.y = delta.client.y / dt; | ||
targetObj.timeStamp = dt; | ||
}, | ||
isNativePointer: function (pointer) { | ||
return (pointer instanceof dom.Event || pointer instanceof dom.Touch); | ||
}, | ||
// Get specified X/Y coords for mouse or event.touches[0] | ||
getXY: function (type, pointer, xy) { | ||
xy = xy || {}; | ||
type = type || 'page'; | ||
xy.x = pointer[type + 'X']; | ||
xy.y = pointer[type + 'Y']; | ||
return xy; | ||
}, | ||
getPageXY: function (pointer, page) { | ||
page = page || { x: 0, y: 0 }; | ||
// Opera Mobile handles the viewport and scrolling oddly | ||
if (browser.isOperaMobile && pointerUtils.isNativePointer(pointer)) { | ||
pointerUtils.getXY('screen', pointer, page); | ||
page.x += window.scrollX; | ||
page.y += window.scrollY; | ||
} | ||
else if (event.touches.length === 0) { | ||
touches[0] = event.changedTouches[0]; | ||
touches[1] = event.changedTouches[1]; | ||
else { | ||
pointerUtils.getXY('page', pointer, page); | ||
} | ||
} | ||
else { | ||
touches[0] = event.touches[0]; | ||
touches[1] = event.touches[1]; | ||
} | ||
} | ||
return touches; | ||
}, | ||
pointerAverage: function (pointers) { | ||
const average = { | ||
pageX : 0, | ||
pageY : 0, | ||
clientX: 0, | ||
clientY: 0, | ||
screenX: 0, | ||
screenY: 0, | ||
}; | ||
for (const pointer of pointers) { | ||
for (const prop in average) { | ||
average[prop] += pointer[prop]; | ||
} | ||
} | ||
for (const prop in average) { | ||
average[prop] /= pointers.length; | ||
} | ||
return average; | ||
}, | ||
touchBBox: function (event) { | ||
if (!event.length && !(event.touches && event.touches.length > 1)) { | ||
return; | ||
} | ||
const touches = pointerUtils.getTouchPair(event); | ||
const minX = Math.min(touches[0].pageX, touches[1].pageX); | ||
const minY = Math.min(touches[0].pageY, touches[1].pageY); | ||
const maxX = Math.max(touches[0].pageX, touches[1].pageX); | ||
const maxY = Math.max(touches[0].pageY, touches[1].pageY); | ||
return { | ||
x: minX, | ||
y: minY, | ||
left: minX, | ||
top: minY, | ||
width: maxX - minX, | ||
height: maxY - minY, | ||
}; | ||
}, | ||
touchDistance: function (event, deltaSource) { | ||
const sourceX = deltaSource + 'X'; | ||
const sourceY = deltaSource + 'Y'; | ||
const touches = pointerUtils.getTouchPair(event); | ||
const dx = touches[0][sourceX] - touches[1][sourceX]; | ||
const dy = touches[0][sourceY] - touches[1][sourceY]; | ||
return hypot(dx, dy); | ||
}, | ||
touchAngle: function (event, prevAngle, deltaSource) { | ||
const sourceX = deltaSource + 'X'; | ||
const sourceY = deltaSource + 'Y'; | ||
const touches = pointerUtils.getTouchPair(event); | ||
const dx = touches[1][sourceX] - touches[0][sourceX]; | ||
const dy = touches[1][sourceY] - touches[0][sourceY]; | ||
const angle = 180 * Math.atan2(dy , dx) / Math.PI; | ||
return angle; | ||
}, | ||
getPointerType: function (pointer) { | ||
return is.string(pointer.pointerType) | ||
? pointer.pointerType | ||
: is.number(pointer.pointerType) | ||
? [undefined, undefined,'touch', 'pen', 'mouse'][pointer.pointerType] | ||
// if the PointerEvent API isn't available, then the "pointer" must | ||
// be either a MouseEvent, TouchEvent, or Touch object | ||
: /touch/.test(pointer.type) || pointer instanceof domObjects.Touch | ||
? 'touch' | ||
: 'mouse'; | ||
}, | ||
// [ event.target, event.currentTarget ] | ||
getEventTargets: function (event) { | ||
const path = is.func(event.composedPath) ? event.composedPath() : event.path; | ||
return [ | ||
domUtils.getActualElement(path ? path[0] : event.target), | ||
domUtils.getActualElement(event.currentTarget), | ||
]; | ||
}, | ||
newCoords () { | ||
return { | ||
page : { x: 0, y: 0 }, | ||
client : { x: 0, y: 0 }, | ||
timeStamp: 0, | ||
}; | ||
}, | ||
coordsToEvent: function ({ page, client, timeStamp }) { | ||
return { | ||
page, | ||
client, | ||
timeStamp, | ||
get pageX () { return page.x; }, | ||
get pageY () { return page.y; }, | ||
get clientX () { return client.x; }, | ||
get clientY () { return client.y; }, | ||
}; | ||
}, | ||
return page; | ||
}, | ||
getClientXY: function (pointer, client) { | ||
client = client || {}; | ||
if (browser.isOperaMobile && pointerUtils.isNativePointer(pointer)) { | ||
// Opera Mobile handles the viewport and scrolling oddly | ||
pointerUtils.getXY('screen', pointer, client); | ||
} | ||
else { | ||
pointerUtils.getXY('client', pointer, client); | ||
} | ||
return client; | ||
}, | ||
getPointerId: function (pointer) { | ||
return is.number(pointer.pointerId) ? pointer.pointerId : pointer.identifier; | ||
}, | ||
setCoords: function (targetObj, pointers, timeStamp) { | ||
const pointer = (pointers.length > 1 | ||
? pointerUtils.pointerAverage(pointers) | ||
: pointers[0]); | ||
const tmpXY = {}; | ||
pointerUtils.getPageXY(pointer, tmpXY); | ||
targetObj.page.x = tmpXY.x; | ||
targetObj.page.y = tmpXY.y; | ||
pointerUtils.getClientXY(pointer, tmpXY); | ||
targetObj.client.x = tmpXY.x; | ||
targetObj.client.y = tmpXY.y; | ||
targetObj.timeStamp = is.number(timeStamp) ? timeStamp : new Date().getTime(); | ||
}, | ||
pointerExtend: pointerExtend, | ||
getTouchPair: function (event) { | ||
const touches = []; | ||
// array of touches is supplied | ||
if (is.array(event)) { | ||
touches[0] = event[0]; | ||
touches[1] = event[1]; | ||
} | ||
// an event | ||
else { | ||
if (event.type === 'touchend') { | ||
if (event.touches.length === 1) { | ||
touches[0] = event.touches[0]; | ||
touches[1] = event.changedTouches[0]; | ||
} | ||
else if (event.touches.length === 0) { | ||
touches[0] = event.changedTouches[0]; | ||
touches[1] = event.changedTouches[1]; | ||
} | ||
} | ||
else { | ||
touches[0] = event.touches[0]; | ||
touches[1] = event.touches[1]; | ||
} | ||
} | ||
return touches; | ||
}, | ||
pointerAverage: function (pointers) { | ||
const average = { | ||
pageX: 0, | ||
pageY: 0, | ||
clientX: 0, | ||
clientY: 0, | ||
screenX: 0, | ||
screenY: 0, | ||
}; | ||
for (const pointer of pointers) { | ||
for (const prop in average) { | ||
average[prop] += pointer[prop]; | ||
} | ||
} | ||
for (const prop in average) { | ||
average[prop] /= pointers.length; | ||
} | ||
return average; | ||
}, | ||
touchBBox: function (event) { | ||
if (!event.length && | ||
!(event.touches && | ||
event.touches.length > 1)) { | ||
return null; | ||
} | ||
const touches = pointerUtils.getTouchPair(event); | ||
const minX = Math.min(touches[0].pageX, touches[1].pageX); | ||
const minY = Math.min(touches[0].pageY, touches[1].pageY); | ||
const maxX = Math.max(touches[0].pageX, touches[1].pageX); | ||
const maxY = Math.max(touches[0].pageY, touches[1].pageY); | ||
return { | ||
x: minX, | ||
y: minY, | ||
left: minX, | ||
top: minY, | ||
width: maxX - minX, | ||
height: maxY - minY, | ||
}; | ||
}, | ||
touchDistance: function (event, deltaSource) { | ||
const sourceX = deltaSource + 'X'; | ||
const sourceY = deltaSource + 'Y'; | ||
const touches = pointerUtils.getTouchPair(event); | ||
const dx = touches[0][sourceX] - touches[1][sourceX]; | ||
const dy = touches[0][sourceY] - touches[1][sourceY]; | ||
return hypot(dx, dy); | ||
}, | ||
touchAngle: function (event, deltaSource) { | ||
const sourceX = deltaSource + 'X'; | ||
const sourceY = deltaSource + 'Y'; | ||
const touches = pointerUtils.getTouchPair(event); | ||
const dx = touches[1][sourceX] - touches[0][sourceX]; | ||
const dy = touches[1][sourceY] - touches[0][sourceY]; | ||
const angle = 180 * Math.atan2(dy, dx) / Math.PI; | ||
return angle; | ||
}, | ||
getPointerType: function (pointer) { | ||
return is.string(pointer.pointerType) | ||
? pointer.pointerType | ||
: is.number(pointer.pointerType) | ||
? [undefined, undefined, 'touch', 'pen', 'mouse'][pointer.pointerType] | ||
// if the PointerEvent API isn't available, then the "pointer" must | ||
// be either a MouseEvent, TouchEvent, or Touch object | ||
: /touch/.test(pointer.type) || pointer instanceof domObjects.Touch | ||
? 'touch' | ||
: 'mouse'; | ||
}, | ||
// [ event.target, event.currentTarget ] | ||
getEventTargets: function (event) { | ||
const path = is.func(event.composedPath) ? event.composedPath() : event.path; | ||
return [ | ||
domUtils.getActualElement(path ? path[0] : event.target), | ||
domUtils.getActualElement(event.currentTarget), | ||
]; | ||
}, | ||
newCoords() { | ||
return { | ||
page: { x: 0, y: 0 }, | ||
client: { x: 0, y: 0 }, | ||
timeStamp: 0, | ||
}; | ||
}, | ||
coordsToEvent: function ({ page, client, timeStamp }) { | ||
return { | ||
page, | ||
client, | ||
timeStamp, | ||
get pageX() { return page.x; }, | ||
get pageY() { return page.y; }, | ||
get clientX() { return client.x; }, | ||
get clientY() { return client.y; }, | ||
}; | ||
}, | ||
}; | ||
export default pointerUtils; | ||
//# sourceMappingURL=pointerUtils.js.map |
53
raf.js
let lastTime = 0; | ||
let request; | ||
let cancel; | ||
function init (window) { | ||
request = window.requestAnimationFrame; | ||
cancel = window.cancelAnimationFrame; | ||
if (!request) { | ||
const vendors = ['ms', 'moz', 'webkit', 'o']; | ||
for (const vendor of vendors) { | ||
request = window[`${vendor}RequestAnimationFrame`]; | ||
cancel = window[`${vendor}CancelAnimationFrame`] || window[`${vendor}CancelRequestAnimationFrame`]; | ||
function init(window) { | ||
request = window.requestAnimationFrame; | ||
cancel = window.cancelAnimationFrame; | ||
if (!request) { | ||
const vendors = ['ms', 'moz', 'webkit', 'o']; | ||
for (const vendor of vendors) { | ||
request = window[`${vendor}RequestAnimationFrame`]; | ||
cancel = window[`${vendor}CancelAnimationFrame`] || window[`${vendor}CancelRequestAnimationFrame`]; | ||
} | ||
} | ||
} | ||
if (!request) { | ||
request = callback => { | ||
const currTime = new Date().getTime(); | ||
const timeToCall = Math.max(0, 16 - (currTime - lastTime)); | ||
const token = setTimeout(function () { callback(currTime + timeToCall); }, | ||
timeToCall); | ||
lastTime = currTime + timeToCall; | ||
return token; | ||
}; | ||
cancel = token => clearTimeout(token); | ||
} | ||
if (!request) { | ||
request = callback => { | ||
const currTime = new Date().getTime(); | ||
const timeToCall = Math.max(0, 16 - (currTime - lastTime)); | ||
const token = setTimeout(function () { callback(currTime + timeToCall); }, timeToCall); | ||
lastTime = currTime + timeToCall; | ||
return token; | ||
}; | ||
cancel = token => clearTimeout(token); | ||
} | ||
} | ||
export default { | ||
request: callback => request(callback), | ||
cancel: token => cancel(token), | ||
init, | ||
request: callback => request(callback), | ||
cancel: token => cancel(token), | ||
init, | ||
}; | ||
//# sourceMappingURL=raf.js.map |
124
rect.js
@@ -0,80 +1,62 @@ | ||
import { closest, getElementRect, parentNode } from './domUtils'; | ||
import extend from './extend'; | ||
import * as is from './is'; | ||
import { | ||
closest, | ||
parentNode, | ||
getElementRect, | ||
} from './domUtils'; | ||
export function getStringOptionResult (value, interactable, element) { | ||
if (!is.string(value)) { | ||
return null; | ||
} | ||
if (value === 'parent') { | ||
value = parentNode(element); | ||
} | ||
else if (value === 'self') { | ||
value = interactable.getRect(element); | ||
} | ||
else { | ||
value = closest(element, value); | ||
} | ||
return value; | ||
export function getStringOptionResult(value, interactable, element) { | ||
if (!is.string(value)) { | ||
return null; | ||
} | ||
if (value === 'parent') { | ||
value = parentNode(element); | ||
} | ||
else if (value === 'self') { | ||
value = interactable.getRect(element); | ||
} | ||
else { | ||
value = closest(element, value); | ||
} | ||
return value; | ||
} | ||
export function resolveRectLike (value, interactable, element, functionArgs) { | ||
value = getStringOptionResult(value, interactable, element) || value; | ||
if (is.func(value)) { | ||
value = value.apply(null, functionArgs); | ||
} | ||
if (is.element(value)) { | ||
value = getElementRect(value); | ||
} | ||
return value; | ||
export function resolveRectLike(value, interactable, element, functionArgs) { | ||
value = getStringOptionResult(value, interactable, element) || value; | ||
if (is.func(value)) { | ||
value = value.apply(null, functionArgs); | ||
} | ||
if (is.element(value)) { | ||
value = getElementRect(value); | ||
} | ||
return value; | ||
} | ||
export function rectToXY (rect) { | ||
return rect && { | ||
x: 'x' in rect ? rect.x : rect.left, | ||
y: 'y' in rect ? rect.y : rect.top, | ||
}; | ||
export function rectToXY(rect) { | ||
return rect && { | ||
x: 'x' in rect ? rect.x : rect.left, | ||
y: 'y' in rect ? rect.y : rect.top, | ||
}; | ||
} | ||
export function xywhToTlbr (rect) { | ||
if (rect && !('left' in rect && 'top' in rect)) { | ||
rect = extend({}, rect); | ||
rect.left = rect.x || 0; | ||
rect.top = rect.y || 0; | ||
rect.right = rect.right || (rect.left + rect.width); | ||
rect.bottom = rect.bottom || (rect.top + rect.height); | ||
} | ||
return rect; | ||
export function xywhToTlbr(rect) { | ||
if (rect && !('left' in rect && 'top' in rect)) { | ||
rect = extend({}, rect); | ||
rect.left = rect.x || 0; | ||
rect.top = rect.y || 0; | ||
rect.right = rect.right || (rect.left + rect.width); | ||
rect.bottom = rect.bottom || (rect.top + rect.height); | ||
} | ||
return rect; | ||
} | ||
export function tlbrToXywh (rect) { | ||
if (rect && !('x' in rect && 'y' in rect)) { | ||
rect = extend({}, rect); | ||
rect.x = rect.left || 0; | ||
rect.y = rect.top || 0; | ||
rect.width = rect.width || (rect.right - rect.x); | ||
rect.height = rect.height || (rect.bottom - rect.y); | ||
} | ||
return rect; | ||
export function tlbrToXywh(rect) { | ||
if (rect && !('x' in rect && 'y' in rect)) { | ||
rect = extend({}, rect); | ||
rect.x = rect.left || 0; | ||
rect.y = rect.top || 0; | ||
rect.width = rect.width || (rect.right - rect.x); | ||
rect.height = rect.height || (rect.bottom - rect.y); | ||
} | ||
return rect; | ||
} | ||
export default { | ||
getStringOptionResult, | ||
resolveRectLike, | ||
rectToXY, | ||
xywhToTlbr, | ||
tlbrToXywh, | ||
getStringOptionResult, | ||
resolveRectLike, | ||
rectToXY, | ||
xywhToTlbr, | ||
tlbrToXywh, | ||
}; | ||
//# sourceMappingURL=rect.js.map |
class Signals { | ||
constructor () { | ||
this.listeners = { | ||
// signalName: [listeners], | ||
}; | ||
} | ||
on (name, listener) { | ||
if (!this.listeners[name]) { | ||
this.listeners[name] = [listener]; | ||
return; | ||
constructor() { | ||
this.listeners = { | ||
// signalName: [listeners], | ||
}; | ||
} | ||
this.listeners[name].push(listener); | ||
} | ||
off (name, listener) { | ||
if (!this.listeners[name]) { return; } | ||
const index = this.listeners[name].indexOf(listener); | ||
if (index !== -1) { | ||
this.listeners[name].splice(index, 1); | ||
on(name, listener) { | ||
if (!this.listeners[name]) { | ||
this.listeners[name] = [listener]; | ||
return; | ||
} | ||
this.listeners[name].push(listener); | ||
} | ||
} | ||
fire (name, arg) { | ||
const targetListeners = this.listeners[name]; | ||
if (!targetListeners) { return; } | ||
for (const listener of targetListeners) { | ||
if (listener(arg, name) === false) { | ||
return false; | ||
} | ||
off(name, listener) { | ||
if (!this.listeners[name]) { | ||
return; | ||
} | ||
const index = this.listeners[name].indexOf(listener); | ||
if (index !== -1) { | ||
this.listeners[name].splice(index, 1); | ||
} | ||
} | ||
} | ||
fire(name, arg) { | ||
const targetListeners = this.listeners[name]; | ||
if (!targetListeners) { | ||
return; | ||
} | ||
for (const listener of targetListeners) { | ||
if (listener(arg, name) === false) { | ||
return false; | ||
} | ||
} | ||
} | ||
} | ||
export default Signals; | ||
//# sourceMappingURL=Signals.js.map |
export default (grid) => { | ||
const coordFields = [ | ||
['x', 'y'], | ||
['left', 'top'], | ||
['right', 'bottom'], | ||
['width', 'height'], | ||
].filter(([xField, yField]) => xField in grid || yField in grid); | ||
return function (x, y) { | ||
const { | ||
range, | ||
limits = { | ||
left : -Infinity, | ||
right : Infinity, | ||
top : -Infinity, | ||
bottom: Infinity, | ||
}, | ||
offset = { x: 0, y: 0 }, | ||
} = grid; | ||
const result = { range }; | ||
for (const [xField, yField] of coordFields) { | ||
const gridx = Math.round((x - offset.x) / grid[xField]); | ||
const gridy = Math.round((y - offset.y) / grid[yField]); | ||
result[xField] = Math.max(limits.left, Math.min(limits.right , gridx * grid[xField] + offset.x)); | ||
result[yField] = Math.max(limits.top, Math.min(limits.bottom , gridy * grid[yField] + offset.y)); | ||
} | ||
return result; | ||
}; | ||
const coordFields = [ | ||
['x', 'y'], | ||
['left', 'top'], | ||
['right', 'bottom'], | ||
['width', 'height'], | ||
].filter(([xField, yField]) => xField in grid || yField in grid); | ||
return function (x, y) { | ||
const { range, limits = { | ||
left: -Infinity, | ||
right: Infinity, | ||
top: -Infinity, | ||
bottom: Infinity, | ||
}, offset = { x: 0, y: 0 }, } = grid; | ||
const result = { range }; | ||
for (const [xField, yField] of coordFields) { | ||
const gridx = Math.round((x - offset.x) / grid[xField]); | ||
const gridy = Math.round((y - offset.y) / grid[yField]); | ||
result[xField] = Math.max(limits.left, Math.min(limits.right, gridx * grid[xField] + offset.x)); | ||
result[yField] = Math.max(limits.top, Math.min(limits.bottom, gridy * grid[yField] + offset.y)); | ||
} | ||
return result; | ||
}; | ||
}; | ||
//# sourceMappingURL=grid.js.map |
import grid from './grid'; | ||
export { | ||
grid, | ||
}; | ||
export { grid, }; | ||
//# sourceMappingURL=index.js.map |
import test from '@interactjs/_dev/test/test'; | ||
import normalizeListeners from '../normalizeListeners'; | ||
import normalizeListeners from '../normalizeListeners.ts'; | ||
@@ -4,0 +4,0 @@ test('utils/normalizeListeners', t => { |
import isWindow from './isWindow'; | ||
const win = { | ||
getWindow, | ||
init, | ||
realWindow: undefined, | ||
window: undefined, | ||
getWindow, | ||
init, | ||
}; | ||
export function init (window) { | ||
// get wrapped window if using Shadow DOM polyfill | ||
win.realWindow = window; | ||
// create a TextNode | ||
const el = window.document.createTextNode(''); | ||
// check if it's wrapped by a polyfill | ||
if (el.ownerDocument !== window.document | ||
&& typeof window.wrap === 'function' | ||
&& window.wrap(el) === el) { | ||
// use wrapped window | ||
window = window.wrap(window); | ||
} | ||
win.window = window; | ||
export function init(window) { | ||
// get wrapped window if using Shadow DOM polyfill | ||
win.realWindow = window; | ||
// create a TextNode | ||
const el = window.document.createTextNode(''); | ||
// check if it's wrapped by a polyfill | ||
if (el.ownerDocument !== window.document | ||
&& typeof window.wrap === 'function' | ||
&& window.wrap(el) === el) { | ||
// use wrapped window | ||
window = window.wrap(window); | ||
} | ||
win.window = window; | ||
} | ||
if (typeof window === 'undefined') { | ||
win.window = undefined; | ||
win.realWindow = undefined; | ||
win.window = undefined; | ||
win.realWindow = undefined; | ||
} | ||
else { | ||
init(window); | ||
init(window); | ||
} | ||
export function getWindow (node) { | ||
if (isWindow(node)) { | ||
return node; | ||
} | ||
const rootNode = (node.ownerDocument || node); | ||
return rootNode.defaultView || win.window; | ||
export function getWindow(node) { | ||
if (isWindow(node)) { | ||
return node; | ||
} | ||
const rootNode = (node.ownerDocument || node); | ||
return rootNode.defaultView || win.window; | ||
} | ||
win.init = init; | ||
export default win; | ||
//# sourceMappingURL=window.js.map |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
137690
92
2771
2