Skip to content

Commit 7dbb562

Browse files
committed
Fix bug: close menu when tap on black area on main menu
1 parent 4015b5f commit 7dbb562

File tree

5 files changed

+35
-42
lines changed

5 files changed

+35
-42
lines changed

src/shared/actions/topcoder_header.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { createActions } from 'redux-actions';
1717
function openMenu(menu, triggerNode, triggeredByTouch) {
1818
return ({
1919
menu,
20-
node: triggerNode.dataset.menu,
2120
trigger: _.toPlainObject(triggerNode.getBoundingClientRect()),
2221
isMobile: triggeredByTouch,
2322
});

src/shared/components/TopcoderHeader/desktop/SubMenu/Item/index.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ export default function Item({
1212
icon,
1313
link,
1414
title,
15+
closeMenu,
1516
}) {
1617
let styleName = 'item';
1718
if (currentSubMenuTitle === title) styleName += ' current';
1819
return (
19-
<li styleName={styleName}>
20+
<li styleName={styleName} onClick={closeMenu}>
2021
<a href={link}>
2122
{icon}
2223
{title}
@@ -30,4 +31,5 @@ Item.propTypes = {
3031
icon: PT.node.isRequired,
3132
link: PT.string.isRequired,
3233
title: PT.string.isRequired,
34+
closeMenu: PT.func.isRequired,
3335
};

src/shared/components/TopcoderHeader/desktop/SubMenu/index.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export default function SubMenu({
1818
items = menu.items.map(item => (
1919
<Item
2020
currentSubMenuTitle={currentSubMenuTitle}
21+
closeMenu={closeMenu}
2122
key={item.title}
2223
{...item}
2324
/>

src/shared/components/TopcoderHeader/index.jsx

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,6 @@ const MENU = [{
110110
}],
111111
}];
112112

113-
function getMenuNode(node) {
114-
if (!node || !node.dataset) {
115-
return null;
116-
}
117-
if (node.dataset.menu) {
118-
return node;
119-
}
120-
return getMenuNode(node.parentNode);
121-
}
122-
123113
export default class TopcoderHeader extends React.Component {
124114
constructor(props) {
125115
super(props);
@@ -128,7 +118,7 @@ export default class TopcoderHeader extends React.Component {
128118
this.addGlobalTouchListener = this.addGlobalTouchListener.bind(this);
129119
this.removeGlobalTouchListener = this.removeGlobalTouchListener.bind(this);
130120
this.closeSearch = this.closeSearch.bind(this);
131-
this.isChildNodeofHeader = this.isChildNodeofHeader.bind(this);
121+
this.getMenuButton = this.getMenuButton.bind(this);
132122

133123
this.listenerRegistered = false;
134124
}
@@ -139,27 +129,32 @@ export default class TopcoderHeader extends React.Component {
139129
this.removeGlobalTouchListener();
140130
}
141131

142-
globalTouchListener(event) {
132+
getMenuButton(node) {
133+
if (!node || !node.dataset || node === this.headerRoot) {
134+
return null;
135+
}
136+
if (node.dataset.menu) {
137+
return node;
138+
}
139+
return this.getMenuButton(node.parentNode);
140+
}
141+
142+
globalTouchListener({ target }) {
143143
const { closeMenu, searchOpened, openedMenu } = this.props;
144144
const closeSearch = this.closeSearch;
145-
const menuNode = getMenuNode(event.target);
145+
const menuButton = this.getMenuButton(target);
146146

147-
if (!this.isChildNodeofHeader(event.target)) {
148-
closeMenu();
147+
if (menuButton) {
148+
if (menuButton.dataset.menu === 'search' && openedMenu) {
149+
closeMenu();
150+
} else if (menuButton.dataset.menu !== 'search' && searchOpened) {
151+
closeSearch();
152+
}
153+
} else if (!this.headerRoot.contains(target) || this.mainMenu.contains(target)) {
149154
closeSearch();
150-
this.removeGlobalTouchListener();
151-
} else if (menuNode.dataset.menu === 'search' && openedMenu) {
152155
closeMenu();
153-
} else if (menuNode.dataset.menu !== 'search' && searchOpened) {
154-
closeSearch();
155-
}
156-
}
157-
158-
isChildNodeofHeader(node) {
159-
if (!node) {
160-
return false;
156+
this.removeGlobalTouchListener();
161157
}
162-
return node === this.rootNode || this.isChildNodeofHeader(node.parentNode);
163158
}
164159

165160
addGlobalTouchListener() {
@@ -181,7 +176,6 @@ export default class TopcoderHeader extends React.Component {
181176

182177
render() {
183178
const {
184-
activeNode,
185179
isMobile,
186180
activeTrigger,
187181
closeMenu,
@@ -215,12 +209,11 @@ export default class TopcoderHeader extends React.Component {
215209
1 + event.pageY < activeTrigger.bottom) closeMenu();
216210
}}
217211
onTouchStart={(event) => {
218-
if (openedMenu && isMobile &&
219-
getMenuNode(event.target).dataset.menu === activeNode) {
212+
if (isMobile && openedMenu && openedMenu.title === item.title) {
220213
closeMenu();
221214
this.removeGlobalTouchListener();
222215
} else {
223-
openMenu(item, getMenuNode(event.target), true);
216+
openMenu(item, this.getMenuButton(event.target), true);
224217
this.addGlobalTouchListener();
225218
}
226219
}}
@@ -279,11 +272,11 @@ export default class TopcoderHeader extends React.Component {
279272
1 + event.pageY < activeTrigger.bottom) closeMenu();
280273
}}
281274
onTouchStart={(event) => {
282-
if (openedMenu && isMobile && getMenuNode(event.target).dataset.menu === activeNode) {
275+
if (isMobile && openedMenu && openedMenu.title === userSubMenu.title) {
283276
closeMenu();
284277
this.removeGlobalTouchListener();
285278
} else {
286-
openMenu(userSubMenu, getMenuNode(event.target), true);
279+
openMenu(userSubMenu, this.getMenuButton(event.target), true);
287280
this.addGlobalTouchListener();
288281
}
289282
}}
@@ -314,22 +307,24 @@ export default class TopcoderHeader extends React.Component {
314307
<a
315308
className="tc-btn-sm tc-btn-primary"
316309
href={`${config.URL.AUTH}/member/registration`}
310+
onClick={closeMenu}
317311
>Join</a>
318312
<a
319313
className="tc-btn-sm tc-btn-default"
320314
href={`${config.URL.AUTH}/member`}
315+
onClick={closeMenu}
321316
>Log In</a>
322317
</div>
323318
);
324319
}
325320

326321
return (
327-
<div styleName="header" ref={(root) => { this.rootNode = root; }}>
322+
<div styleName="header" ref={(div) => { this.headerRoot = div; }}>
328323
<div styleName="main-desktop-header">
329324
<a href={BASE_URL} styleName="logo">
330325
<LogoTopcoderWithName height={53} width={135} />
331326
</a>
332-
<ul styleName="main-menu">
327+
<ul styleName="main-menu" ref={(ul) => { this.mainMenu = ul; }}>
333328
{mainMenu}
334329
</ul>
335330
<div styleName="right-menu">
@@ -344,11 +339,11 @@ export default class TopcoderHeader extends React.Component {
344339
1 + event.pageY < activeTrigger.bottom) closeSearch();
345340
}}
346341
onTouchStart={(event) => {
347-
if (searchOpened && isMobile) {
342+
if (isMobile && searchOpened) {
348343
closeSearch();
349344
this.removeGlobalTouchListener();
350345
} else {
351-
openSearch(getMenuNode(event.target), true);
346+
openSearch(this.getMenuButton(event.target), true);
352347
this.addGlobalTouchListener();
353348
}
354349
}}
@@ -407,12 +402,10 @@ TopcoderHeader.defaultProps = {
407402
openedMenu: null,
408403
profile: null,
409404
searchOpened: false,
410-
activeNode: null,
411405
isMobile: false,
412406
};
413407

414408
TopcoderHeader.propTypes = {
415-
activeNode: PT.string,
416409
isMobile: PT.bool,
417410
activeTrigger: PT.shape({
418411
bottom: PT.number.isRequired,

src/shared/reducers/topcoder_header.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ function create(initialState = {}) {
1919
return {
2020
...state,
2121
openedMenu: null,
22-
activeNode: null,
2322
};
2423
},
2524
[a.closeMobileMenu](state) {
@@ -38,7 +37,6 @@ function create(initialState = {}) {
3837
return {
3938
...state,
4039
openedMenu: action.payload.menu,
41-
activeNode: action.payload.node,
4240
isMobile: state.isMobile || action.payload.isMobile,
4341
activeTrigger: action.payload.trigger,
4442
};

0 commit comments

Comments
 (0)