Skip to content
This repository was archived by the owner on Feb 6, 2023. It is now read-only.

Commit db792ef

Browse files
Matthew Hollowayfacebook-github-bot
Matthew Holloway
authored andcommitted
Adding 'preserveSelectionOnBlur' prop (#2128)
Summary: **Summary** This adds a `preserveSelectionOnBlur` prop as per #2123 **Test Plan** Tests were added for the two possible scenarios. I'm not sure how much to mock in this test because it is just testing a specific branch of code, so I've faked certain details like the rangeCount. What do you think mrkev claudiopro ? Pull Request resolved: #2128 Reviewed By: claudiopro Differential Revision: D16270879 Pulled By: mrkev fbshipit-source-id: 304af92c1211b8ff95741bff434b4fe3c4b6dd7d
1 parent 4064cae commit db792ef

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

src/component/base/DraftEditorProps.js

+5
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,11 @@ export type DraftEditorProps = {
180180
// is used for both rendering and paste processing.
181181
blockRenderMap: DraftBlockRenderMap,
182182

183+
// When the Editor loses focus (blurs) text selections are cleared
184+
// by default to mimic <textarea> behaviour, however in some situations
185+
// users may wish to preserve native behaviour.
186+
preserveSelectionOnBlur?: boolean,
187+
183188
// Overrides for cut, copy & paste, which can be used to implement custom
184189
// behavior like entity cut/copy/paste (see PR #1784)."
185190
onPaste?: (DraftEditor, SyntheticClipboardEvent<>) => void,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @emails oncall+draft_js
8+
* @format
9+
*/
10+
11+
'use strict';
12+
13+
jest.disableAutomock();
14+
15+
const ContentBlock = require('ContentBlock');
16+
const ContentState = require('ContentState');
17+
const EditorState = require('EditorState');
18+
19+
const onBlur = require('editOnBlur');
20+
21+
const getEditorState = (text: string = 'Arsenal') => {
22+
return EditorState.createWithContent(
23+
ContentState.createFromBlockArray([
24+
new ContentBlock({
25+
key: 'a',
26+
text,
27+
}),
28+
]),
29+
);
30+
};
31+
32+
const getBlurEvent = data => ({
33+
data,
34+
});
35+
36+
function withGlobalGetSelectionAs(getSelectionValue = {}, callback) {
37+
const oldGetSelection = global.getSelection;
38+
try {
39+
global.getSelection = () => {
40+
return getSelectionValue;
41+
};
42+
callback();
43+
} finally {
44+
global.getSelection = oldGetSelection;
45+
}
46+
}
47+
48+
test('editor removes selection on blur (default behaviour)', () => {
49+
const anchorNodeText = 'react draftjs';
50+
const anchorNode = document.createTextNode(anchorNodeText);
51+
const globalSelection = {
52+
anchorNode,
53+
focusNode: anchorNode,
54+
removeAllRanges: jest.fn(),
55+
rangeCount: 1,
56+
};
57+
58+
const editorNode = document.createElement('div');
59+
editorNode.appendChild(anchorNode);
60+
61+
withGlobalGetSelectionAs(globalSelection, () => {
62+
const editorState = getEditorState(anchorNodeText);
63+
const editor = {
64+
_latestEditorState: editorState,
65+
props: {
66+
preserveSelectionOnBlur: false,
67+
},
68+
editor: editorNode,
69+
};
70+
71+
onBlur(editor, getBlurEvent());
72+
73+
expect(globalSelection.removeAllRanges).toHaveBeenCalledTimes(1);
74+
});
75+
});
76+
77+
test('editor preserves selection on blur', () => {
78+
const anchorNodeText = 'react draftjs';
79+
const anchorNode = document.createTextNode(anchorNodeText);
80+
const globalSelection = {
81+
anchorNode,
82+
focusNode: anchorNode,
83+
removeAllRanges: jest.fn(),
84+
rangeCount: 1,
85+
};
86+
87+
const editorNode = document.createElement('div');
88+
editorNode.appendChild(anchorNode);
89+
90+
withGlobalGetSelectionAs(globalSelection, () => {
91+
const editorState = getEditorState(anchorNodeText);
92+
const editor = {
93+
_latestEditorState: editorState,
94+
props: {
95+
preserveSelectionOnBlur: true,
96+
},
97+
editor: editorNode,
98+
};
99+
100+
onBlur(editor, getBlurEvent());
101+
102+
expect(globalSelection.removeAllRanges).toHaveBeenCalledTimes(0);
103+
});
104+
});

src/component/handlers/edit/editOnBlur.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ function editOnBlur(editor: DraftEditor, e: SyntheticEvent<>): void {
2727
// We therefore force the issue to be certain, checking whether the active
2828
// element is `body` to force it when blurring occurs within the window (as
2929
// opposed to clicking to another tab or window).
30-
if (getActiveElement() === document.body) {
30+
// However if users wish to override this behaviour they can provide
31+
// a prop preserveSelectionOnBlur of `true`.
32+
if (
33+
!editor.props.preserveSelectionOnBlur &&
34+
getActiveElement() === document.body
35+
) {
3136
const selection = global.getSelection();
3237
const editorNode = editor.editor;
3338
if (

0 commit comments

Comments
 (0)