1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-28 09:29:49 +02:00

cleanup lots of selection code, get tests passing again

This commit is contained in:
Ian Storm Taylor
2016-12-09 18:09:37 -08:00
parent 36bd59b839
commit 59b31fb9b3
5 changed files with 69 additions and 89 deletions

View File

@@ -3,19 +3,6 @@ import getLeafText from '../utils/get-leaf-text'
import warn from '../utils/warn' import warn from '../utils/warn'
import { Record } from 'immutable' import { Record } from 'immutable'
/**
* Start-end-and-edge convenience methods to auto-generate.
*
* @type {Array}
*/
const EDGE_METHODS = [
'has%AtStartOf',
'has%AtEndOf',
'has%Between',
'has%In',
]
/** /**
* Default properties. * Default properties.
* *
@@ -422,38 +409,6 @@ class Selection extends new Record(DEFAULTS) {
}) })
} }
/**
* Move the end point to the start point.
*
* @return {Selection}
*/
collapseToStart() {
return this.merge({
anchorKey: this.startKey,
anchorOffset: this.startOffset,
focusKey: this.startKey,
focusOffset: this.startOffset,
isBackward: false
})
}
/**
* Move the end point to the start point.
*
* @return {Selection}
*/
collapseToEnd() {
return this.merge({
anchorKey: this.endKey,
anchorOffset: this.endOffset,
focusKey: this.endKey,
focusOffset: this.endOffset,
isBackward: false
})
}
/** /**
* Move to the start of a `node`. * Move to the start of a `node`.
* *
@@ -590,45 +545,35 @@ class Selection extends new Record(DEFAULTS) {
} }
/** /**
* Extend the start point forward `n` characters. * Move the anchor offset `n` characters.
* *
* @param {Number} n (optional) * @param {Number} n (optional)
* @return {Selection} * @return {Selection}
*/ */
moveStartOffset(n = 1) { moveAnchorOffset(n = 1) {
if (this.isBackward) { const { anchorKey, focusKey, focusOffset } = this
return this.merge({ const anchorOffset = this.anchorOffset + n
focusOffset: this.focusOffset + n, return this.merge({
isBackward: null anchorOffset,
}) isBackward: anchorKey == focusKey ? anchorOffset > focusOffset : this.isBackward
} else { })
return this.merge({
anchorOffset: this.anchorOffset + n,
isBackward: null
})
}
} }
/** /**
* Extend the end point forward `n` characters. * Move the anchor offset `n` characters.
* *
* @param {Number} n (optional) * @param {Number} n (optional)
* @return {Selection} * @return {Selection}
*/ */
moveEndOffset(n = 1) { moveFocusOffset(n = 1) {
if (this.isBackward) { const { focusKey, anchorKey, anchorOffset } = this
return this.merge({ const focusOffset = this.focusOffset + n
anchorOffset: this.anchorOffset + n, return this.merge({
isBackward: null focusOffset,
}) isBackward: focusKey == anchorKey ? anchorOffset > focusOffset : this.isBackward
} else { })
return this.merge({
focusOffset: this.focusOffset + n,
isBackward: null
})
}
} }
/** /**
@@ -724,14 +669,37 @@ class Selection extends new Record(DEFAULTS) {
}) })
} }
/**
* Flip the selection.
*
* @return {Selection}
*/
flip() {
return this.merge({
anchorKey: this.focusKey,
anchorOffset: this.focusOffset,
focusKey: this.anchorKey,
focusOffset: this.anchorOffset,
isBackward: this.isBackward == null ? null : !this.isBackward,
})
}
} }
/** /**
* Add start, end and edge convenience methods. * Add start, end and edge convenience methods.
*/ */
EDGE_METHODS.forEach((pattern) => { [
const [ p, s ] = pattern.split('%') ['has', 'AtStartOf', true],
['has', 'AtEndOf', true],
['has', 'Between', true],
['has', 'In', true],
['collapseTo', ''],
['move', 'Offset'],
].forEach((opts) => {
const [ p, s, hasEdge ] = opts
const anchor = `${p}Anchor${s}` const anchor = `${p}Anchor${s}`
const edge = `${p}Edge${s}` const edge = `${p}Edge${s}`
const end = `${p}End${s}` const end = `${p}End${s}`
@@ -750,8 +718,10 @@ EDGE_METHODS.forEach((pattern) => {
: this[focus](...args) : this[focus](...args)
} }
Selection.prototype[edge] = function (...args) { if (hasEdge) {
return this[anchor](...args) || this[focus](...args) Selection.prototype[edge] = function (...args) {
return this[anchor](...args) || this[focus](...args)
}
} }
}) })

