I want to select a menu button depending on current page.
The traditional way is to use i++ to iterate the “list”. I want to avoid this, because it is almost unreadable to a newbie:
“`
(function() {
var anchors = document.querySelectorAll(‘.nav a’),
current = window.location.href;
for (var i = 0; i < anchors.length; i++) {
if (current.indexOf(anchors[i].href) != -1) {
anchors[i].classList.add(“active”);
}
}
})();
Less traditional way. More readable:
“`
const navbtn = document.querySelectorAll(‘.navbtn’);
var current = window.location.href;
(function() {
navbtn.forEach(myFunction);
function myFunction(el) {
if (current.indexOf(el.href) != -1) {
el.classList.add(“active”);
}
}
})();
But I am searching for ways to do it even more readable and using less rows. I have search but found no simpler ways to do this.
Is there simpler or more readable ways?
includes
`<i>
</i>(function() {
const navbtn = document.querySelectorAll('.navbtn');
const current = window.location.href;
navbtn.forEach(el => {
if (current.includes(el.href)) {
el.classList.add("active");
}
});
})();
>@Sempervivum#1626338
> You can use an anonymous function
> Your can use includes instead of indexOf
``<i>
</i>const homebtn = document.querySelector(".navbtn").href = "/home";
if (any of this two pages is active) {
homebtn.classList.add("active");
}<i>
</i>
``
>@Sempervivum#1626343 Unfortunately I do not understand your question.
// make all parent li's visible:
// start with current li
let prnt = li[i];
// while parent li is available
while (prnt = prnt.closest('ul').closest('li')) {
// make it visible
prnt.style.display = "";
}
finds all parent elements. Try to adjust it to your needs. Instead of making the element visible you will have to add the class "active".>@Sempervivum#1626349 Take a look at this thread:
>@Sempervivum#1626351 Please explain your situation more detailed and provide some sample code or the URL of your page.
>@Sempervivum#1626353 Possible solution: Add a data attribute to the items in the submenu containing the ID or class of the corresponding item in the main menu.
``<i>
</i>switch (window.location.href) {
case "subitem1","subitem2","subitem3":
select main button 1
break
case "subitem4","subitem5","subitem6":
select main button 2 etc
break
default:
log any missing links
}<i>
</i>
``
// Key: href in sub menu
// value: href in main menu
const assignMainMenu = {
'/prepare': 'prepare',
'/vps': 'prepare'
// and so on
};
Then you can easily get the href in the main menu based on the href in the sub menu.>Is there a solution to select a button by its "href" without looping?
document.querySelector
`// href of sub menu in variable hrefSubmenu
itemMainMenu = document.querySelector('.btnnav[href="' + hrefSubMenu+ '"]);
>@Sempervivum#1626355 Yes, there is: You can use document.querySelector like this:
class="navbtn"
</C><br/>
JS: <C>
.btnnav
```<i>
</i>
const nav = document.querySelector('nav');
const navbtn = document.querySelectorAll('.navbtn');
const subnav = document.querySelector('.subnav');
const subnavbtn = document.querySelectorAll('.subnav a')
const current = window.location.href;
const hrefcurr = window.location.pathname;
btnhome = document.querySelector('.navbtn[href="/home"]');
btntopic = document.querySelector('.navbtn[href="/topics"]');
btnuser = document.querySelector('.navbtn[href="/users"]');
/* select correnspondent sub menu btn */
(function() {
subnavbtn.forEach(el => {
if (current.includes(el.href)) {
el.classList.add("selected");
}
});
})();
/* select correnspondent main menu btn */
switch (hrefcurr) {
case "/":
case "/home":
case "/api":
case "/client":
btnhome.classList.add("selected")
break
case "/topics":
case "/newtopics":
btntopic.classList.add("selected")
break
case "/users":
case "/mod":
btnuser.classList.add("selected")
break
default:
alert("missing "+hrefcurr)
}<i>
</i>
``
// key: path in sub menu
// value: path in main menu
const menuAssign = {
'/home': '/home',
'/client': '/home',
'/api': '/home',
'/topics': '/topics',
'/alltopics': '/topics',
'/users': '/users',
'/mod': '/users'
}
const url = location.href;
// get path, e. g. "/topics", from url
const result = url.match(//[a-z]+$/);
// is there a path?
if (result) {
// get path and path in main menu
const path = result[0],
mainPath = menuAssign[path];
console.log(path, mainPath);
// add class "active" in main menu according to path
document.querySelector('nav a[href="' + mainPath + '"]').classList.add('active');
// add class "active" in sub menu according to path
document.querySelector('div.subnav a[href="' + path + '"]').classList.add('active');
} else {
document.querySelector('nav a[href="/home"]').classList.add('active');
}
<nav class="main-nav">
<a href="/home" class="navbtn"><img src="icn/home.svg" alt="Home">Home</a>
<a href="/topics" class="navbtn"><img src="icn/topics.svg" alt="Messages">Topics</a>
<a href="/users" class="navbtn"><img src="icn/users.svg" alt="Users">Users</a>
</nav>
<i> </i><nav class="subnav">
<i> </i> <ul data-main-path="/topics">
<i> </i> <li><a href="/topics">Recent Topics</a></li>
<i> </i> <li><a href="/alltopics">All Topics</a></li>
<i> </i> </ul>
<i> </i></nav>
<i> </i><script>
<i> </i> const url = location.href;
<i> </i> const result = url.match(//[a-z]+$/);
<i> </i> if (result) {
<i> </i> const path = result[0];
<i> </i> const subItem = document.querySelector('nav.subnav a[href="' + path + '"]');
<i> </i> const mainPath = subItem.closest('ul').dataset.mainPath;
<i> </i> const mainItem = document.querySelector('nav.main-nav a[href="' + mainPath + '"]')
<i> </i> console.log(path, mainPath);
<i> </i> mainItem.classList.add('active');
<i> </i> subItem.classList.add('active');
<i> </i> } else {
<i> </i> document.querySelector('nav a[href="/home"]').classList.add('active');
<i> </i> }
>@Sempervivum#1626394 ... or without an array but a data attribute in the ul of the sub menu:
``<i>
</i>const navbtn = document.querySelectorAll('.navbtn');
const subnavbtn = document.querySelectorAll('.subnav a')
const current = window.location.href;
const data = document.querySelector(".subnav ul").getAttribute("data-mainnav");
/* selecting mainbtn and subnavbtn based on current url */
window.addEventListener('load', (event) => {
navbtn.forEach(el => {
if (data.includes(el.pathname)) {
el.classList.add("selected");
} else {
el.classList.remove("selected")
}
});
subnavbtn.forEach(function(btn) {
if (current.includes(btn.href)){
btn.classList.add("selected");
} else {
btn.classList.remove("selected");
}
});
});<i>
</i>
``