From c855e620ef5835a6ee896315e0a67f2bcd2ef786 Mon Sep 17 00:00:00 2001 From: Tsvetomir Milchev Date: Tue, 25 Jul 2023 16:30:10 +0300 Subject: [PATCH 1/3] feat: allow single pointer drag --- src/main.js | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/main.js b/src/main.js index 741fc03..ba83e07 100644 --- a/src/main.js +++ b/src/main.js @@ -51,16 +51,18 @@ export class Draggable { get document() { return this._element - ? this._element.ownerDocument - : document; + ? this._element.ownerDocument + : document; } - constructor({ press = noop, drag = noop, release = noop, mouseOnly = false }) { + constructor({ press = noop, drag = noop, release = noop, mouseOnly = false, clickMoveClick = false }) { this._pressHandler = proxy(normalizeEvent, press); this._dragHandler = proxy(normalizeEvent, drag); this._releaseHandler = proxy(normalizeEvent, release); this._ignoreMouse = false; + this._isDragging = false; this._mouseOnly = mouseOnly; + this._clickMoveClick = clickMoveClick; this._touchstart = (e) => { if (e.touches.length === 1) { @@ -92,12 +94,24 @@ export class Draggable { const { which } = e; if ((which && which > 1) || this._ignoreMouse) { + bind(this.document, "contextmenu", preventDefault); return; } - bind(this.document, "mousemove", this._mousemove); - bind(this.document, "mouseup", this._mouseup); - this._pressHandler(e); + if (!this._clickMoveClick) { + bind(this.document, "mouseup", this._mouseup); + bind(this.document, "mousemove", this._mousemove); + this._pressHandler(e); + } else { + if (this._isDragging) { + bind(this.document, "mouseup", this._mouseup); + } else { + bind(this.document, "mousemove", this._mousemove); + this._pressHandler(e); + } + + this._isDragging = !this._isDragging; + } }; this._mousemove = (e) => { @@ -112,12 +126,25 @@ export class Draggable { this._pointerdown = (e) => { if (e.isPrimary && e.button === 0) { - bind(this.document, "pointermove", this._pointermove); - bind(this.document, "pointerup", this._pointerup); - bind(this.document, "pointercancel", this._pointerup); - bind(this.document, "contextmenu", preventDefault); - this._pressHandler(e); + if (!this._clickMoveClick) { + bind(this.document, "pointerup", this._pointerup); + bind(this.document, "pointercancel", this._pointerup); + bind(this.document, "contextmenu", preventDefault); + bind(this.document, "pointermove", this._pointermove); + this._pressHandler(e); + } else { + if (this._isDragging) { + bind(this.document, "pointerup", this._pointerup); + bind(this.document, "pointercancel", this._pointerup); + } else { + bind(this.document, "pointermove", this._pointermove); + this._pressHandler(e); + } + + this._isDragging = !this._isDragging; + } + } }; From c2aaca2df58c94f189e35078c0f2199b140d24d9 Mon Sep 17 00:00:00 2001 From: Tsvetomir Milchev Date: Thu, 10 Aug 2023 16:35:08 +0300 Subject: [PATCH 2/3] feat: add cancel event --- src/main.d.ts | 2 ++ src/main.js | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/main.d.ts b/src/main.d.ts index d601f80..e16ac4e 100644 --- a/src/main.d.ts +++ b/src/main.d.ts @@ -2,7 +2,9 @@ interface DraggableOptions { press?: Function; drag?: Function; release?: Function; + cancel?: Function; mouseOnly?: boolean; + clickMoveClick?: boolean; } export class Draggable { diff --git a/src/main.js b/src/main.js index ba83e07..86f7852 100644 --- a/src/main.js +++ b/src/main.js @@ -15,6 +15,7 @@ const touchRegExp = /touch/; // 300ms is the usual mouse interval; // // However, an underpowered mobile device under a heavy load may queue mouse events for a longer period. const IGNORE_MOUSE_TIMEOUT = 2000; +const ESC = 27; function normalizeEvent(e) { if (e.type.match(touchRegExp)) { @@ -55,10 +56,11 @@ export class Draggable { : document; } - constructor({ press = noop, drag = noop, release = noop, mouseOnly = false, clickMoveClick = false }) { + constructor({ press = noop, drag = noop, release = noop, cancel = noop, mouseOnly = false, clickMoveClick = false }) { this._pressHandler = proxy(normalizeEvent, press); this._dragHandler = proxy(normalizeEvent, drag); this._releaseHandler = proxy(normalizeEvent, release); + this._cancelHandler = proxy(normalizeEvent, cancel); this._ignoreMouse = false; this._isDragging = false; this._mouseOnly = mouseOnly; @@ -139,12 +141,17 @@ export class Draggable { bind(this.document, "pointercancel", this._pointerup); } else { bind(this.document, "pointermove", this._pointermove); + bind(this.document, "keydown", this._keydown); this._pressHandler(e); } this._isDragging = !this._isDragging; } + } + if (this._clickMoveClick && e.button == 2) { + this.cancelDrag(e); + this._cancelHandler(e); } }; @@ -161,14 +168,25 @@ export class Draggable { unbind(this.document, "pointercancel", this._pointerup); unbind(this.document, "contextmenu", preventDefault); + if (this.clickMoveClick){ + unbind(this.document, "keydown", this._keydown); + } + this._releaseHandler(e); } }; + + this._keydown = (e) => { + if (e.keyCode === ESC) { + this.cancelDrag(e); + this._cancelHandler(e); + } + }; } bindTo(element) { if (element === this._element) { - return; + return; } if (this._element) { @@ -179,6 +197,18 @@ export class Draggable { this._bindToCurrent(); } + cancelDrag() { + unbind(this.document, "pointermove", this._pointermove); + unbind(this.document, "pointerup", this._pointerup); + unbind(this.document, "pointercancel", this._pointerup); + + if (this.clickMoveClick) { + unbind(this.document, "contextmenu", preventDefault); + } + + this._isDragging = !this._isDragging; + } + _bindToCurrent() { const element = this._element; From 9ecdca6a7a12d69c3caca473dffcef6be134deba Mon Sep 17 00:00:00 2001 From: Tsvetomir Milchev Date: Fri, 11 Aug 2023 11:27:54 +0300 Subject: [PATCH 3/3] feat: add cancel event when mouseonly --- src/main.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main.js b/src/main.js index 86f7852..7cee677 100644 --- a/src/main.js +++ b/src/main.js @@ -97,18 +97,25 @@ export class Draggable { if ((which && which > 1) || this._ignoreMouse) { bind(this.document, "contextmenu", preventDefault); + + this.cancelDrag(e); + + this._cancelHandler(e); + return; } if (!this._clickMoveClick) { bind(this.document, "mouseup", this._mouseup); bind(this.document, "mousemove", this._mousemove); + bind(this.document, "contextmenu", preventDefault); this._pressHandler(e); } else { if (this._isDragging) { bind(this.document, "mouseup", this._mouseup); } else { bind(this.document, "mousemove", this._mousemove); + bind(this.document, "keydown", this._keydown); this._pressHandler(e); } @@ -123,6 +130,12 @@ export class Draggable { this._mouseup = (e) => { unbind(this.document, "mousemove", this._mousemove); unbind(this.document, "mouseup", this._mouseup); + + if (this.clickMoveClick){ + unbind(this.document, "keydown", this._keydown); + unbind(this.document, "contextmenu", preventDefault); + } + this._releaseHandler(e); };