Highlight Parent Navigation Item - javascript

I think I'm close on this but the main navigation item is only getting highlighted when on that actual page, not on any page below it.
The desired effect is if you are on the page for Sub A, Sub B, Sub C then Main Item 1 would get the .primary-link-active class applied to it indicating you are in that section of the site.
Here is a jsfiddle, though because the code is based off of the URL I don't think this can work in a fiddle.
http://jsfiddle.net/richcoy/knjteaoj/1/
I got most of the Javascript script off of another question here on Stackoverflow.
Thanks for any help you can offer.
HTML
<ul class="nav site-nav">
<li class="nav__item has-dropdown">
Main Item 1<i class="icon-down-arrow small-text float--right mr-"></i>
<div class="dropdown">
<ul class="grid">
<li class="grid__item desk--one-third dropdown--column">
<div class="mb- ms- p- color-darker-gray">
Sub A
</div>
<div class="mb- ms- p- color-darker-gray">
Sub B
</div>
<div class="mb- ms- p- color-darker-gray">
Sub C
</div>
</li>
</ul>
</div>
</li>
<li class="nav__item has-dropdown">
Main Item 2<i class="icon-down-arrow small-text float--right mr-"></i>
<div class="dropdown">
<ul class="grid">
<li class="grid__item desk--one-third dropdown--column">
<div class="mb- ms- p- color-darker-gray">
Sub D
</div>
<div class="mb- ms- p- color-darker-gray">
Sub E
</div>
<div class="mb- ms- p- color-darker-gray">
Sub F
</div>
</li>
</ul>
</div>
</li>
</ul>
Javascript
$(function() {
var url = location.pathname; // get current URL
$('nav a.primary-link[href^="' + url + '"]').addClass('primary-link-active');
});
var $activeUL = $('.primary-link-active').closest('.primary-link');
/*
Revise below condition that tests if .primary-link-active is a submenu
*/
if($activeUL.attr('class') != 'primary-link') { //check if it is submenu
$activeUL
.parent() //This should return the li
.children('a') //The childrens are <a> and <ul>
.addClass('primary-link-active'); //add class active to the a
}

i think you dont really need div.dropdown, you can handle that with structure below:
<ul>
<li><a></a></li>
<li><a></a>
<ul>
<li><a></a></li>
<li><a></a></li>
<li><a></a></li>
</ul>
</li>
</ul>
anyway, try this:
html:
<ul class="nav site-nav">
<li class="nav__item has-dropdown"> Main Item 1<i class="icon-down-arrow small-text float--right mr-"></i>
<ul class="grid">
<li class="grid__item desk--one-third dropdown--column"> Sub A
<ul>
<li>link 1
<ul>
<li>link 3</li>
<li>link 4</li>
<li>link 5</li>
<li>link 6</li>
</ul>
</li>
<li>link 2</li>
</ul>
</li>
<li class="grid__item desk--one-third dropdown--column"> Sub B
</li>
<li class="grid__item desk--one-third dropdown--column"> Sub C
</li>
</ul>
</li>
<li class="nav__item has-dropdown"> Main Item 2<i class="icon-down-arrow small-text float--right mr-"></i>
<ul class="grid">
<li class="grid__item desk--one-third dropdown--column"> Sub D
</li>
<li class="grid__item desk--one-third dropdown--column"> Sub E
</li>
<li class="grid__item desk--one-third dropdown--column"> Sub F
</li>
</ul>
</li>
script:
$(function () {
var url = 'tempfornow'; //location.pathname; // get current URL
$('.nav a[href*="' + url + '"]').addClass('primary-link-active'); /*(1)*/
$('>a',$('.primary-link-active').parents('li.nav__item')).addClass('primary-link-active'); /*(2)*/
});
what did we do:
we select anchor which it contains 'url',
we select anchor which in it parents of first selected anchor.
note: you used $('nav .blabla'), nav is a tag, but you have div with class nav, you can use with class selector like this $('.nav .blabla')
I hope it helps.
JsFiddle Demo
JsFiddle Demo-2

Related

How can I make my 'li' click on Services to produce a drop down menu

