1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-16 04:04:06 +02:00

Fix(editable component): reselect the range created by triple click (#4455)

* fix(editable component): reselect the range created by triple click

* Revert "fix(editable component): reselect the range created by triple click"

Reason: attaching a handler for `onClick` event is no longer needed.

* fix(react-editor): reselect DOMSelection when triple clicked

Reason: Triple clicking an element in Chrome will falsely set the focus node as the next sibling node with focusOffset 0

* test: add e2e test for triple click
This commit is contained in:
Trang Le
2021-08-28 19:02:30 +07:00
committed by GitHub
parent 8eb1abac87
commit 2d1aaafa0b
2 changed files with 100 additions and 0 deletions

View File

@@ -560,6 +560,44 @@ export const ReactEditor = {
anchorOffset = domRange.anchorOffset
focusNode = domRange.focusNode
focusOffset = domRange.focusOffset
// When triple clicking a block, Chrome will return a selection object whose
// focus node is the next element sibling and focusOffset is 0.
// This will highlight the corresponding toolbar button for the sibling
// block even though users just want to target the previous block.
// (2021/08/24)
// Within the context of Slate and Chrome, if anchor and focus nodes don't have
// the same nodeValue and focusOffset is 0, then it's definitely a triple click
// behaviour.
if (
IS_CHROME &&
anchorNode?.nodeValue !== focusNode?.nodeValue &&
domRange.focusOffset === 0
) {
// If an anchorNode is an element node when triple clicked, then the focusNode
// should also be the same as anchorNode when triple clicked.
if (anchorNode!.nodeType === 1) {
focusNode = anchorNode
} else {
// Otherwise, anchorNode is a text node and we need to
// - climb up the DOM tree to get the farthest element node that receives
// triple click. It should have atribute 'data-slate-node' = "element"
// - get the last child of that element node
// - climb down the DOM tree to get the text node of the last child
// - this is also the end of the selection aka the focusNode
const anchorElement = anchorNode!.parentNode as HTMLElement
const tripleClickedBlock = anchorElement.closest(
'[data-slate-node="element"]'
)
const focusElement = tripleClickedBlock!.lastElementChild
// Get the element node that holds the focus text node
const innermostFocusElement = focusElement!.querySelector(
'[data-slate-string]'
)
const lastTextNode = innermostFocusElement!.childNodes[0]
focusNode = lastTextNode
}
}
// COMPAT: There's a bug in chrome that always returns `true` for
// `isCollapsed` for a Selection that comes from a ShadowRoot.
// (2020/08/08)