submenu on click must remain open - javascript

I have a vertical menu with some submenu items, and this submenu opens on click.
But the problem is that when I click on one of the submenu items, the submenu closes, whereas I want it to remain open, since when I browse on the submenu items
Here's the html:
<div class="ul_container">
<ul class="mainnav" id="nav" style="list-style:none;">
<li><a id="active" href="index.html"><strong>HOME</strong></a></li>
<li>COLLECTIONS
<ul class="subnav" id="sub1" style="display:none">
<li class="first">spring/summer 2013
<li class="first">autumn/winter 2013
<li class="first">autumn/winter 2012
<li class="first">autumn/winter 2011
</ul>
</li>
<li>PORTRAIT</li>
<li>HERITAGE</li>
<li>PRESS</li>
<li>CONTACTS</li>
</ul>
</div>
and the js
function toggleID(IDS) {
var sel = document.getElementById('nav').getElementsByTagName('ul');
for (var i=0; i<sel.length; i++) {
if (sel[i].id != IDS) { sel[i].style.display = 'none'; }
}
sel = document.getElementById(IDS);
sel.style.display = (sel.style.display != 'block') ? 'block' : 'none';
}

<div class="ul_container">
<ul class="mainnav" id="nav" style="list-style:none;">
<li><a id="active" href="#"><strong>HOME</strong></a></li>
<li>COLLECTIONS
<ul class="subnav" id="sub1" style="display:none">
<li class="first">spring/summer 2013</li>
<li class="first">autumn/winter 2013</li>
<li class="first">autumn/winter 2012</li>
<li class="first">autumn/winter 2011</li>
</ul>
</li>
<li>PORTRAIT</li>
<li>HERITAGE</li>
<li>PRESS</li>
<li>CONTACTS</li>
</ul>
$("#test").click(function() {
var sel = document.getElementById('nav').getElementsByTagName('ul');
for (var i = 0; i < sel.length; i++) {
if (sel[i].id != 'sub1') {
sel[i].style.display = 'none';
}
}
sel = document.getElementById('sub1');
sel.style.display = (sel.style.display != 'block') ? 'block' : 'none';
});
Working Example

Is your problem thay you need to remember the visibility state of the submenu once you klick on the subitems?
If so, you need to remember the state of the submenu. You can accomplish this using cookies or localstorage.
Html (just small changes, like removing onclick and fixing html)
<div class="ul_container">
<ul class="mainnav" id="nav" style="list-style:none;">
<li><a id="active" href="index.html"><strong>HOME</strong></a></li>
<li>COLLECTIONS
<ul class="subnav" id="sub1">
<li class="first">spring/summer 2013</li>
<li class="first">autumn/winter 2013</li>
<li class="first">autumn/winter 2012</li>
<li class="first">autumn/winter 2011</li>
</ul>
</li>
<li>PORTRAIT</li>
<li>HERITAGE</li>
<li>PRESS</li>
<li>CONTACTS</li>
</ul>
</div>
Javascript (using jquery with localstorage)
if(localStorage.getItem("state") == "closed") // <-- this checks closed/open state and sets subnav accordingly
$('.subnav').hide();
$('.subnav').parent().click(function () {
$(this).find('#sub1').toggle(); //<-- This toggles the menu open/close
// ** Remeber state ** //
if (localStorage.getItem("state") == "open") {
localStorage.setItem("state", "closed"); // <-- this remembers "open" after user navigates
} else {
localStorage.setItem("state", "open"); // <-- this remembers "open" after user navigates
}
// ** Remeber state ** //
});
My example uses jquery, if you have the possibility to start using it you should do so.
You can replace most of your javascript with a few lines using jquery
Check out working fiddle here
http://jsfiddle.net/urbanbjorkman/jGwnz/

