My problem appears in Chrome and not Firefox (haven’t checked other browsers) when a single word is selected. In Chrome, if the anchor is at the front and you press Shift+ArrowUp, it will collapse the selection to the front of the word. Similarly, if the anchor is at the end and you press Shift+ArrowDown, it will collapse to the end. It is being clever in a way that Firefox doesn’t attempt; in Firefox those key combinations will select up to the aligned position on the previous/next line, like you’d expect.
Chrome’s cleverness causes UX issues when you double click a word to select it, so they workaround their cleverness for that case by creating a selection that doesn’t actually have an anchor/head yet (though if you document.getSelection()
it will report the anchor and focus as the start and end of the word respectively). If you press ArrowLeft, the front of the word becomes the head. Similarly if you press ArrowRight, the back becomes the head. If you instead press Shift+ArrowUp/Down, it behaves like Firefox.
I have a case that relies heavily on having full words selected, and I currently use a Mark for each word.
If I use native DOM Selection methods to…
const range = document.createRange()
range.selectNode(wordMarkEl);
const sel = document.getSelection();
sel.removeAllRanges();
sel.addRange(range)
…then I can get Chrome into the better state without an anchor/head. But I can’t do this if I use ProseMirror’s tr.setSelection(TextSelection.create(...))
. And I can’t use NodeSelection
on a Mark because this.nodeDOM
is a TextNode.
I was wondering if you had any advice on the best way to do a native selection of a mark node and keep ProseMirror in sync. Or if there is a supported way to get into that headless/anchorless state with ProseMirror transactions alone?
https://github.com/ProseMirror/prosemirror-view/pull/58 seems to indicate that my best bet is to do the native DOM selection and immediately fire a ProseMirror transaction that sets the selection to the exact same positions, and ProseMirror will ignore the transaction. I’ve tried that and it seems to work. Would you say that’s the best way to do it? I’m just worried if the “ignore” behavior of ProseMirror ever changes, then my hack regresses pretty quickly. I also don’t have access to the view from appendTransaction
so I have to add a kludge to get it (and currently I have bugs because the view is out of date within appendTransaction).
Thanks for any help!