diff --git a/src/component/handlers/composition/DraftEditorCompositionHandler.js b/src/component/handlers/composition/DraftEditorCompositionHandler.js index 97490734ac..5be1c58315 100644 --- a/src/component/handlers/composition/DraftEditorCompositionHandler.js +++ b/src/component/handlers/composition/DraftEditorCompositionHandler.js @@ -40,6 +40,7 @@ const RESOLVE_DELAY = 20; let resolved = false; let stillComposing = false; let textInputData = ''; +let formerTextInputData = ''; var DraftEditorCompositionHandler = { onBeforeInput: function(e: SyntheticInputEvent): void { @@ -50,7 +51,8 @@ var DraftEditorCompositionHandler = { * 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(e): void { + formerTextInputData = e.data; stillComposing = true; }, @@ -125,6 +127,9 @@ var DraftEditorCompositionHandler = { const composedChars = textInputData; textInputData = ''; + const formerComposedChars = formerTextInputData; + formerTextInputData = ''; + const editorState = EditorState.set(this.props.editorState, { inCompositionMode: false, }); @@ -149,12 +154,28 @@ var DraftEditorCompositionHandler = { this.exitCurrentMode(); this.removeRenderGuard(); + let contentState = editorState.getCurrentContent(); + let selection = editorState.getSelection(); + if (formerComposedChars && selection.isCollapsed()) { + var anchorOffset = selection.getAnchorOffset() - formerComposedChars.length; + if (anchorOffset < 0) { + anchorOffset = 0; + } + const toRemoveSel = selection.merge({anchorOffset}); + contentState = DraftModifier.removeRange( + editorState.getCurrentContent(), + toRemoveSel, + 'backward', + ); + selection = contentState.getSelectionAfter(); + } + if (composedChars) { // If characters have been composed, re-rendering with the update // is sufficient to reset the editor. - const contentState = DraftModifier.replaceText( - editorState.getCurrentContent(), - editorState.getSelection(), + contentState = DraftModifier.replaceText( + contentState, + selection, composedChars, currentStyle, entityKey diff --git a/src/component/handlers/edit/editOnCompositionStart.js b/src/component/handlers/edit/editOnCompositionStart.js index 18d157864f..98d1e1709a 100644 --- a/src/component/handlers/edit/editOnCompositionStart.js +++ b/src/component/handlers/edit/editOnCompositionStart.js @@ -18,9 +18,10 @@ var EditorState = require('EditorState'); * The user has begun using an IME input system. Switching to `composite` mode * allows handling composition input and disables other edit behavior. */ -function editOnCompositionStart(): void { +function editOnCompositionStart(e): void { this.setRenderGuard(); this.setMode('composite'); + this._onCompositionStart(e); this.update( EditorState.set(this.props.editorState, {inCompositionMode: true}) ); diff --git a/src/component/handlers/edit/editOnInput.js b/src/component/handlers/edit/editOnInput.js index 1878647dfe..f8ffce8667 100644 --- a/src/component/handlers/edit/editOnInput.js +++ b/src/component/handlers/edit/editOnInput.js @@ -21,7 +21,7 @@ var findAncestorOffsetKey = require('findAncestorOffsetKey'); var nullthrows = require('nullthrows'); var isGecko = UserAgent.isEngine('Gecko'); - +var isAndroid = UserAgent.isPlatform('Android'); var DOUBLE_NEWLINE = '\n\n'; /** @@ -40,7 +40,7 @@ function editOnInput(): void { var domSelection = global.getSelection(); var {anchorNode, isCollapsed} = domSelection; - if (anchorNode.nodeType !== Node.TEXT_NODE) { + if (anchorNode.nodeType !== Node.TEXT_NODE && anchorNode.nodeType !== Node.ELEMENT_NODE) { return; } @@ -88,7 +88,7 @@ function editOnInput(): void { var anchorOffset, focusOffset, startOffset, endOffset; - if (isGecko) { + if (isAndroid || isGecko) { // Firefox selection does not change while the context menu is open, so // we preserve the anchor and focus values of the DOM selection. anchorOffset = domSelection.anchorOffset;