How do I keep a submenu open when clicked? - javascript

This was created by someone else, but some submenus stay open while one stays closed when clicked. I have an idea of what I can do, but I have very little knowledge of JS. I was thinking if sub5 (the id for the submenu that stays closed), "something to make it true, then false if not sub5" How can I do this?
HTML
<nav id="rightNav">
<div class="menutitle first" onClick="SwitchMenu('sub1')">fabrics</div>
<div id="sub1" class="submenu">
<ul>
<li>lee jofa</li>
<li>groundworks</li>
<li>threads</li>
<li>gp & j baker</li>
<li>mulberry home</li>
<li>baker lifestyle</li>
<li>blithfield</li>
</ul>
</div>
<!-- end div#sub1 (fabrics) -->
<div class="menutitle" onClick="SwitchMenu('sub2')">furniture</div>
<div id="sub2" class="submenu">
<ul>
<li>lee jofa upholstery</li>
<li>lee jofa occasionals</li>
<li>Bunny Williams Home</li>
<li>holland & co.</li>
<li>macrae</li>
<li>elle & marks</li>
</ul>
</div>
<!-- end div#sub2 (furniture) -->
<div class="menutitle" onClick="SwitchMenu('sub3')">wallcoverings</div>
<div id="sub3" class="submenu">
<ul>
<li>lee jofa</li>
<li>cole & son</li>
<li>groundworks</li>
<li>threads</li>
<li>gP & j baker</li>
<li id="blithfield-wall">blithfield</li>
<li>farrow & ball</li>
<li>lincrusta</li>
</ul>
</div>
<!-- end div#sub3 (wallcoverings) -->
<div class="menutitle">trimmings</div>
<div class="menutitle" onClick="SwitchMenu('sub5')">carpets</div>
<div id="sub5" class="submenu">
<ul>
<li>lee jofa carpet</li>
<li id="gw-carpet">groundworks</li>
<li>threads</li>
</ul>
</div>
<!-- end div#sub5 (carpets) -->
<div class="menutitle" id="archive-collection">designer collections</div>
<div class="menutitle last">archives</div>
</nav>
<!-- end nav#rightNav -->
JS
if (document.getElementById) { //DynamicDrive.com change
document.write('<style type="text/css">\n')
document.write('.submenu{display: none;}\n')
document.write('</style>\n')
}
function SwitchMenu(obj) {
if (document.getElementById) {
var el = document.getElementById(obj);
var ar = document.getElementById("rightNav").getElementsByTagName("div"); //DynamicDrive.com change
if (el.style.display != "block") { //DynamicDrive.com change
for (var i = 0; i < ar.length; i++) {
if (ar[i].className == "submenu") //DynamicDrive.com change
ar[i].style.display = "none";
}
el.style.display = "block";
} else {
el.style.display = "none";
}
}
}

You have a class and a style.
Your style is defined in the class, so you can't access it with element.style.
A simple solution is to change this line:
<div id="sub5" class="submenu">
to
<div id="sub5" class="submenu" style="display:none;">

Related

How to display only one item at a time using JavaScript