Urban Bjorkman, I use your code but something is wrong...is that right?
<html>
<head>
<script type="text/javascript" >
if (localStorage.getItem("state") == "closed") // <-- this checks closed/open state and sets subnav accordingly
$('.subnav').hide();
$('.subnav').parent().click(function () {
$(this).find('#sub1').toggle(); //<-- This toggles the menu open/close
// ** Block to remeber state ** //
if (localStorage.getItem("state") == "open") {
localStorage.setItem("state", "closed"); // <-- this remembers "open" after user navigates
} else {
localStorage.setItem("state", "open"); // <-- this remembers "open" after user navigates
}
// ** Block to remeber state ** //
});
</script>
</head>
<body>
<div class="ul_container">
<ul class="mainnav" id="nav" style="list-style:none;">
<li><a id="active" href="index.html"><strong>HOME</strong></a>
</li>
<li>COLLECTIONS
<ul class="subnav" id="sub1">
<li class="first">spring/summer 2013
</li>
<li class="first">autumn/winter 2013
</li>
<li class="first">autumn/winter 2012
</li>
<li class="first">autumn/winter 2011
</li>
</ul>
</li>
<li>PORTRAIT
</li>
<li>HERITAGE
</li>
<li>PRESS
</li>
<li>CONTACTS
</li>
</ul>
</div>
</body>
</html>

Related

Dismiss dropdown on outside click using vanilla JavaScript and ARIA roles

I've been trying to create a very basic dropdown menu but am unable to get the hide on outside click part right. I've gone through several iterations yet always end up unable to dismiss it correctly or close other opened dropdowns when another is activated. Here is my latest variation.
function Menu(trigger) {
let expanded = trigger.getAttribute("aria-expanded") === "true" || false;
let menu = trigger.nextElementSibling;
trigger.setAttribute("aria-expanded", !expanded);
menu.hidden = !menu.hidden;
}
const menuTriggers = document.querySelectorAll(".menu-trigger");
menuTriggers.forEach((menuTrigger) => {
menuTrigger.addEventListener("click", () => {
Menu(menuTrigger);
});
});
<button class="menu-trigger" aria-expanded="false">Menu</button>
<ul class="menu" hidden>
<li class="menu-item">
<a class="menu-link" href="">Books</a>
</li>
<li class="menu-item">
<a class="menu-link" href="">Authors</a>
</li>
<li class="menu-item">
<a class="menu-link menu-link-separator" href="">Genres</a>
</li>
<li class="menu-item">
<a class="menu-link" href="">Themes</a>
</li>
</ul>
You'll have to listen for a mousedown event on the window object to detect the off-click and only close the drop down menu if the event.target is not contained by the drop down menu itself.
function Menu(trigger)
{
let expanded = trigger.getAttribute("aria-expanded") === "true" || false;
let menu = trigger.nextElementSibling;
trigger.setAttribute("aria-expanded", !expanded);
menu.hidden = !menu.hidden;
if(!menu.hidden)
{
setTimeout(() =>
{
let eventType = "mousedown";
let handler = (e) =>
{
if (trigger !== e.target && !menu.contains(e.target))
{
Menu(trigger);
}
window.removeEventListener(eventType, handler, false);
};
window.addEventListener(eventType, handler, false);
}, 0);
}
}
const menuTriggers = document.querySelectorAll(".menu-trigger");
menuTriggers.forEach((menuTrigger) =>
{
menuTrigger.addEventListener("click", () =>
{
Menu(menuTrigger);
});
});
<div style="display:inline-block">
<button class="menu-trigger" aria-expanded="false">Menu</button>
<ul class="menu" hidden>
<li class="menu-item">
<a class="menu-link" href="https://amazon.com">Books</a>
</li>
<li class="menu-item">
<a class="menu-link" href="">Authors</a>
</li>
<li class="menu-item">
<a class="menu-link menu-link-separator" href="">Genres</a>
</li>
<li class="menu-item">
<a class="menu-link" href="">Themes</a>
</li>
</ul>
</div>

Selecting anchor child of list item

