hope everyone is keeping safe and coding a lot.
I am having a problem and have tried every solution but none are working. I do have a HAMBURGER MENU made of DIV's Elements, when open this menu will display all the MENU OPTIONS. So far it is working great but once the SECOND MENU is open I want to prevent the user to use the HAMBURGER MENU until the second menu is closed.
In my last try I have used POINTER-EVENTS: nome but believe it or not, it does stop the second menu from working and not the first one as it was supposed.
I will post here the code in JS and will be so grateful for any tips that will help me:
document.querySelector('.hamburger-menu').addEventListener('click', () => {
document.querySelector('.nav-wrapper').classList.toggle('change');
document.querySelector('#home-menu').addEventListener('click', () => {
document.getElementById("class-nav-1").style.display = "block";
document.getElementById("#hamburger-menu").style['pointer-events'] = 'none';
});
document.querySelector('#close-window').addEventListener('click', () => {
document.getElementById("class-nav-1").style.display = "none";
document.getElementById('.hamburger-menu').style.pointerEvents = "auto";
});
});
It seems the issue is because you are adding other event listener inside the top one. You may need to separate them
document.querySelector('.hamburger-menu').addEventListener('click', () => {
document.querySelector('.nav-wrapper').classList.toggle('change');
});
document.querySelector('#close-window').addEventListener('click', () => {
document.getElementById("class-nav-1").style.display = "none";
document.getElementById('.hamburger-menu').style.pointerEvents = "auto";
});
document.querySelector('#home-menu').addEventListener('click', () => {
document.getElementById("class-nav-1").style.display = "block";
document.getElementById(".hamburger-menu").style.pointerEvents = 'none';
});
I think you should leave the practice to control elements' behavior based on information gained from the DOM.
It would be much easier to control the behavior of your menu if you just toggled a boolean value in JS:
const btnFirst = document.getElementById('first')
const ddMenu = document.getElementById('second')
const ddItems = document.querySelectorAll('.dd-item')
const textArea = document.getElementById('third')
// this variable controls the behavior of the main menu
let btnFirstIsEnabled = true
btnFirst.addEventListener('click', function(e) {
if (btnFirstIsEnabled) {
btnFirstIsEnabled = false
ddMenu.classList.remove('hidden')
btnFirst.classList.add('disabled')
} else {
textArea.innerHTML = 'Cannot open dropdown again!'
}
})
ddItems.forEach(e => {
e.addEventListener('click', function(e) {
textArea.innerHTML = `Clicked: ${e.target.getAttribute('data-val')}`
ddMenu.classList.add('hidden')
btnFirstIsEnabled = true
btnFirst.classList.remove('disabled')
})
})
.main {
cursor: pointer;
}
.main.disabled {
color: #eaeaea;
}
.hidden {
display: none;
}
.dd-item {
cursor: pointer;
}
<div id="third">Clicked:</div>
<div id="first" class="main">OPEN</div>
<div id="second" class="hidden">
<ul>
<li class="dd-item" data-val="dd 1">Click dropdown item 1</li>
<li class="dd-item" data-val="dd 2">Click dropdown item 2</li>
<li class="dd-item" data-val="dd 3">Click dropdown item 3</li>
</ul>
</div>
I just added some coloring to the main menu in the snippet to show that it's not active, but the behavior is controlled by setting a Boolean variable in JS.
I think it would make your code much simpler if you made it work like this.
Related
This is for a navbar.
The "active" class makes the background of the item in the navbar become darker.
And yes, I made the navbar with "div" instead of "ul".
This code of mine is an attempt, whenever an item in the navbar is selected (and its background is made darker), the other selected items pass their class to "unactive".
The code works perfectly when I don't try the "unactive" part, but doing so it just makes everything I click active.
I would like help with this.
Furthermore, I would like to know how to make the navbar update the parts that are selected according to where I am on the page. Ex.: I am in the voting section and I move to the sponsors section. How do I make the navbar automatically select the session I'm in?
thanks for any help!
HTML
<div class="navigation-header" id="navigation-header">
Votação
Patrocinadores
Redes Sociais
Créditos
</div>
JAVASCRIPT
var navbars = document
.querySelector(".navigation-header")
.querySelectorAll("a");
navbars.forEach(function (item) {
item.addEventListener("click", function (e) {
let classe = this.getAttribute("class");
if (classe != "active") {
navbars.forEach(function (navitem) {
let classe = this.getAttribute("class");
if (classe === "active") {
this.classList.remove(classe);
this.classList.add("unactive");
}
});
this.classList.remove(classe);
this.classList.add("active");
}
});
});
I don't know if I understood well what you need, Check this please and tell me:
var navbars = document
.querySelector(".navigation-header")
.querySelectorAll("a");
navbars.forEach(function (item) {
item.addEventListener("click", function (e) {
let classe = e.target.getAttribute("class");
if (classe != "active") {
navbars.forEach(function (navitem) {
let classe = navitem.getAttribute("class");
if (classe == "active") {
navitem.classList.remove(classe);
navitem.classList.add("unactive");
}
});
e.target.classList.remove(classe);
e.target.classList.add("active");
}
});
});
a.active {
background: #ee0;
}
<div class="navigation-header" id="navigation-header">
Votação
Patrocinadores
Redes Sociais
Créditos
</div>
I'm trying to make it so that when you scroll on my HTML page when you reach a certain section, that respective section should become active,
for example:
<nav class="scrollmenu">
<ul>
<li class="starters">STARTERS</li>
<li class="ramen">RAMEN</li>
</ul>
</nav>
starters should become active when you reach this section on the page:
<section id="starters" class="foodgrid">...</section>
I'm trying to do this with this JS code:
const sections = document.querySelectorAll("section");
const navLi = document.querySelectorAll("nav ul li");
window.addEventListener("scroll", () => {
let current = " ";
sections.forEach((section) => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if (scrollY >= sectionTop) {
current = section.getAttribute("id");
}
});
navLi.forEach((li) => {
li.classList.remove("active");
if (li.classList.contains(current)) {
li.classList.add("active");
}
});
});
I'm still going to expand on this JS code to make it work better but if I'm not mistaken it should already make the class visually active when I'm on the right section.
In case you are wondering my CSS looks like this for the time being:
nav ul li:active {
background-color: blue;
}
what happens here is that you are attaching a class name which is active and you are not declaring that class, you just have the event :active that is triggered when you click on the element, so you must do this
.active {
background-color: blue;
}
and that will work when you set the class and remove it, also leaving the css code as you have it will make that when the html li element is clicked it changes it background and then changes to the normal color, try it and let me know if it works, if it doesn't is something about your js and then ill check it
^I would like to be able for the style to be enabled for only one at a time.
^I'm able to do this, which I don't want the user to be able to do.
So it's weirdly hard framing a question for what is possibly an easy solution. I basically have a list of build versions where I want the user to select one. When one of the versions are selected, it adds a border to the item to display that its clicked. However, with my code right now the user is able to select all 3 items and enable their CSS elements. I would like for the user to be able to only "activate" one item from the list.
HTML and CSS:
<ul class="listContents">
<li><p>Stable</p></li>
<li><p>Preview</p></li>
<li><p>LTS</p></li>
</ul>
<style>
.colorText {
background-color: #58a7ed;
color: white;
}
</style>
and the JS stuff:
const btn = document.querySelectorAll('.links');
for (let i = 0; i < btn.length; i++ ) {
btn[i].addEventListener("click", function() {
btn[i].classList.add('colorText')
})
}
I really hope I made myself clear, I feel like I'm failing my English trying to word this right lol.
You can also use a forEach loop, accessing the clicked link using event.target
const btns = document.querySelectorAll('.links');
btns.forEach(btn => {
btn.addEventListener('click', e => {
// remove any existing active links
btns.forEach(b => b.classList.remove('colorText'));
// activate the clicked link
e.target.classList.add('colorText');
})
});
.colorText {
background-color: #58a7ed;
color: white;
}
<ul class="listContents">
<li>
<p>Stable</p>
</li>
<li>
<p>Preview</p>
</li>
<li>
<p>LTS</p>
</li>
</ul>
Just before you add the colorText class to the desired item, we can remove colorText from ALL of them, ensuring that only 1 at a time gets the class.
// the rest is the same...
btn[i].addEventListener("click", function() {
// remove it from all:
btn.forEach(function(item) {
item.classList.remove('colorText');
});
// add it back to the desired one
btn[i].classList.add('colorText')
})
you can also use simple for of
const btn = document.querySelectorAll(".links");
for (let bt of btn) {
bt.addEventListener("click", (e) => {
btn.forEach((b) => b.classList.remove("colorText"));
e.target.classList.add("colorText");
});
}
I am trying to shrink right side div when left navigation menu is open. Here is my code example,
HTML :
<div id="home" class="full"><p>Home</p></div>
<div id="about" class="full"><p>About</p></div>
<div id="portfolio" class="full"><p>Portfolio</p></div>
<div id="skills" class="full"><p>Skills</p></div>
<div id="contact" class="full"><p>Contact</p></div>
Css :
.full{height: 100vh;color: #fff;}
.PageShrink{margin-left: 30vh;}
JS:
const fullPage = document.querySelector('.full');
let menuOpen = false;
menuBtn.addEventListener('click', () => {
if(!menuOpen) {
fullPage.classList.add('PageShrink');
menuOpen = true;
} else {
fullPage.classList.remove('PageShrink');
menuOpen = false;
}
});
The issue is, when I click on menuBtn to slide in from left, Home shrinks 30vh according to code, but after that if I click on About,portfolio etc its not shrinking even though they have same class. Not sure whats wrong but it just works on 1st div i.e, home.
Please assist,
Thank you in advance.
Your issue is within the JS. You use querySelector which only targets the first element with that class. So you have to use querySelectorAll. However this only gives you an array of all elements and the JS change is only applied to the first element still. So you need to cycle through all elements with that class by using: fullPage.forEach(el => el.classList.add('PageShrink'));
const fullPage = document.querySelectorAll('.full');
let menuOpen = false;
menuBtn.addEventListener('click', () => {
if(!menuOpen) {
fullPage.forEach(el => el.classList.add('PageShrink'));
menuOpen = true;
} else {
fullPage.forEach(el => el.classList.remove('PageShrink'));
menuOpen = false;
}
});
For demonstration and testing:
function caseA() {
document.querySelector(".test").style.color = "red";
}
function caseB() {
document.querySelectorAll(".test").style.color = "green";
}
function caseC() {
document.querySelectorAll(".test").forEach(el => el.style.color = "blue");
}
<ul>
<li class="test">Test</li>
<li class="test">Test</li>
<li class="test">Test</li>
<li class="test">Test</li>
<li class="test">Test</li>
</ul>
<button onclick="caseA()">querySelector</button>
<button onclick="caseB()">querySelectorAll</button>
<button onclick="caseC()">querySelectorAll + forEach</button>
You see that "Case A" is onyl targetign the first element. "Case B" will cause an error as querySelectorAll returns an array of elements not an element itself. If you use forEach you can apply your JS comamnd to all the elements as it cycles through the array and applies it to every element of the array.
I want to toggle the visibility of classes of list items and also toggle the visibility of all the list items. With help of another stack overflow post, I am able to toggle specific classes of list items.
Here's the Javascript I have that toggles specific classes of list items:
var switcher = [false, false, false];
var classes = ['easy', 'fun', 'silly'];
$('.toggler').click(function () {
var x = $(this).hasClass('checked');
switcher[$(this).data('switch')] = !x;
$(this).toggleClass("checked", !x);
$('li').each(function () {
var cur = $(this);
cur.addClass('hidden');
$.each(switcher, function (index, data) {
if (data && cur.hasClass(classes[index])) {
cur.removeClass('hidden');
}
});
});
});
I added the basic functionality to hide and show all the list items, but the function brakes the individual class toggles:
$('.select_all').click(function () {
$(".toggler").toggleClass("checked");
$('li').toggleClass("hidden");
});
How can I keep class toggles, and add another button that toggles all the items?
Here's a fiddle example: http://jsfiddle.net/BMT4x/1/
I'm not sure if this is exactly what you're trying to do, but it should give you a push in the right direction (at least the direction I'd go). I prefer toggling everything with classes. Something like:
<button class="toggler" data-class="easy">Easy</button>,
<button class="toggler" data-class="fun">Fun</button>,
<button class="toggler" data-class="silly">Silly</button>,
<button class="toggler" data-class="all">Select All</button>
<ul id="list">
<li class="easy">Bowling</li>
<li class="fun">Balooning</li>
<li class="fun easy">Boating</li>
<li class="silly">Barfing</li>
<li class="easy fun">Bafooning</li>
</ul>
The CSS:
#list li {
display: none;
}
#list.easy li.easy {
display: block;
}
#list.fun li.fun {
display: block;
}
#list.silly li.silly {
display: block;
}
#list.all li {
display: block;
}
The JS:
$('.toggler').click(function () {
var category = $(this).data('class');
$('#list').toggleClass(category);
});
And a fiddle for reference: http://jsfiddle.net/qLLYj/
You can explicitly add/remove a class by passing a second, switch, parameter to toggleClass (see here).
So, you can change the state of all the individual switches and list items when clicking the .select_all button.
$('.select_all').click(function () {
$('.select_all').toggleClass("checked");
var allChecked = $('.select_all').hasClass("checked");
switcher = [allChecked, allChecked, allChecked];
$(".toggler").toggleClass("checked", allChecked);
$('li').toggleClass("hidden", !allChecked);
});
Some further changes made to get more intuitive behaviour
(e.g. if all checked, clicking one of the toggles deselects .select_all as well as itself; checking all individual toggles means .select_all is automatically checked):
$('.toggler').click(function () {
var x = $(this).hasClass('checked');
switcher[$(this).data('switch')] = !x;
$(this).toggleClass("checked");
$('li').each(function () {
var cur = $(this);
cur.addClass('hidden');
$.each(switcher, function (index, data) {
if (data && cur.hasClass(classes[index])) {
cur.removeClass('hidden');
}
});
});
var allChecked = switcher.indexOf(false) < 0;
$('.select_all').toggleClass("checked", allChecked);
});
Fiddle: http://jsfiddle.net/ET33B/