繁体   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