1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-30 18:39:51 +02:00

fix selection setting for history

This commit is contained in:
Ian Storm Taylor
2016-09-10 17:12:45 -07:00
parent 52c6bb9596
commit 521f0d9f1d
8 changed files with 90 additions and 26 deletions

View File

@@ -99,6 +99,16 @@ class Selection extends new Record(DEFAULTS) {
return this.isBackward == null ? null : !this.isBackward return this.isBackward == null ? null : !this.isBackward
} }
/**
* Check whether the selection's keys are not set.
*
* @return {Boolean}
*/
get isUnset() {
return this.anchorKey == null || this.focusKey == null
}
/** /**
* Get the start key. * Get the start key.
* *
@@ -281,19 +291,18 @@ class Selection extends new Record(DEFAULTS) {
const { isCollapsed } = selection const { isCollapsed } = selection
let { anchorKey, anchorOffset, focusKey, focusOffset, isBackward } = selection let { anchorKey, anchorOffset, focusKey, focusOffset, isBackward } = selection
// If the selection isn't formed yet or is malformed, set it to the // If the selection isn't formed yet or is malformed, ensure that it is
// beginning of the node. // properly zeroed out.
if ( if (
anchorKey == null || anchorKey == null ||
focusKey == null || focusKey == null ||
!node.hasDescendant(anchorKey) || !node.hasDescendant(anchorKey) ||
!node.hasDescendant(focusKey) !node.hasDescendant(focusKey)
) { ) {
const first = node.getTexts().first()
return selection.merge({ return selection.merge({
anchorKey: first.key, anchorKey: null,
anchorOffset: 0, anchorOffset: 0,
focusKey: first.key, focusKey: null,
focusOffset: 0, focusOffset: 0,
isBackward: false isBackward: false
}) })

View File

@@ -42,9 +42,16 @@ class State extends new Record(DEFAULTS) {
static create(properties = {}) { static create(properties = {}) {
if (properties instanceof State) return properties if (properties instanceof State) return properties
properties.document = Document.create(properties.document)
properties.selection = Selection.create(properties.selection).normalize(properties.document) let document = Document.create(properties.document)
return new State(properties) let selection = Selection.create(properties.selection)
if (selection.isUnset) {
const text = document.getTexts().first()
selection = selection.collapseToStartOf(text)
}
return new State({ document, selection })
} }
/** /**

View File

@@ -281,15 +281,17 @@ function setSelection(state, operation) {
let properties = { ...operation.properties } let properties = { ...operation.properties }
let { document, selection } = state let { document, selection } = state
if (properties.anchorPath) { if (properties.anchorPath !== undefined) {
const anchorNode = document.assertPath(properties.anchorPath) properties.anchorKey = properties.anchorPath === null
properties.anchorKey = anchorNode.key ? null
: document.assertPath(properties.anchorPath).key
delete properties.anchorPath delete properties.anchorPath
} }
if (properties.focusPath) { if (properties.focusPath !== undefined) {
const focusNode = document.assertPath(properties.focusPath) properties.focusKey = properties.focusPath === null
properties.focusKey = focusNode.key ? null
: document.assertPath(properties.focusPath).key
delete properties.focusPath delete properties.focusPath
} }

View File

@@ -80,6 +80,7 @@ export function _delete(transform) {
} }
return transform return transform
.unsetSelection()
.deleteAtRange(selection) .deleteAtRange(selection)
.moveTo(after) .moveTo(after)
} }
@@ -154,6 +155,7 @@ export function deleteBackward(transform, n = 1) {
} }
return transform return transform
.unsetSelection()
.deleteBackwardAtRange(selection, n) .deleteBackwardAtRange(selection, n)
.moveTo(after) .moveTo(after)
} }
@@ -213,6 +215,7 @@ export function deleteForward(transform, n = 1) {
} }
return transform return transform
.unsetSelection()
.deleteForwardAtRange(selection, n) .deleteForwardAtRange(selection, n)
.moveTo(after) .moveTo(after)
} }
@@ -230,6 +233,7 @@ export function insertBlock(transform, block) {
let { document, selection } = state let { document, selection } = state
const keys = document.getTexts().map(text => text.key) const keys = document.getTexts().map(text => text.key)
transform.unsetSelection()
transform.insertBlockAtRange(selection, block) transform.insertBlockAtRange(selection, block)
state = transform.state state = transform.state
document = state.document document = state.document
@@ -258,6 +262,7 @@ export function insertFragment(transform, fragment) {
const lastInline = fragment.getClosestInline(lastText) const lastInline = fragment.getClosestInline(lastText)
const beforeTexts = document.getTexts() const beforeTexts = document.getTexts()
transform.unsetSelection()
transform.insertFragmentAtRange(selection, fragment) transform.insertFragmentAtRange(selection, fragment)
state = transform.state state = transform.state
document = state.document document = state.document
@@ -306,6 +311,7 @@ export function insertInline(transform, inline) {
const hasVoid = document.hasVoidParent(startText) const hasVoid = document.hasVoidParent(startText)
const keys = document.getTexts().map(text => text.key) const keys = document.getTexts().map(text => text.key)
transform.unsetSelection()
transform.insertInlineAtRange(selection, inline) transform.insertInlineAtRange(selection, inline)
state = transform.state state = transform.state
document = state.document document = state.document
@@ -353,6 +359,7 @@ export function insertText(transform, text, marks) {
marks = marks || selection.marks marks = marks || selection.marks
return transform return transform
.unsetSelection()
.insertTextAtRange(selection, text, marks) .insertTextAtRange(selection, text, marks)
.moveTo(after) .moveTo(after)
} }
@@ -397,6 +404,7 @@ export function splitBlock(transform, depth = 1) {
let { state } = transform let { state } = transform
let { document, selection } = state let { document, selection } = state
transform.unsetSelection()
transform.splitBlockAtRange(selection, depth) transform.splitBlockAtRange(selection, depth)
state = transform.state state = transform.state
@@ -423,6 +431,7 @@ export function splitInline(transform, depth = Infinity) {
let { document, selection } = state let { document, selection } = state
let after = selection let after = selection
transform.unsetSelection()
transform.splitInlineAtRange(selection, depth) transform.splitInlineAtRange(selection, depth)
state = transform.state state = transform.state
document = state.document document = state.document
@@ -551,6 +560,7 @@ export function wrapInline(transform, properties) {
const { startKey } = selection const { startKey } = selection
const previous = document.getPreviousText(startKey) const previous = document.getPreviousText(startKey)
transform.unsetSelection()
transform.wrapInlineAtRange(selection, properties) transform.wrapInlineAtRange(selection, properties)
state = transform.state state = transform.state
document = state.document document = state.document
@@ -612,6 +622,7 @@ export function wrapText(transform, prefix, suffix = prefix) {
} }
return transform return transform
.unsetSelection()
.wrapTextAtRange(selection, prefix, suffix) .wrapTextAtRange(selection, prefix, suffix)
.moveTo(after) .moveTo(after)
} }

View File

@@ -124,6 +124,7 @@ import {
moveTo, moveTo,
moveToOffsets, moveToOffsets,
moveToRangeOf, moveToRangeOf,
unsetSelection,
} from './on-selection' } from './on-selection'
/** /**
@@ -267,6 +268,7 @@ export default {
moveTo, moveTo,
moveToOffsets, moveToOffsets,
moveToRangeOf, moveToRangeOf,
unsetSelection,
/** /**
* History. * History.

View File

@@ -364,6 +364,7 @@ export function moveForward(transform, n) {
*/ */
export function moveTo(transform, properties) { export function moveTo(transform, properties) {
debugger
return transform.setSelectionOperation(properties) return transform.setSelectionOperation(properties)
} }
@@ -398,3 +399,21 @@ export function moveToRangeOf(transform, start, end) {
const sel = selection.moveToRangeOf(start, end).normalize(document) const sel = selection.moveToRangeOf(start, end).normalize(document)
return transform.setSelectionOperation(sel) return transform.setSelectionOperation(sel)
} }
/**
* Unset the selection, removing an association to a node.
*
* @param {Transform} transform
* @return {Transform}
*/
export function unsetSelection(transform) {
return transform.setSelectionOperation({
anchorKey: null,
anchorOffset: 0,
focusKey: null,
focusOffset: 0,
isFocused: false,
isBackward: false
})
}

