/** * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SimpleEventPlugin */ 'use strict'; var EventConstants = require("./EventConstants"); var EventPluginUtils = require("./EventPluginUtils"); var EventPropagators = require("./EventPropagators"); var SyntheticClipboardEvent = require("./SyntheticClipboardEvent"); var SyntheticEvent = require("./SyntheticEvent"); var SyntheticFocusEvent = require("./SyntheticFocusEvent"); var SyntheticKeyboardEvent = require("./SyntheticKeyboardEvent"); var SyntheticMouseEvent = require("./SyntheticMouseEvent"); var SyntheticDragEvent = require("./SyntheticDragEvent"); var SyntheticTouchEvent = require("./SyntheticTouchEvent"); var SyntheticUIEvent = require("./SyntheticUIEvent"); var SyntheticWheelEvent = require("./SyntheticWheelEvent"); var getEventCharCode = require("./getEventCharCode"); var invariant = require("./invariant"); var keyOf = require("./keyOf"); var warning = require("./warning"); var topLevelTypes = EventConstants.topLevelTypes; var eventTypes = { blur: { phasedRegistrationNames: { bubbled: keyOf({onBlur: true}), captured: keyOf({onBlurCapture: true}) } }, click: { phasedRegistrationNames: { bubbled: keyOf({onClick: true}), captured: keyOf({onClickCapture: true}) } }, contextMenu: { phasedRegistrationNames: { bubbled: keyOf({onContextMenu: true}), captured: keyOf({onContextMenuCapture: 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}), captured: keyOf({onDoubleClickCapture: true}) } }, drag: { phasedRegistrationNames: { bubbled: keyOf({onDrag: true}), captured: keyOf({onDragCapture: true}) } }, dragEnd: { phasedRegistrationNames: { bubbled: keyOf({onDragEnd: true}), captured: keyOf({onDragEndCapture: true}) } }, dragEnter: { phasedRegistrationNames: { bubbled: keyOf({onDragEnter: true}), captured: keyOf({onDragEnterCapture: true}) } }, dragExit: { phasedRegistrationNames: { bubbled: keyOf({onDragExit: true}), captured: keyOf({onDragExitCapture: true}) } }, dragLeave: { phasedRegistrationNames: { bubbled: keyOf({onDragLeave: true}), captured: keyOf({onDragLeaveCapture: true}) } }, dragOver: { phasedRegistrationNames: { bubbled: keyOf({onDragOver: true}), captured: keyOf({onDragOverCapture: true}) } }, dragStart: { phasedRegistrationNames: { bubbled: keyOf({onDragStart: true}), captured: keyOf({onDragStartCapture: true}) } }, drop: { phasedRegistrationNames: { bubbled: keyOf({onDrop: true}), captured: keyOf({onDropCapture: true}) } }, focus: { phasedRegistrationNames: { bubbled: keyOf({onFocus: true}), captured: keyOf({onFocusCapture: true}) } }, input: { phasedRegistrationNames: { bubbled: keyOf({onInput: true}), captured: keyOf({onInputCapture: true}) } }, keyDown: { phasedRegistrationNames: { bubbled: keyOf({onKeyDown: true}), captured: keyOf({onKeyDownCapture: true}) } }, keyPress: { phasedRegistrationNames: { bubbled: keyOf({onKeyPress: true}), captured: keyOf({onKeyPressCapture: true}) } }, keyUp: { phasedRegistrationNames: { bubbled: keyOf({onKeyUp: true}), captured: keyOf({onKeyUpCapture: true}) } }, load: { phasedRegistrationNames: { bubbled: keyOf({onLoad: true}), captured: keyOf({onLoadCapture: true}) } }, error: { phasedRegistrationNames: { bubbled: keyOf({onError: true}), captured: keyOf({onErrorCapture: true}) } }, // Note: We do not allow listening to mouseOver events. Instead, use the // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`. mouseDown: { phasedRegistrationNames: { bubbled: keyOf({onMouseDown: true}), captured: keyOf({onMouseDownCapture: true}) } }, mouseMove: { phasedRegistrationNames: { bubbled: keyOf({onMouseMove: true}), captured: keyOf({onMouseMoveCapture: true}) } }, mouseOut: { phasedRegistrationNames: { bubbled: keyOf({onMouseOut: true}), captured: keyOf({onMouseOutCapture: true}) } }, mouseOver: { phasedRegistrationNames: { bubbled: keyOf({onMouseOver: true}), captured: keyOf({onMouseOverCapture: true}) } }, mouseUp: { phasedRegistrationNames: { bubbled: keyOf({onMouseUp: true}), captured: keyOf({onMouseUpCapture: true}) } }, paste: { phasedRegistrationNames: { bubbled: keyOf({onPaste: true}), captured: keyOf({onPasteCapture: true}) } }, reset: { phasedRegistrationNames: { bubbled: keyOf({onReset: true}), captured: keyOf({onResetCapture: true}) } }, scroll: { phasedRegistrationNames: { bubbled: keyOf({onScroll: true}), captured: keyOf({onScrollCapture: true}) } }, submit: { phasedRegistrationNames: { bubbled: keyOf({onSubmit: true}), captured: keyOf({onSubmitCapture: true}) } }, touchCancel: { phasedRegistrationNames: { bubbled: keyOf({onTouchCancel: true}), captured: keyOf({onTouchCancelCapture: true}) } }, touchEnd: { phasedRegistrationNames: { bubbled: keyOf({onTouchEnd: true}), captured: keyOf({onTouchEndCapture: true}) } }, touchMove: { phasedRegistrationNames: { bubbled: keyOf({onTouchMove: true}), captured: keyOf({onTouchMoveCapture: true}) } }, touchStart: { phasedRegistrationNames: { bubbled: keyOf({onTouchStart: true}), captured: keyOf({onTouchStartCapture: true}) } }, wheel: { phasedRegistrationNames: { bubbled: keyOf({onWheel: true}), captured: keyOf({onWheelCapture: true}) } } }; var topLevelEventsToDispatchConfig = { topBlur: eventTypes.blur, topClick: eventTypes.click, topContextMenu: eventTypes.contextMenu, topCopy: eventTypes.copy, topCut: eventTypes.cut, topDoubleClick: eventTypes.doubleClick, topDrag: eventTypes.drag, topDragEnd: eventTypes.dragEnd, topDragEnter: eventTypes.dragEnter, topDragExit: eventTypes.dragExit, topDragLeave: eventTypes.dragLeave, topDragOver: eventTypes.dragOver, topDragStart: eventTypes.dragStart, topDrop: eventTypes.drop, topError: eventTypes.error, topFocus: eventTypes.focus, topInput: eventTypes.input, topKeyDown: eventTypes.keyDown, topKeyPress: eventTypes.keyPress, topKeyUp: eventTypes.keyUp, topLoad: eventTypes.load, topMouseDown: eventTypes.mouseDown, topMouseMove: eventTypes.mouseMove, topMouseOut: eventTypes.mouseOut, topMouseOver: eventTypes.mouseOver, topMouseUp: eventTypes.mouseUp, topPaste: eventTypes.paste, topReset: eventTypes.reset, topScroll: eventTypes.scroll, topSubmit: eventTypes.submit, topTouchCancel: eventTypes.touchCancel, topTouchEnd: eventTypes.touchEnd, topTouchMove: eventTypes.touchMove, topTouchStart: eventTypes.touchStart, topWheel: eventTypes.wheel }; for (var type in topLevelEventsToDispatchConfig) { topLevelEventsToDispatchConfig[type].dependencies = [type]; } var SimpleEventPlugin = { eventTypes: eventTypes, /** * Same as the default implementation, except cancels the event when return * value is false. This behavior will be disabled in a future release. * * @param {object} Event to be dispatched. * @param {function} Application-level callback. * @param {string} domID DOM ID to pass to the callback. */ executeDispatch: function(event, listener, domID) { var returnValue = EventPluginUtils.executeDispatch(event, listener, domID); ("production" !== process.env.NODE_ENV ? warning( typeof returnValue !== 'boolean', 'Returning `false` from an event handler is deprecated and will be ' + 'ignored in a future release. Instead, manually call ' + 'e.stopPropagation() or e.preventDefault(), as appropriate.' ) : null); if (returnValue === false) { event.stopPropagation(); event.preventDefault(); } }, /** * @param {string} topLevelType Record from `EventConstants`. * @param {DOMEventTarget} topLevelTarget The listening component root node. * @param {string} topLevelTargetID ID of `topLevelTarget`. * @param {object} nativeEvent Native browser event. * @return {*} An accumulation of synthetic events. * @see {EventPluginHub.extractEvents} */ extractEvents: function( topLevelType, topLevelTarget, topLevelTargetID, nativeEvent) { var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType]; if (!dispatchConfig) { return null; } var EventConstructor; switch (topLevelType) { case topLevelTypes.topInput: case topLevelTypes.topLoad: case topLevelTypes.topError: case topLevelTypes.topReset: case topLevelTypes.topSubmit: // HTML Events // @see http://www.w3.org/TR/html5/index.html#events-0 EventConstructor = SyntheticEvent; break; case topLevelTypes.topKeyPress: // FireFox creates a keypress event for function keys too. This removes // the unwanted keypress events. Enter is however both printable and // non-printable. One would expect Tab to be as well (but it isn't). if (getEventCharCode(nativeEvent) === 0) { return null; } /* falls through */ case topLevelTypes.topKeyDown: case topLevelTypes.topKeyUp: EventConstructor = SyntheticKeyboardEvent; break; case topLevelTypes.topBlur: case topLevelTypes.topFocus: EventConstructor = SyntheticFocusEvent; break; case topLevelTypes.topClick: // Firefox creates a click event on right mouse clicks. This removes the // unwanted click events. if (nativeEvent.button === 2) { return null; } /* falls through */ case topLevelTypes.topContextMenu: case topLevelTypes.topDoubleClick: case topLevelTypes.topMouseDown: case topLevelTypes.topMouseMove: case topLevelTypes.topMouseOut: case topLevelTypes.topMouseOver: case topLevelTypes.topMouseUp: EventConstructor = SyntheticMouseEvent; break; case topLevelTypes.topDrag: case topLevelTypes.topDragEnd: case topLevelTypes.topDragEnter: case topLevelTypes.topDragExit: case topLevelTypes.topDragLeave: case topLevelTypes.topDragOver: case topLevelTypes.topDragStart: case topLevelTypes.topDrop: EventConstructor = SyntheticDragEvent; break; case topLevelTypes.topTouchCancel: case topLevelTypes.topTouchEnd: case topLevelTypes.topTouchMove: case topLevelTypes.topTouchStart: EventConstructor = SyntheticTouchEvent; break; case topLevelTypes.topScroll: EventConstructor = SyntheticUIEvent; break; case topLevelTypes.topWheel: EventConstructor = SyntheticWheelEvent; break; case topLevelTypes.topCopy: case topLevelTypes.topCut: case topLevelTypes.topPaste: EventConstructor = SyntheticClipboardEvent; break; } ("production" !== process.env.NODE_ENV ? invariant( EventConstructor, 'SimpleEventPlugin: Unhandled event type, `%s`.', topLevelType ) : invariant(EventConstructor)); var event = EventConstructor.getPooled( dispatchConfig, topLevelTargetID, nativeEvent ); EventPropagators.accumulateTwoPhaseDispatches(event); return event; } }; module.exports = SimpleEventPlugin;