This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 1 year ago.
I want the navbar <ul> to disappear when I click it. With querySelectorAll() I selected all <li>s in the navbar. Then I added a click event listener to it. So when I click it, it should toggle the class of the navbar <ul> to "active" and then disappear.
It works with the toggle button but not with the <li>s.
<i id="togglebtn" class="fas fa-bars"></i>
<nav class="navbar">
<div class="brand-title">brandName</div>
<div class="navbar-links">
<ul id="ul">
<li class="jsscrolltrigger">Start</li>
<li class="jsscrolltrigger">Galerie</li>
<li class="jsscrolltrigger">Anfahrt</li>
<li class="jsscrolltrigger"><a href="#Speisekarte">Speisekarte</>
</li>
</ul>
</div>
</nav>
<script type="text/javascript">
var togglebtn = document.getElementById("togglebtn");
togglebtn.addEventListener("click", function () {
ul.classList.toggle("active");
});
// this following part doesnt work //
// i want the ul(navbar) to disappear when i click it //
var a = document.querySelectorAll(".jsscrolltrigger");
var ul = document.getElementById("ul");
a.addEventListener("click", function () {
ul.classList.toggle("active");
});
</script>
querySelectorAll returns a NodeList. You have to iterate the list and add the event listener to every node.
For example:
var togglebtn = document.getElementById("togglebtn");
togglebtn.addEventListener("click", function() {
ul.classList.toggle("active");
});
var nodeList = document.querySelectorAll(".jsscrolltrigger");
var ul = document.getElementById("ul");
nodeList.forEach(node => {
node.addEventListener("click", function() {
ul.classList.toggle("active");
});
})
<i id="togglebtn" class="fas fa-bars"></i>
<nav class="navbar">
<div class="brand-title">brandName</div>
<div class="navbar-links">
<ul id="ul">
<li class="jsscrolltrigger">Start</li>
<li class="jsscrolltrigger">Galerie</li>
<li class="jsscrolltrigger">Anfahrt</li>
<li class="jsscrolltrigger">Speisekarte</li>
</ul>
</div>
</nav>
When you use Document.querySelectorAll() It doesn't return a single element. It return a NodeList on which you can call forEach to loop through all of the item.
let a = document.querySelectorAll('.jsscrolltrigger');
let ul = document.getElementById("ul");
a.forEach(function(element) {
element.addEventListener('click', function(e){
e.preventDefault();
ul.classList.toggle("active");
});
});
.active {
border: 2px solid red;
}
<nav class="navbar">
<div class="brand-title">brandName</div>
<div class="navbar-links">
<ul id="ul">
<li class="jsscrolltrigger">Start</li>
<li class="jsscrolltrigger">Galerie</li>
<li class="jsscrolltrigger">Anfahrt</li>
<li class="jsscrolltrigger"><a href="#Speisekarte">Speisekarte</>
</li>
</ul>
</div>
</nav>
If you don't want to use forEach to perform the loop you can force the NodeList to be consider as an Array by passing it to the Array.from() method which allows you to perform any array operation on selected elements
Array.from(a).map(function(){ /*...*/ });
Array.from(a).filter(function(){ /*...*/ });
Related
hope you all doing great.
I've been trying to add the (active class )to each of the navbar links when the user is on that specific section of the page with this
Tutorial (i'm stuck at 2:45:05) and no success so far can anyone tell me what i did wrong .thank you.
const menu = document.querySelector(' nav .container ul');
const navItems = menu.querySelectorAll('li');
navItems.forEach(item => {
const link = item.querySelector('a');
ink.addEventListener('click', () => {
link.classList.add(".active");
});
});
nav .container ul li a.active {
background: var(--color-primary);
color: var(--color-white);
}
<nav>
<div class="container">
<a href="#">
<h3> AMANI DEV </h3>
</a>
<ul>
<li>Home</li>
<li>About</li>
<li>Skills</li>
<li>Services </li>
<li>Portfolio </li>
<li>Contact Me </li>
</ul>
</div>
</nav>
Typo with ink not link.
When you assign a class with classList you don't include the .: classList.add('active').
In your CSS background should probably be background-color.
If you want to remove the other active links before applying the new one you can use forEach to iterate over the links and use classList.remove('active') on each one.
You may find event delegation easier to manage. Rather than attaching multiple listeners to multiple elements attach one listener to the list element that watches out for events from its child elements as they "bubble up the DOM. You can then check that the clicked element is a link, remove the active classes from the previous link(s), and then apply the active class to the clicked link.
Here's an example using event delegation.
// Cache the list, and the items
const list = document.querySelector(' nav .container ul');
const links = list.querySelectorAll('a');
// Add one listener to the list element
list.addEventListener('click', handleClick);
// If the clicked element is a link remove all
// the active classes from the other links, and then
// add the active class to the link that was clicked on
function handleClick(e) {
if (e.target.matches('a')) {
links.forEach(link => link.classList.remove('active'));
e.target.classList.add('active');
}
}
:root { --color-white: white; --color-primary: red; }
.active {
background-color: var(--color-primary);
color: var(--color-white);
}
<nav>
<div class="container">
<a href="#">
<h3> AMANI DEV </h3>
</a>
<ul>
<li><a class="active" href="#home">Home</a></li>
<li>About</li>
<li>Skills</li>
<li>Services </li>
<li>Portfolio </li>
<li>Contact Me </li>
</ul>
</div>
</nav>
You need to do querySelectorAll in a tag not on the li tag. Just do this and do let me know.
Modify the code in the following line :
ink.addEventListener('click',() => {
to
link.addEventListener('click',() => {
to be like this
const menu = document.querySelector(' nav .container ul');
const navItems = menu.querySelectorAll('li');
navItems.forEach(item => {
const link = item.querySelector('a');
link.addEventListener('click',() => {
link.classList.add(".active");
});
});
document.querySelectorAll('ul li').forEach(el => {
el.onclick = () => {
document.querySelectorAll('ul li').forEach(el => el.classList.remove('active'));
el.classList.add('active');
}
})
here a demo code:
document.querySelectorAll('#myNav li').forEach(el => {
el.onclick = () => {
document.querySelectorAll('#myNav li').forEach(el => el.classList.remove('active'));
el.classList.add('active');
}
})
.active {
font-size: 70px;
}
<nav>
<div class="container">
<a href="#">
<h3> AMANI DEV </h3>
</a>
<ul id="myNav">
<li><a class="active" href="#home">Home</a></li>
<li>About</li>
<li>Skills</li>
<li>Services </li>
<li>Portfolio </li>
<li>Contact Me </li>
</ul>
</div>
</nav>
// selecting all a element on the page
const links = document.querySelectorAll('a');
// adding a click event on all elements
links.forEach((link) => {
link.addEventListener('click', (e) => {
// if we click first thing is deleting the active class from all link
links.forEach((link) => {
link.classList.remove('active')
})
// then in the end add the active class only in the correct one
e.target.classList.add('active')
})
})
This question already has answers here:
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 1 year ago.
I am trying to update the active state of a navigation tab. When the tab is clicked (newActive) is suppose to gain the class .active and the previous active tab (oldActive) needs to loose it.
So far I am able to remove the active class from oldActive, I also tried aadding a class to it and worked fine, but I am not able to do any changes to newActive when I defined it as $(this) nor when I define it as event.currentTarget.
I am also not getting any errors in the console so I can't get a lead on what's going on.
JQuery code:
$('.navigation_tabs li').click( event => {
let oldActive = $('.navigation_tabs li.active');
let newActive = event.currentTarget;
oldActive.removeClass("active");
// this line is not working nor giving any errors
newActive.addClass("active");
loadContent(data[newActive.dataset.list]);
});
HTML nav markup:
<div class="navigation">
<ul class="navigation_tabs">
<li class="active" data-list="build">Build</li>
<li data-list="plan">Plan</li>
<li data-list="innovate">Innovate</li>
<li data-list="interact">Interact</li>
<li data-list="scale">Scale</li>
<li data-list="service">Service</li>
<li data-list="enhance">Enhance</li>
<li data-list="general">General</li>
</ul>
</div>
There is actually a very simple example of this. why do you choose the hard one? The use of event.currentTarget applies to ES6. Not for jquery.
$('.navigation_tabs li').click(function() {
$(this).addClass('active').after(function() {
$('.active').not($(this)).removeClass('active')
});
});
.active {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="navigation">
<ul class="navigation_tabs">
<li class="active" data-list="build">Build</li>
<li data-list="plan">Plan</li>
<li data-list="innovate">Innovate</li>
<li data-list="interact">Interact</li>
<li data-list="scale">Scale</li>
<li data-list="service">Service</li>
<li data-list="enhance">Enhance</li>
<li data-list="general">General</li>
</ul>
</div>
addClass is a JQuery function, but event.currentTarget is plain javascript event, so you can try this:
$('.navigation_tabs li').click( event => {
let oldActive = $('.navigation_tabs li.active');
let newActive = $(event.currentTarget); // change here
oldActive.removeClass("active");
// this line is now working
newActive.addClass("active");
loadContent(data[newActive.dataset.list]);
});
I want to change 9 of the names in the UL to a red font using a on click button, while the other 3 names remain in a black font. And I want a button to reset the red fonts back to their original font. Can anyone help?
var title = document.getElementById("title");
var buttons = document.getElementsByClassName("btn");
var buttons = document.getElementsByClassName("btn2");
for (var btnIndex = 0; btnIndex < buttons.length; btnIndex++) {
buttons[btnIndex].onclick = function() {
title.style.color = this.getAttribute('data-color');
}
} else {
title1.style.color = this.getAttribute('data-color');
}
<ul>
<li id="title">John</li>
<li id="title">Jack</li>
<li id="title">Joe</li>
<li id="title1">Jim</li>
<li id="title">David</li>
<li id="title">Sam</li>
<li id="title1">Jay</li>
<li id="title">Frank</li>
<li id="title">Tim</li>
<li id="title">Zack</li>
<li id="title">Lewis</li>
<li id="title1">Danny</li>
<button class="btn" data-color="red">Change 9 names to red</button>
<button class="btn2" data-color="black">Reset</button>
</ul>
There are a couple of problems with your markup, which I'll address below, but to answer your actual question, you can do something like this:
// get references to the buttons
const button1 = document.querySelector('.btn');
const button2 = document.querySelector('.btn2');
// declare a function that adds the class 'red' to items matching the given selector
const select = selector => {
[...document.querySelectorAll(selector)].forEach(
element => element.classList.add('red')
);
}
// declare a function that removes the given class from all elements that currently have it
const deselect = className => {
[...document.querySelectorAll('.' + className)].forEach(
element => element.classList.remove(className)
);
}
// add a click handler to the button that invokes the
// select function above for items whose class includes 'title'
button1.addEventListener('click', () => select('.title'));
// add a click handler to the second button that removes the 'red' class from all items
button2.addEventListener('click', () => deselect('red'));
.red {
color: red;
}
<ul>
<li class="title">John</li>
<li class="title">Jack</li>
<li class="title">Joe</li>
<li class="title1">Jim</li>
<li class="title">David</li>
<li class="title">Sam</li>
<li class="title1">Jay</li>
<li class="title">Frank</li>
<li class="title">Tim</li>
<li class="title">Zack</li>
<li class="title">Lewis</li>
<li class="title1">Danny</li>
</ul>
<button class="btn" data-color="red">Change 9 names to red</button>
<button class="btn2" data-color="black">Reset</button>
a more efficient solution
This may not suit your needs, but if you just want to change the color of title items you could toggle a class on the <ul> and apply a css rule:
// get references to the button and ul
const button = document.querySelector('.btn');
const ul = document.querySelector('ul');
// toggle a class on the ul
button.addEventListener('click', () => ul.classList.toggle('red'));
/*
color 'title' items when the
ul has the 'red' class
*/
ul.red .title {
color: red;
}
<ul>
<li class="title">John</li>
<li class="title">Jack</li>
<li class="title">Joe</li>
<li class="title1">Jim</li>
<li class="title">David</li>
<li class="title">Sam</li>
<li class="title1">Jay</li>
<li class="title">Frank</li>
<li class="title">Tim</li>
<li class="title">Zack</li>
<li class="title">Lewis</li>
<li class="title1">Danny</li>
</ul>
<button class="btn">Toggle 'title' items to red</button>
markup issues
id attributes must be unique within a document. if you need to attach the same identifier to multiple elements use class instead.
<button> cannot be a child of <ul>.
First, id values must be unique, so you should be using class to
organize the similar <li> elements and use id to uniquely
identify the two buttons.
Also, the only elements that can be a child of a <ul> are <li>,
<script> and <template> elements, not <button>, so the buttons
have to be moved out of the ul.
From there, it's just a matter of setting the two buttons click handlers to the same event handler that loops over the li elements with the given class (not the buttons as you are trying to do) and adds or removes a pre-made class to the list depending on which button was clicked.
// test.js contents
document.getElementById("btn").addEventListener("click", changeColor);
document.getElementById("btn2").addEventListener("click", changeColor);
let items = document.querySelectorAll(".title");
function changeColor(event){
items.forEach(function(item){
// Figure out which button got us here
if(event.target.id === "btn"){
item.classList.add("red"); // Add red
} else {
item.classList.remove("red"); // Remove red
}
});
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Change the Certain Font Color with JavaScript</title>
<style>
.red {color:red;}
</style>
</head>
<body>
<ul>
<li class="title">John</li>
<li class="title">Jack</li>
<li class="title">Joe</li>
<li class="title1">Jim</li>
<li class="title">David</li>
<li class="title">Sam</li>
<li class="title1">Jay</li>
<li class="title">Frank</li>
<li class="title">Tim</li>
<li class="title">Zack</li>
<li class="title">Lewis</li>
<li class="title1">Danny</li>
</ul>
<button id="btn">Change 9 names to red</button>
<button id="btn2">Reset</button>
<script src="test.js"></script>
</body>
</html>
Additional notes:
You'll want to stay away from using .getElementsByClassName().
Rather than looping with counter indexes, it's much simpler to use
the Array.forEach() method on the collection returned from .querySelectorAll().
You should avoid using inline styles whenever possible as they are the hardest to override and to maintain. Instead, add, remove, or toggle the use of CSS classes with the .classList API, which is much simpler to use.
This question already has answers here:
Methods in ES6 objects: using arrow functions
(6 answers)
Closed 3 years ago.
I'm trying to fix the following code:
const $configuratorMenus = $('.configurators-menu ul li');
$configuratorMenus.click(() => {
let panelID = $(this).data("id");
let panelID2 = $(this).attr("data-id");
console.log(panelID, panelID2);
//$(`#${panelID}`).slideToggle();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="configurators-menu">
<ul>
<li data-id="shapes">
<a href="#">
Shape
</a>
</li>
</ul>
</div>
It keeps consoling undefined, what am I doing wrong? I couldn't relate any other solution.
Note: I would like to solve this by using the arrow function.
Since you are using arrow function , this will refer window object in this case. You can use e.target.Where e is event object. Also the data attribute is on li but the event is originating from a. So change $configuratorMenus to $('.configurators-menu ul li a')
const $configuratorMenus = $('.configurators-menu ul li a');
$configuratorMenus.click((e) => {
// get the parent element from the target
let panelID = $(e.target).parent().data('id');
console.log(panelID);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="configurators-menu">
<ul>
<li data-id="shapes">
<a href="#">
Shape
</a>
</li>
</ul>
</div>
This one should resolve your problem -
const configuratorMenus = $('.configurators-menu ul li a');
configuratorMenus.click(function () {
let panelID = $(this).parent().data("id");
console.log(panelID);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="configurators-menu">
<ul>
<li data-id="shapes">
<a href="#">
Shape
</a>
</li>
</ul>
</div>
I have 10-15 unordered lists in my HTML page, each containing a delete button next to each list item.
For each li to be uniquely identifiable, I have assigned to its id: its parent's id and its own category_name.
However, when I perform the remove() -- it doesn't work. The li does not get removed from its parent.
I already have an input box associated with each ul to add li's to the specific ul which is working.
<script>
function remove_category(ident){
$("#"+ident).remove;
}
function add_category(ul_id, input_id){
var ul = $("#"+ul_id);
var added_category = $("#"+input_id).val();
$(ul)
.append('<li class="list-group-item" id="'+added_category+'">'+added_category+'<button type="button" id="delete-category-btn" onclick="remove_category('+ul_id+added_category+');"><i class="fa fa-times delete-fa" aria-hidden="true"></i></button></li>')
}
</script>
The remove_category() function does not perform any action.
Probably because of the event handler is not taking dynamic element. Use .on to make the click event work on dynamic element
Here is the example.
$(document).on("click", ".added-category", function() {
var parent = $(this).closest("li");
parent.after("<li>" + parent.html() + "</li>");
});
$(document).on("click", ".remove-category", function() {
var parent = $(this).closest("li");
parent.remove();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>
some text
<button class="added-category">Add</button>
<button class="remove-category">Remove</button>
</li>
</ul>
Try to use this,
function removeLi(dhis){
dhis.parent().remove()
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li >list 1 <button onclick="removeLi($(this))">remove</button></li>
<li>list 2 <button onclick="removeLi($(this))">remove</button></li>
<li >list 3 <button onclick="removeLi($(this))">remove</button></li>
<li >list 4 <button onclick="removeLi($(this))">remove</button></li>
<li >list 5 <button onclick="removeLi($(this))">remove</button></li>
</ul>