打开其他菜单时如何折叠 Vanilla JS 多级菜单
How can i collapse Vanilla JS Multi level Menu when other menu is Opened
我使用纯 JS 创建了一个多级基本导航菜单,并试图找到一种在其他子菜单打开时折叠子菜单的逻辑。我使用 foreach 循环所有具有子菜单的菜单。但是不知道如何在单击菜单时检测其他菜单。谁可以帮我这个事。提前致谢!
/* toggle click function for submenus */
slideToggle=(el)=> {
let cs = window.getComputedStyle(el).display;
if(cs==="none") {
el.style.display="block";
}
else {
el.style.display="none";
}
}
/* detecting menus which has submenus */
submenuDetect=()=> {
let li = document.querySelectorAll(".main-navigation-content > ul li");
/* adding a class "has-submenu" for menu which has sublevel menu */
li.forEach((item)=>{
let ul = item.querySelector("ul");
if(ul){
item.classList.add("has-submenu");
ul.classList.add("submenu-content");
/* adding icon */
let iconElement = document.createElement("span");
iconElement.setAttribute("class","down-arrow-icon submenu-trigger");
item.querySelector("a").insertAdjacentElement("afterend", iconElement);
}
});
}
/* assign toggle function to menu which has submenus */
submenuToggle=()=>{
/* find all menu which has submenus and making toggle */
let submenuTrigger = document.querySelectorAll(".has-submenu > a");
submenuTrigger.forEach((item)=>{
item.addEventListener("click",(e)=>{
e.preventDefault();
let submenuContent = e.target.parentElement.querySelector('.submenu-content');
slideToggle(submenuContent);
})
});
}
/* calling submenu detect function and slidetoggle function */
submenuDetect();
submenuToggle();
body {font-family: Arial, Helvetica, sans-serif;;}
.main-navigation-content ul {list-style: none;margin:0;padding:0;transition:all 0.35s ease;}
.main-navigation-content ul li {border:1px solid #cdcdcd;margin-bottom: -1px;/* margin-left: -1px; *//* margin-right: -1px; */background: #f5f5f5;/* margin: -1px; *//* height: 2.5rem; */}
.main-navigation-content ul li a {text-decoration: none;line-height: 2.5rem;padding-left: .5rem;color: #555;display: flex;align-items: center;justify-content: space-between;position: relative;z-index: 1;padding-right: .5rem;transition:all 0.35s ease;/* width: 100%; */height: 2.5rem;flex-grow: 1;}
.main-navigation-content ul li ul li {margin-left: -1px;margin-right: -1px;}
.down-arrow-icon {width: 2.5rem;display: flex;height: 2.5rem;align-items: center;justify-content: center;position: absolute;z-index: 0;right: 0;top: 0;cursor: pointer;margin-right: 0;line-height: 2.5rem;/* background: red; */}
.down-arrow-icon:after { content:""; width: .03rem; height: .03rem; background-color: transparent; border: solid black; border-width: 0 2px 2px 0; display: inline-block; padding: 3px; transform: rotate(45deg); -webkit-transform: rotate(45deg); position: absolute; top: 35%;}
.navigation-master-wrapper {border: 1px solid #cdcdcd; width: auto;background: #f9f9f9;height: 500px;overflow-y: auto;}
.main-navigation {position: relative; height: auto;}
.main-navigation-trigger {margin-left: auto;position: relative;cursor: pointer;left: auto;right: .25rem;display: inline-block;padding: 0;font-size: 12px;top: 0;z-index: 100;margin-bottom: .5rem;display: none;}
.main-navigation-content { display:none;}
.main-navigation-content > ul { list-style: none;padding: 0;margin: 0;}
.main-navigation-content > ul li { position: relative;}
.main-navigation-content .submenu-content {display: none;}
@media only screen and (min-width:800px) {
.main-navigation-content > ul li .submenu-content li a {padding-left:2rem;}
.main-navigation-content > ul li .submenu-content li ul li a {padding-left:3rem}
.main-navigation-content > ul li .submenu-content {margin-top:1px;background: #fff;}
.main-navigation-content > ul li .submenu-content li ul {margin-top:0;}
.main-navigation-content {display:block !important;width: 20rem;}
.main-navigation-content > ul li > ul {top:100%;}
.main-navigation-content > ul li {position: initial;}
.main-navigation-content > ul > li {position: relative;}
.main-navigation-content > ul > li a {/* padding-left: 1rem; *//* padding-right: 1rem; */}
.main-navigation-content > ul li > ul li {position:relative;background: #fff;}
.main-navigation-content > ul li ul {transition:all 0.35s ease;}
}
<div class="main-navigation">
<div class="main-navigation-trigger">
<div class="main-navigation-trigger-inner"></div>
</div>
<div class="main-navigation-content">
<ul>
<li><a href="">Home</a></li>
<li><a href="">About Us</a>
<ul>
<li><a href="">History and Foundation</a></li>
<li><a href="">Company Overview</a></li>
<li><a href="">Working Strategy</a>
<ul>
<li><a href="">Employer Profile</a></li>
<li><a href="">Manpower Allocation</a></li>
<li><a href="">Marketing Strategy</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="">Services</a>
<ul>
<li><a href="">Graphic Designing</a></li>
<li><a href="">Web Designing</a></li>
<li><a href="">App Development</a>
<ul>
<li><a href="">Android</a></li>
<li><a href="">IOS</a></li>
<li><a href="">Hybrid</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="">Contact</a></li>
</ul>
</div>
</div>
您需要循环菜单 2 次才能:
- set click-eventListeners(你用
submenuToggle()
似乎没问题),但点击事件侦听器的回调需要修复。它需要将单击的 link 的 parent <li>
元素设置为参数。
参数:
<li> // submenu's parent list element, set as argument
<a href="">Working Strategy</a> // link with set click
<ul> // submenu to display or hide
编辑的事件侦听器:
item.addEventListener("click",(e)=>{
e.preventDefault();
let linkParentListElement = e.parentElement;
slideToggle(linkParentListElement);
});
- 根据其兄弟
<a>
是否被点击来设置每个子菜单 display-property。我会在专用方法中执行 2. 循环,例如您的初始 slideToggle(linkParentListElement)。使用方法 forEach()
使其在子菜单 children 上循环 <li>
。
在该方法的回调中,比较每个项目是否与点击的 link inside aka 如果它是 linkParentListElement
:
if(true): 将其直接child<ul>
的样式设置为display: block;
,
if (false): 将其直接child<ul>
的样式设置为display: none;
.
/* toggle click function for submenus */
slideToggle=(el)=> {
let submenuParentListElement = el,
listItems = document.querySelectorAll('div > ul > li > ul > li');
listItems.forEach(function(el) {
if (el === linkParentListElement) {
// set display: block to its direct child <ul>
} else {
// set display: block to its direct child <ul>
}
});
}
我试图理解您的代码以改进它,但几个小时后放弃了这个想法。但是,为了不放弃自己,您可以使用以下解决方法...
我希望至少我的代码能在将来帮助您简化您的代码。
const menu =
[ { lib: 'Home', link: '#Home' }
, { lib: 'About Us', link: '#About', sub:
[ { lib: 'History and Foundation', link: '#History' }
, { lib: 'Company Overview', link: '#Company' }
, { lib: 'Working Strategy', link: '#Working', sub:
[ { lib: 'Employer Profile', link: '#Employer' }
, { lib: 'Manpower Allocation', link: '#Manpower' }
, { lib: 'Marketing Strategy', link: '#Marketing' }
] } ] }
, { lib: 'Services', link: '#Services', sub:
[ { lib: 'Graphic Designing', link: '#Graphic' }
, { lib: 'Web Designing', link: '#Web' }
, { lib: 'App Development', link: '#App', sub:
[ { lib: 'Android', link: '#Android' }
, { lib: 'IOS', link: '#IOS' }
, { lib: 'Hybrid', link: '#Hybrid' }
] } ] }
, { lib: 'Contact', link: '#Contact' }
]
const navMenu = document.querySelector('div.main-nav')
const OpenMenus = [] // to memorize DOM (li.show) menus opened
function makeMenu( nav, jso )
{
let eUL = nav.appendChild( document.createElement('ul') )
for (const row of jso)
{
let eLI = eUL.appendChild( document.createElement('li') )
, lnk = eLI.appendChild( document.createElement('a') )
;
lnk.textContent = row.lib
lnk.href = row.link
if (!!row.sub)
{
eLI.className = 'submenu'
makeMenu(eLI,row.sub)
}
}
}
makeMenu( navMenu, menu )
navMenu.addEventListener('click', (e)=>
{
if (!e.target.matches('li.submenu > a')) return
e.preventDefault()
let level = 0
, eLI = e.target.closest('li')
, eUL = e.target.closest('ul')
, mOpen = eLI.classList.toggle('show')
;
for(;;level++) // get menu Level
{
eUL = eUL.parentElement.closest('ul')
if (!eUL || !eUL.matches('div.main-nav ul')) break
}
for(let i = OpenMenus.length; (--i) > level;) // close all < sub levels
{
OpenMenus.pop().classList.remove('show')
}
if (OpenMenus[level] && OpenMenus[level] != eLI )
OpenMenus.pop().classList.remove('show')
if (mOpen) OpenMenus.push(eLI) // memorize adding menu opened
else OpenMenus.pop() // or remove it.
})
body { background: steelblue; font-family: Arial, Helvetica, sans-serif; }
.main-nav * {
box-sizing : border-box;
}
.main-nav {
width : 20rem;
border-bottom : 1px solid #fbfbfb;
}
.main-nav ul {
list-style : none;
margin : 0;
padding : 0;
}
.main-nav a {
display : block;
width : 100%;
border : 1px solid #fbfbfb;
border-bottom : none;
background : #c7c7c7;
text-decoration : none;
line-height : 2.5rem;
padding : 0 .5rem;
color : #2a2a2a;
}
.main-nav a:hover {
background: #ebebeb;
}
.main-nav ul ul a { padding-left:2rem; background: #d5d5d5; }
.main-nav ul ul ul a { padding-left:3rem; background: #e1e1e1; }
.main-nav li.submenu > ul {
max-height : 0;
transition : max-height 0.25s ease-out;
overflow : hidden;
}
.main-nav li.submenu > a::after {
display : block;
float : right;
content : '6F'; /*'05'; */
transition : 180ms;
transform : rotate(90deg);
}
.main-nav li.submenu.show > ul {
max-height : 500px;
transition : max-height 0.35s ease-in;
}
.main-nav li.submenu.show > a {
padding-right : .7rem; /* because '6F' is not symetric ! */
}
.main-nav li.submenu.show > a::after {
transform : rotate(-90deg);
}
<div class="main-nav"></div>
你好朋友Bitski和Jojo先生,我终于找到了解决方案,如下所示。请看一看,让我知道您对我如何改进它的意见。感谢您花宝贵的时间为我度过。谢谢你们!!!
/* toggle click function for submenus */
slideToggle = (el) => {
let cs = window.getComputedStyle(el).display;
if (cs === "none") {
el.style.display = "block";
}
else {
el.style.display = "none";
}
}
/* detecting menus which has submenus */
submenuDetect=()=> {
let li = document.querySelectorAll(".main-navigation-content > ul li");
/* adding a class "has-submenu" for menu which has sublevel menu */
li.forEach((item)=>{
let ul = item.querySelector("ul");
if(ul){
item.classList.add("has-submenu");
ul.classList.add("submenu-content");
/* adding icon */
let iconElement = document.createElement("span");
iconElement.setAttribute("class","down-arrow-icon");
item.querySelector("a").insertAdjacentElement("afterend", iconElement);
}
});
}
let secondlevelToggle=()=>{
let secondlevelSubmenus = document.querySelectorAll(".submenu-content .has-submenu > a");
secondlevelSubmenus.forEach((el)=>{
el.addEventListener("click",(e)=>{
e.preventDefault();
e.stopPropagation();
let submenuContent = e.target.parentElement.querySelector(".submenu-content");
let submenuContentCS = window.getComputedStyle(submenuContent).display;
if(submenuContentCS==="none") {
submenuContent.style.display="block";
}
else {
submenuContent.style.display="none";
}
});
});
}
/* assign toggle function to menu which has submenus */
submenuToggle = () => {
/* find all menu which has submenus and making toggle */
let submenuTrigger = document.querySelectorAll(".has-submenu > a");
submenuTrigger.forEach((item) => {
item.addEventListener("click", (e) => {
e.stopPropagation();
e.preventDefault();
let allSubmenuContent = document.querySelectorAll(".main-navigation-content > ul > li > .submenu-content");
allSubmenuContent.forEach((el) => {
/* Current Submenu */
let referingSubmenu = e.currentTarget.parentElement.querySelector(".main-navigation-content > ul > .has-submenu > .submenu-content");
let referingSubmenuCS = window.getComputedStyle(referingSubmenu).display;
console.log(referingSubmenuCS);
if (referingSubmenuCS === "none") {
allSubmenuContent.forEach((elem) => {
if (window.getComputedStyle(elem).display === "block") {
elem.style.display = "none";
}
})
referingSubmenu.style.display = "block";
}
else {
referingSubmenu.style.display = "none";
}
});
});
});
}
submenuDetect();
submenuToggle();
secondlevelToggle();
body {font-family: Arial, Helvetica, sans-serif;;}
.main-navigation-content ul {list-style: none;margin:0;padding:0;transition:all 0.35s ease;}
.main-navigation-content ul li {border:1px solid #cdcdcd;margin-bottom: -1px;/* margin-left: -1px; *//* margin-right: -1px; */background: #f5f5f5;/* margin: -1px; *//* height: 2.5rem; */}
.main-navigation-content ul li a {text-decoration: none;line-height: 2.5rem;padding-left: .5rem;color: #555;display: flex;align-items: center;justify-content: space-between;position: relative;z-index: 1;padding-right: .5rem;transition:all 0.35s ease;/* width: 100%; */height: 2.5rem;flex-grow: 1;}
.main-navigation-content ul li ul li {margin-left: -1px;margin-right: -1px;}
.down-arrow-icon {width: 2.5rem;display: flex;height: 2.5rem;align-items: center;justify-content: center;position: absolute;z-index: 0;right: 0;top: 0;cursor: pointer;margin-right: 0;line-height: 2.5rem;/* background: red; */}
.down-arrow-icon:after { content:""; width: .03rem; height: .03rem; background-color: transparent; border: solid black; border-width: 0 2px 2px 0; display: inline-block; padding: 3px; transform: rotate(45deg); -webkit-transform: rotate(45deg); position: absolute; top: 35%;}
.navigation-master-wrapper {border: 1px solid #cdcdcd; width: auto;background: #f9f9f9;height: 500px;overflow-y: auto;}
.main-navigation {position: relative; height: auto;}
.main-navigation-trigger {margin-left: auto;position: relative;cursor: pointer;left: auto;right: .25rem;display: inline-block;padding: 0;font-size: 12px;top: 0;z-index: 100;margin-bottom: .5rem;display: none;}
.main-navigation-content { display:none;}
.main-navigation-content > ul { list-style: none;padding: 0;margin: 0;}
.main-navigation-content > ul li { position: relative;}
.main-navigation-content .submenu-content {display: none;}
@media only screen and (min-width:800px) {
.main-navigation-content > ul li .submenu-content li a {padding-left:2rem;}
.main-navigation-content > ul li .submenu-content li ul li a {padding-left:3rem}
.main-navigation-content > ul li .submenu-content {margin-top:1px;background: #fff;}
.main-navigation-content > ul li .submenu-content li ul {margin-top:0;}
.main-navigation-content {display:block !important;width: 20rem;}
.main-navigation-content > ul li > ul {top:100%;}
.main-navigation-content > ul li {position: initial;}
.main-navigation-content > ul > li {position: relative;}
.main-navigation-content > ul > li a {/* padding-left: 1rem; *//* padding-right: 1rem; */}
.main-navigation-content > ul li > ul li {position:relative;background: #fff;}
.main-navigation-content > ul li ul {transition:all 0.35s ease;}
}
<div class="main-navigation">
<div class="main-navigation-trigger">
<div class="main-navigation-trigger-inner"></div>
</div>
<div class="main-navigation-content">
<ul>
<li><a href="">Home</a></li>
<li><a href="">Features</a>
<ul>
<li><a href="">Graphic Designing</a></li>
<li><a href="">Web Designing</a></li>
<li><a href="">App Development</a>
<ul>
<li><a href="">Android</a></li>
<li><a href="">IOS</a></li>
<li><a href="">Hybrid</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="">About Us</a>
<ul>
<li><a href="">History and Foundation</a></li>
<li><a href="">Company Overview</a></li>
<li><a href="">Working Strategy</a>
<ul>
<li><a href="">Employer Profile</a></li>
<li><a href="">Manpower Allocation</a></li>
<li><a href="">Marketing Strategy</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="">Services</a>
<ul>
<li><a href="">Graphic Designing</a></li>
<li><a href="">Web Designing</a></li>
<li><a href="">App Development</a>
<ul>
<li><a href="">Android</a></li>
<li><a href="">IOS</a></li>
<li><a href="">Hybrid</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="">Contact</a></li>
</ul>
</div>
</div>
我使用纯 JS 创建了一个多级基本导航菜单,并试图找到一种在其他子菜单打开时折叠子菜单的逻辑。我使用 foreach 循环所有具有子菜单的菜单。但是不知道如何在单击菜单时检测其他菜单。谁可以帮我这个事。提前致谢!
/* toggle click function for submenus */
slideToggle=(el)=> {
let cs = window.getComputedStyle(el).display;
if(cs==="none") {
el.style.display="block";
}
else {
el.style.display="none";
}
}
/* detecting menus which has submenus */
submenuDetect=()=> {
let li = document.querySelectorAll(".main-navigation-content > ul li");
/* adding a class "has-submenu" for menu which has sublevel menu */
li.forEach((item)=>{
let ul = item.querySelector("ul");
if(ul){
item.classList.add("has-submenu");
ul.classList.add("submenu-content");
/* adding icon */
let iconElement = document.createElement("span");
iconElement.setAttribute("class","down-arrow-icon submenu-trigger");
item.querySelector("a").insertAdjacentElement("afterend", iconElement);
}
});
}
/* assign toggle function to menu which has submenus */
submenuToggle=()=>{
/* find all menu which has submenus and making toggle */
let submenuTrigger = document.querySelectorAll(".has-submenu > a");
submenuTrigger.forEach((item)=>{
item.addEventListener("click",(e)=>{
e.preventDefault();
let submenuContent = e.target.parentElement.querySelector('.submenu-content');
slideToggle(submenuContent);
})
});
}
/* calling submenu detect function and slidetoggle function */
submenuDetect();
submenuToggle();
body {font-family: Arial, Helvetica, sans-serif;;}
.main-navigation-content ul {list-style: none;margin:0;padding:0;transition:all 0.35s ease;}
.main-navigation-content ul li {border:1px solid #cdcdcd;margin-bottom: -1px;/* margin-left: -1px; *//* margin-right: -1px; */background: #f5f5f5;/* margin: -1px; *//* height: 2.5rem; */}
.main-navigation-content ul li a {text-decoration: none;line-height: 2.5rem;padding-left: .5rem;color: #555;display: flex;align-items: center;justify-content: space-between;position: relative;z-index: 1;padding-right: .5rem;transition:all 0.35s ease;/* width: 100%; */height: 2.5rem;flex-grow: 1;}
.main-navigation-content ul li ul li {margin-left: -1px;margin-right: -1px;}
.down-arrow-icon {width: 2.5rem;display: flex;height: 2.5rem;align-items: center;justify-content: center;position: absolute;z-index: 0;right: 0;top: 0;cursor: pointer;margin-right: 0;line-height: 2.5rem;/* background: red; */}
.down-arrow-icon:after { content:""; width: .03rem; height: .03rem; background-color: transparent; border: solid black; border-width: 0 2px 2px 0; display: inline-block; padding: 3px; transform: rotate(45deg); -webkit-transform: rotate(45deg); position: absolute; top: 35%;}
.navigation-master-wrapper {border: 1px solid #cdcdcd; width: auto;background: #f9f9f9;height: 500px;overflow-y: auto;}
.main-navigation {position: relative; height: auto;}
.main-navigation-trigger {margin-left: auto;position: relative;cursor: pointer;left: auto;right: .25rem;display: inline-block;padding: 0;font-size: 12px;top: 0;z-index: 100;margin-bottom: .5rem;display: none;}
.main-navigation-content { display:none;}
.main-navigation-content > ul { list-style: none;padding: 0;margin: 0;}
.main-navigation-content > ul li { position: relative;}
.main-navigation-content .submenu-content {display: none;}
@media only screen and (min-width:800px) {
.main-navigation-content > ul li .submenu-content li a {padding-left:2rem;}
.main-navigation-content > ul li .submenu-content li ul li a {padding-left:3rem}
.main-navigation-content > ul li .submenu-content {margin-top:1px;background: #fff;}
.main-navigation-content > ul li .submenu-content li ul {margin-top:0;}
.main-navigation-content {display:block !important;width: 20rem;}
.main-navigation-content > ul li > ul {top:100%;}
.main-navigation-content > ul li {position: initial;}
.main-navigation-content > ul > li {position: relative;}
.main-navigation-content > ul > li a {/* padding-left: 1rem; *//* padding-right: 1rem; */}
.main-navigation-content > ul li > ul li {position:relative;background: #fff;}
.main-navigation-content > ul li ul {transition:all 0.35s ease;}
}
<div class="main-navigation">
<div class="main-navigation-trigger">
<div class="main-navigation-trigger-inner"></div>
</div>
<div class="main-navigation-content">
<ul>
<li><a href="">Home</a></li>
<li><a href="">About Us</a>
<ul>
<li><a href="">History and Foundation</a></li>
<li><a href="">Company Overview</a></li>
<li><a href="">Working Strategy</a>
<ul>
<li><a href="">Employer Profile</a></li>
<li><a href="">Manpower Allocation</a></li>
<li><a href="">Marketing Strategy</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="">Services</a>
<ul>
<li><a href="">Graphic Designing</a></li>
<li><a href="">Web Designing</a></li>
<li><a href="">App Development</a>
<ul>
<li><a href="">Android</a></li>
<li><a href="">IOS</a></li>
<li><a href="">Hybrid</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="">Contact</a></li>
</ul>
</div>
</div>
您需要循环菜单 2 次才能:
- set click-eventListeners(你用
submenuToggle()
似乎没问题),但点击事件侦听器的回调需要修复。它需要将单击的 link 的 parent<li>
元素设置为参数。
参数:
<li> // submenu's parent list element, set as argument
<a href="">Working Strategy</a> // link with set click
<ul> // submenu to display or hide
编辑的事件侦听器:
item.addEventListener("click",(e)=>{
e.preventDefault();
let linkParentListElement = e.parentElement;
slideToggle(linkParentListElement);
});
- 根据其兄弟
<a>
是否被点击来设置每个子菜单 display-property。我会在专用方法中执行 2. 循环,例如您的初始 slideToggle(linkParentListElement)。使用方法forEach()
使其在子菜单 children 上循环<li>
。 在该方法的回调中,比较每个项目是否与点击的 link inside aka 如果它是linkParentListElement
:
if(true): 将其直接child<ul>
的样式设置为display: block;
,
if (false): 将其直接child<ul>
的样式设置为display: none;
.
/* toggle click function for submenus */
slideToggle=(el)=> {
let submenuParentListElement = el,
listItems = document.querySelectorAll('div > ul > li > ul > li');
listItems.forEach(function(el) {
if (el === linkParentListElement) {
// set display: block to its direct child <ul>
} else {
// set display: block to its direct child <ul>
}
});
}
我试图理解您的代码以改进它,但几个小时后放弃了这个想法。但是,为了不放弃自己,您可以使用以下解决方法...
我希望至少我的代码能在将来帮助您简化您的代码。
const menu =
[ { lib: 'Home', link: '#Home' }
, { lib: 'About Us', link: '#About', sub:
[ { lib: 'History and Foundation', link: '#History' }
, { lib: 'Company Overview', link: '#Company' }
, { lib: 'Working Strategy', link: '#Working', sub:
[ { lib: 'Employer Profile', link: '#Employer' }
, { lib: 'Manpower Allocation', link: '#Manpower' }
, { lib: 'Marketing Strategy', link: '#Marketing' }
] } ] }
, { lib: 'Services', link: '#Services', sub:
[ { lib: 'Graphic Designing', link: '#Graphic' }
, { lib: 'Web Designing', link: '#Web' }
, { lib: 'App Development', link: '#App', sub:
[ { lib: 'Android', link: '#Android' }
, { lib: 'IOS', link: '#IOS' }
, { lib: 'Hybrid', link: '#Hybrid' }
] } ] }
, { lib: 'Contact', link: '#Contact' }
]
const navMenu = document.querySelector('div.main-nav')
const OpenMenus = [] // to memorize DOM (li.show) menus opened
function makeMenu( nav, jso )
{
let eUL = nav.appendChild( document.createElement('ul') )
for (const row of jso)
{
let eLI = eUL.appendChild( document.createElement('li') )
, lnk = eLI.appendChild( document.createElement('a') )
;
lnk.textContent = row.lib
lnk.href = row.link
if (!!row.sub)
{
eLI.className = 'submenu'
makeMenu(eLI,row.sub)
}
}
}
makeMenu( navMenu, menu )
navMenu.addEventListener('click', (e)=>
{
if (!e.target.matches('li.submenu > a')) return
e.preventDefault()
let level = 0
, eLI = e.target.closest('li')
, eUL = e.target.closest('ul')
, mOpen = eLI.classList.toggle('show')
;
for(;;level++) // get menu Level
{
eUL = eUL.parentElement.closest('ul')
if (!eUL || !eUL.matches('div.main-nav ul')) break
}
for(let i = OpenMenus.length; (--i) > level;) // close all < sub levels
{
OpenMenus.pop().classList.remove('show')
}
if (OpenMenus[level] && OpenMenus[level] != eLI )
OpenMenus.pop().classList.remove('show')
if (mOpen) OpenMenus.push(eLI) // memorize adding menu opened
else OpenMenus.pop() // or remove it.
})
body { background: steelblue; font-family: Arial, Helvetica, sans-serif; }
.main-nav * {
box-sizing : border-box;
}
.main-nav {
width : 20rem;
border-bottom : 1px solid #fbfbfb;
}
.main-nav ul {
list-style : none;
margin : 0;
padding : 0;
}
.main-nav a {
display : block;
width : 100%;
border : 1px solid #fbfbfb;
border-bottom : none;
background : #c7c7c7;
text-decoration : none;
line-height : 2.5rem;
padding : 0 .5rem;
color : #2a2a2a;
}
.main-nav a:hover {
background: #ebebeb;
}
.main-nav ul ul a { padding-left:2rem; background: #d5d5d5; }
.main-nav ul ul ul a { padding-left:3rem; background: #e1e1e1; }
.main-nav li.submenu > ul {
max-height : 0;
transition : max-height 0.25s ease-out;
overflow : hidden;
}
.main-nav li.submenu > a::after {
display : block;
float : right;
content : '6F'; /*'05'; */
transition : 180ms;
transform : rotate(90deg);
}
.main-nav li.submenu.show > ul {
max-height : 500px;
transition : max-height 0.35s ease-in;
}
.main-nav li.submenu.show > a {
padding-right : .7rem; /* because '6F' is not symetric ! */
}
.main-nav li.submenu.show > a::after {
transform : rotate(-90deg);
}
<div class="main-nav"></div>
你好朋友Bitski和Jojo先生,我终于找到了解决方案,如下所示。请看一看,让我知道您对我如何改进它的意见。感谢您花宝贵的时间为我度过。谢谢你们!!!
/* toggle click function for submenus */
slideToggle = (el) => {
let cs = window.getComputedStyle(el).display;
if (cs === "none") {
el.style.display = "block";
}
else {
el.style.display = "none";
}
}
/* detecting menus which has submenus */
submenuDetect=()=> {
let li = document.querySelectorAll(".main-navigation-content > ul li");
/* adding a class "has-submenu" for menu which has sublevel menu */
li.forEach((item)=>{
let ul = item.querySelector("ul");
if(ul){
item.classList.add("has-submenu");
ul.classList.add("submenu-content");
/* adding icon */
let iconElement = document.createElement("span");
iconElement.setAttribute("class","down-arrow-icon");
item.querySelector("a").insertAdjacentElement("afterend", iconElement);
}
});
}
let secondlevelToggle=()=>{
let secondlevelSubmenus = document.querySelectorAll(".submenu-content .has-submenu > a");
secondlevelSubmenus.forEach((el)=>{
el.addEventListener("click",(e)=>{
e.preventDefault();
e.stopPropagation();
let submenuContent = e.target.parentElement.querySelector(".submenu-content");
let submenuContentCS = window.getComputedStyle(submenuContent).display;
if(submenuContentCS==="none") {
submenuContent.style.display="block";
}
else {
submenuContent.style.display="none";
}
});
});
}
/* assign toggle function to menu which has submenus */
submenuToggle = () => {
/* find all menu which has submenus and making toggle */
let submenuTrigger = document.querySelectorAll(".has-submenu > a");
submenuTrigger.forEach((item) => {
item.addEventListener("click", (e) => {
e.stopPropagation();
e.preventDefault();
let allSubmenuContent = document.querySelectorAll(".main-navigation-content > ul > li > .submenu-content");
allSubmenuContent.forEach((el) => {
/* Current Submenu */
let referingSubmenu = e.currentTarget.parentElement.querySelector(".main-navigation-content > ul > .has-submenu > .submenu-content");
let referingSubmenuCS = window.getComputedStyle(referingSubmenu).display;
console.log(referingSubmenuCS);
if (referingSubmenuCS === "none") {
allSubmenuContent.forEach((elem) => {
if (window.getComputedStyle(elem).display === "block") {
elem.style.display = "none";
}
})
referingSubmenu.style.display = "block";
}
else {
referingSubmenu.style.display = "none";
}
});
});
});
}
submenuDetect();
submenuToggle();
secondlevelToggle();
body {font-family: Arial, Helvetica, sans-serif;;}
.main-navigation-content ul {list-style: none;margin:0;padding:0;transition:all 0.35s ease;}
.main-navigation-content ul li {border:1px solid #cdcdcd;margin-bottom: -1px;/* margin-left: -1px; *//* margin-right: -1px; */background: #f5f5f5;/* margin: -1px; *//* height: 2.5rem; */}
.main-navigation-content ul li a {text-decoration: none;line-height: 2.5rem;padding-left: .5rem;color: #555;display: flex;align-items: center;justify-content: space-between;position: relative;z-index: 1;padding-right: .5rem;transition:all 0.35s ease;/* width: 100%; */height: 2.5rem;flex-grow: 1;}
.main-navigation-content ul li ul li {margin-left: -1px;margin-right: -1px;}
.down-arrow-icon {width: 2.5rem;display: flex;height: 2.5rem;align-items: center;justify-content: center;position: absolute;z-index: 0;right: 0;top: 0;cursor: pointer;margin-right: 0;line-height: 2.5rem;/* background: red; */}
.down-arrow-icon:after { content:""; width: .03rem; height: .03rem; background-color: transparent; border: solid black; border-width: 0 2px 2px 0; display: inline-block; padding: 3px; transform: rotate(45deg); -webkit-transform: rotate(45deg); position: absolute; top: 35%;}
.navigation-master-wrapper {border: 1px solid #cdcdcd; width: auto;background: #f9f9f9;height: 500px;overflow-y: auto;}
.main-navigation {position: relative; height: auto;}
.main-navigation-trigger {margin-left: auto;position: relative;cursor: pointer;left: auto;right: .25rem;display: inline-block;padding: 0;font-size: 12px;top: 0;z-index: 100;margin-bottom: .5rem;display: none;}
.main-navigation-content { display:none;}
.main-navigation-content > ul { list-style: none;padding: 0;margin: 0;}
.main-navigation-content > ul li { position: relative;}
.main-navigation-content .submenu-content {display: none;}
@media only screen and (min-width:800px) {
.main-navigation-content > ul li .submenu-content li a {padding-left:2rem;}
.main-navigation-content > ul li .submenu-content li ul li a {padding-left:3rem}
.main-navigation-content > ul li .submenu-content {margin-top:1px;background: #fff;}
.main-navigation-content > ul li .submenu-content li ul {margin-top:0;}
.main-navigation-content {display:block !important;width: 20rem;}
.main-navigation-content > ul li > ul {top:100%;}
.main-navigation-content > ul li {position: initial;}
.main-navigation-content > ul > li {position: relative;}
.main-navigation-content > ul > li a {/* padding-left: 1rem; *//* padding-right: 1rem; */}
.main-navigation-content > ul li > ul li {position:relative;background: #fff;}
.main-navigation-content > ul li ul {transition:all 0.35s ease;}
}
<div class="main-navigation">
<div class="main-navigation-trigger">
<div class="main-navigation-trigger-inner"></div>
</div>
<div class="main-navigation-content">
<ul>
<li><a href="">Home</a></li>
<li><a href="">Features</a>
<ul>
<li><a href="">Graphic Designing</a></li>
<li><a href="">Web Designing</a></li>
<li><a href="">App Development</a>
<ul>
<li><a href="">Android</a></li>
<li><a href="">IOS</a></li>
<li><a href="">Hybrid</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="">About Us</a>
<ul>
<li><a href="">History and Foundation</a></li>
<li><a href="">Company Overview</a></li>
<li><a href="">Working Strategy</a>
<ul>
<li><a href="">Employer Profile</a></li>
<li><a href="">Manpower Allocation</a></li>
<li><a href="">Marketing Strategy</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="">Services</a>
<ul>
<li><a href="">Graphic Designing</a></li>
<li><a href="">Web Designing</a></li>
<li><a href="">App Development</a>
<ul>
<li><a href="">Android</a></li>
<li><a href="">IOS</a></li>
<li><a href="">Hybrid</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="">Contact</a></li>
</ul>
</div>
</div>