Add active class to menu li on scrolling through section in div - javascript

In the below set of code basd on selecting the .help-menu elements on left .help-descr div navigated to particular section .
Similarly on scrolling the .help-descr div I want to add active class selection to appropriate .help-menu elements
This what I have tried:
Its something similar to the attached link Add Menu Active Class when scrolling to div I am not able to replicate same approach here
help.js
// on load of page
$(function() {
$('.backend-feature li :first').addClass('active');
$('.backend-head').addClass('active');
$('.selected-item').empty();
$('.selected-item').append('<span>Supported Features</span><i class="ion-android-arrow-dropright"></i><span>Backend</span><i class="ion-android-arrow-dropright"></i><span style="font-weight:bold;">' + $('.backend-feature li :first').text() + '</span');
});
//on click of backend feature menu
$(".backend-feature-li").on('click', function() {
$('.frontend-head').removeClass('active');
$('.frontother-head').removeClass('active');
$('.frontend-feature li').find('a').removeClass('active');
$('.front-otherfeature-li').find('a').removeClass('active');
$(this).siblings().find('a').removeClass('active');
$('.backend-head').addClass('active');
$(this).find('a').addClass('active');
$('.selected-item').empty();
$('.selected-item').append('<span>Supported Features</span><i class="ion-android-arrow-dropright"></i><span>Backend</span><i class="ion-android-arrow-dropright"></i><span style="font-weight:bold;">' + $(this).text() + '</span');
});
// on click of frontend feature menu
$(".frontend-feature-li").on('click', function() {
$('.backend-head').removeClass('active');
$('.frontother-head').removeClass('active');
$('.backend-feature li').find('a').removeClass('active');
$('.front-otherfeature-li').find('a').removeClass('active');
$(this).siblings().find('a').removeClass('active');
$('.frontend-head').addClass('active');
$(this).find('a').addClass('active');
$('.selected-item').empty();
$('.selected-item').append('<span>Supported Features</span><i class="ion-android-arrow-dropright"></i><span>Frontend</span><i class="ion-android-arrow-dropright"></i><span style="font-weight:bold;">' + $(this).text() + '</span');
});
//on click of frontend other features menu
$(".front-otherfeature-li").on('click', function() {
$('.backend-head').removeClass('active');
$('.backend-feature li').find('a').removeClass('active');
$('.frontend-feature-li').find('a').removeClass('active');
$(this).siblings().find('a').removeClass('active');
$('.frontend-head').addClass('active');
$('.frontother-head').addClass('active');
$(this).find('a').addClass('active');
$('.selected-item').empty();
$('.selected-item').append('<span>Supported Features</span><i class="ion-android-arrow-dropright"></i><span>Frontend</span><i class="ion-android-arrow-dropright"></i><span>Other Features</span><i class="ion-android-arrow-dropright"></i><span style="font-weight:bold;">' + $(this).text() + '</span');
});
.ion-help-circled {
cursor: pointer;
}
.help-row {
flex-wrap: nowrap;
max-width: 100%;
}
.help-menu {
background-color: #efefef;
overflow: auto;
padding: 15px;
height: 85vh;
}
.help-descr {
position: relative;
background-color: white;
padding: 25px 25px;
overflow: auto;
height: calc(100vh - 107px);
border: 1px solid #efefef;
}
.help-menu ul .front-otherfeature-li {
margin-left: 18px;
}
.help-menu ul li {
list-style-type: none;
margin: 8px;
}
.help-menu ul .backend-head,
.help-menu ul .frontend-head {
margin-left: 0px;
}
.backend-feature li a,
.frontend-feature li a,
.frontend-otherfeature li a {
padding: 0;
text-decoration: none;
color: black;
}
.help-menu li .active {
font-weight: bold;
}
.help-menu a:hover {
font-weight: bold;
}
.main-section {
background-color: white;
}
section {
display: flex;
flex-direction: column;
padding-bottom: 15px;
}
article {
display: flex;
flex-direction: column;
padding-left: 30px;
}
.main-section ul>li {
margin-top: 6px;
}
.main-section p {
margin-bottom: 0px;
}
.backend-feature-arrow,
.frontend-feature-arrow,
.other-feature-arrow {
margin-right: 6px;
cursor: pointer;
}
.selected-item span {
padding: 6px;
}
.descr-seclevel {
list-style-type: square;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline'">
<link rel="stylesheet" href="./../node_modules/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="./css/style.css">
<link src="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" src_type="url" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="./vendors/css/ionicons.min.css">
<script defer src="./js/help_page.js"></script>
<title>Revive</title>
</head>
<body>
<div id="header">
<div class="dashboard-header">
<div class="dashboard-left-header">
<ul style="margin-bottom: 0px;">
<li>
<a style="cursor: default;" class="logo" href=""><img src="./assets/img/img1.png"></img>
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="row help-row">
<div class="col-sm-3 help-menu">
<ul>
<li style="font-weight: bold;">Supported Features</li>
<li>
<ul>
<li class='backend-head'><i class="backend-feature-arrow ion-ios-arrow-down" style="font-size:18px ;display:inline-block"></i>Backend</li>
<li>
<ul class="backend-feature">
<li class="backend-feature-li">Datasources</li>
<li class="backend-feature-li">Joins</li>
</ul>
</li>
<li class='frontend-head'><i class="frontend-feature-arrow ion-ios-arrow-right" style="font-size:18px ;display:inline-block"></i>Frontend</li>
<li>
<ul class="frontend-feature">
<li class="frontend-feature-li">Properties</li>
<li class="frontother-head"><i class="other-feature-arrow ion-ios-arrow-right" style="font-size:18px ;display:inline-block"></i>Other Features</li>
<li>
<ul class="frontend-otherfeature">
<li class="front-otherfeature-li">Actions</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div class="col-sm-9 help-descr">
<div class='selected-item'></div>
<section class="main-section" id="datasource">
<header>
<h1>Datasources</h1>
</header>
<article>
<p>The supported Datasources:</p>
<ul class="descr-firstlevel" style="margin-left: 20px;">
<li>Excel</li>
<li>Csv</li>
<li>Oracle Database</li>
<li>MSSQL server</li>
<li>PostgreSQL</li>
<li>MySQL</li>
</ul>
</article>
</section>
<section class="main-section" id="joins">
<header>
<h1>Joins</h1>
</header>
<article>
<p>The supported Joins:</p>
<ul class="descr-firstlevel" style="margin-left: 20px;">
<li>Inner Join</li>
<li>Left Join</li>
<li>Right Join</li>
<li>Full Outer Join</li>
</ul>
</article>
</section>
<section class="main-section" id="properties">
<header>
<h1>Properties</h1>
</header>
<article>
<p>The supported Properties:</p>
<ul class="descr-firstlevel" style="margin-left: 20px;">
<li>Titles on charts</li>
<li>X-axis and Y-axis Titles will be renamed</li>
<li>Text Properties like font style ,size and color</li>
<li>Background color</li>
<li>Grid lines</li>
<li>Borders for charts</li>
<li>Alias name for values</li>
<li>Legends will be enabled only if present</li>
<li>Color of Chart:</li>
<ul class="descr-seclevel" style="margin-left: 20px;">
<li>If color is applied it will be added else default color is applied</li>
<li>If a chart contains multiple color representing its data and if palate is assigned it will be applied </li>
</ul>
</ul>
</article>
</section>
<section class="main-section" id="actions">
<header>
<h1>Actions</h1>
</header>
<article>
<p>Actions supported:</p>
<ul class="descr-firstlevel" style="margin-left: 20px;">
<li>Only on-select is supported</li>
<li>With Actions from one dashboard to different dashboard interacts with all charts in target dashboard</li>
</ul>
</article>
</section>
</div>
</div>
</body>
</html>

If you put an IntersectionObserver on each of the main sections the system will tell you when it comes into view or goes out of view.
Then you can add or remove the active class from the related link in the menu.
This snippet gives a demo but it had to shorten the overall length of the menu area just so we got to see the content below and it also fixed it otherwise it scrolled up and the effect of adding the active class couldn't be seen as the menu item was off the screen.
To make it obvious which section(s) are in view a lime background has been put on the link.
Note, there is some thought needed on what 'active' actually means since more than one section can be in the viewport at once. This snippet does not attempt to tackle that - it's ouside the scope of this question.
The snippet needs to be viewed full page.
const callback = (entries, observer) => {
entries.forEach(entry => {
const id = entry.target.id;
const el = document.body.querySelector('[href="#' + id + '"]');
if (entry.isIntersecting) {
el.classList.add('active');
} else {
el.classList.remove('active');
}
});
};
const sections = document.querySelectorAll('.main-section');
const options = {
threshold: 0.33
};
const observer = new IntersectionObserver(callback, options);
sections.forEach(section => {
observer.observe(section);
});
.ion-help-circled {
cursor: pointer;
}
.help-row {
flex-wrap: nowrap;
max-width: 100%;
}
.help-menu {
background-color: #efefef;
overflow: auto;
padding: 15px;
height: 85vh;
height: 30vh;
/* changed for demo so we can see stuff */
}
.help-descr {
position: relative;
background-color: white;
padding: 25px 25px;
overflow: auto;
height: calc(100vh - 107px);
border: 1px solid #efefef;
}
.help-menu ul .front-otherfeature-li {
margin-left: 18px;
}
.help-menu ul li {
list-style-type: none;
margin: 8px;
}
.help-menu ul .backend-head,
.help-menu ul .frontend-head {
margin-left: 0px;
}
.backend-feature li a,
.frontend-feature li a,
.frontend-otherfeature li a {
padding: 0;
text-decoration: none;
color: black;
}
.help-menu li .active {
font-weight: bold;
background-color: lime;
/* ADDED JUST FOR DEMO */
}
.help-menu a:hover {
font-weight: bold;
}
.main-section {
background-color: white;
}
section {
display: flex;
flex-direction: column;
padding-bottom: 15px;
}
article {
display: flex;
flex-direction: column;
padding-left: 30px;
}
.main-section ul>li {
margin-top: 6px;
}
.main-section p {
margin-bottom: 0px;
}
.backend-feature-arrow,
.frontend-feature-arrow,
.other-feature-arrow {
margin-right: 6px;
cursor: pointer;
}
.selected-item span {
padding: 6px;
}
.descr-seclevel {
list-style-type: square;
}
<div style="position: fixed; z-index: 1;">
<!-- added just for demo -->
<div id="header">
<div class="dashboard-header">
<div class="dashboard-left-header">
<ul style="margin-bottom: 0px;">
<li>
<a style="cursor: default;" class="logo" href=""><img src="./assets/img/img1.png"></img>
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="row help-row">
<div class="col-sm-3 help-menu">
<ul>
<li style="font-weight: bold;">Supported Features</li>
<li>
<ul>
<li class='backend-head'><i class="backend-feature-arrow ion-ios-arrow-down" style="font-size:18px ;display:inline-block"></i>Backend</li>
<li>
<ul class="backend-feature">
<li class="backend-feature-li">Datasources</li>
<li class="backend-feature-li">Joins</li>
</ul>
</li>
<li class='frontend-head'><i class="frontend-feature-arrow ion-ios-arrow-right" style="font-size:18px ;display:inline-block"></i>Frontend</li>
<li>
<ul class="frontend-feature">
<li class="frontend-feature-li">Properties</li>
<li class="frontother-head"><i class="other-feature-arrow ion-ios-arrow-right" style="font-size:18px ;display:inline-block"></i>Other Features</li>
<li>
<ul class="frontend-otherfeature">
<li class="front-otherfeature-li">Actions</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<!--ADDED -->
<div class="col-sm-9 help-descr">
<div class='selected-item'></div>
<section class="main-section" id="datasource">
<header>
<h1>Datasources</h1>
</header>
<article>
<p>The supported Datasources:</p>
<ul class="descr-firstlevel" style="margin-left: 20px;">
<li>Excel</li>
<li>Csv</li>
<li>Oracle Database</li>
<li>MSSQL server</li>
<li>PostgreSQL</li>
<li>MySQL</li>
</ul>
</article>
</section>
<section class="main-section" id="joins">
<header>
<h1>Joins</h1>
</header>
<article>
<p>The supported Joins:</p>
<ul class="descr-firstlevel" style="margin-left: 20px;">
<li>Inner Join</li>
<li>Left Join</li>
<li>Right Join</li>
<li>Full Outer Join</li>
</ul>
</article>
</section>
<section class="main-section" id="properties">
<header>
<h1>Properties</h1>
</header>
<article>
<p>The supported Properties:</p>
<ul class="descr-firstlevel" style="margin-left: 20px;">
<li>Titles on charts</li>
<li>X-axis and Y-axis Titles will be renamed</li>
<li>Text Properties like font style ,size and color</li>
<li>Background color</li>
<li>Grid lines</li>
<li>Borders for charts</li>
<li>Alias name for values</li>
<li>Legends will be enabled only if present</li>
<li>Color of Chart:</li>
<ul class="descr-seclevel" style="margin-left: 20px;">
<li>If color is applied it will be added else default color is applied</li>
<li>If a chart contains multiple color representing its data and if palate is assigned it will be applied </li>
</ul>
</ul>
</article>
</section>
<section class="main-section" id="actions">
<header>
<h1>Actions</h1>
</header>
<article>
<p>Actions supported:</p>
<ul class="descr-firstlevel" style="margin-left: 20px;">
<li>Only on-select is supported</li>
<li>With Actions from one dashboard to different dashboard interacts with all charts in target dashboard</li>
</ul>
</article>
</section>
</div>
</div>

Related

Sub menu accordion closes when it should open (nested accordion logic seems off)

I have a multi-nested accordion menu is currently behaving glitchy.
When I'm clicking into a submenu (i.e. "what we deliver 2", it closes the main accordion and then when I open the main accordion, that's when the sub accordion opens. See this gif for a demo of my issue:
I'm trying to simply open and close each accordion on it's li click, but unsure why it closes the entire parent accordion and then appears once the parent accordion opens (it's the same behaviour when closing the sub accordions, as shown in the gif).
Demo:
$(function() {
/*
* define vars
*/
const header = $(".header");
const hamburger_trigger = $(".hamburger__trigger");
const hamburger_popup = $(".hamburger__popup");
/*
* open hamburger on click
*/
$(hamburger_trigger).click(function(e) {
e.preventDefault();
$(header).toggleClass("hamburger--open");
$(hamburger_popup).toggleClass("active");
});
/*
* hamburger submenu
*/
$(".hamburger--has-submenu").click(function() {
console.log("click");
var child_menu = $(this).children(".hamburger__submenu");
if ($(this).hasClass("hamburger__submenu--open")) {
$(this).removeClass("hamburger__submenu--open");
child_menu.removeClass("d-block");
} else {
$(this).addClass("hamburger__submenu--open");
child_menu.addClass("d-block");
}
});
// for children submenus
$(".hamburger-trigger-submenu").click(function() {
console.log("click");
var child_menu = $(this).children(".hamburger__submenu");
if ($(this).hasClass("hamburger__submenu--open")) {
child_menu.removeClass("hamburger__submenu--open");
} else {
child_menu.addClass("hamburger__submenu--open");
}
});
});
/* HEADER */
.header {
padding: 30px 0;
}
/* HAMBURGER */
.hamburger__trigger {
cursor: pointer;
}
.hamburger__trigger:hover {
color: green;
}
.hamburger__popup {
background: black;
visibility: hidden;
display: none;
height: 0;
padding: 40px 15px 140px 15px;
overflow-y: scroll;
}
.hamburger__popup.active {
visibility: visible;
-webkit-animation: fadeIn 0.3s;
animation: fadeIn 0.3s;
display: block;
position: absolute;
left: 0;
top: 100px;
width: 100%;
height: 100vh;
z-index: 9999;
}
.hamburger__popup-inner {
display: flex;
align-items: flex-start;
flex-direction: column;
overflow: auto;
flex-grow: 1;
}
.hamburger__li > a {
margin: 10px 0;
display: block;
text-decoration: none !important;
}
.hamburger__submenu--level-2, .hamburger__submenu--level-3, .hamburger__submenu--level-4 {
display: none;
padding-left: 10px;
}
/* GENERAL */
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.background--black {
background: #000000;
}
.color--white {
color: #ffffff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<header class="header background--black">
<div class="container">
<div class="row justify-content-end">
<div class="col-4">
<div class="hamburger">
<span class="hamburger__trigger color--white">Click me</span>
</div>
</div>
</div>
</div>
<div class="hamburger__popup">
<div class="hamburger__popup-inner color--white">
<nav class="hamburger__menu w-100">
<ul class="hamburger__menu-ul">
<!-- MAIN GROUP -->
<li class="hamburger__li hamburger__depth-1 hamburger--has-submenu ">
<a class="hamburger__parent-item color--white" href="#">
What we deliver
</a>
<!-- SUB MENU IN MAIN GROUP -->
<ul class="hamburger__submenu hamburger__submenu--level-2">
<li class="hamburger__li hamburger__depth-2 hamburger--has-submenu hamburger-trigger-submenu">
<a class="hamburger__link color--white hamburger__submenu-trigger" href="#">
<span>What we deliver 2</span>
</a>
<!-- SUB MENU WITHIN SUBMENU -->
<ul class="hamburger__submenu hamburger__submenu--level-3">
<li class="hamburger__li hamburger__depth-3 hamburger-trigger-submenu">
<a class="hamburger__link color--white position-relative" href="#">
What we deliver 2.1
</a>
</li>
</ul>
<!-- SUB MENU WITHIN SUBMENU END-->
</li>
<li class="hamburger__li hamburger__depth-2 hamburger--has-submenu hamburger-trigger-submenu">
<a class="hamburger__link color--white hamburger__submenu-trigger" href="#">
<span>What we deliver 3</span>
</a>
<!-- SUB MENU WITHIN SUBMENU -->
<ul class="hamburger__submenu hamburger__submenu--level-3">
<li class="hamburger__li hamburger__depth-3 hamburger-trigger-submenu">
<a class="hamburger__link color--white position-relative" href="#">
What we deliver 3.1
</a>
</li>
</ul>
<!-- SUB MENU WITHIN SUBMENU END-->
</li>
</ul>
<!-- SUB MENU IN MAIN GROUP END -->
</li>
<!-- MAIN GROUP END -->
</ul>
</nav>
</div>
</div>
</header>
You need to add e.stopPropagation(); (docs) within the $(".hamburger-trigger-submenu").click(...) handler to prevent the event from bubbling up to $(".hamburger--has-submenu").click(...).
Full Code:
$(function() {
/*
* define vars
*/
const header = $(".header");
const hamburger_trigger = $(".hamburger__trigger");
const hamburger_popup = $(".hamburger__popup");
/*
* open hamburger on click
*/
$(hamburger_trigger).click(function(e) {
e.preventDefault();
$(header).toggleClass("hamburger--open");
$(hamburger_popup).toggleClass("active");
});
/*
* hamburger submenu
*/
$(".hamburger--has-submenu").click(function() {
console.log("click");
var child_menu = $(this).children(".hamburger__submenu");
if ($(this).hasClass("hamburger__submenu--open")) {
$(this).removeClass("hamburger__submenu--open");
child_menu.removeClass("d-block");
} else {
$(this).addClass("hamburger__submenu--open");
child_menu.addClass("d-block");
}
});
// for children submenus
$(".hamburger-trigger-submenu").click(function(e) {
console.log("click");
e.stopPropagation();
var child_menu = $(this).children(".hamburger__submenu");
if ($(this).hasClass("hamburger__submenu--open")) {
child_menu.removeClass("hamburger__submenu--open");
} else {
child_menu.addClass("hamburger__submenu--open");
}
});
});
/* HEADER */
.header {
padding: 30px 0;
}
/* HAMBURGER */
.hamburger__trigger {
cursor: pointer;
}
.hamburger__trigger:hover {
color: green;
}
.hamburger__popup {
background: black;
visibility: hidden;
display: none;
height: 0;
padding: 40px 15px 140px 15px;
overflow-y: scroll;
}
.hamburger__popup.active {
visibility: visible;
-webkit-animation: fadeIn 0.3s;
animation: fadeIn 0.3s;
display: block;
position: absolute;
left: 0;
top: 100px;
width: 100%;
height: 100vh;
z-index: 9999;
}
.hamburger__popup-inner {
display: flex;
align-items: flex-start;
flex-direction: column;
overflow: auto;
flex-grow: 1;
}
.hamburger__li > a {
margin: 10px 0;
display: block;
text-decoration: none !important;
}
.hamburger__submenu--level-2, .hamburger__submenu--level-3, .hamburger__submenu--level-4 {
display: none;
padding-left: 10px;
}
/* GENERAL */
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.background--black {
background: #000000;
}
.color--white {
color: #ffffff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<header class="header background--black">
<div class="container">
<div class="row justify-content-end">
<div class="col-4">
<div class="hamburger">
<span class="hamburger__trigger color--white">Click me</span>
</div>
</div>
</div>
</div>
<div class="hamburger__popup">
<div class="hamburger__popup-inner color--white">
<nav class="hamburger__menu w-100">
<ul class="hamburger__menu-ul">
<!-- MAIN GROUP -->
<li class="hamburger__li hamburger__depth-1 hamburger--has-submenu ">
<a class="hamburger__parent-item color--white" href="#">
What we deliver
</a>
<!-- SUB MENU IN MAIN GROUP -->
<ul class="hamburger__submenu hamburger__submenu--level-2">
<li class="hamburger__li hamburger__depth-2 hamburger--has-submenu hamburger-trigger-submenu">
<a class="hamburger__link color--white hamburger__submenu-trigger" href="#">
<span>What we deliver 2</span>
</a>
<!-- SUB MENU WITHIN SUBMENU -->
<ul class="hamburger__submenu hamburger__submenu--level-3">
<li class="hamburger__li hamburger__depth-3 hamburger-trigger-submenu">
<a class="hamburger__link color--white position-relative" href="#">
What we deliver 2.1
</a>
</li>
</ul>
<!-- SUB MENU WITHIN SUBMENU END-->
</li>
<li class="hamburger__li hamburger__depth-2 hamburger--has-submenu hamburger-trigger-submenu">
<a class="hamburger__link color--white hamburger__submenu-trigger" href="#">
<span>What we deliver 3</span>
</a>
<!-- SUB MENU WITHIN SUBMENU -->
<ul class="hamburger__submenu hamburger__submenu--level-3">
<li class="hamburger__li hamburger__depth-3 hamburger-trigger-submenu">
<a class="hamburger__link color--white position-relative" href="#">
What we deliver 3.1
</a>
</li>
</ul>
<!-- SUB MENU WITHIN SUBMENU END-->
</li>
</ul>
<!-- SUB MENU IN MAIN GROUP END -->
</li>
<!-- MAIN GROUP END -->
</ul>
</nav>
</div>
</div>
</header>
since the two functions basically do the same you could simplify them like that:
$(function() {
/*
* define vars
*/
const header = $(".header");
const hamburger_trigger = $(".hamburger__trigger");
const hamburger_popup = $(".hamburger__popup");
/*
* open hamburger on click
*/
$(hamburger_trigger).click(function(e) {
e.preventDefault();
$(header).toggleClass("hamburger--open");
$(hamburger_popup).toggleClass("active");
});
/*
* open menus on click
*/
$('.hamburger--has-submenu, .hamburger-trigger-submenu').on('click', function (e){
e.stopPropagation();
let child_menu = $(this).children('.hamburger__submenu');
$(this).toggleClass('hamburger__submenu--open');
child_menu.toggleClass('d-block');
})
});
you can solve it with simple pseudo class in css named :focus-within;
:focus-within CSS pseudo-class matches an element if the element or any of its descendants are focused.
ul:focus-within {
display: block;
}
(no need complex js )

Javascript stopped working after switching to another display [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Each time I change displays within one HTML file JS stops working (I've tried to replace HTML onclick call with JS function, but it's still the same)
UPD: Sorry for bad explanation. The problem is that if I move from the main display of this site by clicking links on nav panel (e.g. from #main to #contacts or #cart) JS script stops responding on burger icon click (clicking on burger nav panel for screen max-width of 800px doing nothing)
Code:
const burger = document.querySelector('.burger i');
const nav = document.querySelector('.nav');
function toggleNav() {
burger.classList.toggle('fa-bars');
burger.classList.toggle('fa-times');
nav.classList.toggle('nav-active');
}
burger.addEventListener('click', function() {
toggleNav();
});
html,
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
.header {
width: 100%;
height: 70px;
display: flex;
align-items: center;
justify-content: space-around;
background: #ffffff;
color: #343434;
border-bottom: 1px solid #343434;
border-top: 1px solid #343434;
}
.logo {
letter-spacing: 3px;
}
.nav {
display: flex;
justify-content: space-around;
width: 30%;
}
.navlink {
list-style: none;
margin: 0;
}
.navlink a {
color: #343434;
text-decoration: none;
font-size: 1.2em;
}
.burger {
font-size: 1.2em;
display: none;
}
#media screen and (max-width: 800px) {
.burger {
display: block;
}
.nav {
margin: 0;
background: #ffffff;
position: absolute;
right: -100%;
top: 70px;
width: 50%;
height: calc(100% - 70px);
flex-direction: column;
justify-content: space-around;
padding: 0;
transition: all 400ms;
}
.navlink {
text-align: center;
}
.nav-active {
right: 0;
}
}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css">
<link rel="stylesheet" href="./site.css">
<script src="site.js" type="javascript"></script>
<title>Атлас</title>
</head>
<body>
<div id="main" style="display:block">
<header class="header">
<img class="logo" src="logo.png" alt="Атлас - мы волокем в оптоволокне!" onclick="document.getElementById('main').style.display='none'; document.getElementById('main').style.display='block';">
<ul class="nav">
<li class="navlink">Контакты
</li>
<li class="navlink">Доставка
</li>
<li class="navlink">Корзина
</li>
</ul>
<div class="burger">
<i class="fas fa-bars"></i>
</div>
</header>
</div>
<div id="contacts" style="display:none">
<header class="header">
<img class="logo" src="logo.png" alt="Атлас - мы волокем в оптоволокне!" onclick="document.getElementById('contacts').style.display='none'; document.getElementById('main').style.display='block';">
<ul class="nav">
<li class="navlink">Контакты
</li>
<li class="navlink">Доставка
</li>
<li class="navlink">Корзина
</li>
</ul>
<div class="burger">
<i class="fas fa-bars"></i>
</div>
</header>
</div>
<div id="delivery" style="display:none">
<header class="header">
<img class="logo" src="logo.png" alt="Атлас - мы волокем в оптоволокне!" onclick="document.getElementById('about').style.display='none'; document.getElementById('main').style.display='block';">
<ul class="nav">
<li class="navlink">Контакты
</li>
<li class="navlink">Доставка
</li>
<li class="navlink">Корзина
</li>
</ul>
<div class="burger">
<i class="fas fa-bars"></i>
</div>
</header>
</div>
<div id="cart" style="display:none">
<header class="header">
<img class="logo" src="logo.png" alt="Атлас - мы волокем в оптоволокне!" onclick="document.getElementById('cart').style.display='none'; document.getElementById('main').style.display='block';">
<ul class="nav">
<li class="navlink">Контакты
</li>
<li class="navlink">Доставка
</li>
<li class="navlink">Корзина
</li>
</ul>
<div class="burger">
<i class="fas fa-bars"></i>
</div>
<script src="./site.js"></script>
</header>
</div>
<div id="payment" style="display:none">
</div>
<script src="./site.js"></script>
</body>
</html>
The problem is that you have several .burger in your HTML and you only define a Javascript event for the very first one. You could remedy this via:
const burgers = document.querySelectorAll('.burger i');
and
for (let burger of burgers) {
//define your event
}
but it's not the best approach. The very best thing that you could do is to refactor your HTML and have a single item with the .burger class, but with more reliable event.

fix the code to prevent dropdown menu from closing when on click

I got the code from w3scgool and modified it. The dropdown menu opens but when I click inside of it - submenu, then it closes. Here is the pure JavaScript code.
var dropdown = document.getElementsByClassName('dropdown-btn');
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';
}
});
}
nav.side-nav {
order: 0;
display: flex;
flex: 1 1;
flex-direction: column;
align-self: stretch;
margin-bottom: 0.67rem;
}
nav.side-nav ul {
margin: 0;
}
nav.side-nav li {
border-bottom: 1px solid #d9dadc;
border-left: 1px solid #d9dadc;
border-right: 1px solid #d9dadc;
list-style: none;
padding: 5px 15px;
font-size: 17px;
line-height: 24px;
}
nav.side-nav li:first-child {
background: #092a31;
color: white;
border: none;
font-size: 20px;
padding: 15px;
line-height: 1.1;
}
nav.side-nav li:not(:first-child):hover {
background: #cda600;
color: white;
cursor: pointer;
}
/*dropdown menu*/
.dropdown-container {
display: none;
background-color: #ffffff;
padding-left: 8px;
}
<html>
<nav class="side-nav">
<ul>
<li style="text-align:left;">some1</li>
<li href="#">some1</li>
<li href="#">some1</li>
<li href="#">some1</li>
<li id="navDrop" class="dropdown-btn">
Menu</li>
<div class="dropdown-container">
<form>
<a class="dropdown-container-link" id="navItem1" href="#">Submenu1</a><br>
<a class="dropdown-container-link" id="navItem2" href="#">Submenu2</a><br>
<a class="dropdown-container-link" id="navItem3" href="#">Submenu3</a><br>
<a class="dropdown-container-link" id="navItem4" href="#">Submenu4</a>
</form>
</div>
<li href="#">Menu</li>
</ul>
</nav>
</html>
I am new to JS. Could someone navigate/show how to edit the code to prevent dropdown from closing when click on its submenu.
Update: took out the onclick feature. Took from my code too.
Any suggestions about the code because it stays the same. In this case I am using just JS without jquery library.
After making the modifications suggested by #Heretic Monkey and #Ganesh chaitanya, you can simplify your code by using map() instead of a for loop, and again classList.toggle() instead of else if.
just modify your css a little with a new class that you add to your div. Like that
var dropdown = document.getElementsByClassName("dropdown-btn");
// here dropdown.map() don't work, use
Array.prototype.map.call(dropdown, function(drop) {
drop.addEventListener("click", function() {
drop.classList.toggle("active");
var dropdownContent = drop.nextElementSibling;
//use classList.toggle with the new class added at the div
dropdownContent.classList.toggle("disp-container");
});
});
nav.side-nav li:not(:first-child):hover {
background: #cda600;
color: white;
cursor: pointer;
}
/*dropdown menu*/
/*remove display here*/
.dropdown-container {
background-color: #ffffff;
padding-left: 8px;
}
/*create a new class and add display here*/
.disp-container {
display: none;
}
<nav class="side-nav">
<ul>
<li style="text-align:left;">some1</li>
<li href="#">some1</li>
<li href="#">some1</li>
<li href="#">some1</li>
<li id="navDrop" class="dropdown-btn">
Menu
</li>
<!-- add your new class here -->
<div class="disp-container dropdown-container">
<form>
<a class="dropdown-container-link" id="navItem1" href="#">Submenu1</a><br />
<a class="dropdown-container-link" id="navItem2" href="#">Submenu2</a><br />
<a class="dropdown-container-link" id="navItem3" href="#">Submenu3</a><br />
<a class="dropdown-container-link" id="navItem4" href="#">Submenu4</a>
</form>
</div>
<li id="navDrop2" class="dropdown-btn">
Menu
</li>
<!-- add your new class here -->
<div class="disp-container dropdown-container">
<form>
<a class="dropdown-container-link" id="navItem1" href="#">Submenu1</a><br />
<a class="dropdown-container-link" id="navItem2" href="#">Submenu2</a><br />
<a class="dropdown-container-link" id="navItem3" href="#">Submenu3</a><br />
<a class="dropdown-container-link" id="navItem4" href="#">Submenu4</a>
</form>
</div>
</ul>
</nav>

How do I shift content to left in nav bar

So I know this will be a very easy fix, however, I cannot figure it out for the life of me.
How can I shift the letters in this nav bar to the very left?
$(document).ready(function() {
$(".letter").click(function(e) {
$(".letter").parent().removeClass('current');
$(this).parent().addClass('current');
var letter = $(this).html().trim();
$(".submenuDiv").hide();
x = e.clientX - 100;
pos = $(this).position();
y = pos.top + 50;
$("#div" + letter).css({
left: x,
top: y,
position: 'absolute'
});
$("#div" + letter).show();
});
});
.alphabetNav {
background-color: #D9DDDF;
}
.alphabetNav li {
text-decoration: none;
cursor: pointer;
float: left;
display: inline;
list-style: none;
background-color: #E9EDEF;
padding: 3px;
margin: 2px;
}
.letter:hover {
color: red;
}
}
.submenuDiv ul {
display: inline;
}
.submenuDiv ul li {
float: left;
list-style: none;
padding: 5px;
margin: 10px;
background-color: #F1F5F7;
border: solid 1px black;
border-radius: 10px;
font-size: 12px;
}
.submenuDiv {
display: none;
}
.alphabetNav {
width: 550px;
height: 27px
}
.noNav li {
cursor: default;
color: #ccc
}
li.current {
background: #fff
}
.alphabetNav li {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<body>
<ul class='alphabetNav'>
<li><a class='letter' id='letterA'>A</a>
</li>
<li><a class='letter' id='letterB'>B</a>
</li>
<li><a class='letter' id='letterC'>C</a>
</li>
<ul class='noNav'>
<li>D</li>
</ul>
<li><a class='letter' id='letterE'>E</a>
</li>
<ul class='noNav'>
<li>F</li>
</ul>
</ul>
<!-- Submenu for letter A -->
<div class='submenuDiv' id='divA'>
<ul>
<li>
Abbotsford-Mission (B.C.)
</li>
</ul>
</div>
<!-- Submenu for letter B -->
<div class='submenuDiv' id='divB'>
<ul>
<li>
Barrie (Ont.)
</li>
<li>
Brantford (Ont.)
</li>
</ul>
</div>
<!-- Submenu for letter C -->
<div class='submenuDiv' id='divC'>
<ul>
<li>
Calgary (Alta.)
</li>
</ul>
</div>
<!-- Submenu for letter D -->
<div class='submenuDiv' id='divD'>
<ul>
<li>
Apple
</li>
<li>
Artist
</li>
</ul>
</div>
<!-- Submenu for letter E -->
<div class='submenuDiv' id='divE'>
<ul>
<li>
Edmonton (Alta.)
</li>
</ul>
</div>
</body>
Thanks in advance!
All you need is:
.alphabetNav{
padding-left: 0px;
}
Get familiar with using the Web Inspector in the browser, you will get to know what you need to do to fix your problem. :)
Here is a snapshot from Chrome (the green part is for padding):
Remove the padding from the container.
.alphabetNav{
padding:0;
background-color:#D9DDDF;
}
Or just the left padding.
.alphabetNav{
padding-left:0;
background-color:#D9DDDF;
}
Set padding to 0 on alphabetNav

