From b230b2effffc990801c7920f979027f94066380c Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Thu, 4 Nov 2021 10:13:56 +0000 Subject: [PATCH] Fixed inputs being toggled / events being fired at end of `{{movable}}` drag no issue - moves disabling of scroll and pointer events into the `drag` handler so we don't inadvertently stop genuine clicks on elements inside the movable container - adds a timeout for re-enabling pointer-events and clicks when drag finishes so we can still capture the unwanted events that would otherwise fire on mouseup - uses a `click` event handler as that event is still fired even though we're preventing `mouseup`, fixes problems where the `pointer-events: none` on the movable container lets events through to the element behind it which could cause the movable container to be removed (eg, click event on the editor background moving a card out of edit mode) --- ghost/admin/app/modifiers/movable.js | 39 ++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/ghost/admin/app/modifiers/movable.js b/ghost/admin/app/modifiers/movable.js index 40a13601b6..1bb27a72da 100644 --- a/ghost/admin/app/modifiers/movable.js +++ b/ghost/admin/app/modifiers/movable.js @@ -2,6 +2,7 @@ import Modifier from 'ember-modifier'; import {action} from '@ember/object'; export default class MovableModifier extends Modifier { + active = false; currentX = undefined; currentY = undefined; initialX = undefined; @@ -60,8 +61,6 @@ export default class MovableModifier extends Modifier { for (const elem of (e.path || e.composedPath())) { if (elem === this.element) { - this.disableScroll(); - this.disablePointerEvents(); this.addActiveEventListeners(); break; } @@ -72,17 +71,32 @@ export default class MovableModifier extends Modifier { @action dragEnd(e) { e.preventDefault(); - this.enableScroll(); - this.enablePointerEvents(); + e.stopPropagation(); + + this.active = false; + this.initialX = this.currentX; this.initialY = this.currentY; + this.removeActiveEventListeners(); + this.enableScroll(); + + // timeout required so immediate events are still blocked + setTimeout(() => { + this.enablePointerEvents(); + }, 5); } @action drag(e) { e.preventDefault(); + if (!this.active) { + this.disableScroll(); + this.disablePointerEvents(); + this.active = true; + } + if (e.type === 'touchmove') { this.currentX = e.touches[0].clientX - this.initialX; this.currentY = e.touches[0].clientY - this.initialY; @@ -97,6 +111,12 @@ export default class MovableModifier extends Modifier { this.setTranslate(this.currentX, this.currentY); } + @action + cancelClick(e) { + e.preventDefault(); + e.stopPropagation(); + } + setTranslate(xPos, yPos) { this.element.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`; } @@ -110,13 +130,16 @@ export default class MovableModifier extends Modifier { this.element.style.overflow = this.originalOverflow; } - // TODO: pointer events are not disabled because dragging to an area off - // central editor canvas exits edit mode - investigate further + // disabling pointer events prevents inputs being activated when drag finishes, + // preventing clicks stops any event handlers that may otherwise result in the + // movable element being closed when the drag finishes disablePointerEvents() { - // this.element.style.pointerEvents = 'none'; + this.element.style.pointerEvents = 'none'; + window.addEventListener('click', this.cancelClick, {capture: true, passive: false}); } enablePointerEvents() { - // this.element.style.pointerEvents = ''; + this.element.style.pointerEvents = ''; + window.removeEventListener('click', this.cancelClick, {capture: true, passive: false}); } }