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

Commit

Permalink
Change handlers to pass editor as an argument (#740)
Browse files Browse the repository at this point in the history
* Change handlers to pass `editor` as an argument

This allows Flow to type them better and catch bugs.

* Fix Flow errors exposed by added types

No behavior change.
  • Loading branch information
sophiebits authored and flarnie committed Nov 29, 2016
1 parent d1d3def commit e64c2c3
Show file tree
Hide file tree
Showing 16 changed files with 137 additions and 111 deletions.
5 changes: 3 additions & 2 deletions src/component/base/DraftEditor.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class DraftEditor extends React.Component {
_clipboard: ?BlockMap;
_handler: ?Object;
_dragCount: number;
_internalDrag: boolean;
_editorKey: string;
_placeholderAccessibilityID: string;
_latestEditorState: EditorState;
Expand Down Expand Up @@ -115,7 +116,7 @@ class DraftEditor extends React.Component {
blur: () => void;
setMode: (mode: DraftEditorModes) => void;
exitCurrentMode: () => void;
restoreEditorDOM: (scrollPosition: DraftScrollPosition) => void;
restoreEditorDOM: (scrollPosition?: DraftScrollPosition) => void;
setClipboard: (clipboard?: BlockMap) => void;
getClipboard: () => ?BlockMap;
getEditorKey: () => string;
Expand Down Expand Up @@ -181,7 +182,7 @@ class DraftEditor extends React.Component {
return (e) => {
if (!this.props.readOnly) {
const method = this._handler && this._handler[eventName];
method && method.call(this, e);
method && method(this, e);
}
};
}
Expand Down
4 changes: 2 additions & 2 deletions src/component/base/DraftEditorProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export type DraftEditorProps = {
// A function that accepts a synthetic key event and returns
// the matching DraftEditorCommand constant, or null if no command should
// be invoked.
keyBindingFn?: (e: SyntheticKeyboardEvent) => ?string,
keyBindingFn: (e: SyntheticKeyboardEvent) => ?string,

// Set whether the `DraftEditor` component should be editable. Useful for
// temporarily disabling edit behavior or allowing `DraftEditor` rendering
Expand Down Expand Up @@ -92,7 +92,7 @@ export type DraftEditorProps = {

// Map a key command string provided by your key binding function to a
// specified behavior.
handleKeyCommand?: (command: DraftEditorCommand) => DraftHandleValue,
handleKeyCommand?: (command: DraftEditorCommand | string) => DraftHandleValue,

// Handle intended text insertion before the insertion occurs. This may be
// useful in cases where the user has entered characters that you would like
Expand Down
30 changes: 16 additions & 14 deletions src/component/handlers/composition/DraftEditorCompositionHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const Keys = require('Keys');
const getEntityKeyForSelection = require('getEntityKeyForSelection');
const isSelectionAtLeafStart = require('isSelectionAtLeafStart');

import type DraftEditor from 'DraftEditor.react';

/**
* Millisecond delay to allow `compositionstart` to fire again upon
* `compositionend`.
Expand All @@ -42,15 +44,15 @@ let stillComposing = false;
let textInputData = '';

var DraftEditorCompositionHandler = {
onBeforeInput: function(e: SyntheticInputEvent): void {
onBeforeInput: function(editor: DraftEditor, e: SyntheticInputEvent): void {
textInputData = (textInputData || '') + e.data;
},

/**
* A `compositionstart` event has fired while we're still in composition
* mode. Continue the current composition session to prevent a re-render.
*/
onCompositionStart: function(): void {
onCompositionStart: function(editor: DraftEditor): void {
stillComposing = true;
},

Expand All @@ -68,12 +70,12 @@ var DraftEditorCompositionHandler = {
* twice could break the DOM, we only use the first event. Example: Arabic
* Google Input Tools on Windows 8.1 fires `compositionend` three times.
*/
onCompositionEnd: function(): void {
onCompositionEnd: function(editor: DraftEditor): void {
resolved = false;
stillComposing = false;
setTimeout(() => {
if (!resolved) {
DraftEditorCompositionHandler.resolveComposition.call(this);
DraftEditorCompositionHandler.resolveComposition(editor);
}
}, RESOLVE_DELAY);
},
Expand All @@ -83,14 +85,14 @@ var DraftEditorCompositionHandler = {
* the arrow keys are used to commit, prevent default so that the cursor
* doesn't move, otherwise it will jump back noticeably on re-render.
*/
onKeyDown: function(e: SyntheticKeyboardEvent): void {
onKeyDown: function(editor: DraftEditor, e: SyntheticKeyboardEvent): void {
if (!stillComposing) {
// If a keydown event is received after compositionend but before the
// 20ms timer expires (ex: type option-E then backspace, or type A then
// backspace in 2-Set Korean), we should immediately resolve the
// composition and reinterpret the key press in edit mode.
DraftEditorCompositionHandler.resolveComposition.call(this);
this._onKeyDown(e);
DraftEditorCompositionHandler.resolveComposition(editor);
editor._onKeyDown(e);
return;
}
if (e.which === Keys.RIGHT || e.which === Keys.LEFT) {
Expand All @@ -104,7 +106,7 @@ var DraftEditorCompositionHandler = {
* characters that we do not want. `preventDefault` allows the composition
* to be committed while preventing the extra characters.
*/
onKeyPress: function(e: SyntheticKeyboardEvent): void {
onKeyPress: function(editor: DraftEditor, e: SyntheticKeyboardEvent): void {
if (e.which === Keys.RETURN) {
e.preventDefault();
}
Expand All @@ -125,7 +127,7 @@ var DraftEditorCompositionHandler = {
* Resetting innerHTML will move focus to the beginning of the editor,
* so we update to force it back to the correct place.
*/
resolveComposition: function(): void {
resolveComposition: function(editor: DraftEditor): void {
if (stillComposing) {
return;
}
Expand All @@ -134,7 +136,7 @@ var DraftEditorCompositionHandler = {
const composedChars = textInputData;
textInputData = '';

const editorState = EditorState.set(this._latestEditorState, {
const editorState = EditorState.set(editor._latestEditorState, {
inCompositionMode: false,
});

Expand All @@ -152,10 +154,10 @@ var DraftEditorCompositionHandler = {
);

if (mustReset) {
this.restoreEditorDOM();
editor.restoreEditorDOM();
}

this.exitCurrentMode();
editor.exitCurrentMode();

if (composedChars) {
// If characters have been composed, re-rendering with the update
Expand All @@ -167,7 +169,7 @@ var DraftEditorCompositionHandler = {
currentStyle,
entityKey
);
this.update(
editor.update(
EditorState.push(
editorState,
contentState,
Expand All @@ -178,7 +180,7 @@ var DraftEditorCompositionHandler = {
}

if (mustReset) {
this.update(
editor.update(
EditorState.set(editorState, {
nativelyRenderedContent: null,
forceSelection: true,
Expand Down
29 changes: 15 additions & 14 deletions src/component/handlers/drag/DraftEditorDragHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const getTextContentFromFiles = require('getTextContentFromFiles');
const getUpdatedSelectionState = require('getUpdatedSelectionState');
const nullthrows = require('nullthrows');

import type DraftEditor from 'DraftEditor.react';
import type SelectionState from 'SelectionState';
const isEventHandled = require('isEventHandled');

Expand Down Expand Up @@ -63,24 +64,24 @@ var DraftEditorDragHandler = {
/**
* Drag originating from input terminated.
*/
onDragEnd: function(): void {
this.exitCurrentMode();
onDragEnd: function(editor: DraftEditor): void {
editor.exitCurrentMode();
},

/**
* Handle data being dropped.
*/
onDrop: function(e: Object): void {
onDrop: function(editor: DraftEditor, e: Object): void {
const data = new DataTransfer(e.nativeEvent.dataTransfer);

const editorState: EditorState = this._latestEditorState;
const editorState: EditorState = editor._latestEditorState;
const dropSelection: ?SelectionState = getSelectionForEvent(
e.nativeEvent,
editorState
);

e.preventDefault();
this.exitCurrentMode();
editor.exitCurrentMode();

if (dropSelection == null) {
return;
Expand All @@ -89,14 +90,14 @@ var DraftEditorDragHandler = {
const files = data.getFiles();
if (files.length > 0) {
if (
this.props.handleDroppedFiles &&
isEventHandled(this.props.handleDroppedFiles(dropSelection, files))
editor.props.handleDroppedFiles &&
isEventHandled(editor.props.handleDroppedFiles(dropSelection, files))
) {
return;
}

getTextContentFromFiles(files, fileText => {
fileText && this.update(
fileText && editor.update(
insertTextAtSelection(
editorState,
nullthrows(dropSelection), // flow wtf
Expand All @@ -107,20 +108,20 @@ var DraftEditorDragHandler = {
return;
}

const dragType = this._internalDrag ? 'internal' : 'external';
const dragType = editor._internalDrag ? 'internal' : 'external';
if (
this.props.handleDrop &&
isEventHandled(this.props.handleDrop(dropSelection, data, dragType))
editor.props.handleDrop &&
isEventHandled(editor.props.handleDrop(dropSelection, data, dragType))
) {
return;
}

if (this._internalDrag) {
this.update(moveText(editorState, dropSelection));
if (editor._internalDrag) {
editor.update(moveText(editorState, dropSelection));
return;
}

this.update(
editor.update(
insertTextAtSelection(editorState, dropSelection, data.getText())
);
},
Expand Down
15 changes: 8 additions & 7 deletions src/component/handlers/edit/editOnBeforeInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var getEntityKeyForSelection = require('getEntityKeyForSelection');
var isSelectionAtLeafStart = require('isSelectionAtLeafStart');
var nullthrows = require('nullthrows');

import type DraftEditor from 'DraftEditor.react';
import type {DraftInlineStyle} from 'DraftInlineStyle';
const isEventHandled = require('isEventHandled');

Expand Down Expand Up @@ -73,7 +74,7 @@ function replaceText(
* preserve spellcheck highlighting, which disappears or flashes if re-render
* occurs on the relevant text nodes.
*/
function editOnBeforeInput(e: SyntheticInputEvent): void {
function editOnBeforeInput(editor: DraftEditor, e: SyntheticInputEvent): void {
var chars = e.data;

// In some cases (ex: IE ideographic space insertion) no character data
Expand All @@ -88,8 +89,8 @@ function editOnBeforeInput(e: SyntheticInputEvent): void {
// decorator, or setting a block to be a list item after typing '- ' at the
// start of the block.
if (
this.props.handleBeforeInput &&
isEventHandled(this.props.handleBeforeInput(chars))
editor.props.handleBeforeInput &&
isEventHandled(editor.props.handleBeforeInput(chars))
) {
e.preventDefault();
return;
Expand All @@ -98,12 +99,12 @@ function editOnBeforeInput(e: SyntheticInputEvent): void {
// If selection is collapsed, conditionally allow native behavior. This
// reduces re-renders and preserves spellcheck highlighting. If the selection
// is not collapsed, we will re-render.
var editorState = this._latestEditorState;
var editorState = editor._latestEditorState;
var selection = editorState.getSelection();

if (!selection.isCollapsed()) {
e.preventDefault();
this.update(
editor.update(
replaceText(
editorState,
chars,
Expand All @@ -130,7 +131,7 @@ function editOnBeforeInput(e: SyntheticInputEvent): void {

if (!mayAllowNative) {
e.preventDefault();
this.update(newEditorState);
editor.update(newEditorState);
return;
}

Expand Down Expand Up @@ -161,7 +162,7 @@ function editOnBeforeInput(e: SyntheticInputEvent): void {
});
}

this.update(newEditorState);
editor.update(newEditorState);
}

module.exports = editOnBeforeInput;
10 changes: 6 additions & 4 deletions src/component/handlers/edit/editOnBlur.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ var UserAgent = require('UserAgent');

var getActiveElement = require('getActiveElement');

import type DraftEditor from 'DraftEditor.react';

var isWebKit = UserAgent.isEngine('WebKit');

function editOnBlur(e: SyntheticEvent): void {
function editOnBlur(editor: DraftEditor, e: SyntheticEvent): void {
// Webkit has a bug in which blurring a contenteditable by clicking on
// other active elements will trigger the `blur` event but will not remove
// the DOM selection from the contenteditable. We therefore force the
Expand All @@ -30,15 +32,15 @@ function editOnBlur(e: SyntheticEvent): void {
global.getSelection().removeAllRanges();
}

var editorState = this._latestEditorState;
var editorState = editor._latestEditorState;
var currentSelection = editorState.getSelection();
if (!currentSelection.getHasFocus()) {
return;
}

var selection = currentSelection.set('hasFocus', false);
this.props.onBlur && this.props.onBlur(e);
this.update(EditorState.acceptSelection(editorState, selection));
editor.props.onBlur && editor.props.onBlur(e);
editor.update(EditorState.acceptSelection(editorState, selection));
}

module.exports = editOnBlur;
12 changes: 7 additions & 5 deletions src/component/handlers/edit/editOnCompositionStart.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@

var EditorState = require('EditorState');

import type DraftEditor from 'DraftEditor.react';

/**
* The user has begun using an IME input system. Switching to `composite` mode
* allows handling composition input and disables other edit behavior.
*/
function editOnCompositionStart(e: SyntheticEvent): void {
this.setMode('composite');
this.update(
EditorState.set(this._latestEditorState, {inCompositionMode: true})
function editOnCompositionStart(editor: DraftEditor, e: SyntheticEvent): void {
editor.setMode('composite');
editor.update(
EditorState.set(editor._latestEditorState, {inCompositionMode: true})
);
// Allow composition handler to interpret the compositionstart event
this._onCompositionStart(e);
editor._onCompositionStart(e);
}

module.exports = editOnCompositionStart;
8 changes: 5 additions & 3 deletions src/component/handlers/edit/editOnCopy.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@

var getFragmentFromSelection = require('getFragmentFromSelection');

import type DraftEditor from 'DraftEditor.react';

/**
* If we have a selection, create a ContentState fragment and store
* it in our internal clipboard. Subsequent paste events will use this
* fragment if no external clipboard data is supplied.
*/
function editOnCopy(e: SyntheticClipboardEvent): void {
var editorState = this._latestEditorState;
function editOnCopy(editor: DraftEditor, e: SyntheticClipboardEvent): void {
var editorState = editor._latestEditorState;
var selection = editorState.getSelection();

// No selection, so there's nothing to copy.
Expand All @@ -29,7 +31,7 @@ function editOnCopy(e: SyntheticClipboardEvent): void {
return;
}

this.setClipboard(getFragmentFromSelection(this._latestEditorState));
editor.setClipboard(getFragmentFromSelection(editor._latestEditorState));
}

module.exports = editOnCopy;
Loading

0 comments on commit e64c2c3

Please sign in to comment.