View File

@@ -361,39 +361,53 @@ export function setSelectionOperation(transform, properties) {
const { document, selection } = state const { document, selection } = state
const prevProps = {} const prevProps = {}
if (properties.marks == selection.marks) { // If the current selection has marks, and the new selection doesn't change
// them in some way, they are old and should be removed.
if (selection.marks && properties.marks == selection.marks) {
properties.marks = null properties.marks = null
} }
// Create a dictionary of the previous values for all of the properties that
// are being changed, for the inverse operation.
for (const k in properties) { for (const k in properties) {
prevProps[k] = selection[k] prevProps[k] = selection[k]
} }
// Resolve the selection keys into paths.
if (properties.anchorKey) { if (properties.anchorKey) {
properties.anchorPath = document.getPath(properties.anchorKey) properties.anchorPath = document.getPath(properties.anchorKey)
prevProps.anchorPath = document.getPath(prevProps.anchorKey)
delete properties.anchorKey delete properties.anchorKey
}
if (prevProps.anchorKey) {
prevProps.anchorPath = document.getPath(prevProps.anchorKey)
delete prevProps.anchorKey delete prevProps.anchorKey
} }
if (properties.focusKey) { if (properties.focusKey) {
properties.focusPath = document.getPath(properties.focusKey) properties.focusPath = document.getPath(properties.focusKey)
prevProps.focusPath = document.getPath(prevProps.focusKey)
delete properties.focusKey delete properties.focusKey
}
if (prevProps.focusKey) {
prevProps.focusPath = document.getPath(prevProps.focusKey)
delete prevProps.focusKey delete prevProps.focusKey
} }
// Define an inverse of the operation for undoing.
const inverse = [{ const inverse = [{
type: 'set_selection', type: 'set_selection',
properties: prevProps properties: prevProps
}] }]
// Define the operation.
const operation = { const operation = {
type: 'set_selection', type: 'set_selection',
properties, properties,
inverse, inverse,
} }
// Apply the operation.
return transform.applyOperation(operation) return transform.applyOperation(operation)
} }

