mirror of
https://github.com/Shopify/draggable.git
synced 2026-02-01 16:46:56 +00:00
Add test coverage for utils.closest
Add docblock Move test to new location Fix linting issues
This commit is contained in:
parent
1c21f18ca1
commit
aaa5c2b597
68
src/shared/utils/closest/tests/closest.test.js
Normal file
68
src/shared/utils/closest/tests/closest.test.js
Normal file
@ -0,0 +1,68 @@
|
||||
import {closest} from 'utils';
|
||||
|
||||
import {
|
||||
createSandbox,
|
||||
} from 'helper';
|
||||
|
||||
const sampleMarkup = `
|
||||
<div class="tree">
|
||||
<section class="branch">
|
||||
<ul class="twig">
|
||||
<li class="leaf"></li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
`;
|
||||
|
||||
describe('utils', () => {
|
||||
let sandbox;
|
||||
|
||||
beforeEach(() => {
|
||||
sandbox = createSandbox(sampleMarkup);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.parentNode.removeChild(sandbox);
|
||||
});
|
||||
|
||||
test('should return null when no element specified', () => {
|
||||
expect(closest()).toBe(null);
|
||||
});
|
||||
|
||||
test('should return null when string selector does not match', () => {
|
||||
const element = sandbox.querySelector('.leaf');
|
||||
|
||||
expect(closest(element, 'will-not-match')).toBe(null);
|
||||
});
|
||||
|
||||
test('should return null when function selector does not match', () => {
|
||||
const element = sandbox.querySelector('.leaf');
|
||||
function selector() { return false; }
|
||||
|
||||
expect(closest(element, selector)).toBe(null);
|
||||
});
|
||||
|
||||
test('should return null when selector targets child element', () => {
|
||||
const element = sandbox.querySelector('.twig');
|
||||
|
||||
expect(closest(element, '.leaf')).toBe(null);
|
||||
});
|
||||
|
||||
[
|
||||
'.twig',
|
||||
'ul',
|
||||
'.branch',
|
||||
'section',
|
||||
'.tree',
|
||||
'div',
|
||||
'body',
|
||||
'document',
|
||||
].forEach((expectedMatchingSelector) => {
|
||||
test(`should return matched element when selector targets parent element matching selector ${expectedMatchingSelector}`, () => {
|
||||
const element = sandbox.querySelector('.leaf');
|
||||
const expected = sandbox.querySelector(expectedMatchingSelector);
|
||||
|
||||
expect(closest(element, expectedMatchingSelector)).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
61
src/utils.js
Normal file
61
src/utils.js
Normal file
@ -0,0 +1,61 @@
|
||||
/** @module utils */
|
||||
|
||||
/**
|
||||
* Get the closest parent element of a given element that matches the given
|
||||
* selector string or matching function
|
||||
*
|
||||
* @param {Element} element The child element to find a parent of
|
||||
* @param {String|Function} selector The string or function to use to match
|
||||
* the parent element
|
||||
* @return {Element|null}
|
||||
*/
|
||||
export function closest(element, selector) {
|
||||
if (!element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function conditionFn(currentElement) {
|
||||
if (!currentElement) {
|
||||
return currentElement;
|
||||
} else if (typeof selector === 'string') {
|
||||
const matchFunction = Element.prototype.matches ||
|
||||
Element.prototype.webkitMatchesSelector ||
|
||||
Element.prototype.mozMatchesSelector ||
|
||||
Element.prototype.msMatchesSelector;
|
||||
return matchFunction.call(currentElement, selector);
|
||||
} else {
|
||||
return selector(currentElement);
|
||||
}
|
||||
}
|
||||
|
||||
let current = element;
|
||||
|
||||
do {
|
||||
current = current.correspondingUseElement || current.correspondingElement || current;
|
||||
if (conditionFn(current)) {
|
||||
return current;
|
||||
}
|
||||
current = current.parentNode;
|
||||
} while (current !== document.body && current !== document);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
let scrollAnimationFrame;
|
||||
|
||||
export function scroll(element, {clientX, clientY, speed, sensitivity}) {
|
||||
if (scrollAnimationFrame) {
|
||||
cancelAnimationFrame(scrollAnimationFrame);
|
||||
}
|
||||
|
||||
function scrollFn() {
|
||||
const rect = element.getBoundingClientRect();
|
||||
const offsetY = (Math.abs(rect.bottom - clientY) <= sensitivity) - (Math.abs(rect.top - clientY) <= sensitivity);
|
||||
const offsetX = (Math.abs(rect.right - clientX) <= sensitivity) - (Math.abs(rect.left - clientX) <= sensitivity);
|
||||
element.scrollTop += offsetY * speed;
|
||||
element.scrollLeft += offsetX * speed;
|
||||
scrollAnimationFrame = requestAnimationFrame(scrollFn);
|
||||
}
|
||||
|
||||
scrollAnimationFrame = requestAnimationFrame(scrollFn);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user