From a8f26df61bceb2ac1e825c847040798dd81ae704 Mon Sep 17 00:00:00 2001 From: Ian Storm Taylor Date: Thu, 30 Jun 2016 18:42:10 -0700 Subject: [PATCH] fix deleting for void nodes; --- lib/components/void.js | 26 +------------------ lib/models/node.js | 4 ++- lib/models/selection.js | 55 ++++++++++++++++++++++++++++++++++++++++ lib/models/state.js | 12 +++++++++ lib/models/transform.js | 24 ++++++++++-------- lib/models/transforms.js | 33 ++++++++++++++++-------- 6 files changed, 107 insertions(+), 47 deletions(-) diff --git a/lib/components/void.js b/lib/components/void.js index 462064dea..09b30a835 100644 --- a/lib/components/void.js +++ b/lib/components/void.js @@ -27,36 +27,12 @@ class Void extends React.Component { state = state .transform() .moveToStartOf(text) + .focus() .apply() editor.onChange(state) } - onKeyDown(e) { - let { state, editor } = this.props - const key = keycode(e) - - switch (key) { - default: - return - case 'left arrow': - case 'up arrow': - state = state - .transform() - .moveToEndOfPreviousBlock() - .apply() - case 'right arrow': - case 'down arrow': - state = state - .transform() - .moveToStartOfNextBlock() - .apply() - } - - e.preventDefault() - editor.onChange(state) - } - render() { const { children, node } = this.props const Tag = node.kind == 'block' ? 'div' : 'span' diff --git a/lib/models/node.js b/lib/models/node.js index e74e8fd19..ea112098a 100644 --- a/lib/models/node.js +++ b/lib/models/node.js @@ -842,7 +842,9 @@ const Node = { // That void nodes contain no text. if (desc.isVoid && desc.length) { - const text = Text.create() + let text = desc.getTextNodes().first() + let characters = text.characters.clear() + text = text.merge({ characters }) const nodes = desc.nodes.clear().push(text) desc = desc.merge({ nodes }) } diff --git a/lib/models/selection.js b/lib/models/selection.js index 23b53573b..e607871d9 100644 --- a/lib/models/selection.js +++ b/lib/models/selection.js @@ -183,6 +183,7 @@ class Selection extends Record(DEFAULTS) { normalize(node) { let selection = this + const { isCollapsed } = selection let { anchorKey, anchorOffset, focusKey, focusOffset, isBackward } = selection // If the selection isn't formed yet, abort. @@ -220,6 +221,36 @@ class Selection extends Record(DEFAULTS) { : anchorIndex > focusIndex } + // If the selection is expanded and has an edge on a void block, move it. + // if (isExpanded) { + // let anchorBlock = node.getClosestBlock(anchorNode) + // let focusBlock = node.getClosestBlock(focusNode) + + // if (anchorBlock.isVoid) { + // while (anchorBanchorBlock.isVoid) { + // anchorBlock = isBackward + // ? node.getPreviousBlock(anchorBlock) + // : node.getNextBlock(anchorBlock) + // } + + // anchorNode = isBackward + // ? anchorBlock.getTextNodes().last() + // : anchorBlock.getTextNodes().first() + // anchorOffset = isBackward + // ? anchorNode.length + // : 0 + // } + + // else if (focusBlock.isVoid) { + // focusNode = isBackward + // ? node.getNextBlock(focusBlock).getTextNodes().first() + // : node.getPreviousBlock(focusBlock).getTextNodes().last() + // focusOffset = isBackward + // ? 0 + // : focusNode.length + // } + // } + // Merge in any updated properties. return selection.merge({ anchorKey: anchorNode.key, @@ -230,6 +261,30 @@ class Selection extends Record(DEFAULTS) { }) } + /** + * Focus the selection. + * + * @return {Selection} selection + */ + + focus() { + return this.merge({ + isFocused: true + }) + } + + /** + * Blur the selection. + * + * @return {Selection} selection + */ + + blur() { + return this.merge({ + isFocused: false + }) + } + /** * Move the focus point to the anchor point. * diff --git a/lib/models/state.js b/lib/models/state.js index ef00445a7..1ff730ec5 100644 --- a/lib/models/state.js +++ b/lib/models/state.js @@ -408,13 +408,25 @@ class State extends Record(DEFAULTS) { deleteForward(n = 1) { let state = this let { document, selection } = state + let { startKey } = selection let after = selection // Determine what the selection should be after deleting. + const block = document.getClosestBlock(startKey) + const inline = document.getClosestInline(startKey) + if (selection.isExpanded) { after = selection.moveToStart() } + else if ((block && block.isVoid) || (inline && inline.isVoid)) { + const next = document.getNextText(startKey) + const previous = document.getPreviousText(startKey) + after = next + ? selection.moveToStartOf(next) + : selection.moveToEndOf(previous) + } + // Delete forward and then update the selection. document = document.deleteForwardAtRange(selection) selection = after diff --git a/lib/models/transform.js b/lib/models/transform.js index cf74cde84..ef4b17d1b 100644 --- a/lib/models/transform.js +++ b/lib/models/transform.js @@ -49,19 +49,21 @@ const DOCUMENT_TRANSFORMS = [ */ const SELECTION_TRANSFORMS = [ - 'moveToAnchor', - 'moveToFocus', - 'moveToStart', - 'moveToEnd', - 'moveToStartOf', - 'moveToEndOf', - 'moveToRangeOf', - 'moveForward', - 'moveBackward', - 'extendForward', + 'blur', 'extendBackward', + 'extendForward', + 'extendToEndOf', 'extendToStartOf', - 'extendToEndOf' + 'focus', + 'moveBackward', + 'moveForward', + 'moveToAnchor', + 'moveToEnd', + 'moveToEndOf', + 'moveToFocus', + 'moveToRangeOf', + 'moveToStart', + 'moveToStartOf' ] /** diff --git a/lib/models/transforms.js b/lib/models/transforms.js index 86b1147ed..11070fcb2 100644 --- a/lib/models/transforms.js +++ b/lib/models/transforms.js @@ -97,15 +97,22 @@ const Transforms = { deleteBackwardAtRange(range, n = 1) { let node = this - - // When collapsed at the start of the node, there's nothing to do. - if (range.isCollapsed && range.isAtStartOf(node)) return node + const { startKey } = range // When the range is still expanded, just do a regular delete. if (range.isExpanded) return node.deleteAtRange(range) + // When collapsed at the start of the node, there's nothing to do. + if (range.isAtStartOf(node)) return node + + // When collapsed in a void node, remove that node. + const block = node.getClosestBlock(startKey) + if (block && block.isVoid) return node.removeDescendant(block) + + const inline = node.getClosestInline(startKey) + if (inline && inline.isVoid) return node.removeDescendant(inline) + // When at start of a text node, merge forwards into the next text node. - const { startKey } = range const startNode = node.getDescendant(startKey) if (range.isAtStartOf(startNode)) { @@ -131,17 +138,23 @@ const Transforms = { deleteForwardAtRange(range, n = 1) { let node = this - - // When collapsed at the end of the node, there's nothing to do. - if (range.isCollapsed && range.isAtEndOf(node)) return node + const { startKey } = range // When the range is still expanded, just do a regular delete. if (range.isExpanded) return node.deleteAtRange(range) - // When at end of a text node, merge forwards into the next text node. - const { startKey } = range - const startNode = node.getDescendant(startKey) + // When collapsed at the end of the node, there's nothing to do. + if (range.isAtEndOf(node)) return node + // When collapsed in a void node, remove that node. + const block = node.getClosestBlock(startKey) + if (block && block.isVoid) return node.removeDescendant(block) + + const inline = node.getClosestInline(startKey) + if (inline && inline.isVoid) return node.removeDescendant(inline) + + // When at end of a text node, merge forwards into the next text node. + const startNode = node.getDescendant(startKey) if (range.isAtEndOf(startNode)) { const next = node.getNextText(startNode) range = range.extendToStartOf(next)