From fa7db13c108d1f67b5e408b4f5596871b8497a6d Mon Sep 17 00:00:00 2001 From: Nicholas Clawson Date: Mon, 15 May 2017 11:54:32 -0700 Subject: [PATCH] Work out last few issues in touch --- CHANGELOG.md | 2 + src/index.js | 58 +++++++++++-------- src/util.js | 9 +++ ...ngth-test.js => strength-creators-test.js} | 10 ++++ 4 files changed, 56 insertions(+), 23 deletions(-) rename test/{createHorizontalStrength-test.js => strength-creators-test.js} (86%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c78e4f..5b9f88f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * Adds a hard dependency on using `react-dnd` which was theoretically optional before. * Fix double dispatch of `onDragOver` prop +* Default strength functions always return 0 if the point is anywhere + outside the box. ### `v3.2.0` * Use `prop-types` package instead of deprecated `React.PropTypes` diff --git a/src/index.js b/src/index.js index a4aa96e..dcffbd3 100644 --- a/src/index.js +++ b/src/index.js @@ -5,15 +5,17 @@ import throttle from 'lodash.throttle'; import raf from 'raf'; import getDisplayName from 'react-display-name'; import hoist from 'hoist-non-react-statics'; -import { noop, intBetween } from './util'; +import { noop, intBetween, getCoords } from './util'; const DEFAULT_BUFFER = 150; export function createHorizontalStrength(_buffer) { - return function defaultHorizontalStrength({ x, w }, point) { + return function defaultHorizontalStrength({ x, w, y, h }, point) { const buffer = Math.min(w / 2, _buffer); + const inRange = point.x >= x && point.x <= x + w; + const inBox = inRange && point.y >= y && point.y <= y + h; - if (point.x >= x && point.x <= x + w) { + if (inBox) { if (point.x < x + buffer) { return (point.x - x - buffer) / buffer; } else if (point.x > (x + w - buffer)) { @@ -26,10 +28,12 @@ export function createHorizontalStrength(_buffer) { } export function createVerticalStrength(_buffer) { - return function defaultVerticalStrength({ y, h }, point) { + return function defaultVerticalStrength({ y, h, x, w }, point) { const buffer = Math.min(h / 2, _buffer); + const inRange = point.y >= y && point.y <= y + h; + const inBox = inRange && point.x >= x && point.x <= x + w; - if (point.y >= y && point.y <= y + h) { + if (inBox) { if (point.y < y + buffer) { return (point.y - y - buffer) / buffer; } else if (point.y > (y + h - buffer)) { @@ -75,11 +79,17 @@ export default function createScrollingComponent(WrappedComponent) { this.scaleX = 0; this.scaleY = 0; this.frame = null; + this.attached = false; + this.dragging = false; } componentDidMount() { this.container = findDOMNode(this.wrappedInstance); + this.container.addEventListener('dragover', this.handleEvent); + // touchmove events don't seem to work across siblings, so we unfortunately + // have to attach the listeners to the body + window.document.body.addEventListener('touchmove', this.handleEvent); this.clearMonitorSubscription = this.context .dragDropManager @@ -88,46 +98,48 @@ export default function createScrollingComponent(WrappedComponent) { } componentWillUnmount() { + this.container.removeEventListener('dragover', this.handleEvent); + window.document.body.removeEventListener('touchmove', this.handleEvent); this.clearMonitorSubscription(); this.stopScrolling(); } - getCoords(evt) { - if (evt.type === 'touchmove') { - return { x: evt.changedTouches[0].clientX, y: evt.changedTouches[0].clientY }; + handleEvent = (evt) => { + if (this.dragging && !this.attached) { + this.attach(); + this.updateScrolling(evt); } + } + + handleMonitorChange() { + const isDragging = this.context.dragDropManager.getMonitor().isDragging(); - return { x: evt.clientX, y: evt.clientY }; + if (!this.dragging && isDragging) { + this.dragging = true; + } else if (this.dragging && !isDragging) { + this.dragging = false; + this.stopScrolling(); + } } attach() { this.attached = true; - window.document.body.addEventListener('mousemove', this.updateScrolling); + window.document.body.addEventListener('dragover', this.updateScrolling); window.document.body.addEventListener('touchmove', this.updateScrolling); } detach() { this.attached = false; - window.document.body.removeEventListener('mousemove', this.updateScrolling); + window.document.body.removeEventListener('dragover', this.updateScrolling); window.document.body.removeEventListener('touchmove', this.updateScrolling); } - handleMonitorChange() { - const isDragging = this.context.dragDropManager.getMonitor().isDragging(); - - if (!this.attached && isDragging) { - this.attach(); - } else if (this.attached && !isDragging) { - this.stopScrolling(); - } - } - // Update scaleX and scaleY every 100ms or so // and start scrolling if necessary updateScrolling = throttle(evt => { const { left: x, top: y, width: w, height: h } = this.container.getBoundingClientRect(); const box = { x, y, w, h }; - const coords = this.getCoords(evt); + const coords = getCoords(evt); // calculate strength this.scaleX = this.props.horizontalStrength(box, coords); @@ -189,7 +201,7 @@ export default function createScrollingComponent(WrappedComponent) { tick(); } - stopScrolling = () => { + stopScrolling() { this.detach(); this.scaleX = 0; this.scaleY = 0; diff --git a/src/util.js b/src/util.js index 5ee9aab..5d99f15 100644 --- a/src/util.js +++ b/src/util.js @@ -8,3 +8,12 @@ export function intBetween(min, max, val) { Math.min(max, Math.max(min, val)) ); } + + +export function getCoords(evt) { + if (evt.type === 'touchmove') { + return { x: evt.changedTouches[0].clientX, y: evt.changedTouches[0].clientY }; + } + + return { x: evt.clientX, y: evt.clientY }; +} diff --git a/test/createHorizontalStrength-test.js b/test/strength-creators-test.js similarity index 86% rename from test/createHorizontalStrength-test.js rename to test/strength-creators-test.js index b9bb80c..2252af3 100644 --- a/test/createHorizontalStrength-test.js +++ b/test/strength-creators-test.js @@ -24,6 +24,11 @@ describe('strength functions', function() { expect(hFn(box, { x: 450, y: 0 })).to.equal(0); }); + it('should return 0 when outside the box', function() { + expect(hFn(box, { x: 0, y: -100 })).to.equal(0); + expect(hFn(box, { x: 0, y: 900 })).to.equal(0); + }); + it('should scale linearly from the boundary to respective buffer', function() { expect(hFn(box, { x: 75, y: 0 })).to.equal(-.5); expect(hFn(box, { x: 525, y: 0 })).to.equal(.5); @@ -52,6 +57,11 @@ describe('strength functions', function() { expect(vFn(box, { x: 0, y: 450 })).to.equal(0); }); + it('should return 0 when outside the box', function() { + expect(vFn(box, { x: -100, y: 0 })).to.equal(0); + expect(vFn(box, { x: 900, y: 0 })).to.equal(0); + }); + it('should scale linearly from the boundary to respective buffer', function() { expect(vFn(box, { x: 0, y: 75 })).to.equal(-.5); expect(vFn(box, { x: 0, y: 525 })).to.equal(.5);