芝麻web文件管理V1.00
编辑当前文件:/home/freeclou/app.optimyar.com/backend/node_modules/draft-js/lib/DraftEditorCompositionHandler.js
/** * 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. * * @format * * @emails oncall+draft_js */ 'use strict'; var DOMObserver = require("./DOMObserver"); var DraftModifier = require("./DraftModifier"); var DraftOffsetKey = require("./DraftOffsetKey"); var EditorState = require("./EditorState"); var Keys = require("fbjs/lib/Keys"); var UserAgent = require("fbjs/lib/UserAgent"); var editOnSelect = require("./editOnSelect"); var getContentEditableContainer = require("./getContentEditableContainer"); var getDraftEditorSelection = require("./getDraftEditorSelection"); var getEntityKeyForSelection = require("./getEntityKeyForSelection"); var nullthrows = require("fbjs/lib/nullthrows"); var isIE = UserAgent.isBrowser('IE'); /** * Millisecond delay to allow `compositionstart` to fire again upon * `compositionend`. * * This is used for Korean input to ensure that typing can continue without * the editor trying to render too quickly. More specifically, Safari 7.1+ * triggers `compositionstart` a little slower than Chrome/FF, which * leads to composed characters being resolved and re-render occurring * sooner than we want. */ var RESOLVE_DELAY = 20; /** * A handful of variables used to track the current composition and its * resolution status. These exist at the module level because it is not * possible to have compositions occurring in multiple editors simultaneously, * and it simplifies state management with respect to the DraftEditor component. */ var resolved = false; var stillComposing = false; var domObserver = null; function startDOMObserver(editor) { if (!domObserver) { domObserver = new DOMObserver(getContentEditableContainer(editor)); domObserver.start(); } } 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 onCompositionStart(editor) { stillComposing = true; startDOMObserver(editor); }, /** * Attempt to end the current composition session. * * Defer handling because browser will still insert the chars into active * element after `compositionend`. If a `compositionstart` event fires * before `resolveComposition` executes, our composition session will * continue. * * The `resolved` flag is useful because certain IME interfaces fire the * `compositionend` event multiple times, thus queueing up multiple attempts * at handling the composition. Since handling the same composition event * 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 onCompositionEnd(editor) { resolved = false; stillComposing = false; setTimeout(function () { if (!resolved) { DraftEditorCompositionHandler.resolveComposition(editor); } }, RESOLVE_DELAY); }, onSelect: editOnSelect, /** * In Safari, keydown events may fire when committing compositions. If * 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 onKeyDown(editor, e) { 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(editor); editor._onKeyDown(e); return; } if (e.which === Keys.RIGHT || e.which === Keys.LEFT) { e.preventDefault(); } }, /** * Keypress events may fire when committing compositions. In Firefox, * pressing RETURN commits the composition and inserts extra newline * characters that we do not want. `preventDefault` allows the composition * to be committed while preventing the extra characters. */ onKeyPress: function onKeyPress(_editor, e) { if (e.which === Keys.RETURN) { e.preventDefault(); } }, /** * Attempt to insert composed characters into the document. * * If we are still in a composition session, do nothing. Otherwise, insert * the characters into the document and terminate the composition session. * * If no characters were composed -- for instance, the user * deleted all composed characters and committed nothing new -- * force a re-render. We also re-render when the composition occurs * at the beginning of a leaf, to ensure that if the browser has * created a new text node for the composition, we will discard it. * * Resetting innerHTML will move focus to the beginning of the editor, * so we update to force it back to the correct place. */ resolveComposition: function resolveComposition(editor) { if (stillComposing) { return; } var mutations = nullthrows(domObserver).stopAndFlushMutations(); domObserver = null; resolved = true; var editorState = EditorState.set(editor._latestEditorState, { inCompositionMode: false }); editor.exitCurrentMode(); if (!mutations.size) { editor.update(editorState); return; } // TODO, check if Facebook still needs this flag or if it could be removed. // Since there can be multiple mutations providing a `composedChars` doesn't // apply well on this new model. // if ( // gkx('draft_handlebeforeinput_composed_text') && // editor.props.handleBeforeInput && // isEventHandled( // editor.props.handleBeforeInput( // composedChars, // editorState, // event.timeStamp, // ), // ) // ) { // return; // } var contentState = editorState.getCurrentContent(); mutations.forEach(function (composedChars, offsetKey) { var _DraftOffsetKey$decod = DraftOffsetKey.decode(offsetKey), blockKey = _DraftOffsetKey$decod.blockKey, decoratorKey = _DraftOffsetKey$decod.decoratorKey, leafKey = _DraftOffsetKey$decod.leafKey; var _editorState$getBlock = editorState.getBlockTree(blockKey).getIn([decoratorKey, 'leaves', leafKey]), start = _editorState$getBlock.start, end = _editorState$getBlock.end; var replacementRange = editorState.getSelection().merge({ anchorKey: blockKey, focusKey: blockKey, anchorOffset: start, focusOffset: end, isBackward: false }); var entityKey = getEntityKeyForSelection(contentState, replacementRange); var currentStyle = contentState.getBlockForKey(blockKey).getInlineStyleAt(start); contentState = DraftModifier.replaceText(contentState, replacementRange, composedChars, currentStyle, entityKey); // We need to update the editorState so the leaf node ranges are properly // updated and multiple mutations are correctly applied. editorState = EditorState.set(editorState, { currentContent: contentState }); }); // When we apply the text changes to the ContentState, the selection always // goes to the end of the field, but it should just stay where it is // after compositionEnd. var documentSelection = getDraftEditorSelection(editorState, getContentEditableContainer(editor)); var compositionEndSelectionState = documentSelection.selectionState; editor.restoreEditorDOM(); // See: // - https://github.com/facebook/draft-js/issues/2093 // - https://github.com/facebook/draft-js/pull/2094 // Apply this fix only in IE for now. We can test it in // other browsers in the future to ensure no regressions var editorStateWithUpdatedSelection = isIE ? EditorState.forceSelection(editorState, compositionEndSelectionState) : EditorState.acceptSelection(editorState, compositionEndSelectionState); editor.update(EditorState.push(editorStateWithUpdatedSelection, contentState, 'insert-characters')); } }; module.exports = DraftEditorCompositionHandler;