I am trying to produce a custom navigation bar. Clicking on the Services or Plans list items should produce a drop down menu. However currently when you click on the items it does not work as expected instead, it produces an error that says: 'cannot read property contains of undefined'.
I simply want to be able to select the sub-menu class and add sub-menu-active class(which I have set in my CSS to display as block). I have initially set the display property in my CSS file to 'none'.
Here is the select html file I am trying to manipulate
<nav class="custom-navigationbar-container" >
<ul class="menu">
<li class="logo">Home</li>
<li class="item">About</li>
<li class="item">Blog</li>
<li class="item special">
<a tabindex="0">Services <i class="fas fa-sort-down"></i></a>
<ul class="sub-menu" >
<li class="sub-item" >Web Design</li>
<li class="sub-item" >Web Development</li>
<li class="sub-item" >SEO</li>
<li class="sub-item" >Digital Marketing</li>
</ul>
</li>
<li class="item special has-sub-menu">
<a tabindex="0">Plans <i class="fas fa-sort-down"></i></a>
<ul class="sub-menu">
<li class="sub-item" >Freelancer</li>
<li class="sub-item" >StartUp</li>
<li class="sub-item" >Enterprise</li>
</ul>
</li>
<li class="item" >Blog</li>
<li class="item" >Contact</li>
<li class="item button" >Log In</li>
<li class="item button secondary" >Sign Up</li>
<li class="toggle"><i class="fas fa-bars" ></i></li>
</ul>
</nav>
This is the .Js code
const special = document.querySelectorAll(".special");
const specialToggle = function(){
const subMenu = this.getElementsByClassName('sub-menu');
if(subMenu.classList.contains(".sub-menu-active")){
console.log('I am removing sub-menu-active now');
ul.classList.remove('.sub-menu-active');
}else{
console.log('I am adding sub-menu-active now');
ul.classList.add('.sub-menu-active');
}
};
for(const specials of special){
specials.addEventListener('click', specialToggle)
}
Your main problem is this line:
const subMenu = this.getElementsByClassName('sub-menu');
This will return multiple elements. Or at least it will return a COLLECTION of zero or one elements.
You might consider:
const subMenu = this.getElementsByClassName('sub-menu')[0];
But this will only get the first one, even if you clicked on the second one.
So maybe it's best to return the event in the function, get the target's parent, and find the 'sub-menu' within it. Then you're good to go:
const subMenu = e.target.parentElement.getElementsByClassName('sub-menu')
Here's a working version of the code against a simplified HTML structure:
const special = document.querySelectorAll(".special");
const specialToggle = function(e){
const subMenu = e.target.parentElement.getElementsByClassName('sub-menu')[0];
if (subMenu == null) {
console.log('No sub-menu. Perhaps you have clicked on a child element?');
} else if(subMenu.classList.contains(".sub-menu-active")){
console.log('I am removing sub-menu-active now');
subMenu.classList.remove('.sub-menu-active');
} else{
console.log('I am adding sub-menu-active now');
subMenu.classList.add('.sub-menu-active');
}
};
for(const specials of special){
specials.addEventListener('click', specialToggle)
}
<ul class="menu">
<li class="logo">Home</li>
<li class="item special">
<a tabindex="0">Services <i class="fas fa-sort-down"></i></a>
<ul class="sub-menu" >
<li class="sub-item" >Web Design</li>
<li class="sub-item" >Web Development</li>
</ul>
</li>
<li class="item special has-sub-menu">
<a tabindex="0">Plans <i class="fas fa-sort-down"></i></a>
<ul class="sub-menu">
<li class="sub-item" >Freelancer</li>
<li class="sub-item" >StartUp</li>
</ul>
</li>
</ul>

Multilevel sidebar menu using JS/jquery