I'm creating a sidebar menu for Archiving news items. My list shows the years of the news items: 2019, 2018, 2017. When clicked these then display a drop-down container showing the months - September 2019, August 2019, etc.
I'm using a bit of JavaScript to display the drop-down container. The problem I have is that when you click on 2019 and then 2018 both years are showing their relevant months. How do I only show the information for one year at a time? i.e. when clicking on 2019 it displays the months for that year, then when I click on 2018 the content for 2019 hides and only the content for 2018 then shows.
var dropdown = document.getElementsByClassName("dropdown-btn-2");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
.dropdown-container-2 {
display: none;
background-color: transparent;
}
.dropdown-btn-2 {
display: inline-block;
}
<div class="py-1">
<div class="dropdown-btn-2">
<i class="fas fa-chevron-circle-right fa-fw colour-2"></i> 2019
</div>
<div class="dropdown-container-2 ml-4">
<ul class="list-unstyled">
<li class="pt-1">December 2019</li>
<li class="pt-1">November 2019</li>
<li class="pt-1">October 2019</li>
<li class="pt-1">September 2019</li>
</ul>
</div>
</div>
<div class="py-1">
<div class="dropdown-btn-2">
<i class="fas fa-chevron-circle-right fa-fw colour-2"></i> 2018
</div>
<div class="dropdown-container-2 ml-4">
<ul class="list-unstyled">
<li class="pt-1">December 2018</li>
<li class="pt-1">November 2018</li>
<li class="pt-1">October 2018</li>
<li class="pt-1">September 2018</li>
</ul>
</div>
</div>
Whenever you toggle a dropdown, remove the active class from all the other ones.
Also it's better to add the active class to the dropdown container and then hide the content when that class is missing using css.
Finally, I think it's more neat to manage each group separately (loop the dropdown containers and then add the event listener to the button that is inside them).
document.querySelectorAll(".py-1").forEach(function(dropdown, index, list) {
dropdown.querySelector(".dropdown-btn-2").addEventListener("click", function() {
list.forEach(function(item) {
if (item !== dropdown) item.classList.remove("active");
});
dropdown.classList.toggle("active");
});
});
.dropdown-btn-2 {
display: inline-block;
}
.py-1>.dropdown-container-2 {
background-color: transparent;
display: none;
}
.py-1.active>.dropdown-container-2 {
display: block;
}
<div class="py-1">
<div class="dropdown-btn-2">
<i class="fas fa-chevron-circle-right fa-fw colour-2"></i> 2019
</div>
<div class="dropdown-container-2 ml-4">
<ul class="list-unstyled">
<li class="pt-1">December 2019</li>
<li class="pt-1">November 2019</li>
<li class="pt-1">October 2019</li>
<li class="pt-1">September 2019</li>
</ul>
</div>
</div>
<div class="py-1">
<div class="dropdown-btn-2">
<i class="fas fa-chevron-circle-right fa-fw colour-2"></i> 2018
</div>
<div class="dropdown-container-2 ml-4">
<ul class="list-unstyled">
<li class="pt-1">December 2018</li>
<li class="pt-1">November 2018</li>
<li class="pt-1">October 2018</li>
<li class="pt-1">September 2018</li>
</ul>
</div>
</div>
Keep in mind that if cannot have smooth transitions when using display: none and display: block to hide and show the element (opacity:0 and opacity:1 works)
When the click event is fired, you should look for all the other active dropdowns and remove the class. It will become something like this:
var dropdown = document.getElementsByClassName("dropdown-btn-2");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
// Start changes
var activeDropdowns = document.querySelectorAll(".dropdown-btn-2.active");
for (btn of activeDropdowns) {
if (btn != this) {
btn.classList.remove("active");
var cont = btn.nextElementSibling;
cont.style.display = "none";
}
}
// End changes
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
.dropdown-container-2 {
display: none;
background-color: transparent;
}
.dropdown-btn-2 {
display: inline-block;
}
<div class="py-1">
<div class="dropdown-btn-2">
<i class="fas fa-chevron-circle-right fa-fw colour-2"></i> 2019
</div>
<div class="dropdown-container-2 ml-4">
<ul class="list-unstyled">
<li class="pt-1">December 2019</li>
<li class="pt-1">November 2019</li>
<li class="pt-1">October 2019</li>
<li class="pt-1">September 2019</li>
</ul>
</div>
</div>
<div class="py-1">
<div class="dropdown-btn-2">
<i class="fas fa-chevron-circle-right fa-fw colour-2"></i> 2018
</div>
<div class="dropdown-container-2 ml-4">
<ul class="list-unstyled">
<li class="pt-1">December 2018</li>
<li class="pt-1">November 2018</li>
<li class="pt-1">October 2018</li>
<li class="pt-1">September 2018</li>
</ul>
</div>
</div>
Since only one element will be shown at a time, you can also use "querySelector" instead of "querySelectorAll" and avoid the loop, but this is probably safer.
How about updating ONLY your javascript like this:
var dropdown = document.getElementsByClassName("dropdown-btn-2");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
var container = document.getElementsByClassName("dropdown-container-2");
var dropdownContent = this.nextElementSibling;
if(dropdownContent.style.display == "block") {
dropdownContent.style.display = "none";
return;
}
for (var j = 0; j < container.length; j++) {
if(container[j].style.display = "block") {
container[j].style.display = "none";
}
}
dropdownContent.style.display = "block";
});
}
Check all other containers and hide them
toggles show/hide if you are clicking on the same element
codePen available Here: https://codepen.io/ermiarch/pen/XWrQodo

How to enable and disable tab-pane inputs elements

