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:
@@ -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)
|
||||
|
Reference in New Issue
Block a user