View File

@@ -107,7 +107,7 @@ function markProperties(value = {}) {
case 'object': { case 'object': {
for (const k in value) { for (const k in value) {
if (k == 'data') { if (k == 'data') {
if (value[k] != null) ret[k] = Data.create(value[k]) if (value[k] !== undefined) ret[k] = Data.create(value[k])
} else { } else {
ret[k] = value[k] ret[k] = value[k]
} }
@@ -138,10 +138,10 @@ function nodeProperties(value = {}) {
break break
} }
case 'object': { case 'object': {
if (value.isVoid != null) ret.isVoid = !!value.isVoid if (value.isVoid !== undefined) ret.isVoid = !!value.isVoid
for (const k in value) { for (const k in value) {
if (k == 'data') { if (k == 'data') {
if (value[k] != null) ret[k] = Data.create(value[k]) if (value[k] !== undefined) ret[k] = Data.create(value[k])
} else { } else {
ret[k] = value[k] ret[k] = value[k]
} }
@@ -188,12 +188,12 @@ function selectionProperties(value = {}) {
switch (typeOf(value)) { switch (typeOf(value)) {
case 'object': { case 'object': {
if (value.anchorKey != null) ret.anchorKey = value.anchorKey if (value.anchorKey !== undefined) ret.anchorKey = value.anchorKey
if (value.anchorOffset != null) ret.anchorOffset = value.anchorOffset if (value.anchorOffset !== undefined) ret.anchorOffset = value.anchorOffset
if (value.focusKey != null) ret.focusKey = value.focusKey if (value.focusKey !== undefined) ret.focusKey = value.focusKey
if (value.focusOffset != null) ret.focusOffset = value.focusOffset if (value.focusOffset !== undefined) ret.focusOffset = value.focusOffset
if (value.isBackward != null) ret.isBackward = !!value.isBackward if (value.isBackward !== undefined) ret.isBackward = !!value.isBackward
if (value.isFocused != null) ret.isFocused = !!value.isFocused if (value.isFocused !== undefined) ret.isFocused = !!value.isFocused
if (value.marks !== undefined) ret.marks = value.marks if (value.marks !== undefined) ret.marks = value.marks
break break
} }