From eb1eeb3fde80d812e528df41fe34a5b0f9afdd9f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 14 Aug 2017 15:43:48 +0200 Subject: [PATCH] Ignore clicks on block decorations Previously, clicking on a block decoration to interact with it would cause the editor to scroll to the line next to it. This is inconvenient, especially if the decoration was designed to be interactive and contained buttons or links. If the decoration was close to the bottom of the screen, clicking on a button inside of it would make the editor scroll down and abort the click. This behavior regressed during the editor rendering layer rewrite and with this commit we are restoring the original behavior by simply ignoring clicks that land on block decorations. --- spec/text-editor-component-spec.js | 33 ++++++++++++++++++++++++++++++ src/text-editor-component.js | 12 +++++++++++ 2 files changed, 45 insertions(+) diff --git a/spec/text-editor-component-spec.js b/spec/text-editor-component-spec.js index a4631b541..4c0108b33 100644 --- a/spec/text-editor-component-spec.js +++ b/spec/text-editor-component-spec.js @@ -2153,6 +2153,39 @@ describe('TextEditorComponent', () => { expect(component.refs.blockDecorationMeasurementArea.offsetWidth).toBe(component.getScrollWidth()) }) + it('does not change the cursor position when clicking on a block decoration', async () => { + const {editor, component} = buildComponent() + + const decorationElement = document.createElement('div') + decorationElement.textContent = 'Parent' + const childElement = document.createElement('div') + childElement.textContent = 'Child' + decorationElement.appendChild(childElement) + const marker = editor.markScreenPosition([4, 0]) + editor.decorateMarker(marker, {type: 'block', item: decorationElement}) + await component.getNextUpdatePromise() + + const decorationElementClientRect = decorationElement.getBoundingClientRect() + component.didMouseDownOnContent({ + target: decorationElement, + detail: 1, + button: 0, + clientX: decorationElementClientRect.left, + clientY: decorationElementClientRect.top + }) + expect(editor.getCursorScreenPosition()).toEqual([0, 0]) + + const childElementClientRect = childElement.getBoundingClientRect() + component.didMouseDownOnContent({ + target: childElement, + detail: 1, + button: 0, + clientX: childElementClientRect.left, + clientY: childElementClientRect.top + }) + expect(editor.getCursorScreenPosition()).toEqual([0, 0]) + }) + function createBlockDecorationAtScreenRow(editor, screenRow, {height, margin, position}) { const marker = editor.markScreenPosition([screenRow, 0], {invalidate: 'never'}) const item = document.createElement('div') diff --git a/src/text-editor-component.js b/src/text-editor-component.js index 403f24bbd..e409001a8 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -1689,6 +1689,18 @@ class TextEditorComponent { const {target, button, detail, ctrlKey, shiftKey, metaKey} = event const platform = this.getPlatform() + // Ignore clicks on block decorations. + if (target) { + let element = target + while (element && element !== this.element) { + if (this.blockDecorationsByElement.has(element)) { + return + } + + element = element.parentElement + } + } + // On Linux, position the cursor on middle mouse button click. A // textInput event with the contents of the selection clipboard will be // dispatched by the browser automatically on mouseup.