简体   繁体   中英

How to hide a dropdown menu in html/javascript

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?

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');

event.target returns the element, if you want to retrieve the elements class name use .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'

UPDATE building on @charlietfl's comment add this function to check for ancestor class and use if(checkClass (event.tagent, 'dropbtn') === false) instead

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

//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):

//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') );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM