From c563d5721fa6e76ea2ce837e44e3a9076f178378 Mon Sep 17 00:00:00 2001 From: Tsvetomir Tsonev Date: Thu, 15 Mar 2018 16:01:57 +0200 Subject: [PATCH] feat: add mouseOnly option --- README.md | 29 ++++++++++++++++++++++---- e2e/draggable-compat.js | 25 ++++++++++++++++++++++ e2e/draggable.js | 19 +++++++++++++++++ src/main.d.ts | 3 ++- src/main.js | 46 +++++++++++++++++++++++++++++------------ 5 files changed, 104 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 4ca751d..17b232d 100644 --- a/README.md +++ b/README.md @@ -70,12 +70,9 @@ The Kendo UI Draggable supports: - Mouse events - Touch events +- Pointer events - Handling of multiple touches. Rather, not getting confused by them. -## What's Next - -Support for Pointer events support, necessary for the Windows Phone platform. - ## Dragging on iOS/Android Handling the drag sequence on mobile devices may require the disabling of the touch-based scrolling. The Draggable will not do that out of the box. The recommended way to handle this issue is by setting a [`touch-action`](https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action) CSS property. Depending on the type of drags that are handled, you may need `touch-action: none`, `touch-action: pan-y`, or `touch-action: pan-x`. @@ -92,6 +89,30 @@ Handling the drag sequence on mobile devices may require the disabling of the to The dragging of elements that contain text activates the browser text selection, which, in most cases, is not desirable. To avoid this behavior, use the [`user-select: none`](https://developer.mozilla.org/en-US/docs/Web/CSS/user-select) CSS property with its respective browser prefixes. +## Mouse-Only mode + +To ignore all touch and pointer events, set `mouseOnly` to `true`. This is useful when you want to keep the default touch-drag behavior, e.g. horizontal scroll. + +```javascript +import Draggable from '@telerik/kendo-draggable'; + +const draggable = new Draggable({ + mouseOnly: true, + press: function(e) { + console.log("pressed", e.pageX, e.pageY); + }, + drag: function(e) { + console.log("drag", e.pageX, e.pageY); + }, + release: function(e) { + console.log("release", e.pageX, e.pageY); + } +}); + +draggable.bindTo(document.getElementById("my-element")); +``` + + ## Browser Support - Google Chrome diff --git a/e2e/draggable-compat.js b/e2e/draggable-compat.js index b550d0d..2b1c9b0 100644 --- a/e2e/draggable-compat.js +++ b/e2e/draggable-compat.js @@ -235,4 +235,29 @@ describe('Draggable with Mouse and Touch events fallback', () => { clock.uninstall(); }); }); + + describe("with mouseOnly set to true", () => { + beforeEach(() => { + handler = jasmine.createSpy("onPress"); + + draggable = new Draggable({ + press: handler, + mouseOnly: true + }); + + draggable.bindTo(el); + }); + + it("emits press on mousedown", () => { + mousedown(el, 100, 200); + + expect(handler).toHaveBeenCalled(); + }); + + it("does not emit press on touchstart", () => { + touchstart(el, 100, 200); + + expect(handler).not.toHaveBeenCalled(); + }); + }); }); diff --git a/e2e/draggable.js b/e2e/draggable.js index 66d57d6..0f3d5d1 100644 --- a/e2e/draggable.js +++ b/e2e/draggable.js @@ -147,5 +147,24 @@ describe('Draggable with Pointer events', () => { expect(el.style.touchAction).toEqual('pan-y'); }); }); + + describe("with mouseOnly set to true", () => { + beforeEach(() => { + handler = jasmine.createSpy("onPress"); + + draggable = new Draggable({ + press: handler, + mouseOnly: true + }); + + draggable.bindTo(el); + }); + + it("does not emit press on pointerdown", () => { + pointerdown(el, 100, 200); + + expect(handler).not.toHaveBeenCalled(); + }); + }); }); diff --git a/src/main.d.ts b/src/main.d.ts index 0216e77..cbe2a35 100644 --- a/src/main.d.ts +++ b/src/main.d.ts @@ -1,7 +1,8 @@ interface DraggableOptions { press?: Function, drag?: Function, - release?: Function + release?: Function, + mouseOnly?: boolean } export default class Draggable { diff --git a/src/main.js b/src/main.js index ec3baa1..34f0de2 100644 --- a/src/main.js +++ b/src/main.js @@ -42,11 +42,12 @@ export class Draggable { return window.PointerEvent; } - constructor({ press = noop, drag = noop, release = noop }) { + constructor({ press = noop, drag = noop, release = noop, mouseOnly = false }) { this._pressHandler = proxy(normalizeEvent, press); this._dragHandler = proxy(normalizeEvent, drag); this._releaseHandler = proxy(normalizeEvent, release); this._ignoreMouse = false; + this._mouseOnly = mouseOnly; this._touchAction; this._touchstart = (e) => { @@ -133,12 +134,21 @@ export class Draggable { } this._element = element; + this._bindToCurrent(); + } + + _bindToCurrent() { + const element = this._element; - if (Draggable.supportPointerEvent()) { + if (this._usePointers()) { bind(element, "pointerdown", this._pointerdown); bind(element, "pointerup", this._pointerup); - } else { - bind(element, "mousedown", this._mousedown); + return; + } + + bind(element, "mousedown", this._mousedown); + + if (!this._mouseOnly) { bind(element, "touchstart", this._touchstart); bind(element, "touchmove", this._touchmove); bind(element, "touchend", this._touchend); @@ -146,18 +156,28 @@ export class Draggable { } _unbindFromCurrent() { - if (Draggable.supportPointerEvent()) { - unbind(this._element, "pointerdown", this._pointerdown); - unbind(this._element, "pointermove", this._pointermove); - unbind(this._element, "pointerup", this._pointerup); - } else { - unbind(this._element, "mousedown", this._mousedown); - unbind(this._element, "touchstart", this._touchstart); - unbind(this._element, "touchmove", this._touchmove); - unbind(this._element, "touchend", this._touchend); + const element = this._element; + + if (this._usePointers()) { + unbind(element, "pointerdown", this._pointerdown); + unbind(element, "pointermove", this._pointermove); + unbind(element, "pointerup", this._pointerup); + return; + } + + unbind(element, "mousedown", this._mousedown); + + if (!this._mouseOnly) { + unbind(element, "touchstart", this._touchstart); + unbind(element, "touchmove", this._touchmove); + unbind(element, "touchend", this._touchend); } } + _usePointers() { + return !this._mouseOnly && Draggable.supportPointerEvent(); + } + destroy() { this._unbindFromCurrent(); this._element = null;