I have created a tab-pane using bootstrap as shown in my code snippet below (2 tabs) and both contain multiple ul->li->input check boxes. I am trying to do as if Tab_01(tab_urban) is active then allow to select check boxes from Tab_01 not from Tab_02(tab_rural)-> disable check boxes vice versa. Unable to identify where I am doing mistake.
##JS
var el_u = document.getElementById('urban');
var chk_r = document.getElementsByClassName('myCheck_u');
var el_r = document.getElementById('rural');
var chk_u = document.getElementsByClassName('myCheck_r');
if ((hasClass(el_u, 'active')) == true && (hasClass(el_r, 'active')) !== true) {
console.log('urban selected');
for (var k = 0; k < chk_r.length; k++) {
chk_r[k].disabled = false;
}
for (var k = 0; k < chk_u.length; k++) {
chk_u[k].disabled = true;
}
} else if ((hasClass(el_r, 'active')) == true && (hasClass(el_u, 'active')) !== true) {
console.log('rural selected');
for (var k = 0; k < chk_u.length; k++) {
chk_r[k].disabled = true;
}
for (var k = 0; k < chk_r.length; k++) {
chk_u[k].disabled = false;
}
}
/*******************************************/
##HTML
<ul class="nav nav-tabs">
<li id="urban" class="active">Tab 1</li>
<li id="rural" class="">Tab 2</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab_urban">
<ul>
<li>
<input class="myCheck_u" type="checkbox" name="Wave_fiters[]" value="1"> Wave-1 </li>
<li>
<input class="myCheck_u" type="checkbox" name="Wave_fiters[]" value="2"> Wave-2 </li>
</ul>
</div>
<div class="tab-pane" id="tab_rural">
<ul>
<li>
<input class="myCheck_r" type="checkbox" name="HS1_fiters[]" value="1"> Entertainment Sites </li>
<li>
<input class="myCheck_r" type="checkbox" name="HS1_fiters[]" value="2"> News </li>
</ul>
</div>
</div>
Tabs are changing it's state.
Initially in Tab_01 all inputs all can be checked and in Tab_02 are
disabled When I am change tab(Tab_01 to Tab_02) not enabling the
input check boxes of Tab_02 and disabling Tab_01
This works as you've requested, but I started again with the code as I felt it could be simplified a little using jquery.
The jquery is fully commented, but let me know if you don't understand something or were hoping for something else.
I commented out the display: none; CSS rule so you could see the other checkboxes were disabled.
Hope it helps
Demo
// Add click event to tab links
$("a[data-toggle='tab']").click(function() {
// Remove active classes from tab link and panels
$("a[data-toggle='tab'].active").removeClass("active");
$("div.tab-pane.active").removeClass("active");
// Add active class to the tab link and panel
$(this).addClass("active");
$("div.tab-pane" + $(this).attr("href")).addClass("active");
// Disable all inputs
$("div.tab-pane input").attr("disabled", "disabled");
// Enable inputs on the active tab
$("div.tab-pane.active input").removeAttr("disabled");
});
// Click the link to run function on load
$("#urban > a").click();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<ul class="nav nav-tabs">
<li id="urban" class="active">Urban Tab 1</li>
<li id="rural" class="">Rural Tab 2</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab_urban">
<ul>
<li>
<input class="myCheck_u" type="checkbox" name="Wave_fiters[]" value="1"> Wave-1 </li>
<li>
<input class="myCheck_u" type="checkbox" name="Wave_fiters[]" value="2"> Wave-2 </li>
</ul>
</div>
<div class="tab-pane" id="tab_rural">
<ul>
<li>
<input class="myCheck_r" type="checkbox" name="HS1_fiters[]" value="1"> Entertainment Sites </li>
<li>
<input class="myCheck_r" type="checkbox" name="HS1_fiters[]" value="2"> News </li>
</ul>
</div>
</div>

jQuery: change text color of a fixed top navbar at the scrolling of the page