I'm struggling to select in the DOM the anchor link that is a direct child of my list item "dropdown-nav. It should change the link when the list item is clicked but doesn't. The active class applies perfectly. What am I doing wrong here?
var acc = document.getElementsByClassName("dropdown-nav");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active-hit");
this.find("a").attr("href", "http://www.google.com/");
});
}
<ul>
<li class="dropdown-nav">
<a href="/about">About
<span class="nav-desc">Our company</span>
</a>
<div class="hide-border"></div>
<ul class="second-tier">
<div class="hide-corner"></div>
<li>Our Mission</li>
<li>Our People</li>
<li>Work with us</li>
<li>High Value Manufacturing</li>
</ul>
</li>
</ul>
You included jQuery so you may update your code to simply use jQuery like this:
$(".dropdown-nav").click(function() {
$(this).toggleClass('active-hit');
$(this).find('a').attr("href", "http://www.google.com/");
})
.active-hit {
background:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="dropdown-nav">
<a href="/about">About
<span class="nav-desc">Our company</span>
</a>
<div class="hide-border"></div>
<ul class="second-tier">
<div class="hide-corner"></div>
<li>Our Mission</li>
<li>Our People</li>
<li>Work with us</li>
<li>High Value Manufacturing</li>
</ul>
</li>
</ul>
this is not jQuery object. Replace this line:
this.find("a").attr("href", "http://www.google.com/");
With this (this will change href of first link, if you need to change all of them, then iterate):
this.getElementsByTagName('a')[0].setAttribute('href', 'http://www.google.com/');
If you have included jQuery, you can do this too:
$(this).find("a").attr("href", "http://www.google.com/");

Detecting selected element

I have the following Javascript to operate my accordion menu.
<script src="http://thecodeplayer.com/uploads/js/jquery-1.7.1.min.js"></script>
<script src="http://thecodeplayer.com/uploads/js/prefixfree-1.0.7.js"></script>
<script>
$(document).ready(function() {
$("#accordian a").click(function() {
var link = $(this);
var closest_ul = link.closest("ul");
var parallel_active_links = closest_ul.find(".active")
var closest_li = link.closest("li");
var link_status = closest_li.hasClass("active");
var count = 0;
closest_ul.find("ul").slideUp(function() {
if (++count == closest_ul.find("ul").length)
parallel_active_links.removeClass("active");
});
if (!link_status) {
closest_li.children("ul").slideDown();
closest_li.addClass("active");
}
})
$(".selected").parent().slideDown();
})
</script>
How do I modify the code to detect the 'selected' class and open the corresponding panel from the following html script.
<div id="accordian">
<ul>
<li>
<h3 class="mtop"> </h3>
</li>
<li>
<h3>Dashboard</h3>
<ul>
<li class="litop">Reports</li>
<li class="limid">Search</li>
<li class="limid">Graphs</li>
<li class="libot">Settings</li>
</ul>
</li>
<li>
<h3>Calendar</h3>
<ul>
<li class="litop">Current Month</li>
<li class="limid">Current Week</li>
<li class="limid">Previous Month</li>
<li class="limid">Previous Week</li>
<li class="limid">Next Month</li>
<li class="limid">Next Week</li>
<li class="limid">Team Calendar</li>
<li class="limid">Private Calendar</li>
<li class="libot">Settings</li>
</ul>
</li>
<li>
<h3>Favourites</h3>
<ul>
<li class="litop">Global favs</li>
<li class="limid selected">My favs</li>
<li class="limid">Team favs</li>
<li class="libot">Settings</li>
</ul>
</li>
<li>
<h3 class="mbot"> </h3>
</li>
</ul>
</div>
Here IS Fiddle Link - https://jsfiddle.net/p7wm4tL2/
You have old version of jquery,
Try updating your jquery version.
$(document).ready(function() {
$("#accordian a").click(function() {
var link = $(this);
var closest_ul = link.closest("ul");
var parallel_active_links = closest_ul.find(".active")
var closest_li = link.closest("li");
var link_status = closest_li.hasClass("active");
var count = 0;
closest_ul.find("ul").slideUp(function() {
if (++count == closest_ul.find("ul").length)
parallel_active_links.removeClass("active");
});
if (!link_status) {
closest_li.children("ul").slideDown();
closest_li.addClass("active");
}
})
$(".selected").parent().slideDown();
});
Once check working code here.

Expand parent menu if child menu is selected

I have a menu with sub child menus. The problem I am facing is that whenever I select a child menu after page loads, the menu collapses. I want to open the parent menu expanded.
The HTML Code is:
<div id='cssmenu'>
<ul>
<li><a href='http://internallink.com/home'><span>Home</span></a></li>
<li class='active has-sub'><a href='http://internallink.com/products'><span>Products</span></a>
<ul>
<li class='has-sub'><a href='http://internallink.com/product1'><span>Product 1</span></a>
<ul>
<li><a href='http://internallink.com/subProduct'><span>Sub Product</span></a></li>
<li class='last'><a href='http://internallink.com/subProduct'><span>Sub Product</span></a></li>
</ul>
</li>
<li class='has-sub'><a href='http://internallink.com/product2'><span>Product 2</span></a>
<ul>
<li><a href='http://internallink.com/subProduct'><span>Sub Product</span></a></li>
<li class='last'><a href='http://internallink.com/subProduct'><span>Sub Product</span></a></li>
</ul>
</li>
</ul>
</li>
<li><a href='http://internallink.com/about'><span>About</span></a></li>
<li class='last'><a href='http://internallink.com/contact'><span>Contact</span></a></li>
</ul>
</div>
The JS is:
jQuery(document).ready(function () {
jQuery('#cssmenu').on("click","li.has-sub .holder",function () {
var element = jQuery(this).parent('li');
if (element.hasClass('open')) {
element.removeClass('open');
element.find('li').removeClass('open');
element.find('ul').slideUp();
}
else {
element.addClass('open');
element.children('ul').slideDown();
element.siblings('li').children('ul').slideUp();
element.siblings('li').removeClass('open');
element.siblings('li').find('li').removeClass('open');
element.siblings('li').find('ul').slideUp();
}
});
jQuery('#cssmenu ul li.has-sub').prepend('<span class="holder"></span>');
});
How can i expand the parent menu if child menu is selected.
Fiddle: https://jsfiddle.net/x415mjfq/
You have the full, absolute URL's in the links; that can be used to your advantage. Simply use document.querySelector with the square bracket selector, and the location.href property:
document.querySelector("a[href='" + location.href + "']").classList.add("selected");
Then, do whatever you need to do to it. In this example, I'm adding the selected class.
Fiddle

.click() functionality when clicking elements

Basically i want to click on a tab and a drop down menu appears then when you re-click the same tab or any of the others I want it to hide that tab/show the other tab if clicked on the same/other tab.
I tried
$('.click').click(function() {
$(this).find('.sub-nav-list').toggleClass('active');
});
and tried
$('.click').click(function() {
$('.sub-nav-list').removeClass('active');
$(this).find('.sub-nav-list').toggleClass('active');
});
but cant work it out! any insight? Thanks
html:
<nav class="secondary-nav">
<ul class="list clearfix">
<li class="leaders click">Leadership <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Management</li>
<li>Board of Directors</li>
</ul>
</li>
<li class="contact click">Contact Info <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Email Notification</li>
<li>Information Request</li>
</ul>
</li>
<li class="docs click">Documents <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Governance Documents</li>
<li>Press Release</li>
<li>Reports & Presentations</li>
<li>Sec Filings</li>
<li>Frenquently Asked Questions</li>
<li>Tax Information</li>
</ul>
</li>
<li class="research click">Research <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Dividends and Distributions</li>
<li>Stock Information</li>
<li>Analyst Coverage</li>
<li>Market Makers</li>
</ul>
</li>
</ul>
</nav>
I can see at least two possible issues there.
1) sub-nav-list is not a children of click element. If they are on the same level something like that might work:
$('.click').click(function() {
$(this).parent().find('.sub-nav-list').toggleClass('active');
});
2) You have these elements generated dynamically - so you need use on with selector of any parent element that exists before you dynamically generate your sub-menus (let say nav-list):
$(".click").on("click", ".nav-list", function() {
$(this).parent().find('.sub-nav-list').toggleClass('active');
});

Categories