I need to have a responsive sidebar navigation (as part of making the website responsive) for a multilevel menu of depth 3. The html markup is as below,
<nav>
<div data-level="1">
<ul>
<li class="main-menu">
Level1
<div data-level="2">
<ul>
<li class="submodule">
example1.1
<div data-level="3">
<ul>
<li>example1.1.1</li>
<li>example1.1.2</li>
<li>example1.1.3</li>
</ul>
</div>
</li>
<li class="submodule">
example1.2
<div data-level="2">
<ul>
<li>example1.2.1</li>
<li>example1.2.2</li>
<li>example1.2.3</li>
</ul>
</div>
</li>
<li class="submodule">
example1.3
<div data-level="2">
<ul>
<li>example1.3.1</li>
<li>example1.3.2</li>
<li>example1.3.3</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li>
Level2
<div data-level="2">
<ul>
<li>
example2.1
<div data-level="3">
<ul>
<li>example2.1.2</li>
<li>example2.1.3</li>
<li>example2.1.4</li>
</ul>
</div>
</li>
<li>
example2.2
<div data-level="2">
<ul>
<li>example2.2.1</li>
<li>example2.2.2</li>
<li>example2.2.3</li>
</ul>
</div>
</li>
<li>
example2.3
<div data-level="2">
<ul>
<li>example2.3.1</li>
<li>example2.3.2</li>
<li>example2.3.4</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</nav>
At first menu shows only the top level,
Level1
Level2
When Level1 is clicked menu should show,
Back to Main Menu
example 1.1
example 1.2
When example1.1 is clicked,
Back to sublevel
example1.1.1
example1.1.2
example1.1.3
Each of back button takes to the menu before.
How to do the navigation using JS/jQuery?
It was necessary to adjust your navigation a little bit - the navigation for Level 2 was missing the submodule class. In addition you could consider to adjust your usage of <div data-level="3"> as you only use it for the 2nd and 3rd sublevel navigation while the 1st sublevel is in a <div data-level="2">. The following navigation fulfills your requirements while it is not complete - you can adjust it so a visible sublevel navigation gets toggled when the main navigation gets clicked. I already took care about the issue to only have one main navigation and submodule navigation visible at the same time.
$(".main-menu").on("click", function() {
if ($(".main-menu").not(this).find(".submodule").is(":visible")) {
$(".main-menu").not(this).find(" > div[data-level='2'], .submodule").hide();
}
$(this).find(" > div[data-level='2'], .submodule").toggle();
});
$(".submodule").on("click", function(e) {
e.stopPropagation();
$(".submodule").not(this).each(function() {
if ($(this).find(" > div[data-level='3'], > div[data-level='2']").is(":visible")) {
$(this).find(" > div[data-level='3'], > div[data-level='2']").hide();
}
});
$(this).find(" > div[data-level='3'], > div[data-level='2']").toggle();
});
$(".submodule.back").on("click", function(e) {
e.stopPropagation();
$(this).closest(".main-menu").find(" > div[data-level='2'], .submodule").hide();;
});
$(".back").not(".submodule").on("click", function(e) {
e.stopPropagation();
$(this).closest(".submodule").find(" > div[data-level='3'], > div[data-level='2']").hide();
});
div[data-level ="2"]{
display:none;
}
div[data-level ="3"]{
display:none;
}
.submodule {
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<div data-level="1">
<ul>
<li class="main-menu">
Level1
<div data-level="2">
<ul>
<li class="submodule back">
Back to main menu
</li>
<li class="submodule">
example1.1
<div data-level="3">
<ul>
<li class="back">Back to sublevel</li>
<li>example1.1.1</li>
<li>example1.1.2</li>
<li>example1.1.3</li>
</ul>
</div>
</li>
<li class="submodule">
example1.2
<div data-level="2">
<ul>
<li class="back">Back to sublevel</li>
<li>example1.2.1</li>
<li>example1.2.2</li>
<li>example1.2.3</li>
</ul>
</div>
</li>
<li class="submodule">
example1.3
<div data-level="2">
<ul>
<li class="back">Back to sublevel</li>
<li>example1.3.1</li>
<li>example1.3.2</li>
<li>example1.3.3</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li class="main-menu">
Level2
<div data-level="2">
<ul>
<li class="submodule back">
Back to main menu
</li>
<li class="submodule">
example2.1
<div data-level="3">
<ul>
<li class="back">Back to sublevel</li>
<li>example2.1.2</li>
<li>example2.1.3</li>
<li>example2.1.4</li>
</ul>
</div>
</li>
<li class="submodule">
example2.2
<div data-level="2">
<ul>
<li class="back">Back to sublevel</li>
<li>example2.2.1</li>
<li>example2.2.2</li>
<li>example2.2.3</li>
</ul>
</div>
</li>
<li class="submodule">
example2.3
<div data-level="2">
<ul>
<li class="back">Back to sublevel</li>
<li>example2.3.1</li>
<li>example2.3.2</li>
<li>example2.3.4</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</nav>

Combine Navigation UL jQuery Function

I am trying to write a function that will combine two children ul#level_2and append them to their parent li#level_1 within a dropdown #navigation.
I currently have the following which does the job, but it means I have to manually target each category. I'm sure there is a far shorter way to produce the same results with very little code.
$('li#furniture ul.level_2').children('li').appendTo('li#furniture ul.level_2:first');
$('li#furniture ul.level_2').children('li').not(':first').remove();
Here is a shortened version of my current html structure & below is the desired result:
Simple Current HTML
<div id="navigation">
<ul id="level_1">
<li class="level_1">
<div class="subnav_wrapper">
<ul class="level_2">
<li class="level_2">
Link A
</li>
</ul>
<ul class="level_2">
<li class="level_2">
Link B
</li>
</ul>
</div>
</li>
</ul>
</div>
Desire HTML
<div id="navigation">
<ul id="level_1">
<li class="level_1">
<ul class="level_2">
<li class="level_2">
Link A
</li>
<li class="level_2">
Link B
</li>
</ul>
</li>
</ul>
</div>
Full Detailed HTML
<div id="navigation">
<ul id="level_1">
<li class="level_1 furniture">
Furniture
<div class="subnav_wrapper">
<ul class="level_2">
<li class="level_2 sofa">
Sofa
</li>
</ul>
<ul class="level_2">
<li class="level_2 bed">
Bed
</li>
</ul>
</div>
</li>
<li class="level_1 bathroom">
Bathroom
<div class="subnav_wrapper">
<ul class="level_2">
<li class="level_2 shower">
<a href="#">Shower/a>
</li>
</ul>
<ul class="level_2">
<li class="level_2 bath">
Bath
</li>
</ul>
</div>
</li>
</ul>
</div>
This should do what you need.
var wrapper = $(".subnav_wrapper").contents();
$(".subnav_wrapper").replaceWith(wrapper );
$('ul.level_2').children('li').appendTo('ul.level_2:first');
$('ul.level_2').not(':first').remove();
JSFIDDLE DEMO

Show nested UL using jQuery

I have a nested ul to make a sub menu. I want a click event to show the child ul and keep the others collapsed.
HTML
<div class="sideMenu">
<ul>
<li class="titledUl"><b>Dashboard</b>
</li>
<ul class="subUl">
<li>Dash Tool 1
</li>
<li class="subUl">Dash Tool 2
</li>
</ul>
</ul>
<ul>
<li class="titledUl"><b>User Managment</b>
</li>
<ul class="subUl">
<li>UM Tool 1
</li>
<li>UM Tool 2
</li>
</ul>
</ul>
</div>
jQuery
$( document ).ready(function() {
console.log( "ready!" );
$('.titledUl').click(function() {
console.log('clicked')
$(this).closest('.subUl').show();
console.log("should show")
});
});
It shows all my console logs when I click on the parent ul. (also the sub uls are hidden using css display none)
Thanks!
Hello your job done here: http://jsfiddle.net/webcarvers/RYvGv/
HTML:
<div class="sideMenu">
<ul>
<li class="titledUl"><b>Dashboard</b>
<ul class="subUl">
<li>Dash Tool 1</li>
<li>Dash Tool 2</li>
</ul>
</li>
</ul>
<ul>
<li class="titledUl"><b>User Managment</b>
<ul class="subUl">
<li>UM Tool 1</li>
<li>UM Tool 2</li>
</ul>
</li>
</ul>
</div>
CSS:
.subUl{
display:none;
}
.titledUl{
cursor:pointer;
}
JS:
$(document).ready(function(){
$('.titledUl').on('click', function() {
$(this).closest('ul').find(".subUl").slideToggle(500);
});
});
I got it working with the help of you all. Thank you!
New HTML
<div class="sideMenu">
<ul>
<li class="titledUl"><b>Dashboard</b>
<ul class="subUl">
<li>Dash Tool 1
</li>
<li class="subUl">Dash Tool 2
</li>
</ul>
</li>
</ul>
<ul>
<li class="titledUl"><b>User Managment</b>
<ul class="subUl">
<li>UM Tool 1
</li>
<li>UM Tool 2
</li>
</ul>
</li>
</ul>
</div>
New jQuery
$( document ).ready(function() {
console.log( "ready!" );
$('.titledUl').click(function() {
console.log('clicked');
$(this).children().show();
console.log("should show");
});
});

how can i make my nav bar with js

okay so i have a Nav bar, and now i want to make it when it loads the page, it builds the nav bar
<div id="nav">
<div id="nav_holder">
<ul>
<li class="first"> Home </li>
<li>Rules </li>
<ul class="drop">
<li>Help
<ul class="drop">
<li>Beginnen</li>
<li>Geld Verdienen</li>
<li>Protection Blocks</li>
<li>Trade Signs</li>
<li>Sign beveiliging</li>
<li>Item ID List</li>
</ul>
</li>
</ul></li>
<li>Donate </li>
<ul class="drop">
<li>Staff
<ul class="drop">
<li>Faircraft team</li>
<li>Solliciteren</li>
</ul>
</li>
</ul></li>
<li>Videos </li>
<li></li>
<li>Forum </li>
</ul>
<ul class="right">
<li class="first">Sign Up! </li>
</ul>
</div>
</div>
so i think i need this code
function holder()
{ // check if adding 1 exceeds number of pics in array
var build='<img border="0" src="'+picArray[picCount]+'" width="649">\n';
document.getElementById("nav_holder").innerHTML=build;
}
}
but then i need it to make the nav bar,
btw i need help with the body onload feature too:p, please help
Instead of window.onload, try using jQuery http://jquery.com/:
$(document).ready(function(){
// build menu
)};
this will execute when the DOM finishes loading.

Categories