Skip to content

Commit

Permalink
[BUGFIX] Do not handle key events when the editor has no cursor
Browse files Browse the repository at this point in the history
It is possible for the editor's element to be focused but not have a
cursor (selection). In this case, key events will fire on the editor's
element but the editor will not be able to determine a logical
`Position` (since there is no selection). When this happens, we abort
handling the key event.

fixes #344
  • Loading branch information
bantic committed Mar 24, 2016
1 parent 61adff6 commit 251675e
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 11 deletions.
15 changes: 13 additions & 2 deletions src/js/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ class Editor {
}

handleNewline(event) {
if (!this.cursor.hasCursor()) { return; }
if (!this.hasCursor()) { return; }

event.preventDefault();

Expand Down Expand Up @@ -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
}
Expand Down
20 changes: 11 additions & 9 deletions src/js/editor/event-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
19 changes: 19 additions & 0 deletions tests/acceptance/basic-editor-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});
5 changes: 5 additions & 0 deletions tests/helpers/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down

0 comments on commit 251675e

Please sign in to comment.