I am new to Javascript and trying to create a dropdown menu that hides when a user clicks on another spot on the screen. My code is shown below, why doesn't it work?
我是Javascript的新手并尝试创建一个下拉菜单,当用户点击屏幕上的其他位置时,该菜单会隐藏。我的代码如下所示,为什么它不起作用?
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
2 个解决方案
#1
0
event.target
returns the element, if you want to retrieve the elements class name use .className
, event.target.className
event.target返回元素,如果要检索元素类名,请使用.className,event.target.className
https://developer.mozilla.org/en-US/docs/Web/API/Event/target
replace !event.target.matches('.dropbtn')
with event.target.className!= 'dropbtn'
with event.target.className!='dropbtn'
UPDATE building on @charlietfl's comment add this function to check for ancestor class and use if(checkClass (event.tagent, 'dropbtn') === false)
instead
建立在@ charlietfl的注释上的UPDATE添加此函数来检查祖先类并使用if(checkClass(event.tagent,'dropbtn')=== false)代替
function checkClass (el, cls) {
if(el.classList.contains(cls)) return true;
return typeof el.parentElement !== null ? checkClass (el.parentElement, cls) : false;
}
UPDATE: maybe look into using the blur event https://developer.mozilla.org/en-US/docs/Web/Events/blur
更新:也许考虑使用模糊事件https://developer.mozilla.org/en-US/docs/Web/Events/blur
#2
0
//first a mod of WalksAway's `checkClass()`
function checkClass(el, cls) {
return !!el && (el.classList.contains(cls) || checkClass(el.parentElement, cls));
}
//or with a loop:
function checkClass(el, cls) {
while(el){
if(el.classList.contains(cls)) return true;
el = el.parentElement;
}
return false;
}
and a modification of your code:
并修改您的代码:
//a handy little utility-function:
function $$(selector, context){
if(!context || !context.querySelectorAll) context = document;
return Array.from( context.querySelectorAll( selector ) );
}
window.onclick = function(event) {
if(!checkClass(event.target, '.dropbtn')){
$$('.dropdown-content.show').forEach(function(el){
el.classList.remove('show');
});
}
}
or let's go even a bit further (#ES6, #FP):
或者让我们走得更远(#ES6,#FP):
//more utils:
var traverseUp = el => {
for(var result = []; el; el = el.parentElement) result.push( el );
return result;
}
var hasClass = cls => el => el.classList.contains(cls);
var addClass = cls => el => el.classList.add(cls);
var removeClass = cls => el => el.classList.remove(cls);
window.onclick = function(event) {
if( !traverseUp(event.target).some( hasClass('.dropbtn') ) )
$$('.dropdown-content.show').forEach( removeClass('show') );
}
#1
0
event.target
returns the element, if you want to retrieve the elements class name use .className
, event.target.className
event.target返回元素,如果要检索元素类名,请使用.className,event.target.className
https://developer.mozilla.org/en-US/docs/Web/API/Event/target
replace !event.target.matches('.dropbtn')
with event.target.className!= 'dropbtn'
with event.target.className!='dropbtn'
UPDATE building on @charlietfl's comment add this function to check for ancestor class and use if(checkClass (event.tagent, 'dropbtn') === false)
instead
建立在@ charlietfl的注释上的UPDATE添加此函数来检查祖先类并使用if(checkClass(event.tagent,'dropbtn')=== false)代替
function checkClass (el, cls) {
if(el.classList.contains(cls)) return true;
return typeof el.parentElement !== null ? checkClass (el.parentElement, cls) : false;
}
UPDATE: maybe look into using the blur event https://developer.mozilla.org/en-US/docs/Web/Events/blur
更新:也许考虑使用模糊事件https://developer.mozilla.org/en-US/docs/Web/Events/blur
#2
0
//first a mod of WalksAway's `checkClass()`
function checkClass(el, cls) {
return !!el && (el.classList.contains(cls) || checkClass(el.parentElement, cls));
}
//or with a loop:
function checkClass(el, cls) {
while(el){
if(el.classList.contains(cls)) return true;
el = el.parentElement;
}
return false;
}
and a modification of your code:
并修改您的代码:
//a handy little utility-function:
function $$(selector, context){
if(!context || !context.querySelectorAll) context = document;
return Array.from( context.querySelectorAll( selector ) );
}
window.onclick = function(event) {
if(!checkClass(event.target, '.dropbtn')){
$$('.dropdown-content.show').forEach(function(el){
el.classList.remove('show');
});
}
}
or let's go even a bit further (#ES6, #FP):
或者让我们走得更远(#ES6,#FP):
//more utils:
var traverseUp = el => {
for(var result = []; el; el = el.parentElement) result.push( el );
return result;
}
var hasClass = cls => el => el.classList.contains(cls);
var addClass = cls => el => el.classList.add(cls);
var removeClass = cls => el => el.classList.remove(cls);
window.onclick = function(event) {
if( !traverseUp(event.target).some( hasClass('.dropbtn') ) )
$$('.dropdown-content.show').forEach( removeClass('show') );
}