You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
425 lines
12 KiB
425 lines
12 KiB
10 years ago
|
/**
|
||
|
* 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;
|