关闭 <li> 上的下拉菜单单击原版 javascript

Close dropdown menu on <li> click with vanilla javascript

我有一个带有过渡的下拉菜单,它完全符合我的要求。我想保持过渡状态。下拉菜单还提供用户过滤页面上显示的视频的选项。

我遇到的问题是,我希望在用户单击任何

  • 选项后关闭菜单。目前它只能使用主按钮再次关闭。

    我尝试了几种不同的选择,但我的 Javascript 还不够强大,不知道我哪里出错了,我真的不想使用 JQuery 或 Bootstrap.

    如有任何帮助,我们将不胜感激!

    // Video Filter
    var filterItems = document.querySelectorAll('.item')
    
    function showAll() {
        filterItems.forEach(function(element) {
            element.classList.add('show')
        })
    }
    
    function showCategory(category) {
        filterItems.forEach(function(element){
            if (element.classList.contains(category)) {
                element.classList.add('show')
            }
            else {
                element.classList.remove('show')
            }
        })
    }
    showAll()
    
    //  Dropdown Button
    var filterBtn = document.getElementsByClassName("dropbtn");
    var i;
    
    for (i = 0; i < filterBtn.length; i++) {
      filterBtn[i].addEventListener("click", function() {
        this.classList.toggle("active");
        var content = this.nextElementSibling;
        if (content.style.maxHeight){
          content.style.maxHeight = null;
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
        } 
      })
    }
    
    .dropbtn {
      position: relative;
      left: 50%;
      transform: translateX(-50%);  
      text-decoration: none;
      padding: 20px 20px 18px 20px;
      color: black;
      background-color: rgb(245, 235, 244);
      border-radius: 100px;
      display: inline-block;
      cursor: pointer;
      font-weight: 400;
      letter-spacing: 1px;
      text-transform: uppercase;
      border: none;
    }
    
    .dropdown {
      position: relative;
      display: inline-block;
      left: 50%;
      transform: translateX(-50%);  
      margin-bottom: 20px;
    }
    
    .dropdown-content {
      position: relative;  
      background-color: rgba(245, 235, 244);
      min-width: 160px;
      z-index: 1;
      margin: 0;
      list-style-type: none;
      font-weight: 400;
      letter-spacing: 1px;
      text-transform: uppercase;
      padding: 0 10px;
      text-align: center; 
    
      max-height: 0;
      overflow: hidden;
      transition: max-height 0.25s ease-out;
    }
    
    .dropdown-content li {
      color: black;
      padding: 12px 16px;
      text-decoration: none;
      display: flex;
      flex-direction: column;
      justify-content: center;
      cursor: pointer;
    }
    
    
    .dropdown-content li:hover {filter: opacity(60%);}
    .dropbtn:hover {opacity: 60%;}
    .dropbtn:focus {outline-color: white;}
    
    
    .video-main h2 {
      font-weight: 600;
      text-transform: uppercase;
      font-size: 1.8em;
      letter-spacing: 1.5px;
      margin: 30px 0;
      color: rgb(245, 235, 244);
      align-self: center;
    }
    
    .video-main {
      display: flex;
      flex-direction: column;
      align-content: center;
      background-color: black;
    }
    
    .video-boxes {
      display: flex;
      width: 100%;
      justify-content: space-evenly;
      flex-direction: row;
      flex-wrap: wrap;
      text-align: center;
      
    }
    
    .video-boxes video {
      width: 100%;
      max-width: 1280px;
      max-height: 40vh;
    }
    
    .item {
      display: none;
      width: 90%;
      flex-wrap: wrap;
      text-align: center;
      margin-bottom: 20px;
    }
    
    
    .video-boxes .item h4 {
      color: rgb(245, 235, 244);
      font-weight: 400;
      letter-spacing: 2px;
      text-transform: uppercase;
    }
    
    .show {
      display: block;  
    }
    
    <main class="video-main">
        <h2>Video</h2>
          <div class="dropdown">
            <button class="dropbtn">Filter Projects</button>
            <ul class="dropdown-content">
                <li class="filter-list-item" id="all" onclick="showAll()">All Items</li>
                <li class="filter-list-item" onclick="showCategory('category-nike')">Nike</li>
                <li class="filter-list-item" onclick="showCategory('category-BSpace')">BlankSpace</li>
                <li class="filter-list-item" onclick="showCategory('category-AfterEff')">After Effects</li>
                <li class="filter-list-item" onclick="showCategory('category-vegan')">Vegan</li>
              </ul>
          </div>
        <div class="video-boxes">
          <div class="item category-nike">
            <video src="" controls></video>
            <h4 class="video-title">Nike</h4>
          </div>
          <div class="item category-BSpace">
            <video src="" controls></video>
            <h4 class="video-title">Blankspace</h4>
          </div>
           <div class="item category-AfterEff">
            <video src="" controls></video>
            <h4 class="video-title">Logo Animation</h4>
          </div>
          <div class="item category-vegan">
            <video src="" controls></video>
            <h4 class="video-title">Vegan</h4>
          </div>
         </div>
        </main>
    

  • 当单击其中一个列表项时,您需要将列表项容器的 max-height 设置为零。您还需要通过从中删除活动的 class 来重置过滤器按钮。首先为您的列表项定义一个变量:

    var listItems = document.querySelectorAll('.filter-list-item');
    

    然后为每个列表项添加一个事件侦听器,这会在单击时折叠列表项容器:

    listItems.forEach(item => {
      item.addEventListener("click", function() {
        filterBtn[0].classList.remove("active");
        var content = filterBtn[0].nextElementSibling;
        content.style.maxHeight = "";
      });
    });
    

    完整代码:

    // Video Filter
    var filterItems = document.querySelectorAll('.item');
    var listItems = document.querySelectorAll('.filter-list-item');
    
    function showAll() {
      filterItems.forEach(function(element) {
        element.classList.add('show')
      })
    }
    
    function showCategory(category) {
      filterItems.forEach(function(element) {
        if (element.classList.contains(category)) {
          element.classList.add('show')
        } else {
          element.classList.remove('show')
        }
      })
    }
    showAll()
    
    //  Dropdown Button
    var filterBtn = document.getElementsByClassName("dropbtn");
    var i;
    
    for (i = 0; i < filterBtn.length; i++) {
      filterBtn[i].addEventListener("click", function() {
        this.classList.toggle("active");
        var content = this.nextElementSibling;
        if (content.style.maxHeight) {
          content.style.maxHeight = null;
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
        }
      })
    }
    
    listItems.forEach(item => {
      item.addEventListener("click", function() {
        filterBtn[0].classList.remove("active");
        var content = filterBtn[0].nextElementSibling;
        content.style.maxHeight = "";
      });
    });
    
    .dropbtn {
      position: relative;
      left: 50%;
      transform: translateX(-50%);
      text-decoration: none;
      padding: 20px 20px 18px 20px;
      color: black;
      background-color: rgb(245, 235, 244);
      border-radius: 100px;
      display: inline-block;
      cursor: pointer;
      font-weight: 400;
      letter-spacing: 1px;
      text-transform: uppercase;
      border: none;
    }
    
    .dropdown {
      position: relative;
      display: inline-block;
      left: 50%;
      transform: translateX(-50%);
      margin-bottom: 20px;
    }
    
    .dropdown-content {
      position: relative;
      background-color: rgba(245, 235, 244);
      min-width: 160px;
      z-index: 1;
      margin: 0;
      list-style-type: none;
      font-weight: 400;
      letter-spacing: 1px;
      text-transform: uppercase;
      padding: 0 10px;
      text-align: center;
      max-height: 0;
      overflow: hidden;
      transition: max-height 0.25s ease-out;
    }
    
    .dropdown-content li {
      color: black;
      padding: 12px 16px;
      text-decoration: none;
      display: flex;
      flex-direction: column;
      justify-content: center;
      cursor: pointer;
    }
    
    .dropdown-content li:hover {
      filter: opacity(60%);
    }
    
    .dropbtn:hover {
      opacity: 60%;
    }
    
    .dropbtn:focus {
      outline-color: white;
    }
    
    .video-main h2 {
      font-weight: 600;
      text-transform: uppercase;
      font-size: 1.8em;
      letter-spacing: 1.5px;
      margin: 30px 0;
      color: rgb(245, 235, 244);
      align-self: center;
    }
    
    .video-main {
      display: flex;
      flex-direction: column;
      align-content: center;
      background-color: black;
    }
    
    .video-boxes {
      display: flex;
      width: 100%;
      justify-content: space-evenly;
      flex-direction: row;
      flex-wrap: wrap;
      text-align: center;
    }
    
    .video-boxes video {
      width: 100%;
      max-width: 1280px;
      max-height: 40vh;
    }
    
    .item {
      display: none;
      width: 90%;
      flex-wrap: wrap;
      text-align: center;
      margin-bottom: 20px;
    }
    
    .video-boxes .item h4 {
      color: rgb(245, 235, 244);
      font-weight: 400;
      letter-spacing: 2px;
      text-transform: uppercase;
    }
    
    .show {
      display: block;
    }
    
    <main class="video-main">
      <h2>Video</h2>
      <div class="dropdown">
        <button class="dropbtn">Filter Projects</button>
        <ul class="dropdown-content">
          <li class="filter-list-item" id="all" onclick="showAll()">All Items</li>
          <li class="filter-list-item" onclick="showCategory('category-nike')">Nike</li>
          <li class="filter-list-item" onclick="showCategory('category-BSpace')">BlankSpace</li>
          <li class="filter-list-item" onclick="showCategory('category-AfterEff')">After Effects</li>
          <li class="filter-list-item" onclick="showCategory('category-vegan')">Vegan</li>
        </ul>
      </div>
      <div class="video-boxes">
        <div class="item category-nike">
          <video src="" controls></video>
          <h4 class="video-title">Nike</h4>
        </div>
        <div class="item category-BSpace">
          <video src="" controls></video>
          <h4 class="video-title">Blankspace</h4>
        </div>
        <div class="item category-AfterEff">
          <video src="" controls></video>
          <h4 class="video-title">Logo Animation</h4>
        </div>
        <div class="item category-vegan">
          <video src="" controls></video>
          <h4 class="video-title">Vegan</h4>
        </div>
      </div>
    </main>
    

    只需使用 class filter-list-item.

    将事件侦听器附加到每个元素
    document.querySelectorAll('.filter-list-item').forEach(li => li.addEventListener('click', function(e){
          var content = this.parentNode;
        if (content.style.maxHeight){
          content.style.maxHeight = null;
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
        } 
    }));
    

    // Video Filter
    var filterItems = document.querySelectorAll('.item')
    
    function showAll() {
        filterItems.forEach(function(element) {
            element.classList.add('show')
        })
    }
    
    function showCategory(category) {
        filterItems.forEach(function(element){
            if (element.classList.contains(category)) {
                element.classList.add('show')
            }
            else {
                element.classList.remove('show')
            }
        })
    }
    showAll()
    
    //  Dropdown Button
    var filterBtn = document.getElementsByClassName("dropbtn");
    var i;
    
    for (i = 0; i < filterBtn.length; i++) {
      filterBtn[i].addEventListener("click", function() {
        this.classList.toggle("active");
        var content = this.nextElementSibling;
        if (content.style.maxHeight){
          content.style.maxHeight = null;
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
        } 
      })
    }
    
    document.querySelectorAll('.filter-list-item').forEach(li => li.addEventListener('click', function(e){
          var content = this.parentNode;
        if (content.style.maxHeight){
          content.style.maxHeight = null;
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
        } 
    }));
    
    .dropbtn {
      position: relative;
      left: 50%;
      transform: translateX(-50%);  
      text-decoration: none;
      padding: 20px 20px 18px 20px;
      color: black;
      background-color: rgb(245, 235, 244);
      border-radius: 100px;
      display: inline-block;
      cursor: pointer;
      font-weight: 400;
      letter-spacing: 1px;
      text-transform: uppercase;
      border: none;
    }
    
    .dropdown {
      position: relative;
      display: inline-block;
      left: 50%;
      transform: translateX(-50%);  
      margin-bottom: 20px;
    }
    
    .dropdown-content {
      position: relative;  
      background-color: rgba(245, 235, 244);
      min-width: 160px;
      z-index: 1;
      margin: 0;
      list-style-type: none;
      font-weight: 400;
      letter-spacing: 1px;
      text-transform: uppercase;
      padding: 0 10px;
      text-align: center; 
    
      max-height: 0;
      overflow: hidden;
      transition: max-height 0.25s ease-out;
    }
    
    .dropdown-content li {
      color: black;
      padding: 12px 16px;
      text-decoration: none;
      display: flex;
      flex-direction: column;
      justify-content: center;
      cursor: pointer;
    }
    
    
    .dropdown-content li:hover {filter: opacity(60%);}
    .dropbtn:hover {opacity: 60%;}
    .dropbtn:focus {outline-color: white;}
    
    
    .video-main h2 {
      font-weight: 600;
      text-transform: uppercase;
      font-size: 1.8em;
      letter-spacing: 1.5px;
      margin: 30px 0;
      color: rgb(245, 235, 244);
      align-self: center;
    }
    
    .video-main {
      display: flex;
      flex-direction: column;
      align-content: center;
      background-color: black;
    }
    
    .video-boxes {
      display: flex;
      width: 100%;
      justify-content: space-evenly;
      flex-direction: row;
      flex-wrap: wrap;
      text-align: center;
      
    }
    
    .video-boxes video {
      width: 100%;
      max-width: 1280px;
      max-height: 40vh;
    }
    
    .item {
      display: none;
      width: 90%;
      flex-wrap: wrap;
      text-align: center;
      margin-bottom: 20px;
    }
    
    
    .video-boxes .item h4 {
      color: rgb(245, 235, 244);
      font-weight: 400;
      letter-spacing: 2px;
      text-transform: uppercase;
    }
    
    .show {
      display: block;  
    }
    
    <main class="video-main">
        <h2>Video</h2>
          <div class="dropdown">
            <button class="dropbtn">Filter Projects</button>
            <ul class="dropdown-content">
                <li class="filter-list-item" id="all" onclick="showAll()">All Items</li>
                <li class="filter-list-item" onclick="showCategory('category-nike')">Nike</li>
                <li class="filter-list-item" onclick="showCategory('category-BSpace')">BlankSpace</li>
                <li class="filter-list-item" onclick="showCategory('category-AfterEff')">After Effects</li>
                <li class="filter-list-item" onclick="showCategory('category-vegan')">Vegan</li>
              </ul>
          </div>
        <div class="video-boxes">
          <div class="item category-nike">
            <video src="" controls></video>
            <h4 class="video-title">Nike</h4>
          </div>
          <div class="item category-BSpace">
            <video src="" controls></video>
            <h4 class="video-title">Blankspace</h4>
          </div>
           <div class="item category-AfterEff">
            <video src="" controls></video>
            <h4 class="video-title">Logo Animation</h4>
          </div>
          <div class="item category-vegan">
            <video src="" controls></video>
            <h4 class="video-title">Vegan</h4>
          </div>
         </div>
        </main>