Dragging to create selection is direction-dependently buggy with Decoration.widget in some circumstances #1445

Open
opened 2024-02-10 03:50:41 +01:00 by Nantris · 3 comments
Nantris commented 2024-02-10 03:50:41 +01:00 (Migrated from github.com)

We hide sections of the editor using decorations and it works great when dragging from top to bottom, but for bottom to top the behavior is different and the selection is interrupted.

Rather than being caused by the hidden content itself, this appears in some way to be related to Decoration.widget. If we remove the widgets but keep everything else the same, the selection can be expanded in either direction as expected. I'm not sure why they might interfere.

The issue does not affect Shift+Click to expand selections, only pure drag-based selections.

https://github.com/ProseMirror/prosemirror/assets/6835891/eeaea307-e316-4ed4-b03d-ab06b9bfc88d

The video is from Chrome on Linux. It behaves fundamentally the same in Firefox, although it does select some text on the upper line unlike Chrome.


I'm sure this is entirely insufficient to really reveal the root cause, but I found commenting this line out prevents the issue:

github.com/ProseMirror/prosemirror-view@39fb7c2e71/src/selection.ts (L89)

We hide sections of the editor using decorations and it works great when dragging from top to bottom, but for bottom to top the behavior is different and the selection is interrupted. Rather than being caused by the hidden content itself, this appears in some way to be related to `Decoration.widget`. If we remove the widgets but keep everything else the same, the selection can be expanded in either direction as expected. I'm not sure why they might interfere. The issue does not affect `Shift+Click` to expand selections, only pure drag-based selections. https://github.com/ProseMirror/prosemirror/assets/6835891/eeaea307-e316-4ed4-b03d-ab06b9bfc88d The video is from Chrome on Linux. It behaves fundamentally the same in Firefox, although it does select some text on the upper line unlike Chrome. ---- I'm sure this is entirely insufficient to really reveal the root cause, but I found commenting this line out prevents the issue: https://github.com/ProseMirror/prosemirror-view/blob/39fb7c2e71287d6ac2013f5a8c878873a074244e/src/selection.ts#L89
marijnh commented 2024-02-10 10:24:37 +01:00 (Migrated from github.com)

ProseMirror relies on the native browser drag-selection behavior. Some browsers glitch out when the DOM is changed in certain ways during selection. Delaying your decoration until the mouse button is released may be a way to work around this.

ProseMirror relies on the native browser drag-selection behavior. Some browsers glitch out when the DOM is changed in certain ways during selection. Delaying your decoration until the mouse button is released may be a way to work around this.
Nantris commented 2024-02-11 00:52:30 +01:00 (Migrated from github.com)

Thank you so much for your reply @marijnh.

When you say changing the DOM, do you mean the way we change the color of our widget?

Unfortunately even patching our decorations to disable updating them once they exist doesn't seem to make a difference:

apply: (tr, oldSet, oldState, state) => {
  const decorations = [];
  const { from, to, empty } = state.selection;

  // Prevent decoration updates
  if (decorations.length > 0) return decorations;

  // ... rest of decoration code
}

Is there any possibility this could be due to an internal bug in ProseMirror rather than browser-specific behaviors? It's just curious to me that it works in one direction but not the other and that it affects both Chrome and Firefox.

Here's a demo of Firefox, which has that slight difference but presents overall the same:

https://github.com/ProseMirror/prosemirror/assets/6835891/431f6838-7f08-4c3f-8a1a-b69c1be9809e

Thank you so much for your reply @marijnh. When you say changing the DOM, do you mean the way we change the color of our widget? Unfortunately even patching our decorations to disable updating them once they exist doesn't seem to make a difference: ```js apply: (tr, oldSet, oldState, state) => { const decorations = []; const { from, to, empty } = state.selection; // Prevent decoration updates if (decorations.length > 0) return decorations; // ... rest of decoration code } ``` Is there any possibility this could be due to an internal bug in ProseMirror rather than browser-specific behaviors? It's just curious to me that it works in one direction but not the other and that it affects both Chrome and Firefox. Here's a demo of Firefox, which has that slight difference but presents overall the same: https://github.com/ProseMirror/prosemirror/assets/6835891/431f6838-7f08-4c3f-8a1a-b69c1be9809e
Nantris commented 2024-02-25 02:11:23 +01:00 (Migrated from github.com)

I determined that setting the following styles prevents the bug (but also, expectedly, prevents view.posAtCoords from functioning.)

While this isn't definitive proof, I think it's a decent indicator this may not be a browser bug.

.ProseMirror { pointer-events: none; } 
.ProseMirror * { pointer-events: all; }
I determined that setting the following styles prevents the bug (but also, expectedly, prevents `view.posAtCoords` from functioning.) While this isn't definitive proof, I think it's a decent indicator this may not be a browser bug. ```css .ProseMirror { pointer-events: none; } .ProseMirror * { pointer-events: all; } ```
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
prosemirror/prosemirror#1445
No description provided.