Add cut, copy, paste
Add clipboard events to React. For forms, these shouldn't really be necessary -- the onChange event should handle deletions and insertions. For contenteditables, however, we need to be able to access clipboard data.
Isaac Salier-Hellendag committed
Sep 9, 2013 at 23:31 UTC
5388d70bb12cb93885f23d695f476cc2e1971b18
4 files changed
+81
src/core/ReactEventEmitter.js
+6
@@ -301,6 +301,12 @@ var ReactEventEmitter = merge(ReactEventEmitterMixin, {
301
trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt);
302
trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt);
303
}
304
+
305
+ if (isEventSupported('copy')) {
306
+ trapBubbledEvent(topLevelTypes.topCopy, 'copy', mountAt);
307
+ trapBubbledEvent(topLevelTypes.topCut, 'cut', mountAt);
308
+ trapBubbledEvent(topLevelTypes.topPaste, 'paste', mountAt);
309
+ }
310
},
311
312
registrationNames: EventPluginHub.registrationNames,
src/event/EventConstants.js
+3
@@ -29,6 +29,8 @@ var topLevelTypes = keyMirror({
29
topBlur: null,
30
topChange: null,
31
topClick: null,
32
+ topCopy: null,
33
+ topCut: null,
34
topDOMCharacterDataModified: null,
35
topDoubleClick: null,
36
topDrag: null,
@@ -49,6 +51,7 @@ var topLevelTypes = keyMirror({
51
topMouseOut: null,
52
topMouseOver: null,
53
topMouseUp: null,
54
+ topPaste: null,
55
topScroll: null,
56
topSelectionChange: null,
57
topSubmit: null,
src/event/synthetic/SyntheticClipboardEvent.js
new
+45
@@ -0,0 +1,45 @@
1
+/**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule SyntheticClipboardEvent
17
+ * @typechecks static-only
18
+ */
19
+
20
+"use strict";
21
+
22
+var SyntheticEvent = require('SyntheticEvent');
23
+
24
+/**
25
+ * @interface Event
26
+ * @see http://www.w3.org/TR/clipboard-apis/
27
+ */
28
+var ClipboardEventInterface = {
29
+ clipboardData: null
30
+};
31
+
32
+/**
33
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
34
+ * @param {string} dispatchMarker Marker identifying the event target.
35
+ * @param {object} nativeEvent Native browser event.
36
+ * @extends {SyntheticUIEvent}
37
+ */
38
+function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent) {
39
+ SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
40
+}
41
+
42
+SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);
43
+
44
+module.exports = SyntheticClipboardEvent;
45
+
src/eventPlugins/SimpleEventPlugin.js
+27
@@ -20,6 +20,7 @@
20
21
var EventConstants = require('EventConstants');
22
var EventPropagators = require('EventPropagators');
23
+var SyntheticClipboardEvent = require('SyntheticClipboardEvent');
24
var SyntheticEvent = require('SyntheticEvent');
25
var SyntheticFocusEvent = require('SyntheticFocusEvent');
26
var SyntheticKeyboardEvent = require('SyntheticKeyboardEvent');
@@ -47,6 +48,18 @@ var eventTypes = {
48
captured: keyOf({onClickCapture: true})
49
}
50
},
51
+ copy: {
52
+ phasedRegistrationNames: {
53
+ bubbled: keyOf({onCopy: true}),
54
+ captured: keyOf({onCopyCapture: true})
55
+ }
56
+ },
57
+ cut: {
58
+ phasedRegistrationNames: {
59
+ bubbled: keyOf({onCut: true}),
60
+ captured: keyOf({onCutCapture: true})
61
+ }
62
+ },
63
doubleClick: {
64
phasedRegistrationNames: {
65
bubbled: keyOf({onDoubleClick: true}),
@@ -157,6 +170,12 @@ var eventTypes = {
170
captured: keyOf({onMouseUpCapture: true})
171
}
172
},
173
+ paste: {
174
+ phasedRegistrationNames: {
175
+ bubbled: keyOf({onPaste: true}),
176
+ captured: keyOf({onPasteCapture: true})
177
+ }
178
+ },
179
scroll: {
180
phasedRegistrationNames: {
181
bubbled: keyOf({onScroll: true}),
@@ -204,6 +223,8 @@ var eventTypes = {
223
var topLevelEventsToDispatchConfig = {
224
topBlur: eventTypes.blur,
225
topClick: eventTypes.click,
226
+ topCopy: eventTypes.copy,
227
+ topCut: eventTypes.cut,
228
topDoubleClick: eventTypes.doubleClick,
229
topDOMCharacterDataModified: eventTypes.DOMCharacterDataModified,
230
topDrag: eventTypes.drag,
@@ -222,6 +243,7 @@ var topLevelEventsToDispatchConfig = {
243
topMouseDown: eventTypes.mouseDown,
244
topMouseMove: eventTypes.mouseMove,
245
topMouseUp: eventTypes.mouseUp,
246
+ topPaste: eventTypes.paste,
247
topScroll: eventTypes.scroll,
248
topSubmit: eventTypes.submit,
249
topTouchCancel: eventTypes.touchCancel,
@@ -315,6 +337,11 @@ var SimpleEventPlugin = {
337
case topLevelTypes.topWheel:
338
EventConstructor = SyntheticWheelEvent;
339
break;
340
+ case topLevelTypes.topCopy:
341
+ case topLevelTypes.topCut:
342
+ case topLevelTypes.topPaste:
343
+ EventConstructor = SyntheticClipboardEvent;
344
+ break;
345
}
346
invariant(
347
EventConstructor,