diff --git a/src/js/editor/editor.js b/src/js/editor/editor.js index 9e1587b29..3f2b569c6 100644 --- a/src/js/editor/editor.js +++ b/src/js/editor/editor.js @@ -258,7 +258,7 @@ class Editor { } handleNewline(event) { - if (!this.cursor.hasCursor()) { return; } + if (!this.hasCursor()) { return; } event.preventDefault(); @@ -503,9 +503,20 @@ class Editor { this._views = []; } + /** + * Whether the editor has a cursor (or a selected range). + * It is possible for the editor to be focused but not have a selection. + * In this case, key events will fire but the editor will not be able to + * determine a cursor position. + * @return {bool} + */ + hasCursor() { + return this.cursor.hasCursor(); + } + destroy() { this._isDestroyed = true; - if (this.cursor.hasCursor()) { + if (this.hasCursor()) { this.cursor.clearSelection(); this.element.blur(); // FIXME This doesn't blur the element on IE11 } diff --git a/src/js/editor/event-manager.js b/src/js/editor/event-manager.js index 9263aa084..96731bb82 100644 --- a/src/js/editor/event-manager.js +++ b/src/js/editor/event-manager.js @@ -83,14 +83,16 @@ export default class EventManager { } keypress(event) { + let { editor } = this; + if (!editor.hasCursor()) { return; } + let key = Key.fromEvent(event); if (!key.isPrintable()) { return; + } else { + event.preventDefault(); } - event.preventDefault(); - - let { editor } = this; if (editor.handleExpansion(event)) { return; } else { @@ -100,17 +102,15 @@ export default class EventManager { keydown(event) { let { editor } = this; - if (!editor.isEditable) { - return; - } + if (!editor.hasCursor()) { return; } + if (!editor.isEditable) { return; } + let key = Key.fromEvent(event); if (key.isShiftKey()) { this.isShift = true; } - if (editor.handleKeyCommand(event)) { - return; - } + if (editor.handleKeyCommand(event)) { return; } if (editor.post.isBlank) { editor._insertEmptyMarkupSectionAtCursor(); @@ -145,6 +145,8 @@ export default class EventManager { } keyup(event) { + let { editor } = this; + if (!editor.hasCursor()) { return; } let key = Key.fromEvent(event); if (key.isShiftKey()) { this.isShift = false; diff --git a/tests/acceptance/basic-editor-test.js b/tests/acceptance/basic-editor-test.js index 4570096f4..759a4581c 100644 --- a/tests/acceptance/basic-editor-test.js +++ b/tests/acceptance/basic-editor-test.js @@ -265,3 +265,22 @@ test('adding/removing bold text between two bold markers works', (assert) => { assert.hasElement('#editor b:contains(def)', 'removes B from middle, leaves def'); assert.hasNoElement('#editor b:contains(123)', 'removes B from middle'); }); + +test('keypress events when the editor does not have selection are ignored', (assert) => { + let expected; + editor = Helpers.mobiledoc.renderInto(editorElement, ({post, markupSection, marker}) => { + expected = post([markupSection('p', [marker('abc')])]); + return post([ + markupSection('p', [marker('abc')]) + ]); + }); + + Helpers.dom.clearSelection(); + + assert.ok(document.activeElement === editorElement, 'precond - editor is focused'); + assert.equal(window.getSelection().rangeCount, 0, 'nothing selected'); + + Helpers.dom.insertText(editor, 'v'); + + assert.postIsSimilar(editor.post, expected, 'post is not changed'); +}); diff --git a/tests/helpers/dom.js b/tests/helpers/dom.js index 4d4eb0a6a..10d97d036 100644 --- a/tests/helpers/dom.js +++ b/tests/helpers/dom.js @@ -247,6 +247,11 @@ function triggerKeyCommand(editor, string, modifiers=[]) { _triggerEditorEvent(editor, keyEvent); } +function triggerKeyEvent(editor, type, options) { + let event = createMockEvent(type, editor.element, options); + _triggerEditorEvent(editor, event); +} + function triggerRightArrowKey(editor, modifier) { if (!(editor instanceof Editor)) { throw new Error('Must pass editor to triggerRightArrowKey');