Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes some edge cases on entity selection #168

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

- Stop unnecessarily calling `onSave` in the editor’s `onBlur` ([#173](https://github.com/springload/draftail/issues/173)).
- Prevent crash when filtering pasted content whose last block is to be removed (e.g. unsupported image) ([#179](https://github.com/springload/draftail/issues/179)).
- Prevent crash in `DraftUtils.getEntitySelection`, when the provided entity key isn't valid (undefined, missing) ([#168](https://github.com/springload/draftail/pull/168))
- Fix entity removal and editing not doing anything when the selection is backwards (right to left) ([#168](https://github.com/springload/draftail/pull/168)).

### Changed

Expand Down
18 changes: 14 additions & 4 deletions lib/api/DraftUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,15 @@ export default {

/**
* Creates a selection on a given entity in the currently selected block.
* Returns the current selection if no entity key is provided, or if the entity could not be found.
*/
getEntitySelection(editorState, entityKey) {
const selectionState = editorState.getSelection();
const selection = editorState.getSelection();

if (!entityKey) {
return selection;
}

const block = this.getSelectedBlock(editorState);
let entityRange;
// https://github.com/jpuri/draftjs-utils/blob/e81c0ae19c3b0fdef7e0c1b70d924398956be126/js/inline.js#L111
Expand All @@ -77,9 +83,13 @@ export default {
},
);

return selectionState.merge({
anchorOffset: entityRange.start,
focusOffset: entityRange.end,
if (!entityRange) {
return selection;
}

return selection.merge({
anchorOffset: selection.isBackward ? entityRange.end : entityRange.start,
focusOffset: selection.isBackward ? entityRange.start : entityRange.end,
});
},

Expand Down
74 changes: 56 additions & 18 deletions lib/api/DraftUtils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,33 +152,71 @@ describe("DraftUtils", () => {

describe("#getEntitySelection", () => {
it("works", () => {
const contentBlocks = convertFromHTML("<h1>aaaaaaaaaa</h1>");
const contentState = ContentState.createFromBlockArray(contentBlocks);
let editorState = EditorState.createWithContent(contentState);
const updatedSelection = editorState.getSelection().merge({
const content = ContentState.createFromText("hello, world");
let editorState = EditorState.createWithContent(content);
const selection = editorState.getSelection().merge({
anchorOffset: 0,
focusOffset: 5,
focusOffset: 4,
});

const contentStateWithEntity = content.createEntity("LINK", "MUTABLE", {
url: "www.testing.com",
});
const contentStateWithEntity = contentState.createEntity(
"LINK",
"MUTABLE",
{ url: "www.testing.com" },
);
const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
editorState = RichUtils.toggleLink(
editorState = RichUtils.toggleLink(editorState, selection, entityKey);
editorState = EditorState.forceSelection(
editorState,
updatedSelection,
entityKey,
selection.merge({ focusOffset: 0 }),
);
const entitySelection = DraftUtils.getEntitySelection(
expect(
DraftUtils.getEntitySelection(editorState, entityKey).toJS(),
).toMatchObject({
anchorOffset: 0,
focusOffset: 4,
});
});

it("supports backwards selections (#168)", () => {
const content = ContentState.createFromText("hello, world");
let editorState = EditorState.createWithContent(content);
const selection = editorState.getSelection().merge({
anchorOffset: 5,
focusOffset: 0,
isBackward: true,
});
const contentStateWithEntity = content.createEntity("LINK", "MUTABLE", {
url: "www.testing.com",
});
const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
editorState = RichUtils.toggleLink(editorState, selection, entityKey);
editorState = EditorState.forceSelection(
editorState,
entityKey,
selection.merge({ anchorOffset: 0 }),
);
expect(entitySelection.toJS()).toMatchObject({
anchorOffset: 0,
focusOffset: 5,
expect(
DraftUtils.getEntitySelection(editorState, entityKey).toJS(),
).toMatchObject({
anchorOffset: 5,
focusOffset: 0,
isBackward: true,
});
});

it("entity not found should not change selection (#168)", () => {
const content = ContentState.createFromText("hello, world");
const editorState = EditorState.createWithContent(content);
expect(DraftUtils.getEntitySelection(editorState, "1")).toBe(
editorState.getSelection(),
);
});

it("missing entity key should not change selection (#168)", () => {
const content = ContentState.createFromText("hello, world");
const editorState = EditorState.createWithContent(content);
expect(DraftUtils.getEntitySelection(editorState, null)).toBe(
editorState.getSelection(),
);
});
});

describe("#updateBlockEntity", () => {
Expand Down