Saturday 2 January 2021

sidebar multi level animated dropdown menu in vanilla js

Following this answer I try to make left sidebar multi level animated dropdown (toggle) menu in vanilla js (below example code)..

Note: I search it on google to find library something like but i did not find.. if anyone know please put link as a comment (only vanilla js library)...

Problem If you click on Dropdown 1 & Dropdown 2. you will see how it's work.. then click on Dropdown 1 > menu 1, menu 2, menu 3. you will see it's not working like Dropdown 1 & Dropdown 2. need to calculation height & add or remove height conditionally. many commented code are here in example code what i have tried before asking. so I need to fix it.

also if you can solve it others way in vanilla js it will be acceptable

const dataKeys = document.querySelectorAll('nav ul')
dataKeys.forEach(function(el,key){
    el.setAttribute('data-key',key);
})


const lists = document.querySelectorAll('ul ul')
lists.forEach(function(el){
    el.className = 'sub-menu';
    el.style.height =  0 + "px"; 
})
document.querySelectorAll("ul li").forEach(el => el.addEventListener('click', function(e){
    e.preventDefault();
    e.stopPropagation();
    // let el = e.target.parentElement.children[1]; 
    let el = e.target.parentElement.children[1]; 

    // console.log(el)
    let ul = e.target.parentElement.closest('ul');
    if(ul){
      ul.querySelectorAll('ul').forEach(function(item){
        item.style.height = 0 + 'px';
      })
    }
    if(parseInt(getComputedStyle(el).height) > 0){
      el.style.height = 0 + "px";
    }else{
      el.style.height =  el.scrollHeight + "px";
    }
     return false;
}));



  document.querySelectorAll("ul ul li").forEach(el => el.addEventListener('click', function(e){

    e.preventDefault();
    e.stopPropagation();
    
    let el = e.target.parentElement.children[1];

    let sh  = el.scrollHeight;
    let elKey = parseInt(el.getAttribute('data-key'));
    

    try {
      let ul = e.target.parentElement.closest('ul');
   
      let prevHight = 0;
    if(ul){
      ul.querySelectorAll('li ul').forEach(function(item){
        // console.log(item)
        // console.log(item.getAttribute('data-key'))
        let itemKey = parseInt(item.getAttribute('data-key'));
        if(itemKey !== elKey){
          item.style.height = 0 + 'px';
          // item.querySelectorAll('li').forEach(function(subItem){
          //   item.style.height = 0 +  "px";
          // })
        }else{
          // I think i need to work here.....
         prevHight =  sh;
         el.style.height =  sh + "px";
         ul.style.height = parseInt(getComputedStyle(item).height) + sh +  "px";
        //  el.style.height =  sh + "px";
          // item.style.height = (parseInt(getComputedStyle(item).height) - prevHight) + "px";
          // item.style.height = parseInt(getComputedStyle(item).height) + sh +  "px";
          // item.querySelectorAll('li').forEach(function(subItem){
          //   item.style.height = subItem.scrollHeight +  "px";
          // })
        }
      })
    }
    }
    catch(err) {
      
    }

      // el.style.height =  sh + "px";
      // ul.style.height = parseInt(getComputedStyle(item).height) + sh +  "px";
   

     return false;
  }));
a{
    display: inline-block;
    width: 100%;
    height: 100%;
    padding: 5px 10px;
   
    color: white;
}

nav  ul,
nav  ul ul{
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

nav  ul{
   width: 200px;
   background: dodgerblue;
 
}


nav  ul ul {
    
    background: rgb(13, 130, 141);
   margin-left: 15px;
   border-left: 1px dashed white;
   /* height: 10px; */
   transition: height .5s ease-in-out;
   
}

nav  ul ul ul {
    background: rgb(1, 8, 8);
   margin-left: 15px;
   border-left: 1px dashed white;
   /* height: 10px; */
   transition: height .5s ease-in-out;
}

nav  ul ul ul ul {
    background: rgb(10, 41, 179);
   margin-left: 15px;
   border-left: 1px dashed white;
   /* height: 10px; */
   transition: height .5s ease-in-out;
}
 <nav>
        <ul>
            <li><a href="javascript:void(0)">Home</a></li>
            <li><a href="javascript:void(0)">Dropdown 1 </a>
                <ul >
                    <li><a href="javascript:void(0)"> Menu 1</a></li>
                    <li><a href="javascript:void(0)">Menu 2</a>
                        <ul >
                            <li><a href="javascript:void(0)"> 1 Sub Menu 1</a></li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 2</a></li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 3</a> </li>
                        </ul>
                    </li>
                    <li><a href="javascript:void(0)">Menu 3</a>
                        <ul >
                            <li><a href="javascript:void(0)"> 1 Sub Menu 1</a></li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 2</a></li>
                            <!-- <li><a href="javascript:void(0)"> 1 Sub Menu 3</a> </li> -->
                        </ul>
                    </li>
                </ul>
            </li>
            <li><a href="javascript:void(0)">Dropdown 2 </a>
                <ul >
                    <li><a href="javascript:void(0)">Menu 2 </a>
                        <ul >
                            <li><a href="javascript:void(0)"> 2 Sub Menu 1</a></li>
                            <li><a href="javascript:void(0)"> 2 Sub Menu 2</a></li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </nav>


from sidebar multi level animated dropdown menu in vanilla js

No comments:

Post a Comment