1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-13 10:44:02 +02:00

refactor selection snapshotting

This commit is contained in:
Ian Storm Taylor
2016-11-22 16:52:55 -08:00
parent 6893884174
commit fe836b1daa
5 changed files with 25 additions and 62 deletions

View File

@@ -285,16 +285,11 @@ function removeNode(state, operation) {
function removeText(state, operation) { function removeText(state, operation) {
const { path, offset, length } = operation const { path, offset, length } = operation
const rangeOffset = offset + length
let { document, selection } = state let { document, selection } = state
const { startKey, endKey, startOffset, endOffset } = selection const { startKey, endKey, startOffset, endOffset } = selection
let node = document.assertPath(path) let node = document.assertPath(path)
const rangeOffset = offset + length
// Update the document
node = node.removeText(offset, length)
document = document.updateDescendant(node)
// Update the selection // Update the selection
if (startKey == node.key && startOffset >= rangeOffset) { if (startKey == node.key && startOffset >= rangeOffset) {
selection = selection.moveStartOffset(-length) selection = selection.moveStartOffset(-length)
@@ -303,6 +298,8 @@ function removeText(state, operation) {
selection = selection.moveEndOffset(-length) selection = selection.moveEndOffset(-length)
} }
node = node.removeText(offset, length)
document = document.updateDescendant(node)
state = state.merge({ document, selection }) state = state.merge({ document, selection })
return state return state
} }

View File

@@ -38,64 +38,16 @@ export function addMark(transform, mark) {
export function _delete(transform) { export function _delete(transform) {
const { state } = transform const { state } = transform
const { document, selection } = state const { selection } = state
// If the selection is collapsed, there's nothing to delete.
if (selection.isCollapsed) return if (selection.isCollapsed) return
const { startText } = state
const { startKey, startOffset, endKey, endOffset } = selection
const block = document.getClosestBlock(startKey)
const highest = block.getHighestChild(startKey)
const previous = block.getPreviousSibling(highest.key)
const next = block.getNextSibling(highest.key)
let after
// If there's a previous node, and we're at the start of the current node,
// and the selection encompasses the entire current node, it won't exist after
// deleting, so we need to update the selection's keys.
if (
previous &&
startOffset == 0 &&
(endKey != startKey || endOffset == startText.length)
) {
// If the nodes on either sides are text nodes, they will end up being
// combined, so we need to set the selection to right in between them.
if (previous.kind == 'text' && next && next.kind == 'text') {
after = selection.merge({
anchorKey: previous.key,
anchorOffset: previous.length,
focusKey: previous.key,
focusOffset: previous.length
})
}
// Otherwise, if only the previous node is a text node, it won't be merged,
// so collapse to the end of it.
else if (previous.kind == 'text') {
after = selection.collapseToEndOf(previous)
}
// Otherwise, if the previous node isn't a text node, we need to get the
// last text node inside of it and collapse to the end of that.
else {
const last = previous.getLastText()
after = selection.collapseToEndOf(last)
}
}
// Otherwise, if the inline is an online child
// Otherwise simply collapse the selection.
else {
after = selection.collapseToStart()
}
transform transform
.unsetSelection() .snapshotSelection()
.deleteAtRange(selection) .deleteAtRange(selection)
.moveTo(after) // Ensure that the selection is collapsed to the start, because in certain
// cases when deleting across inline nodes this isn't guaranteed.
.collapseToStart()
.snapshotSelection()
} }
/** /**

View File

@@ -133,6 +133,7 @@ import {
moveToRangeOf, moveToRangeOf,
unsetMarks, unsetMarks,
unsetSelection, unsetSelection,
snapshotSelection,
} from './on-selection' } from './on-selection'
/** /**
@@ -288,6 +289,7 @@ export default {
moveToRangeOf, moveToRangeOf,
unsetMarks, unsetMarks,
unsetSelection, unsetSelection,
snapshotSelection,
/** /**
* History. * History.

View File

@@ -412,6 +412,18 @@ export function unsetMarks(transform) {
transform.setSelectionOperation({ marks: null }) transform.setSelectionOperation({ marks: null })
} }
/**
* Snapshot the current selection.
*
* @param {Transform} transform
*/
export function snapshotSelection(transform) {
const { state } = transform
const { selection } = state
transform.setSelectionOperation(selection, { snapshot: true })
}
/** /**
* Unset the selection, removing an association to a node. * Unset the selection, removing an association to a node.
* *

View File

@@ -352,7 +352,7 @@ export function setNodeOperation(transform, path, properties) {
* @param {Mixed} selection * @param {Mixed} selection
*/ */
export function setSelectionOperation(transform, properties) { export function setSelectionOperation(transform, properties, options = {}) {
properties = Normalize.selectionProperties(properties) properties = Normalize.selectionProperties(properties)
const { state } = transform const { state } = transform
@@ -364,7 +364,7 @@ export function setSelectionOperation(transform, properties) {
// create a dictionary of the previous values for all of the properties that // create a dictionary of the previous values for all of the properties that
// are being changed, for the inverse operation. // are being changed, for the inverse operation.
for (const k in properties) { for (const k in properties) {
if (properties[k] == selection[k]) continue if (!options.snapshot && properties[k] == selection[k]) continue
props[k] = properties[k] props[k] = properties[k]
prevProps[k] = selection[k] prevProps[k] = selection[k]
} }