问题
A css / javascript trigger menu doesnt close when someone click or touch outside.
You have to press the menu button to close it. I tried some jquery functions like:
$('#menucontainer').click(function(event) {
event.stopPropagation();
});
But this does not work. Here I made a simple jsfiddle with all related code:
https://jsfiddle.net/4sgf84jL/
I would appreciate some help. Thank you
回答1:
When you open the menu, you should listen for clicks on document. Then when the document is clicked you close the popup (and you remove the listener on the document as well).
PS: keep your listener on the menu-container as well ;)
Here is an example you can use (I edited your fiddle) :
(function(){
//Remember if the menu is opened or not
var menuOpened = false;
var menuElement = document.getElementById('menu_control');
var menuContainer = document.getElementById('menu-standard');
// Add click listener on menu icon
menuElement.addEventListener('click', onMenu_click);
// Add click listener on menu
menuContainer.addEventListener('click', onMenuContainer_click);
function toggleMenu(){
menuOpened = !menuOpened;
if (menuOpened){
menuContainer.className += ' show_menu';
document.addEventListener('click', onDoc_click);
}
else{
menuContainer.className = menuContainer.className.replace('show_menu', '').trim();
document.removeEventListener('click', onDoc_click);
}
}
function onMenu_click(domEvent){
domEvent.stopPropagation();
toggleMenu();
}
function onDoc_click(domEvent){
domEvent.stopPropagation();
toggleMenu();
}
function onMenuContainer_click(domEvent){
domEvent.stopPropagation();
}
})();
.nav,
.menu_control{font-size:16px;line-height:23px;}
.nav{display:none;position:relative;width:219px;height:0;top:7px;list-style:none;z-index:9;background-color:#666;color:#fff}
.nav .sub-menu{list-style:none;padding-left:14px;}
.nav .sub-menu li{width:192px;background-color:#666;}
.nav .sub-menu .current-menu-item > a{background-color:#666;}
.nav a,
.show_menu{display:block;}
.nav a{color:#fff;padding:7px 14px;}
.nav a:hover{color:white;background-color:#999;}
.nav .current-menu-item > a{color:#fff;background-color:#666;cursor:text;}
.nav li{background-color:#666;}
.menu_control{display:block;color:#111111;cursor:pointer;margin:7px -27px 0 -27px;padding-right:27px;padding-left:27px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
.navicon-line{width:32px;height:4px;border-radius:1px;margin-bottom:5px;background-color:#333;}
<span id="menu_control" class="menu_control">
<div class="navicon-line"></div>
<div class="navicon-line"></div>
<div class="navicon-line"></div>
</span>
<ul id="menu-standard" class="nav">
<li id="menu-item"><a href="/">Home</a></li>
<li id="menu-item"><a href="#">test</a>
<ul class="sub-menu">
<li id="menu-item"><a href="#">test</a></li>
<li id="menu-item"><a href="#">test</a></li>
<li id="menu-item"><a href="#">test</a></li>
<li id="menu-item"><a href="#">test</a></li>
</ul>
</li>
<li id="menu-item"><a href="#">test</a></li>
</ul>
<br />
Content Content Content
It's not the best way to do it because you add several click listeners... You could have just one listener on the doc and do different things depending on the target of the event...
回答2:
Thanks to finding-closest-element-without-jquery my solution is based on:
- window.onload: try to insert always your code in such handler to be sure all the elements are already loaded and so ready for your code
- to test if an element has a class use
menu.classList.contains('show_menu')
- to add/remove classes use
menu.classList.remove('show_menu');
ormenu.classList.add('show_menu');
- add a listener for the whole document so that if you clicked ouside your menu you can remove the corresponding show_menu if added
My snippet:
function closest(el, selector) {
var matchesFn;
// find vendor prefix
['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
if (typeof document.body[fn] == 'function') {
matchesFn = fn;
return true;
}
return false;
})
var parent;
// traverse parents
while (el) {
parent = el.parentElement;
if (parent && parent[matchesFn](selector)) {
return parent;
}
el = parent;
}
return null;
}
window.onload = function() {
(function(){
document.addEventListener('click', function(e) {
if (e.target.className.indexOf('menu_control') == -1 &&
e.target.className.indexOf('navicon-line') == -1 &&
closest(e.target, '#menu-standard.nav') == null) {
// menu-standard
document.getElementById('menu-standard').classList.remove('show_menu');
}
}, false);
var classes = document.getElementsByClassName('menu_control');
for (i = 0; i < classes.length; i++) {
classes[i].onclick = function() {
var menu = this.nextElementSibling;
if (menu.classList.contains('show_menu'))
menu.classList.remove('show_menu');
else
menu.classList.add('show_menu');
};
}
})();
}
.nav,
.menu_control{font-size:16px;line-height:23px;}
.nav{display:none;position:relative;width:219px;height:0;top:7px;list-style:none;z-index:9;background-color:#666;color:#fff}
.nav .sub-menu{list-style:none;padding-left:14px;}
.nav .sub-menu li{width:192px;background-color:#666;}
.nav .sub-menu .current-menu-item > a{background-color:#666;}
.nav a,
.show_menu{display:block;}
.nav a{color:#fff;padding:7px 14px;}
.nav a:hover{color:white;background-color:#999;}
.nav .current-menu-item > a{color:#fff;background-color:#666;cursor:text;}
.nav li{background-color:#666;}
.menu_control{display:block;color:#111111;cursor:pointer;margin:7px -27px 0 -27px;padding-right:27px;padding-left:27px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
.navicon-line{width:32px;height:4px;border-radius:1px;margin-bottom:5px;background-color:#333;}
<span class="menu_control">
<div class="navicon-line"></div>
<div class="navicon-line"></div>
<div class="navicon-line"></div>
</span>
<ul id="menu-standard" class="nav">
<li id="menu-item"><a href="/">Home</a></li>
<li id="menu-item"><a href="#">test</a>
<ul class="sub-menu">
<li id="menu-item"><a href="#">test</a></li>
<li id="menu-item"><a href="#">test</a></li>
<li id="menu-item"><a href="#">test</a></li>
<li id="menu-item"><a href="#">test</a></li>
</ul>
</li>
<li id="menu-item"><a href="#">test</a></li>
</ul>
<br />
Content Content Content
来源:https://stackoverflow.com/questions/38358950/close-menu-when-click-touch-outside-javascript