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

Move selection in moveNode operation

This commit is contained in:
Samy Pessé
2016-10-26 16:55:42 +02:00
parent 6c43cd57e1
commit 41df908e33
2 changed files with 89 additions and 2 deletions

View File

@@ -595,6 +595,32 @@ class Selection extends new Record(DEFAULTS) {
: this.merge({ focusOffset: this.focusOffset + n })
}
/**
* Move the start key, while preserving the direction
*
* @param {String} key
* @return {Selection} selection
*/
moveStartTo(key, offset = 0) {
return this.isBackward
? this.merge({ focusKey: key, focusOffset: offset })
: this.merge({ anchorKey: key, anchorOffset: offset })
}
/**
* Move the end key, while preserving the direction
*
* @param {String} key
* @return {Selection} selection
*/
moveEndTo(key, offset = 0) {
return this.isBackward
? this.merge({ anchorKey: key, anchorOffset: offset })
: this.merge({ focusKey: key, focusOffset: offset })
}
/**
* Extend the focus point to the start of a `node`.
*
@@ -625,6 +651,23 @@ class Selection extends new Record(DEFAULTS) {
})
}
/**
* Unset the selection
*
* @return {Selection} selection
*/
unset() {
return this.merge({
anchorKey: null,
anchorOffset: 0,
focusKey: null,
focusOffset: 0,
isFocused: false,
isBackward: false
})
}
}
/**

View File

@@ -178,12 +178,14 @@ function moveNode(state, operation) {
let { document } = state
const node = document.assertPath(path)
// Remove the node from its current parent
let parent = document.getParent(node)
const isParent = document == parent
const index = parent.nodes.indexOf(node)
parent = parent.removeNode(index)
document = isParent ? parent : document.updateDescendant(parent)
// Insert the new node to its new parent
let target = document.assertPath(newPath)
const isTarget = document == target
target = target.insertNode(newIndex, node)
@@ -221,14 +223,56 @@ function removeMark(state, operation) {
function removeNode(state, operation) {
const { path } = operation
let { document } = state
let { document, selection } = state
const { startKey, endKey } = selection
// Preserve previous document
const prevDocument = document
// Update the document
const node = document.assertPath(path)
let parent = document.getParent(node)
const index = parent.nodes.indexOf(node)
const isParent = document == parent
parent = parent.removeNode(index)
document = isParent ? parent : document.updateDescendant(parent)
state = state.merge({ document })
function getRemoved(key) {
if (key === node.key) return node
if (node.kind == 'text') return null
return node.getDescendant(key)
}
// Update the selection, if one of the anchor/focus has been removed
const startDesc = startKey ? getRemoved(startKey) : null
const endDesc = endKey ? getRemoved(endKey) : null
if (startDesc) {
const prevText = prevDocument.getTexts()
.takeUntil(text => text.key == startKey)
.filter(text => !getRemoved(text.key))
.last()
if (!prevText) selection = selection.unset()
else selection = selection.moveStartTo(prevText.key, prevText.length)
}
if (endDesc) {
// The whole selection is inside the node, we collapse to the previous text node
if (startKey == endKey) {
selection = selection.collapseToStart()
} else {
const nextText = prevDocument.getTexts()
.skipUntil(text => text.key == startKey)
.slice(1)
.filter(text => !getRemoved(text.key))
.first()
if (!nextText) selection = selection.unset()
else selection = selection.moveEndTo(nextText.key, 0)
}
}
state = state.merge({ document, selection })
return state
}