toggle menu function does not work with data-Attributes

Asked

Viewed 82 times

2

I am trying to make a function that causes the buttons to change only the data-Attributes of the menu with corresponding value, however, no error is shown on the console, but also does not work:

function menu(){
      var doc = document.documentElement;
      var openMenus = document.querySelectorAll("button[data-menu=open]");
      var closeMenus = document.querySelectorAll("button[data-menu=close]");
      var menus = document.querySelectorAll("ul[data-collapse=collapse-menu]");
      function openMenu(i){
        if(openMenus[i].dataset.menuId == i){
          menus[i].dataset.menuActive = "active";
          document.documentElement.dataset.menuActive="active";
        }
      }
      function closeMenu(i){
        if(closeMenus[i].dataset.menuId == i){
          menus[i].dataset.menuActive = "";
          document.documentElement.dataset.menuActive="";
        }
      }
      for(var i = 0; i < menus.length; i++){
        openMenus[i].onclick = openMenu(i);
        closeMenus[i].onclick = closeMenu(i);
      }
    }
/*Default Styles*/
*{
    margin:0;
    padding:0;
    text-decoration:none;
    color:inherit;
    background-color:transparent;
    box-sizing:border-box;
}
.sr-only{
    position:absolute;
    width:1px;
    height:1px;
    padding:0;
    margin:-1px;
    overflow:hidden;
    clip:rect(0,0,0,0);
    border:0;
}
.container{
    display:flex;
    align-items:center;
    justify-content:space-between;
    width:100%;
    max-width:1480px;
    padding:8px 20px;
    margin:0 auto;
    position:relative;
}
nav{
    width:100%;
    display:flex;
    align-items:center;
}
.menu-button-holder{
    display:none;
}







/*Default Media Queries*/
/*Aqui viria uma media querie com min-width 1024px, removi para que pudessem testar na resolução do computador*/
    .menu-button-holder{
        display:inline-block;
    }
    ul[data-collapse="collapse-menu"]{
        position:absolute;
        min-height:100vh;
        top:0;
        left:-100%;
        padding:8px 0;
        background-color:#FFFFFF;
        width:90%;
        z-index:10;
        transition:all 1s ease-in-out;
    }
    html[data-menu-active="active"] ul[data-collapse="collapse-menu"][data-menu-active="active"]{
        left:0;
    }
    html[data-menu-active="active"]:before{
        content:"";
        position:absolute;
        top:0;
        left:0;
        right:0;
        bottom:0;
        background-color:rgba(0,0,0,.4);
        z-index:5;
        opacity:0;
    }
<!DOCTYPE html>
<html lang="en" data-menu-active="">
<head>
</head>
<body>
    <div>
        <!-- Navbar -->
        <nav>
            <div class="container">
                <div>
                    <img src="" alt="logo">
                </div>
                <div class="menu-button-holder">
                    <button data-menu="open" data-menu-id="0"><span class="sr-only">Abrir menu</span><svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="#000000" d="M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z" /></svg></button>
                </div>
                <ul data-collapse="collapse-menu" data-menu-id="0" data-menu-active="">
                    <div class="menu-button-holder">
                        <button data-menu="close" data-menu-id="0"><span class="sr-only">Fechar menu</span><svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="#000000" d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" /></svg></button>
                    </div>
                    <li><a href="">Início</a></li>
                    <li><a href="">Serviços</a></li>
                    <li><a href="">Contato</a></li>
                </ul>
            </div>
        </nav>
        <!-- Main Content -->
        <div></div>
        <!-- Footer -->
        <div></div>
    </div>
</body>
</html>

I also tried using setAttribute functions.

What’s wrong? Why does it happen, and how can I fix it ?

  • Why are you wearing the document.documentElement?

  • to add a data-attribute to the <html>

  • And why not document.body?

  • 1

    You can mount an example here or jsFiddle with the code, to see the live problem?

  • because I don’t want to access the body, but the html

  • I made the change :D

Show 1 more comment

1 answer

1


Well, after some time dedicated to solving this problem, I came up with a solution to my problem. In this case, by printing i at certain points of the main function, it returned either a number, or an element according to the position of the element. corrected the code using the following:

function menu(){
    //Declaração de variáveis
    var doc = document.documentElement;
    var openMenus = document.querySelectorAll("button[data-menu=open]");
    var closeMenus = document.querySelectorAll("button[data-menu=close]");
    var menus = document.querySelectorAll("ul[data-collapse=collapse-menu]");
    //Varrer o array de menus coletando suas id's e usando para as funções dos botões
    for(var i = 0; i < menus.length; i++){
        //Declaração da variável id para selecionar os menus corretamente
        openMenus[i].onclick = function(){
            var id = parseFloat(this.dataset.menuId)
            doc.setAttribute("data-menu-active", "active");
            menus[id].setAttribute("data-menu-active", "active");
            setTimeout(function(){
                doc.setAttribute("data-opacity", "1"); 
            },50);
        };
        closeMenus[i].onclick = function(){
            var id = parseFloat(this.dataset.menuId)
            doc.setAttribute("data-opacity", "0");
            menus[id].setAttribute("data-menu-active", "");
            setTimeout(function(){
                doc.setAttribute("data-menu-active", "");
            },600);
        };
    };
    //Fechar qualquer/todos os menus ao clicar no document-overlay
    doc.addEventListener("click", function(event){
        //document.documentElement apenas, filhos não são selecionados pela condição
        if(event.target === document.documentElement){
            var menusAtivos = document.querySelectorAll("ul[data-menu-active=active]");
            for(var i = 0; i < menusAtivos.length; i++){
                menusAtivos[i].setAttribute("data-menu-active", "");    
            };
            doc.setAttribute("data-opacity", "0");
            setTimeout(function(){
                doc.setAttribute("data-menu-active", "");
            },600);
        };
    });
}menu();
  • Why use i - 1? - Because the value returned by i always starts with 1, not 0, so we wouldn’t be able to use the first element of an array, and also by changing the entire order of the menus;
  • Added the function to close any and all menus opened by clicking on the side layer of the menu (::before of documentElement); This function can be used with any number of menus.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.