I need help for my personal website. I want to make a one page site with a fixed top navbar (with transparent background). At the scrolling of the page, the color of the menu elements must change dinamically from black to white on the sections that have a dark background (they have a ".dark-bg" class) and return white on the other sections. All sections are 100vh height (except for the menu, of course). This is the HTML main structure of the site:
<section class="section--menu fixed-header">
<nav class="menu" id="navigation">
<ul class="menu__list pull-md-right">
<li class="menu__item menu__item--current">
<a class="menu__link" data-target="intro-fabio">home</a>
</li>
<li class="menu__item">
<a class="menu__link" data-target="about-fabio">about</a>
</li>
<li class="menu__item">
<a class="menu__link" data-target="skills-fabio">skills</a>
</li>
<li class="menu__item">
<a class="menu__link" data-target="works-fabio">works</a>
</li>
<li class="menu__item">
<a class="menu__link" data-target="contacts-fabio">contacts</a>
</li>
</ul>
</nav>
</section>
<!-- HOME
======================================================== -->
<section id="intro-fabio">
</section>
<!-- ABOUT
======================================================== -->
<section id="about-fabio" class="dark-bg">
</section>
<!-- SKILLS
======================================================== -->
<section id="skills-fabio">
</section>
<!-- WORKS
======================================================== -->
<section id="works-fabio" class="dark-bg">
</section>
<!-- CONTACTS
======================================================== -->
<section id="contacts-fabio">
</section>
I wrote this jQuery script but it seems to work only for the last section with ".dark-bg" class.
$(document).ready(function() {
$(".dark-bg").each(function() {
detectBg( $(this) );
});
function detectBg(sezione) {
$(window).scroll(function() {
var finestra = $(window).scrollTop();
var sezCurr = sezione.offset().top;
var sezNext = sezione.next().offset().top;
if (finestra >= sezCurr && finestra < sezNext) {
$('.menu__link').css("color", "#ebebeb");
}
else {
$('.menu__link').css("color", "#1c1c1c");
}
});
}
});
Thanks in advance!
You need to handle scroll event of the window, and in that handler, check if any of the dark section is under the menu, if so, then change the color of the menu links. Here is an example of changing the color for all links, but it can be easily extended to do it separately for each link:
$(window).scroll(function() {
var vpHeight = $(window).height();
var isBlack = false;
$(".dark-bg").each(function(i, section) {
if(isBlack) {
return;
}
var offset = $(section).offset().top - $(window).scrollTop();
if(((offset + vpHeight) >= 0) && ((offset + vpHeight) <= vpHeight)) {
isBlack = true;
return;
}
});
$(".menu__link").css("color", isBlack ? "white" : "black");
});
body {
padding: 0;
margin: 0;
}
ul {
position:fixed;
background: orange;
padding: 0;
margin: 0;
list-style-type: none;
}
ul > li {
float: left;
padding: 0 4px;
}
section {
background:red;
height: 100vh;
}
.dark-bg {
background: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu__list pull-md-right">
<li class="menu__item menu__item--current">
<a class="menu__link" data-target="intro-fabio">home</a>
</li>
<li class="menu__item">
<a class="menu__link" data-target="about-fabio">about</a>
</li>
<li class="menu__item">
<a class="menu__link" data-target="skills-fabio">skills</a>
</li>
<li class="menu__item">
<a class="menu__link" data-target="works-fabio">works</a>
</li>
<li class="menu__item">
<a class="menu__link" data-target="contacts-fabio">contacts</a>
</li>
</ul>
<!-- HOME
======================================================== -->
<section id="intro-fabio">
</section>
<!-- ABOUT
======================================================== -->
<section id="about-fabio" class="dark-bg">
</section>
<!-- SKILLS
======================================================== -->
<section id="skills-fabio">
</section>
<!-- WORKS
======================================================== -->
<section id="works-fabio" class="dark-bg">
</section>
<!-- CONTACTS
======================================================== -->
<section id="contacts-fabio">
</section>

Load JavaScript if Breadrumb exists

So i made a javascript and would like to make it load only if a certain breadcrumb exists in a page, lets say this breadcrumb is called "support" and my breadcrumb code is:
<ol class="breadcrumb top ipsList_inline left" id="breadcrumb">
<li itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb" class="first">
<a href="https://www.website.com" itemprop="url">
<span itemprop="title">website</span>
</a>
</li>
<li itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
<span itemprop="title">website</span>
</li>
<li itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
<span itemprop="title">Section</span>
</li>
<li itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
<span itemprop="title">Support</span>
</li>
</ol>
You can do something like this:
window.onload = function () {
var breadcrumb = document.getElementById("breadcrumb");
var titles = breadcrumb.getElementsByTagName("span");
var support = 0;
for(var i = 0; i < titles.length; ++i){
support += titles[i].innerHTML == "Support";
}
if(support) initialize();
}
function initialize() {
/* Do your stuff. */
}

submenu on click must remain open

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>

Categories