I want to make my section(contents 1~4) swap when I click each navigation elements. [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Fisrt, I want to make Home contents is active when I open the website.
other contents should be hidden, Second each content should be link with the navigation element. So when I click the element it should swap the contents with the matched content. If I need to use javascript please let me know.
welcome critics :) and Thank You.
#font-face {
font-family: font1;
src: url('fonts/CaviarDreams.woff');
}
#wrapper {
margin:0 auto;
background: white;
border:1px solid black;
max-width: 1060px;
}
header {
max-width: 1060px;
width: 100%;
height: 76px;
top: 0;
left: 0;
border:1px solid black;
}
#logo {
margin-top: 37px;
margin-left: 10px;
float: left;
width: 160px;
height: 30px;
background: url(logo6.png) no-repeat center;
display: block;
}
nav {
float: right;
margin-top: 27px;
margin-right: 10px;
}
nav ul {
list-style: none;
}
nav ul li {
display: inline-block;
float: left;
font-family: font1;
font-size: 15px;
padding: 10px;
text-decoration: none;
cursor: pointer;
}
nav ul li:hover {
color: #6F6F6F;
}
#menu {
display: hidden;
width: 40px;
height: 40px;
background: url(menu-icon.png) center;
}
#menu:hover {
background-color: #CBCBCB;
border-radius: 3px 3px 0 0;
}
/* MEDIA QUERY */
#media all and (max-width:640px) {
#menu {
display:inline-block;
}
nav ul, nav:active ul {
display: none;
position: absolute;
padding: 10px;
background: #fff;
border: 3px solid #CBCBCB;
right: 18px;
top: 57px;
width: 30%;
border-radius: 3px 0 3px 3px;
z-index: 200;
}
nav ul li {
text-align: center;
width: 100%;
margin: 0 auto;
}
nav:hover ul {
display: block;
}
}
#swap{
margin: 40px auto 40px;
max-width: 980px;
position: relative;
padding: 20px;
border: 1px solid black;
z-index:100;
overflow: hidden;
}
#sns {
text-align: center;
}
#sns li{
display: inline-block;
margin-right: 10px;
}
#copyright li{
font-family: inherit;
font-size: 13px;
text-align: center;
list-style: none;
}
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<link rel="stylesheet" href="GalleryResStyle.css">
</head>
<body>
<div id="wrapper">
<header class="header-site" role="banner">
<nav>
<ul>
<li>
Home
</li>
<li>
Profile
</li>
<li>
Gallery
</li>
<li>
Contact
</li>
</ul>
</nav>
</header>
<div id="swap">
<div id="Home_contents">Home contents</div>
<div id="Profile_contents">Profile contents</div>
<div id="Gallery_contents">Gallery Contents</div>
<div id="Contact_contents">Contact contents</div>
</div>
<footer>
<div id="sns">
<li>
<a class="Facebook-icon" href=""><img src="FACEBOOK.png"></a>
</li>
<li>
<a class="instagram-icon" href=""><img src="INSTAGRAM.png"></a>
</li>
</div>
<div id="copyright">
<li> COPYRIGHT © 2015 INKYU PARK.<br>ALL RIGHTS RESERVED. </li>
</div>
</footer>
</div>
</body>
</html>
Yes you need JavaScript (other languages could do it, but it is the simplest I know)
for example, you can change HTML to (slightly simplified for the sake of clarity):
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<link rel="stylesheet" href="./test.css">
<!-- Must have this line first, to enable functions in test.js -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Here you get the hide/show functions -->
<script type="text/javascript" src="./test.js"></script>
</head>
<body>
<div id="wrapper">
<header class="header-site" role="banner">
<nav>
<ul>
<li class=showhome>Home</li>
<li class=showProfile>Profile</li>
<li class=showGallery>Gallery</li>
<li class=showContact>Contact</li>
</ul>
</nav>
</header>
<div id="swap">
<div id="Home_contents" class=home >Home contents</div>
<div id="Profile_contents" class=Profile >Profile contents</div>
<div id="Gallery_contents" class=Gallery >Gallery Contents</div>
<div id="Contact_contents" class=Contact >Contact contents</div>
</div>
</div>
</body>
</html>
so you can use class to define which area you click and which area hide/show
then use a js file with a .ready function (in my example, save as test.js in same folder as HTML:
$(document).ready(function(){
$(".showhome").click(function(){
$(".home").show();
$(".Profile").hide();
$(".Gallery").hide();
$(".Contact").hide();
});
$(".showProfile").click(function(){
$(".home").hide();
$(".Profile").show();
$(".Gallery").hide();
$(".Contact").hide();
});
$(".showGallery").click(function(){
$(".home").hide();
$(".Profile").hide();
$(".Gallery").show();
$(".Contact").hide();
});
$(".showContact").click(function(){
$(".home").hide();
$(".Profile").hide();
$(".Gallery").hide();
$(".Contact").show();
});
// Hide all and show home on page loading
$(".home").show();
$(".Profile").hide();
$(".Gallery").hide();
$(".Contact").hide();
});
for a cleaner function, you can also use things like $(".home").toggle();, it would switch the state (if it was shown it would hide and vice versa). but I don't see how right now :)
You will need to use some kind of scripting for this (alternatively just 4 raw html pages).
I'd suggest using bootstrap, it's simple if you're a javascript novice.
<div class="container">
<div role="tabpanel">
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">Home</li>
<li role="presentation">Profile</li>
<li role="presentation">Gallery</li>
<li role="presentation">Contact</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="home">Home</div>
<div role="tabpanel" class="tab-pane" id="profile">Profile</div>
<div role="tabpanel" class="tab-pane" id="gallery">Gallery</div>
<div role="tabpanel" class="tab-pane" id="contact">Contact</div>
</div>
</div>
Above is pulled from getbootstrap.com, fiddle here.

Categories

Resources