View File

@@ -104,7 +104,7 @@ function insertNode(state, operation) {
function insertText(state, operation) { function insertText(state, operation) {
const { path, offset, text, marks } = operation const { path, offset, text, marks } = operation
let { document, selection } = state let { document, selection } = state
const { startKey, endKey, startOffset, endOffset } = selection const { anchorKey, focusKey, anchorOffset, focusOffset } = selection
let node = document.assertPath(path) let node = document.assertPath(path)
// Update the document // Update the document
@@ -112,11 +112,11 @@ function insertText(state, operation) {
document = document.updateDescendant(node) document = document.updateDescendant(node)
// Update the selection // Update the selection
if (startKey == node.key && startOffset >= offset) { if (anchorKey == node.key && anchorOffset >= offset) {
selection = selection.moveStartOffset(text.length) selection = selection.moveAnchorOffset(text.length)
} }
if (endKey == node.key && endOffset >= offset) { if (focusKey == node.key && focusOffset >= offset) {
selection = selection.moveEndOffset(text.length) selection = selection.moveFocusOffset(text.length)
} }
state = state.merge({ document, selection }) state = state.merge({ document, selection })
@@ -287,15 +287,15 @@ function removeText(state, operation) {
const { path, offset, length } = operation const { path, offset, length } = operation
const rangeOffset = offset + length const rangeOffset = offset + length
let { document, selection } = state let { document, selection } = state
const { startKey, endKey, startOffset, endOffset } = selection const { anchorKey, focusKey, anchorOffset, focusOffset } = selection
let node = document.assertPath(path) let node = document.assertPath(path)
// Update the selection // Update the selection
if (startKey == node.key && startOffset >= rangeOffset) { if (anchorKey == node.key && anchorOffset >= rangeOffset) {
selection = selection.moveStartOffset(-length) selection = selection.moveAnchorOffset(-length)
} }
if (endKey == node.key && endOffset >= rangeOffset) { if (focusKey == node.key && focusOffset >= rangeOffset) {
selection = selection.moveEndOffset(-length) selection = selection.moveFocusOffset(-length)
} }
node = node.removeText(offset, length) node = node.removeText(offset, length)

View File

@@ -466,12 +466,18 @@ export function wrapText(transform, prefix, suffix = prefix) {
const { selection } = state const { selection } = state
transform.wrapTextAtRange(selection, prefix, suffix) transform.wrapTextAtRange(selection, prefix, suffix)
// Adding the suffix will have pushed the end of the selection further on, so
// we need to move it back to account for this.
transform.moveEndOffset(0 - suffix.length)
// If the selection was collapsed, it will have moved the start offset too. // If the selection was collapsed, it will have moved the start offset too.
if (selection.isCollapsed) { if (selection.isCollapsed) {
transform.moveStartOffset(0 - prefix.length) transform.moveStartOffset(0 - prefix.length)
} }
// Adding the suffix will have pushed the end of the selection further on, so
// we need to move it back to account for this.
transform.moveEndOffset(0 - suffix.length)
// There's a chance that the selection points moved "through" each other,
// resulting in a now-incorrect selection direction.
if (selection.isForward != transform.state.selection.isForward) {
transform.flipSelection()
}
} }

View File

@@ -144,6 +144,7 @@ import {
extendForward, extendForward,
extendToEndOf, extendToEndOf,
extendToStartOf, extendToStartOf,
flipSelection,
focus, focus,
moveBackward, moveBackward,
moveForward, moveForward,
@@ -321,6 +322,7 @@ export default {
extendToEndOf, extendToEndOf,
extendToStartOf, extendToStartOf,
focus, focus,
flipSelection,
moveBackward, moveBackward,
moveForward, moveForward,
moveEndOffset, moveEndOffset,

View File

@@ -22,6 +22,8 @@ export const moveToRangeOf = generate('moveToRangeOf')
export const moveStartOffset = generate('moveStartOffset') export const moveStartOffset = generate('moveStartOffset')
export const moveEndOffset = generate('moveEndOffset') export const moveEndOffset = generate('moveEndOffset')
export const flipSelection = generate('flip')
/** /**
* Move the selection to the end of the next block. * Move the selection to the end of the next block.
* *