UNPKG

ember-sortable

Version:
114 lines (107 loc) 3.11 kB
import { find, triggerEvent, settled, waitUntil } from '@ember/test-helpers'; import { getOffset } from '../utils/offset.js'; /** Drags elements by an offset specified in pixels. Examples drag( 'mouse', '.some-list li[data-item=uno]', function() { return { dy: 50, dx: 20 }; } ); @method drag @param {'mouse'|'touch'} [mode] event mode @param {String} [itemSelector] selector for the element to drag @param {Function} [offsetFn] function returning the offset by which to drag @param {Object} [callbacks] callbacks that are fired at the different stages of the interaction @return {Promise} */ async function drag(mode, itemSelector, // or Parameters<typeof find>[0][] offsetFn, callbacks = {}) { let start; let move; let end; let which; if (mode === 'mouse') { start = 'mousedown'; move = 'mousemove'; end = 'mouseup'; which = 1; } else if (mode === 'touch') { start = 'touchstart'; move = 'touchmove'; end = 'touchend'; } else { throw new Error(`Unsupported mode: '${mode}'`); } const itemElement = find(itemSelector); if (!itemElement) { throw new Error(`Element with selector '${itemSelector}' not found!`); } const itemOffset = getOffset(itemElement); const offset = offsetFn(); const rect = itemElement.getBoundingClientRect(); // firefox gives some elements, like <svg>, a clientHeight of 0. // we can try to grab it off the parent instead to have a better // guess at what the scale is. // https://bugzilla.mozilla.org/show_bug.cgi?id=874811#c14 // https://stackoverflow.com/a/13647345 // https://stackoverflow.com/a/5042051 const dx = offset.dx || 0; const dy = offset.dy || 0; const clientHeight = itemElement.clientHeight || itemElement.offsetHeight || itemElement.parentNode?.offsetHeight || 0; const scale = clientHeight / (rect.bottom - rect.top); const halfwayX = itemOffset.left + dx * scale / 2; const halfwayY = itemOffset.top + dy * scale / 2; const targetX = itemOffset.left + dx * scale; const targetY = itemOffset.top + dy * scale; await triggerEvent(itemElement, start, { clientX: itemOffset.left, clientY: itemOffset.top, which }); if (callbacks.dragstart) { await callbacks.dragstart(); await settled(); } await triggerEvent(itemElement, move, { clientX: itemOffset.left, clientY: itemOffset.top }); if (callbacks.dragmove) { await callbacks.dragmove(); await settled(); } await triggerEvent(itemElement, move, { clientX: halfwayX, clientY: halfwayY }); await triggerEvent(itemElement, move, { clientX: targetX, clientY: targetY }); if (callbacks.beforedragend) { await callbacks.beforedragend(); } await triggerEvent(itemElement, end, { clientX: targetX, clientY: targetY }); if (callbacks.dragend) { await callbacks.dragend(); await settled(); } await waitUntil(() => { return !find('.is-dropping'); }, { timeout: 2000 }); } export { drag }; //# sourceMappingURL=drag.js.map