Skip to content

Commit

Permalink
Handle forward-delete in list items
Browse files Browse the repository at this point in the history
fixes #118
  • Loading branch information
bantic committed Sep 14, 2015
1 parent a8e19da commit ae42ab2
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 1 deletion.
39 changes: 38 additions & 1 deletion src/js/editor/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,44 @@ class PostEditor {
* @private
*/
_deleteForwardFrom(position) {
return this._deleteForwardFromMarkerPosition(position);
const { section, offset } = position;
if (section.isBlank) {
// remove this section, focus on start of next markerable section
const nextPosition = position.clone();
const next = section.immediatelyNextMarkerableSection();
if (next) {
this.removeSection(section);
nextPosition.section = next;
nextPosition.offset = 0;
}
return nextPosition;
} else if (offset === section.length) {
// join next markerable section to this one
return this._joinPositionToNextSection(position);
} else {
return this._deleteForwardFromMarkerPosition(position.markerPosition);
}
}

_joinPositionToNextSection(position) {
const { section } = position;
let nextPosition = position.clone();

if (!isMarkerable(section)) {
throw new Error('Cannot join non-markerable section to next section');
} else {
const next = section.immediatelyNextMarkerableSection();
if (next) {
section.join(next);
section.renderNode.markDirty();
this.removeSection(next);

this.scheduleRerender();
this.scheduleDidUpdate();
}
}

return nextPosition;
}

_deleteForwardFromMarkerPosition(markerPosition) {
Expand Down
131 changes: 131 additions & 0 deletions tests/acceptance/editor-list-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ test('deleting at start of empty section after list item joins it with list item
});
createEditorWithMobiledoc(mobiledoc);

assert.hasElement('#editor p br', 'precond - br');
const node = $('#editor p br')[0];
Helpers.dom.moveCursorTo(node, 0);
Helpers.dom.triggerDelete(editor);
Expand All @@ -255,3 +256,133 @@ test('deleting at start of empty section after list item joins it with list item

assert.hasElement('#editor li:contains(abcX)', 'inserts text at right spot');
});

test('forward-delete in empty list item with nothing after it does nothing', (assert) => {
const mobiledoc = Helpers.mobiledoc.build(builder => {
const {post, listSection, listItem} = builder;
return post([
listSection('ul', [listItem()])
]);
});
createEditorWithMobiledoc(mobiledoc);

assert.hasElement('#editor li br', 'precond - br');
const node = $('#editor li br')[0];
Helpers.dom.moveCursorTo(node, 0);
Helpers.dom.triggerForwardDelete(editor);

assert.hasElement('#editor li', 'li remains');

Helpers.dom.insertText(editor, 'X');

assert.hasElement('#editor li:contains(X)', 'inserts text at right spot');
});

test('forward-delete in empty li with li after it joins with li', (assert) => {
const mobiledoc = Helpers.mobiledoc.build(builder => {
const {post, listSection, listItem, marker} = builder;
return post([
listSection('ul', [listItem(), listItem([marker('abc')])])
]);
});
createEditorWithMobiledoc(mobiledoc);

assert.equal($('#editor li').length, 2, 'precond - 2 lis');
assert.hasElement('#editor li br', 'precond - br');
const node = $('#editor li br')[0];
Helpers.dom.moveCursorTo(node, 0);
Helpers.dom.triggerForwardDelete(editor);

assert.equal($('#editor li').length, 1, '1 li remains');
assert.hasElement('#editor li:contains(abc)', 'correct li remains');

Helpers.dom.insertText(editor, 'X');

assert.hasElement('#editor li:contains(Xabc)', 'inserts text at right spot');
});

test('forward-delete in empty li with markup section after it deletes li', (assert) => {
const mobiledoc = Helpers.mobiledoc.build(builder => {
const {post, listSection, listItem, markupSection, marker} = builder;
return post([
listSection('ul', [listItem()]),
markupSection('p', [marker('abc')])
]);
});
createEditorWithMobiledoc(mobiledoc);

assert.hasElement('#editor li br', 'precond - br');
const node = $('#editor li br')[0];
Helpers.dom.moveCursorTo(node, 0);
Helpers.dom.triggerForwardDelete(editor);

assert.hasNoElement('#editor li', 'li is removed');
assert.hasElement('#editor p:contains(abc)', 'p remains');

Helpers.dom.insertText(editor, 'X');

assert.hasElement('#editor p:contains(Xabc)', 'inserts text at right spot');

});

test('forward-delete end of li with nothing after', (assert) => {
const mobiledoc = Helpers.mobiledoc.build(builder => {
const {post, listSection, listItem, marker} = builder;
return post([
listSection('ul', [listItem([marker('abc')])])
]);
});
createEditorWithMobiledoc(mobiledoc);

const node = $('#editor li')[0].childNodes[0];
Helpers.dom.moveCursorTo(node, 'abc'.length);
Helpers.dom.triggerForwardDelete(editor);

assert.hasElement('#editor li:contains(abc)', 'li remains');
Helpers.dom.insertText(editor, 'X');
assert.hasElement('#editor li:contains(abcX)', 'inserts text at right spot');
});

test('forward-delete end of li with li after', (assert) => {
const mobiledoc = Helpers.mobiledoc.build(builder => {
const {post, listSection, listItem, marker} = builder;
return post([
listSection('ul', [
listItem([marker('abc')]),
listItem([marker('def')])
])
]);
});
createEditorWithMobiledoc(mobiledoc);

assert.equal($('#editor li').length, 2, 'precond - 2 lis');
const node = $('#editor li')[0].childNodes[0];
Helpers.dom.moveCursorTo(node, 'abc'.length);
Helpers.dom.triggerForwardDelete(editor);

assert.hasElement('#editor li:contains(abcdef)', 'li is joined');
assert.equal($('#editor li').length, 1, 'only 1 li');
Helpers.dom.insertText(editor, 'X');
assert.hasElement('#editor li:contains(abcXdef)', 'inserts text at right spot');
});

test('forward-delete end of li with markup section after', (assert) => {
const mobiledoc = Helpers.mobiledoc.build(builder => {
const {post, listSection, listItem, marker, markupSection} = builder;
return post([
listSection('ul', [listItem([marker('abc')])]),
markupSection('p', [marker('def')])
]);
});
createEditorWithMobiledoc(mobiledoc);

const node = $('#editor li')[0].childNodes[0];
Helpers.dom.moveCursorTo(node, 'abc'.length);
Helpers.dom.triggerForwardDelete(editor);

assert.hasElement('#editor li:contains(abcdef)', 'li is joined');
assert.equal($('#editor li').length, 1, 'only 1 li');
assert.hasNoElement('#editor p', 'p is removed');
Helpers.dom.insertText(editor, 'X');
assert.hasElement('#editor li:contains(abcXdef)', 'inserts text at right spot');
});
1 change: 1 addition & 0 deletions tests/helpers/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function selectText(startText,
}

function moveCursorTo(node, offset=0, endNode=node, endOffset=offset) {
if (!node) { throw new Error('Cannot moveCursorTo node without node'); }
selectRange(node, offset, endNode, endOffset);
}

Expand Down

0 comments on commit ae42ab2

Please sign in to comment.