From a1ea85cd42ca7b592950cf94d352ded10c0ea15b Mon Sep 17 00:00:00 2001 From: "leon.shi" Date: Mon, 25 Apr 2016 17:15:56 +0800 Subject: [PATCH 1/2] support `onMouseEnter/onMouseLeave` for MenuItem and SubMenu ant-design/ant-design#1445 --- src/MenuItem.jsx | 39 ++++++++++++++++++++++--------- src/SubMenu.jsx | 61 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/src/MenuItem.jsx b/src/MenuItem.jsx index 5dee9f44..2ae00c75 100644 --- a/src/MenuItem.jsx +++ b/src/MenuItem.jsx @@ -1,6 +1,7 @@ import React from 'react'; import {KeyCode} from 'rc-util'; import classnames from 'classnames'; +import {noop} from './util'; const MenuItem = React.createClass({ propTypes: { @@ -16,14 +17,15 @@ const MenuItem = React.createClass({ parentMenu: React.PropTypes.object, onItemHover: React.PropTypes.func, onDestroy: React.PropTypes.func, + onMouseEnter: React.PropTypes.func, + onMouseLeave: React.PropTypes.func, }, getDefaultProps() { return { - onSelect() { - }, - onMouseEnter() { - }, + onSelect: noop, + onMouseEnter: noop, + onMouseLeave: noop, }; }, @@ -42,12 +44,13 @@ const MenuItem = React.createClass({ } }, - onMouseLeave() { - const eventKey = this.props.eventKey; - const parentMenu = this.props.parentMenu; + onMouseLeave(e) { + const props = this.props; + const eventKey = props.eventKey; + const parentMenu = props.parentMenu; parentMenu.menuItemMouseLeaveTimer = setTimeout(()=> { - if (this.isMounted() && this.props.active) { - this.props.onItemHover({ + if (this.isMounted() && props.active) { + props.onItemHover({ key: eventKey, item: this, hover: false, @@ -55,11 +58,19 @@ const MenuItem = React.createClass({ }); } }, 30); + if (props.mode === 'inline') { + if (props.onMouseLeave) { + props.onMouseLeave({ + key: eventKey, + domEvent: e, + }); + } + } }, - onMouseEnter() { + onMouseEnter(e) { const props = this.props; - const parentMenu = this.props.parentMenu; + const parentMenu = props.parentMenu; if (parentMenu.menuItemMouseLeaveTimer) { clearTimeout(parentMenu.menuItemMouseLeaveTimer); parentMenu.menuItemMouseLeaveTimer = null; @@ -71,6 +82,12 @@ const MenuItem = React.createClass({ hover: true, trigger: 'mouseenter', }); + if (props.onMouseEnter) { + props.onMouseEnter({ + key: eventKey, + domEvent: e, + }); + } }, onClick(e) { diff --git a/src/SubMenu.jsx b/src/SubMenu.jsx index de9847f4..8c2c92ab 100644 --- a/src/SubMenu.jsx +++ b/src/SubMenu.jsx @@ -3,6 +3,7 @@ import React from 'react'; import {KeyCode, guid} from 'rc-util'; import classnames from 'classnames'; import assign from 'object-assign'; +import {noop} from './util'; const SubMenu = React.createClass({ propTypes: { @@ -21,14 +22,16 @@ const SubMenu = React.createClass({ onDeselect: React.PropTypes.func, onDestroy: React.PropTypes.func, onItemHover: React.PropTypes.func, + onMouseEnter: React.PropTypes.func, + onMouseLeave: React.PropTypes.func, }, mixins: [require('./SubMenuStateMixin')], getDefaultProps() { return { - onMouseEnter() { - }, + onMouseEnter: noop, + onMouseLeave: noop, title: '', }; }, @@ -93,11 +96,21 @@ const SubMenu = React.createClass({ } }, - onSubTreeMouseEnter() { + onSubTreeMouseEnter(e) { if (this.leaveTimer) { clearTimeout(this.leaveTimer); this.leaveTimer = null; } + const props = this.props; + const eventKey = props.eventKey; + if (props.onMouseEnter) { + if (props.mode === 'inline') { + props.onMouseEnter({ + key: eventKey, + domEvent: e, + }); + } + } }, onOpenChange(e) { @@ -129,22 +142,36 @@ const SubMenu = React.createClass({ }); }, - onMouseLeave() { + onMouseLeave(e) { // prevent popup menu and submenu gap this.leaveTimer = setTimeout(()=> { - // leave whole sub tree - // still active - if (this.isMounted() && this.props.active) { - this.props.onItemHover({ - key: this.props.eventKey, - item: this, - hover: false, - trigger: 'mouseleave', - }); - } - if (this.isMounted() && this.props.open) { - if (this.props.closeSubMenuOnMouseLeave) { - this.triggerOpenChange(false); + const props = this.props; + const eventKey = props.eventKey; + if (this.isMounted()) { + // leave whole sub tree + // still active + if (props.active) { + props.onItemHover({ + key: eventKey, + item: this, + hover: false, + trigger: 'mouseleave', + }); + } + if (props.open) { + if (props.closeSubMenuOnMouseLeave) { + this.triggerOpenChange(false); + } + } + // trigger mouseleave + // when leaving whole sub tree on `inline` mode + if (props.mode === 'inline') { + if (props.onMouseLeave) { + props.onMouseLeave({ + key: eventKey, + domEvent: e, + }); + } } } }, 100); From 2b173f8f74c1561ad16dc634d24b07b642c1b835 Mon Sep 17 00:00:00 2001 From: Leon Shi Date: Mon, 25 Apr 2016 20:34:10 +0800 Subject: [PATCH 2/2] do not check props onMouseEnter/onMouseLeave --- src/MenuItem.jsx | 14 +++++++------- src/SubMenu.jsx | 22 +++++++++------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/MenuItem.jsx b/src/MenuItem.jsx index 2ae00c75..0350ab26 100644 --- a/src/MenuItem.jsx +++ b/src/MenuItem.jsx @@ -58,13 +58,12 @@ const MenuItem = React.createClass({ }); } }, 30); + // triggered only on `inline` mode if (props.mode === 'inline') { - if (props.onMouseLeave) { - props.onMouseLeave({ - key: eventKey, - domEvent: e, - }); - } + props.onMouseLeave({ + key: eventKey, + domEvent: e, + }); } }, @@ -82,7 +81,8 @@ const MenuItem = React.createClass({ hover: true, trigger: 'mouseenter', }); - if (props.onMouseEnter) { + // triggered only on `inline` mode + if (props.mode === 'inline') { props.onMouseEnter({ key: eventKey, domEvent: e, diff --git a/src/SubMenu.jsx b/src/SubMenu.jsx index 8c2c92ab..c64ded20 100644 --- a/src/SubMenu.jsx +++ b/src/SubMenu.jsx @@ -103,13 +103,11 @@ const SubMenu = React.createClass({ } const props = this.props; const eventKey = props.eventKey; - if (props.onMouseEnter) { - if (props.mode === 'inline') { - props.onMouseEnter({ - key: eventKey, - domEvent: e, - }); - } + if (props.mode === 'inline') { + props.onMouseEnter({ + key: eventKey, + domEvent: e, + }); } }, @@ -166,12 +164,10 @@ const SubMenu = React.createClass({ // trigger mouseleave // when leaving whole sub tree on `inline` mode if (props.mode === 'inline') { - if (props.onMouseLeave) { - props.onMouseLeave({ - key: eventKey, - domEvent: e, - }); - } + props.onMouseLeave({ + key: eventKey, + domEvent: e, + }); } } }, 100);