UNPKG

4.75 kBJavaScriptView Raw
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 * @format
8 *
9 * @emails oncall+draft_js
10 */
11'use strict';
12
13var DataTransfer = require("fbjs/lib/DataTransfer");
14
15var DraftModifier = require("./DraftModifier");
16
17var EditorState = require("./EditorState");
18
19var findAncestorOffsetKey = require("./findAncestorOffsetKey");
20
21var getCorrectDocumentFromNode = require("./getCorrectDocumentFromNode");
22
23var getTextContentFromFiles = require("./getTextContentFromFiles");
24
25var getUpdatedSelectionState = require("./getUpdatedSelectionState");
26
27var getWindowForNode = require("./getWindowForNode");
28
29var isEventHandled = require("./isEventHandled");
30
31var nullthrows = require("fbjs/lib/nullthrows");
32/**
33 * Get a SelectionState for the supplied mouse event.
34 */
35
36
37function getSelectionForEvent(event, editorState) {
38 var node = null;
39 var offset = null;
40 var eventTargetDocument = getCorrectDocumentFromNode(event.currentTarget);
41 /* $FlowFixMe[prop-missing] (>=0.68.0 site=www,mobile) This comment
42 * suppresses an error found when Flow v0.68 was deployed. To see the error
43 * delete this comment and run Flow. */
44
45 if (typeof eventTargetDocument.caretRangeFromPoint === 'function') {
46 /* $FlowFixMe[incompatible-use] (>=0.68.0 site=www,mobile) This comment
47 * suppresses an error found when Flow v0.68 was deployed. To see the error
48 * delete this comment and run Flow. */
49 var dropRange = eventTargetDocument.caretRangeFromPoint(event.x, event.y);
50 node = dropRange.startContainer;
51 offset = dropRange.startOffset;
52 } else if (event.rangeParent) {
53 node = event.rangeParent;
54 offset = event.rangeOffset;
55 } else {
56 return null;
57 }
58
59 node = nullthrows(node);
60 offset = nullthrows(offset);
61 var offsetKey = nullthrows(findAncestorOffsetKey(node));
62 return getUpdatedSelectionState(editorState, offsetKey, offset, offsetKey, offset);
63}
64
65var DraftEditorDragHandler = {
66 /**
67 * Drag originating from input terminated.
68 */
69 onDragEnd: function onDragEnd(editor) {
70 editor.exitCurrentMode();
71 endDrag(editor);
72 },
73
74 /**
75 * Handle data being dropped.
76 */
77 onDrop: function onDrop(editor, e) {
78 var data = new DataTransfer(e.nativeEvent.dataTransfer);
79 var editorState = editor._latestEditorState;
80 var dropSelection = getSelectionForEvent(e.nativeEvent, editorState);
81 e.preventDefault();
82 editor._dragCount = 0;
83 editor.exitCurrentMode();
84
85 if (dropSelection == null) {
86 return;
87 }
88
89 var files = data.getFiles();
90
91 if (files.length > 0) {
92 if (editor.props.handleDroppedFiles && isEventHandled(editor.props.handleDroppedFiles(dropSelection, files))) {
93 return;
94 }
95 /* $FlowFixMe[incompatible-call] This comment suppresses an error found
96 * DataTransfer was typed. getFiles() returns an array of <Files extends
97 * Blob>, not Blob */
98
99
100 getTextContentFromFiles(files, function (fileText) {
101 fileText && editor.update(insertTextAtSelection(editorState, dropSelection, fileText));
102 });
103 return;
104 }
105
106 var dragType = editor._internalDrag ? 'internal' : 'external';
107
108 if (editor.props.handleDrop && isEventHandled(editor.props.handleDrop(dropSelection, data, dragType))) {// handled
109 } else if (editor._internalDrag) {
110 editor.update(moveText(editorState, dropSelection));
111 } else {
112 editor.update(insertTextAtSelection(editorState, dropSelection, data.getText()));
113 }
114
115 endDrag(editor);
116 }
117};
118
119function endDrag(editor) {
120 editor._internalDrag = false; // Fix issue #1383
121 // Prior to React v16.5.0 onDrop breaks onSelect event:
122 // https://github.com/facebook/react/issues/11379.
123 // Dispatching a mouseup event on DOM node will make it go back to normal.
124
125 var editorNode = editor.editorContainer;
126
127 if (editorNode) {
128 var mouseUpEvent = new MouseEvent('mouseup', {
129 view: getWindowForNode(editorNode),
130 bubbles: true,
131 cancelable: true
132 });
133 editorNode.dispatchEvent(mouseUpEvent);
134 }
135}
136
137function moveText(editorState, targetSelection) {
138 var newContentState = DraftModifier.moveText(editorState.getCurrentContent(), editorState.getSelection(), targetSelection);
139 return EditorState.push(editorState, newContentState, 'insert-fragment');
140}
141/**
142 * Insert text at a specified selection.
143 */
144
145
146function insertTextAtSelection(editorState, selection, text) {
147 var newContentState = DraftModifier.insertText(editorState.getCurrentContent(), selection, text, editorState.getCurrentInlineStyle());
148 return EditorState.push(editorState, newContentState, 'insert-fragment');
149}
150
151module.exports = DraftEditorDragHandler;
\No newline at end of file