@samitouri / QOS-React-2 / commits / 5388d70bb1

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,