簡體   English   中英

當使用 Javascript 並且沒有 jQuery 單擊另一個菜單項的按鈕(第一個的“堂兄”)時關閉一個菜單項的子菜單

[英]Close submenus of one menu item when another menu item's button ('cousin' of first) is clicked with Javascript and no jQuery

我有一個純 html、css(沒有 Bootstrap)、vanilla javascript 和沒有 jQuery 的可點擊/可點擊菜單(它可以有無限級別)。

當我單擊鏈接到帶有子菜單的菜單項的按鈕時,它會打開子菜單,當我再次單擊該按鈕時,它會關閉子菜單。 一切都很好。

但是,當我單擊另一個頂級主項目的按鈕(我稱之為元素的“表親”:元素的父級的兄弟級的子級)以打開其子菜單時,我無法弄清楚如何關閉已經打開的子菜單. 所以我最終會並排打開兩個或多個子菜單並重疊。

我在這里嘗試了一個版本的答案: Stackoverflow.com question 41202059這似乎是最接近我想要做的,但沒有成功。

這是我的片段:

 /// this script opens the sub-menu when the li button is clicked document.getElementById("menucontent").addEventListener("click", openSubMenu); function openSubMenu(event){ if(event.target.type === "button"){ event.target.nextElementSibling.classList.toggle("hidden"); event.target.classList.add("clicked"); event.target.classList.remove("not-clicked"); } } // this script switches the triangle direction when the button is clicked document.getElementById("menucontent").addEventListener("click", triangle); function triangle(event){ if(event.target.type === "button"){ event.target.classList.toggle("triangle"); } } // this script closes the submenus when clicking anywhere outside the menu and reverts the triangle to pointing down document.getElementById("mainbody").addEventListener("click", closeMenu); function closeMenu(event) { if(event.target.type != "button") { var level1 = document.getElementsByClassName("level-1"); var level2 = document.getElementsByClassName("level-2"); var btnlevel1 = document.getElementsByClassName("btn-level-1"); var btnlevel2 = document.getElementsByClassName("btn-level-2"); for (var i = 0; i < level1.length; i++) { level1[i].classList.add("hidden"); } for (var i = 0; i < level2.length; i++) { level2[i].classList.add("hidden"); } for (var i = 0; i < btnlevel1.length; i++){ btnlevel1[i].classList.remove("triangle"); btnlevel1[i].classList.remove("clicked");} for (var i = 0; i < btnlevel2.length; i++) { btnlevel2[i].classList.remove("triangle"); btnlevel2[i].classList.remove("clicked");} } } document.getElementById("mainbody").addEventListener("click", addClass); function addClass(event) { // the click is triggered outside the menu if(event.target.type != 'button') { // these are top level buttons only var buttons = document.querySelectorAll('.btn-level-1.clicked'); for (var i = 0; i < buttons.length; i++) { buttons[i].classList.add('not-clicked'); buttons[i].classList.remove('clicked'); } } }
 .outer { border: 2px solid gray; margin: 1rem; padding: 1rem; } .stickymenuwrapper { background-color: #fff; transition-duration: 0s; padding: 0; margin: 0 auto; z-index: 995; } .scrabble-menu .hidden { display: none; } .scrabble-menu .navbar > li { display: inline-block; } .scrabble-menu ul { list-style: none; margin-bottom: 0; white-space: nowrap; padding: 0; } .scrabble-menu ul.navbar { background-color: pink; padding: 0 1rem; } .scrabble-menu li ul { position: absolute; top: 100%; background-color: pink; border: 1px solid red; padding: 0 12px 0 12px; } .scrabble-menu ul.level-2, .scrabble-menu ul.level-3 { background-color: yellow; top: 0%; left: 100%; padding-bottom: 0.5rem; } .scrabble-menu ul.level-3 { background-color: orange; } .scrabble-menu li.active > a { text-decoration: underline; } .scrabble-menu a.separator:hover { text-decoration: none; } .scrabble-menu button, .scrabble-menu button:focus { background: none; border: none; height: 2.5rem; width: 1.75rem; outline:none; padding: 0; } .scrabble-menu li { position: relative; display: flex; margin: 0; padding: 0; line-height: 1.5rem; } .scrabble-menu .navbar > li > a { padding: 0.5rem 0 0.5rem 0.5rem; margin-left: 1rem; } .scrabble-menu .navbar > li:first-child > a { padding: 0.5rem 0.5rem 0.5rem 0; margin-left: 0; } .scrabble-menu li button:after { font-size: 0.8rem; position: relative; right: -3px; top: 0; } .scrabble-menu ul.level-1 > li a { padding-top: 0.5rem; } .scrabble-menu li button[class^="btn-level"]:after { content: "\\25B6"; cursor: pointer; } .scrabble-menu .triangle{ } .scrabble-menu li button[class^="btn-level"].triangle:after { content: "\\25C0"; } .scrabble-menu li button.btn-level-1:after { content: "\\25BC"; } .scrabble-menu li button.btn-level-1.triangle:after { content: "\\25B2"; }
 <div id="mainbody" class="outer">This is a menu that works with pure html, css and vanilla Javascript. There is no jQuery.<br>There is JS to close the menu when clicking outside the menu and to close each open submenu when its parent's button is clicked. The arrows (including for submenus) switch accordingly. <div class="row sticky-main-menu"> <div id="stickymenuwrapper" class="col stickymenuwrapper scrabble-menu"> <ul id="menucontent" class="navbar"> <li class="item-101 single current active"> <a href="/" class="one">HOME</a></li> <li class="item-122 single divider deeper parent"> <a class="two">TEST TWO</a> <button class="btn-level-1" type="button"></button> <ul id="drop-122" class="hidden level-1"> <li class="item-121 single"> <a href="/" class="">Test level 2</a> </li> </ul> </li> <li class="item-103 single deeper parent"> <a href="/" class="two">ABOUT</a> <button class="btn-level-1" type="button"></button> <ul class="level-1 hidden"> <li class="item-104 single"> <a href="/" class="">About us</a> </li> <li class="item-104 single"> <a href="/" class="">More</a> </li> </ul> </li> </ul> </div> </div> </div>

謝謝你。

我已經稍微簡化了代碼,現在從包裝器委托

 function openLowerMenu(e) { const tgt = e.target; e.currentTarget.nextElementSibling.classList.toggle('test1', tgt.type === "button"); e.currentTarget.nextElementSibling.classList.add('test2', tgt.type !== "button"); } document.getElementById("stickymenuwrapper").addEventListener("click", function(e) { const tgt = e.target; if (tgt.type==="button") { const level = tgt.className.replace(/[^\\d]/g,""); [...document.querySelectorAll('ul.level-'+level)].forEach(ul => ul.classList.add("hidden")); const show = tgt.classList.contains("triangle") tgt.nextElementSibling.classList.toggle("hidden",!show); tgt.classList.toggle("triangle",!show); } });
 .row { margin: 0 1rem; } .outer { border: 2px solid gray; margin: 1rem; padding: 1rem; } .sticky-main-menu { z-index: 9999; } .stickymenuwrapper { background-color: #fff; transition-duration: 0s; padding: 0; margin: 0 auto; z-index: 995; } .scrabble-menu .hidden { display: none; } .scrabble-menu .navbar>li { display: inline-block; } .scrabble-menu ul { list-style: none; margin-bottom: 0; white-space: nowrap; padding: 0; } .scrabble-menu ul.navbar { background-color: pink; padding: 0 1rem; /* text-align: center;*/ } .scrabble-menu li ul { position: absolute; top: 100%; background-color: pink; border: 1px solid red; padding: 0 12px 0 12px; } .scrabble-menu ul.level-2, .scrabble-menu ul.level-3 { background-color: yellow; top: 0%; left: 100%; padding-bottom: 0.5rem; } .scrabble-menu ul.level-3 { background-color: orange; } .scrabble-menu li.active>a { text-decoration: underline; } .scrabble-menu a.separator:hover { text-decoration: none; } .scrabble-menu button, .scrabble-menu button:focus { background: none; border: none; height: 2.5rem; width: 1.75rem; outline: none; padding: 0; } .scrabble-menu li { position: relative; display: flex; margin: 0; padding: 0; line-height: 1.5rem; } .scrabble-menu .navbar>li>a { padding: 0.5rem 0 0.5rem 0.5rem; margin-left: 1rem; } .scrabble-menu .navbar>li:first-child>a { padding: 0.5rem 0.5rem 0.5rem 0; margin-left: 0; } /* separator line code here */ .scrabble-menu li button:after { font-size: 0.8rem; position: relative; right: -3px; top: 0; } .scrabble-menu ul.level-1>li a { padding-top: 0.5rem; } .scrabble-menu li button[class^="btn-level"]:after { content: "\\25B6"; cursor: pointer; } .scrabble-menu li button[class^="btn-level"].triangle:after { content: "\\25C0"; } .scrabble-menu li button.btn-level-1:after { content: "\\25B2"; } .scrabble-menu li button.btn-level-1.triangle:after { content: "\\25BC"; } .scrabble-menu li button.btn-level-1.triangle2:after { content: "\\25BC"; } .scrabble-menu .clicked {} .scrabble-menu li button[class^="btn-level"].not-clicked:after { content: "\\25B0"; cursor: pointer; } .scrabble-menu li button.btn-level-1.not-clicked::after { content: "\\25BC"; }
 <div class="row sticky-main-menu"> <div id="stickymenuwrapper" class="col stickymenuwrapper scrabble-menu"> <ul id="menucontent" class="scrabblemenu navbar"> <li class="item-122 single divider deeper parent"> <a class="two">ITEM ONE</a> <button class="btn-level-1 triangle" type="button"></button> <ul id="drop-122" class="hidden level-1"> <li class="item-121 single"> <a href="/" class="">Item One level 2</a> </li> <li class="item-134 single deeper parent"> <a class="nav-header two">Item One level 2 menu heading</a> <button class="btn-level-2" type="button"></button> <ul id="drop-134" class="level-2 hidden"> <li class="item-135 single"> <a href="/" class="">Article under menu heading</a> </li> </ul> </li> </ul> </li> <li class="item-122 single divider deeper parent"> <a class="two">ITEM TWO</a> <button class="btn-level-1 triangle" type="button"></button> <ul id="drop-122" class="hidden level-1"> <li class="item-121 single"> <a href="/" class="">Item Two level 2</a> </li> <li class="item-134 single deeper parent"> <a class="nav-header two">Item Two level 2 menu heading</a> <button class="btn-level-2" type="button"></button> <ul id="drop-134" class="level-2 hidden"> <li class="item-135 single"> <a href="/" class="">Article under menu heading</a> </li> </ul> </li> </ul> </li> <li class="item-103 single deeper parent"> <a href="/" class="two">ITEM THREE WITH LINK</a> <button class="btn-level-1 triangle" type="button"></button> <ul class="not-separator level-1 hidden"> <li class="item-104 single"> <a href="/" class="">Article under Item Three</a> </li> <li class=""> <a class="two separator">Item Three Level 2 separator</a> <button class="btn-level-2" type="button"></button> <ul id="drop-107" class="level-2 hidden"> <li class="item-108 single"> <a href="/" class="">Lower article</a> </li> </ul> </li> </ul> </li> </ul> </div> </div>

暫無
暫無

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

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