/** * Copyright 2013-present, 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. * */ 'use strict'; var EventPropagators = require('./EventPropagators'); var ReactDOMComponentTree = require('./ReactDOMComponentTree'); var SyntheticMouseEvent = require('./SyntheticMouseEvent'); var eventTypes = { mouseEnter: { registrationName: 'onMouseEnter', dependencies: ['topMouseOut', 'topMouseOver'] }, mouseLeave: { registrationName: 'onMouseLeave', dependencies: ['topMouseOut', 'topMouseOver'] } }; var EnterLeaveEventPlugin = { eventTypes: eventTypes, /** * For almost every interaction we care about, there will be both a top-level * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that * we do not extract duplicate events. However, moving the mouse into the * browser from outside will not fire a `mouseout` event. In this case, we use * the `mouseover` top-level event. */ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { if (topLevelType === 'topMouseOver' && (nativeEvent.relatedTarget || nativeEvent.fromElement)) { return null; } if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') { // Must not be a mouse in or mouse out - ignoring. return null; } var win; if (nativeEventTarget.window === nativeEventTarget) { // `nativeEventTarget` is probably a window object. win = nativeEventTarget; } else { // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. var doc = nativeEventTarget.ownerDocument; if (doc) { win = doc.defaultView || doc.parentWindow; } else { win = window; } } var from; var to; if (topLevelType === 'topMouseOut') { from = targetInst; var related = nativeEvent.relatedTarget || nativeEvent.toElement; to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null; } else { // Moving to a node from outside the window. from = null; to = targetInst; } if (from === to) { // Nothing pertains to our managed components. return null; } var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from); var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to); var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget); leave.type = 'mouseleave'; leave.target = fromNode; leave.relatedTarget = toNode; var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget); enter.type = 'mouseenter'; enter.target = toNode; enter.relatedTarget = fromNode; EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to); return [leave, enter]; } }; module.exports = EnterLeaveEventPlugin;