From 5388d70bb12cb93885f23d695f476cc2e1971b18 Mon Sep 17 00:00:00 2001 From: Isaac Salier-Hellendag Date: Mon, 9 Sep 2013 23:31:53 -0700 Subject: [PATCH] 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. --- src/core/ReactEventEmitter.js | 6 +++ src/event/EventConstants.js | 3 ++ .../synthetic/SyntheticClipboardEvent.js | 45 +++++++++++++++++++ src/eventPlugins/SimpleEventPlugin.js | 27 +++++++++++ 4 files changed, 81 insertions(+) create mode 100644 src/event/synthetic/SyntheticClipboardEvent.js diff --git a/src/core/ReactEventEmitter.js b/src/core/ReactEventEmitter.js index 40fc7fd20e..bad66ee2fd 100644 --- a/src/core/ReactEventEmitter.js +++ b/src/core/ReactEventEmitter.js @@ -301,6 +301,12 @@ var ReactEventEmitter = merge(ReactEventEmitterMixin, { trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt); trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt); } + + if (isEventSupported('copy')) { + trapBubbledEvent(topLevelTypes.topCopy, 'copy', mountAt); + trapBubbledEvent(topLevelTypes.topCut, 'cut', mountAt); + trapBubbledEvent(topLevelTypes.topPaste, 'paste', mountAt); + } }, registrationNames: EventPluginHub.registrationNames, diff --git a/src/event/EventConstants.js b/src/event/EventConstants.js index a3bedfa4e2..e150d6879e 100644 --- a/src/event/EventConstants.js +++ b/src/event/EventConstants.js @@ -29,6 +29,8 @@ var topLevelTypes = keyMirror({ topBlur: null, topChange: null, topClick: null, + topCopy: null, + topCut: null, topDOMCharacterDataModified: null, topDoubleClick: null, topDrag: null, @@ -49,6 +51,7 @@ var topLevelTypes = keyMirror({ topMouseOut: null, topMouseOver: null, topMouseUp: null, + topPaste: null, topScroll: null, topSelectionChange: null, topSubmit: null, diff --git a/src/event/synthetic/SyntheticClipboardEvent.js b/src/event/synthetic/SyntheticClipboardEvent.js new file mode 100644 index 0000000000..1f86b9e662 --- /dev/null +++ b/src/event/synthetic/SyntheticClipboardEvent.js @@ -0,0 +1,45 @@ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule SyntheticClipboardEvent + * @typechecks static-only + */ + +"use strict"; + +var SyntheticEvent = require('SyntheticEvent'); + +/** + * @interface Event + * @see http://www.w3.org/TR/clipboard-apis/ + */ +var ClipboardEventInterface = { + clipboardData: null +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticUIEvent} + */ +function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent) { + SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); +} + +SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface); + +module.exports = SyntheticClipboardEvent; + diff --git a/src/eventPlugins/SimpleEventPlugin.js b/src/eventPlugins/SimpleEventPlugin.js index b11de71145..ecde32a95f 100644 --- a/src/eventPlugins/SimpleEventPlugin.js +++ b/src/eventPlugins/SimpleEventPlugin.js @@ -20,6 +20,7 @@ var EventConstants = require('EventConstants'); var EventPropagators = require('EventPropagators'); +var SyntheticClipboardEvent = require('SyntheticClipboardEvent'); var SyntheticEvent = require('SyntheticEvent'); var SyntheticFocusEvent = require('SyntheticFocusEvent'); var SyntheticKeyboardEvent = require('SyntheticKeyboardEvent'); @@ -47,6 +48,18 @@ var eventTypes = { captured: keyOf({onClickCapture: true}) } }, + copy: { + phasedRegistrationNames: { + bubbled: keyOf({onCopy: true}), + captured: keyOf({onCopyCapture: true}) + } + }, + cut: { + phasedRegistrationNames: { + bubbled: keyOf({onCut: true}), + captured: keyOf({onCutCapture: true}) + } + }, doubleClick: { phasedRegistrationNames: { bubbled: keyOf({onDoubleClick: true}), @@ -157,6 +170,12 @@ var eventTypes = { captured: keyOf({onMouseUpCapture: true}) } }, + paste: { + phasedRegistrationNames: { + bubbled: keyOf({onPaste: true}), + captured: keyOf({onPasteCapture: true}) + } + }, scroll: { phasedRegistrationNames: { bubbled: keyOf({onScroll: true}), @@ -204,6 +223,8 @@ var eventTypes = { var topLevelEventsToDispatchConfig = { topBlur: eventTypes.blur, topClick: eventTypes.click, + topCopy: eventTypes.copy, + topCut: eventTypes.cut, topDoubleClick: eventTypes.doubleClick, topDOMCharacterDataModified: eventTypes.DOMCharacterDataModified, topDrag: eventTypes.drag, @@ -222,6 +243,7 @@ var topLevelEventsToDispatchConfig = { topMouseDown: eventTypes.mouseDown, topMouseMove: eventTypes.mouseMove, topMouseUp: eventTypes.mouseUp, + topPaste: eventTypes.paste, topScroll: eventTypes.scroll, topSubmit: eventTypes.submit, topTouchCancel: eventTypes.touchCancel, @@ -315,6 +337,11 @@ var SimpleEventPlugin = { case topLevelTypes.topWheel: EventConstructor = SyntheticWheelEvent; break; + case topLevelTypes.topCopy: + case topLevelTypes.topCut: + case topLevelTypes.topPaste: + EventConstructor = SyntheticClipboardEvent; + break; } invariant( EventConstructor,