Skip to content
This repository was archived by the owner on Feb 6, 2023. It is now read-only.
Closed
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
5 changes: 5 additions & 0 deletions src/component/base/DraftEditorProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ export type DraftEditorProps = {
// is used for both rendering and paste processing.
blockRenderMap: DraftBlockRenderMap,

// When the Editor loses focus (blurs) text selections are cleared
// by default to mimic <textarea> behaviour, however in some situations
// users may wish to preserve native behaviour.
preserveSelectionOnBlur?: Boolean,

// Overrides for cut, copy & paste, which can be used to implement custom
// behavior like entity cut/copy/paste (see PR #1784)."
onPaste?: (DraftEditor, SyntheticClipboardEvent<>) => void,
Expand Down
104 changes: 104 additions & 0 deletions src/component/handlers/edit/__tests__/editOnBlur-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails oncall+draft_js
* @format
*/

'use strict';

jest.disableAutomock();

const ContentBlock = require('ContentBlock');
const ContentState = require('ContentState');
const EditorState = require('EditorState');

const onBlur = require('editOnBlur');

const getEditorState = (text: string = 'Arsenal') => {
return EditorState.createWithContent(
ContentState.createFromBlockArray([
new ContentBlock({
key: 'a',
text,
}),
]),
);
};

const getBlurEvent = data => ({
data,
});

function withGlobalGetSelectionAs(getSelectionValue = {}, callback) {
const oldGetSelection = global.getSelection;
try {
global.getSelection = () => {
return getSelectionValue;
};
callback();
} finally {
global.getSelection = oldGetSelection;
}
}

test('editor removes selection on blur (default behaviour)', () => {
const anchorNodeText = 'react draftjs';
const anchorNode = document.createTextNode(anchorNodeText);
const globalSelection = {
anchorNode,
focusNode: anchorNode,
removeAllRanges: jest.fn(),
rangeCount: 1,
};

const editorNode = document.createElement('div');
editorNode.appendChild(anchorNode);

withGlobalGetSelectionAs(globalSelection, () => {
const editorState = getEditorState(anchorNodeText);
const editor = {
_latestEditorState: editorState,
props: {
preserveSelectionOnBlur: false,
},
editor: editorNode,
};

onBlur(editor, getBlurEvent());

expect(globalSelection.removeAllRanges).toHaveBeenCalledTimes(1);
});
});

test('editor preserves selection on blur', () => {
const anchorNodeText = 'react draftjs';
const anchorNode = document.createTextNode(anchorNodeText);
const globalSelection = {
anchorNode,
focusNode: anchorNode,
removeAllRanges: jest.fn(),
rangeCount: 1,
};

const editorNode = document.createElement('div');
editorNode.appendChild(anchorNode);

withGlobalGetSelectionAs(globalSelection, () => {
const editorState = getEditorState(anchorNodeText);
const editor = {
_latestEditorState: editorState,
props: {
preserveSelectionOnBlur: true,
},
editor: editorNode,
};

onBlur(editor, getBlurEvent());

expect(globalSelection.removeAllRanges).toHaveBeenCalledTimes(0);
});
});
7 changes: 6 additions & 1 deletion src/component/handlers/edit/editOnBlur.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ function editOnBlur(editor: DraftEditor, e: SyntheticEvent<>): void {
// We therefore force the issue to be certain, checking whether the active
// element is `body` to force it when blurring occurs within the window (as
// opposed to clicking to another tab or window).
if (getActiveElement() === document.body) {
// However if users wish to override this behaviour they can provide
// a prop preserveSelectionOnBlur of `true`.
if (
!editor.props.preserveSelectionOnBlur &&
getActiveElement() === document.body
) {
const selection = global.getSelection();
const editorNode = editor.editor;
if (
Expand Down