From 60e6f0c723dcd224f5f14a914823a292bfbab5d7 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Tue, 31 Jul 2018 13:45:31 +0100 Subject: [PATCH] Add delete to start of line for MacOS refs https://github.com/bustle/mobiledoc-kit/issues/445 - add `Position.atStartOfLine` method that takes an existing position from which to find the start of it's line - add `line` unit for use in `editor.performDelete` - update delete key event handler to pass `line` unit when Meta+Backspace is pressed --- src/js/editor/event-manager.js | 2 ++ src/js/editor/post.js | 11 ++++++- src/js/utils/cursor/position.js | 52 +++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/js/editor/event-manager.js b/src/js/editor/event-manager.js index a744243cc..b73aee934 100644 --- a/src/js/editor/event-manager.js +++ b/src/js/editor/event-manager.js @@ -184,6 +184,8 @@ export default class EventManager { let unit = 'char'; if (key.altKey && Browser.isMac()) { unit = 'word'; + } else if (key.metaKey && Browser.isMac()) { + unit = 'line'; } else if (key.ctrlKey && Browser.isWin()) { unit = 'word'; } diff --git a/src/js/editor/post.js b/src/js/editor/post.js index 3051078dd..ac9fb5be8 100644 --- a/src/js/editor/post.js +++ b/src/js/editor/post.js @@ -401,7 +401,16 @@ class PostEditor { this.toggleSection('p', position); return this._range.head; } else { - let prevPosition = unit === 'word' ? position.moveWord(BACKWARD) : position.move(BACKWARD); + let prevPosition; + + if (unit === 'word') { + prevPosition = position.moveWord(BACKWARD); + } else if (unit === 'line') { + prevPosition = Position.atStartOfLine(position, this.editor); + } else { + prevPosition = position.move(BACKWARD); + } + let range = prevPosition.toRange(position); return this.deleteRange(range); } diff --git a/src/js/utils/cursor/position.js b/src/js/utils/cursor/position.js index 7e2fac370..97af5d437 100644 --- a/src/js/utils/cursor/position.js +++ b/src/js/utils/cursor/position.js @@ -62,6 +62,40 @@ function findOffsetInSection(section, node, offset) { } } +// TODO: expose as utility function, update cursor._findNodeForPosition +function findNodeForPosition(position) { + let { section } = position; + let node, offset; + if (section.isCardSection) { + offset = 0; + if (position.offset === 0) { + node = section.renderNode.element.firstChild; + } else { + node = section.renderNode.element.lastChild; + } + } else if (section.isBlank) { + node = section.renderNode.cursorElement; + offset = 0; + } else { + let { marker, offsetInMarker } = position; + if (marker.isAtom) { + if (offsetInMarker > 0) { + // FIXME -- if there is a next marker, focus on it? + offset = 0; + node = marker.renderNode.tailTextNode; + } else { + offset = 0; + node = marker.renderNode.headTextNode; + } + } else { + node = marker.renderNode.element; + offset = offsetInMarker; + } + } + + return { node, offset }; +} + let Position, BlankPosition; Position = class Position { @@ -101,6 +135,24 @@ Position = class Position { return Position.fromNode(_renderTree, node, offset); } + static atStartOfLine(position, editor) { + let isPostBoundary = position.isHeadOfPost(); + if (isPostBoundary) { + return position; + } + + let { node, offset } = findNodeForPosition(position); + + let range = document.createRange(); + range.setStart(node, offset); + range.setEnd(node, offset); + + let { y, height } = range.getBoundingClientRect(); + let { left } = position.section.renderNode.element.getBoundingClientRect(); + + return Position.atPoint(left, y + height / 2, editor); + } + static blankPosition() { return new BlankPosition(); }