mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-02-02 22:28:46 +01:00
Avoid finding native selection focus position when selection is collapsed (#1100)
* Avoid finding native selection focus position when selection is collapsed. Use already calculated anchor position instead. Move code to get caret position from a selection point in `utils`. * Update content.js * Update get-caret-position.js
This commit is contained in:
parent
5135f98845
commit
25d54e30b0
@ -12,7 +12,7 @@ import Selection from '../models/selection'
|
||||
import SlateTypes from '../utils/prop-types'
|
||||
import extendSelection from '../utils/extend-selection'
|
||||
import findClosestNode from '../utils/find-closest-node'
|
||||
import findDeepestNode from '../utils/find-deepest-node'
|
||||
import getCaretPosition from '../utils/get-caret-position'
|
||||
import getHtmlFromNativePaste from '../utils/get-html-from-native-paste'
|
||||
import getPoint from '../utils/get-point'
|
||||
import getTransferData from '../utils/get-transfer-data'
|
||||
@ -147,7 +147,7 @@ class Content extends React.Component {
|
||||
|
||||
updateSelection = () => {
|
||||
const { editor, state } = this.props
|
||||
const { document, selection } = state
|
||||
const { selection } = state
|
||||
const window = getWindow(this.element)
|
||||
const native = window.getSelection()
|
||||
|
||||
@ -168,49 +168,18 @@ class Content extends React.Component {
|
||||
if (selection.isUnset) return
|
||||
|
||||
// Otherwise, figure out which DOM nodes should be selected...
|
||||
const { anchorText, focusText } = state
|
||||
const { anchorKey, anchorOffset, focusKey, focusOffset } = selection
|
||||
const schema = editor.getSchema()
|
||||
const anchorDecorators = document.getDescendantDecorators(anchorKey, schema)
|
||||
const focusDecorators = document.getDescendantDecorators(focusKey, schema)
|
||||
const anchorRanges = anchorText.getRanges(anchorDecorators)
|
||||
const focusRanges = focusText.getRanges(focusDecorators)
|
||||
let a = 0
|
||||
let f = 0
|
||||
let anchorIndex
|
||||
let focusIndex
|
||||
let anchorOff
|
||||
let focusOff
|
||||
|
||||
anchorRanges.forEach((range, i, ranges) => {
|
||||
const { length } = range.text
|
||||
a += length
|
||||
if (a < anchorOffset) return
|
||||
anchorIndex = i
|
||||
anchorOff = anchorOffset - (a - length)
|
||||
return false
|
||||
})
|
||||
|
||||
focusRanges.forEach((range, i, ranges) => {
|
||||
const { length } = range.text
|
||||
f += length
|
||||
if (f < focusOffset) return
|
||||
focusIndex = i
|
||||
focusOff = focusOffset - (f - length)
|
||||
return false
|
||||
})
|
||||
|
||||
const anchorSpan = this.element.querySelector(`[data-offset-key="${anchorKey}-${anchorIndex}"]`)
|
||||
const focusSpan = this.element.querySelector(`[data-offset-key="${focusKey}-${focusIndex}"]`)
|
||||
const anchorEl = findDeepestNode(anchorSpan)
|
||||
const focusEl = findDeepestNode(focusSpan)
|
||||
const { anchorKey, anchorOffset, focusKey, focusOffset, isCollapsed } = selection
|
||||
const anchor = getCaretPosition(anchorKey, anchorOffset, state, editor, this.element)
|
||||
const focus = isCollapsed
|
||||
? anchor
|
||||
: getCaretPosition(focusKey, focusOffset, state, editor, this.element)
|
||||
|
||||
// If they are already selected, do nothing.
|
||||
if (
|
||||
anchorEl == native.anchorNode &&
|
||||
anchorOff == native.anchorOffset &&
|
||||
focusEl == native.focusNode &&
|
||||
focusOff == native.focusOffset
|
||||
anchor.node == native.anchorNode &&
|
||||
anchor.offset == native.anchorOffset &&
|
||||
focus.node == native.focusNode &&
|
||||
focus.offset == native.focusOffset
|
||||
) {
|
||||
return
|
||||
}
|
||||
@ -219,9 +188,9 @@ class Content extends React.Component {
|
||||
this.tmp.isSelecting = true
|
||||
native.removeAllRanges()
|
||||
const range = window.document.createRange()
|
||||
range.setStart(anchorEl, anchorOff)
|
||||
range.setStart(anchor.node, anchor.offset)
|
||||
native.addRange(range)
|
||||
extendSelection(native, focusEl, focusOff)
|
||||
if (!isCollapsed) extendSelection(native, focus.node, focus.offset)
|
||||
|
||||
// Then unset the `isSelecting` flag after a delay.
|
||||
setTimeout(() => {
|
||||
|
45
src/utils/get-caret-position.js
Normal file
45
src/utils/get-caret-position.js
Normal file
@ -0,0 +1,45 @@
|
||||
import findDeepestNode from './find-deepest-node'
|
||||
|
||||
/**
|
||||
* Get caret position from selection point.
|
||||
*
|
||||
* @param {String} key
|
||||
* @param {Number} offset
|
||||
* @param {State} state
|
||||
* @param {Editor} editor
|
||||
* @param {Element} el
|
||||
* @return {Object}
|
||||
*/
|
||||
|
||||
function getCaretPosition(key, offset, state, editor, el) {
|
||||
const { document } = state
|
||||
const text = document.getDescendant(key)
|
||||
const schema = editor.getSchema()
|
||||
const decorators = document.getDescendantDecorators(key, schema)
|
||||
const ranges = text.getRanges(decorators)
|
||||
|
||||
let a = 0
|
||||
let index
|
||||
let off
|
||||
|
||||
ranges.forEach((range, i) => {
|
||||
const { length } = range.text
|
||||
a += length
|
||||
if (a < offset) return
|
||||
index = i
|
||||
off = offset - (a - length)
|
||||
return false
|
||||
})
|
||||
|
||||
const span = el.querySelector(`[data-offset-key="${key}-${index}"]`)
|
||||
const node = findDeepestNode(span)
|
||||
return { node, offset: off }
|
||||
}
|
||||
|
||||
/**
|
||||
* Export.
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
export default getCaretPosition
|
Loading…
x
Reference in New Issue
Block a user