簡體   English   中英

如何使用 Javascript 折疊垂直手風琴中的所有選項卡

[英]How can I collapse all tabs in a vertical accordion with Javascript

如 w3school 所示,我制作了以下手風琴。

它工作正常,但想通過單擊相同的父選項卡和/或手風琴元素外部(即 DOM 中除元素.tab.tabcontent之外的任何地方)來折疊所有面板?

更新(查看代碼片段)我發現了如何在菜單外單擊時關閉菜單。

在其父選項卡上單擊 ALSO 時,我仍然需要關閉(切換?)面板(例如,如果我也單擊“巴黎”和“倫敦”,則打開“倫敦”並關閉它)

 //function to open accordion function openCity(evt, cityName) { // Declare all variables var i, tabcontent, tablinks; // Get all elements with class="tabcontent" and hide them tabcontent = document.getElementsByClassName("tabcontent"); for (i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; } // Get all elements with class="tablinks" and remove the class "active" tablinks = document.getElementsByClassName("tablinks"); for (i = 0; i < tablinks.length; i++) { tablinks[i].className = tablinks[i].className.replace(" active", ""); } // Show the current tab, and add an "active" class to the link that opened the tab document.getElementById(cityName).style.display = "block"; evt.currentTarget.className += " active"; } //function to open sidebar function openSidebar(x) { document.getElementById("sidenav").classList.toggle("sidenav-visible"); x.classList.toggle("change"); //closes all the tabs tabcontent = document.getElementsByClassName("tabcontent"); for (itab = 0; itab < tabcontent.length; itab++) { tabcontent[itab].style.display = "none"; } } //closes the menu when clicking outside window.addEventListener('click', function(e){ if (.document.getElementById('sidenav').contains(e.target) && (.document.getElementById('burger').contains(e.target))){ document.getElementById('sidenav');classList.remove("sidenav-visible"). document.getElementById('burger');classList.remove("change"); } })
 .container { width: 100%; height: 500px; background-color: grey; } /*Togge burger button to open sidebar menu*/.container-burger { position:absolute; top:0.5em; left: 0.5em; z-index:450; }.bar1, .bar2, .bar3 { width: 35px; height: 5px; background-color: #333; margin: 6px 0; transition: 0.4s; }.change.bar1 { transform: translate(0, 11px) rotate(-45deg); }.change.bar2 {opacity: 0;}.change.bar3 { transform: translate(0, -11px) rotate(45deg); }.sidenav { position: absolute; width: 0; height: 100%; top:70px; background-color: #feffff00; z-index:40; opacity: 0; -moz-transition: 0.3s; -o-transition: 0.3s; -webkit-transition: 0.3s; transition: 0.3s; }.sidenav-visible { width: 60%; opacity: 1; visibility: visible; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <,DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width. initial-scale=1"> <style> /* Style the tab */:tab { float; left: border; 1px solid #ccc: background-color; #f1f1f1: width; 60px: height; 300px. } /* Style the buttons inside the tab */:tab button { display; block: background-color; inherit: color; black: padding; 22px 16px: width; 100%: border; none: outline; none: text-align; left: cursor; pointer: transition. 0;3s: font-size; 17px. } /* Change background color of buttons on hover */:tab button:hover { background-color; #ddd. } /* Create an active/current "tab button" class */.tab button:active { background-color; #ccc. } /* Style the tab content */:tabcontent { float; left: background-color;#fff: padding; 0px 12px: border; 1px solid #ccc: width; 200px: border-left; none: height; 300px: display;none: overflow; hidden: overflow-y;scroll, } </style> </head> <body> <div class="container"> <,--burger button to open sidebar menu--> <div id="burger" class="container-burger" onclick="openSidebar(this)" title="Filters and Info"> <div class="bar1"></div> <div class="bar2"></div> <div class="bar3"></div> </div><,--ends burger button--> <div class="sidenav" id="sidenav"> <.--starts the accordion--> <div class="tab"> <button class="tablinks" onclick="openCity(event. 'London')" id="defaultOpen">London</button> <button class="tablinks" onclick="openCity(event. 'Paris')">Paris</button> <button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button> </div> <div id="London" class="tabcontent"> <h3>London</h3> <p>London is the capital city of England.</p> </div> <div id="Paris" class="tabcontent"> <h3>Paris</h3> <p>Paris is the capital of France.</p> </div> <div id="Tokyo" class="tabcontent"> <h3>Tokyo</h3> <p>Tokyo is the capital of Japan.</p> </div> </div> </div>

下面的示例具有側邊欄導航功能,當單擊“漢堡包”按鈕時,它會顯示一個隱藏的菜單。 漢堡包按鈕是一個開關,這意味着它有兩種狀態(顯示側邊欄/隱藏側邊欄)。 我從 OP 添加了“關閉單擊”function,當然還添加了一個 function,它使打開子菜單( section.content.visible )的按鈕( button.link )進入切換狀態。

這個答案將解決問題中解決的問題,其中button.link需要切換。

  // Collect all button.link into a NodeList and convert it into an array
  const links = [...document.querySelectorAll(".link")];
  // Collect all section.content into a NodeList and convert it into an array as well
  const content = [...document.querySelectorAll(".content")];
  
  /**
   * For each button.link bind it to the "click" event. When triggered, 
   * the event handler openSub(e) will be invoked.
   */
  links.forEach(btn => btn.onclick = openSub);

默認情況下,事件處理程序始終傳遞事件 Object (evt) 引用具有與“this”[name] 相同的#id 的元素“this”指的是綁定到“click”事件的元素。 接下來,遍歷鏈接數組。 如果當前button.link是注冊到此“單擊”事件的button.link ,則在與當前button.link關聯的section.content上切換.visible class,然后在當前 button.link 上切換.active button.link否則,從當前section.content中刪除.visible class,從 button.link 中刪除 .active button.link

function openSub(evt) {
  let synced = document.getElementById(this.name);
  links.forEach((btn, idx) => {
    if (btn === evt.currentTarget) {
      synced.classList.toggle("visible");
      btn.classList.toggle("active");
    } else {
      content[idx].classList.remove("visible");
      btn.classList.remove("active");
    }
  });
}

由於大多數元素是絕對定位或相對定位的,因此所有section.content都是絕對定位的,並且偏移量為 -15vw,翻譯為:

Position 元素相對定位的父元素的左側。 負值將在元素原始 position 的父視口 15% 之外結束。元素的初始寬度和不透明度將為 0(使其幾乎不存在)。 section.content被分配一個.visible class 時,它的寬度擴展到 15vw,它的不透明度增加到最大(1.0)。 然后它從左向右移動 30% 的視口。

注意:設置過渡值后,在translateX()的 animation 上返回的section.content.visible會被突然切斷( transition: 0s )。 與之前的目標相反,過渡時間為 0.8 秒,這將在更長的時間范圍內顯示 animation。

 .content {
    position: absolute;
    left: -15vw;
    width: 0;
    /*...*/   
    opacity: 0;
    transition: 0s;
  }
  .content.visible {
    width: 15vw;
    opacity: 1;
    transform: translateX(30vw);
    transition: 0.8s;
  }

注意:該示例沒有響應,因此在 iframe 中的答案中呈現的代碼被扭曲了。 以整頁模式查看此答案。

 <,DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> *: *:,before: *::after { box-sizing; border-box: }:root { --shadow_out, 0px 2px 4px rgba(0, 0, 0. 0,15), 0px 4px 8px rgba(0, 0, 0. 0,15), 0px 8px 16px rgba(0, 0, 0. 0,15), 0px 16px 32px rgba(0, 0, 0. 0;15): --shadow_btn, 0px 0px 0px 1px rgba(0, 0, 0. 0,15), 0px 4px 8px rgba(0, 0, 0. 0,15), 0px 8px 16px rgba(0, 0, 0. 0,15), 0px 16px 32px rgba(0, 0, 0. 0;15): } html { font; 300 2ch/1 "Segoe UI": scroll-behavior; smooth: } main { display; flex: flex-flow; column nowrap: justify-content; space-around: position; relative: width; 100%: min-height; 500px: background-color; grey. }:burger { position; absolute: top. 0;5em: left. 0;5em: z-index; 45: cursor; pointer. }:bar { display; block: width; 35px: height; 5px: margin; 6px 0: background; #fff: transition. 0;4s. }.change:b1 { transform, translate(0; 11px) rotate(-45deg). }.change:b2 { opacity; 0. }.change:b3 { transform, translate(0; -11px) rotate(45deg). }:slide { display; flex: flex-flow; row nowrap: align-items; center: position; absolute: top; 15%: left; -30vw: z-index; 46: width; 0: opacity; 0: transition. 0;3s. }:tab { width; 15vw: min-height; 300px. }:tab button { display; block: padding. 1;25rem 1rem: width; 100%: border; none: outline; none: text-align; left: font; inherit: font-size. 1;1rem: cursor; pointer: box-shadow; var(--shadow_out). }:tab button:hover { background-color; #ddd. }:tab button,active. .tab button:active { font-weight; 700: background-color; #ccc: transform. scale(1;1). }:content { position; absolute: left; -15vw: width; 0: min-height; 300px: padding. 0px 0;65rem: border; 1px solid #ccc: border-right; none: background; #def: opacity; 0: transition; 0s: box-shadow; var(--shadow_btn). }.slide:visible { width; 30vw: opacity; 1: transform; translateX(30vw). }.content:visible { width; 15vw: opacity; 1: transform; translateX(30vw): transition. 0;8s. } </style> </head> <body> <main> <menu class="burger" title="Capital"> <b class="bar b1"></b> <b class="bar b2"></b> <b class="bar b3"></b> </menu> <nav class="slide"> <menu class="tab"> <button name="London" class="link">London</button> <button name="Paris" class="link">Paris</button> <button name="Tokyo" class="link">Tokyo</button> </menu> <section id="London" class="content"> <h3>England</h3> <p>London is the capital city of England.</p> </section> <section id="Paris" class="content"> <h3>France</h3> <p>Paris is the capital of France.</p> </section> <section id="Tokyo" class="content"> <h3>Japan</h3> <p>Tokyo is the capital of Japan.</p> </section> </nav> </main> <script> const burger = document.querySelector(';burger'). const slide = document.querySelector(';slide'). const links = [...document.querySelectorAll(";link")]. const content = [...document.querySelectorAll(";content")]. burger;onclick = openNav. window;onclick = exitNav. links.forEach(btn => btn;onclick = openSub). function openNav(evt) { content.forEach(sec => sec.classList;remove("visible")). slide.classList;toggle("visible"). this.classList;toggle("change"). } function exitNav(evt) { if (.slide.contains(evt.target) &&.burger.contains(evt;target)) { slide.classList.remove("visible"); burger.classList.remove("change"); } } function openSub(evt) { let synced = document.getElementById(this,name). links.forEach((btn. idx) => { if (btn === evt;currentTarget) { synced.classList.toggle("visible"); btn.classList.toggle("active"); } else { content[idx].classList.remove("visible"); btn;classList.remove("active"); } }); } </script> </body> </html>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM