I am working on a site with an accordion style script i've found. I'm quite new to jquery/javascript, so please bear with me...
My basic page opens an accordion, where the first one is locked open, and the other ones opens/closes if pressed. What keeps my top panel locked open is a
<li class="locked">.
The other panels have only
<li>
no class. I guess I can call them
<li class="somethingelse">
I want a button in my top panel that changes all the
to
<li class="locked">, so that the user can view the entire site.
I have tried:
<div>
<ul>
<li class="locked">Something
<button onclick="myFunction()">Click me</button>
</li>
<li id="abcd" class="somethingelse">somethingelse</li>
<li id="abcd"class="somethingelse">somethingelse</li>
</ul>
</div>
<script>
function myFunction() {
document.getElementById("abcd").class = "locked";
}
</script>
In plain JavaScript, I'd suggest:
function myFunction() {
// retrieves a NodeList of all <li> elements that do not
// have the 'locked' class-name:
var liElements = document.querySelectorAll('li:not(.locked)');
// uses Array.prototype.forEach to iterate over the array-like
// NodeList:
Array.prototype.forEach.call(liElements, function (li, index, list) {
// first argument ('li' ): the current array-element,
// second argument ('index'): unused, the index of the current
// array-element in the array,
// third argument ('list'): the array itself
// adding the 'locked' class-name to the list of classes
// of the current node:
li.classList.add('locked');
});
}
li {
opacity: 0.3;
}
li.locked {
opacity: 1;
}
<div>
<ul>
<li class="locked">Something
<button onclick="myFunction()">Click me</button>
</li>
<li class="somethingelse">somethingelse</li>
<li class="somethingelse">somethingelse</li>
</ul>
</div>
<script>
function myFunction() {
var liElements = document.querySelectorAll('li:not(.locked)');
Array.prototype.forEach.call(liElements, function (li, index, list) {
li.classList.add('locked');
});
}
</script>
Further, I'd suggest binding the event-handling in JavaScript, rather than using in-line HTML attributes (onclick, etc), which makes for easier long-term maintenance (since everything's updated in the same place, and you don't have to remember where all the event-handling was assigned):
function myFunction() {
var liElements = document.querySelectorAll('li:not(.locked)');
Array.prototype.forEach.call(liElements, function(li, index, list) {
li.classList.add('locked');
});
}
// finding the first element that matches the CSS selector.
// adding the named function (myFunction) as a 'click'
// event-handler:
document.querySelector('li.locked button').addEventListener('click', myFunction);
li {
opacity: 0.3;
}
li.locked {
opacity: 1;
}
<div>
<ul>
<li class="locked">Something
<button onclick="myFunction()">Click me</button>
</li>
<li class="somethingelse">somethingelse</li>
<li class="somethingelse">somethingelse</li>
</ul>
</div>
References:
CSS:
Negation (:not()) pseudo-class.
JavaScript:
document.querySelector().
document.querySelectorAll().
EventTarget.addEventListener().
Element.classList.
You should be changing element class as below
document.getElementById("abcd").className = "locked";
If you want to select more then one element use class name:
var nodes = document.getElementsByClassName("somethingelse");
So your final function will look like:
function myFunction() {
var nodes = document.getElementsByClassName("somethingelse");
var arr = Array.prototype.slice.call(nodes);
arr.forEach( function(node) {
node.className = "locked";
});
}
li {
color: #000000;
}
li.locked {
color: #ff0000;
}
<div>
<ul>
<li class="locked">Something
<button onclick="myFunction()">Click me</button>
</li>
<li id="abcd" class="somethingelse">somethingelse</li>
<li id="abcd" class="somethingelse">somethingelse</li>
</ul>
</div>
Related
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(){ /*...*/ });
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.
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>
Since I'm new in Java Script, I need to know how can I change list item color or style using Java Script?
For example I have following unordered list in my HTML file:
<ul id="list">
<li>Text1</li>
<li>Text2</li>
<li>Text3</li>
<li>Text4</li>
</ul>
Now when I click on item it should change the color and when clicking next item it will keep the new color of the previous item and change also color of the newly clicked item (example screenshot below):
Try the below solution. This will toggle the click as well.
var ul = document.getElementById("list");
var listItems = ul.getElementsByTagName("li");
for(li of listItems){
li.addEventListener('click', function(){
if(this.classList.contains('active')){
this.classList.remove("active");
} else {
this.classList.add("active");
}
})
}
.active{
color: red;
}
<ul id="list">
<li>Text1</li>
<li>Text2</li>
<li>Text3</li>
<li>Text4</li>
</ul>
Array.from(document.getElementById('list').children).forEach(function(elem){
elem.addEventListener('click', function(e){e.target.style.color = 'red';})
});
EDIT: All the people suggesting jQuery are crazy importing an entire library just to do one little thing
Use addEventListener to bind an event listener function to the element.
// find all the <li> elements
var listItems = document.querySelectorAll('#list li');
// iterate over the <li> elements
listItems.forEach(function (listItem) {
// this function is called for each <li> element
listItem.addEventListener('click', function () {
// as soon as the list item is clicked, change its color to red
this.style.color = 'red';
});
});
<ul id="list">
<li>Text1</li>
<li>Text2</li>
<li>Text3</li>
<li>Text4</li>
</ul>
Or shorter:
document.querySelectorAll('li').forEach(li => li.addEventListener('click', _ => li.style.color = 'red'));
Below is the jquery code to achieve this
$('li').click(function(){
$(this).css('background-color','red');
})
Add/remove color on each click of element,
Here is the working Fiddle
https://jsfiddle.net/jvk3/5Lyx827b/
html
<ul id="list">
<li>Text1</li>
<li>Text2</li>
<li>Text3</li>
<li>Text4</li>
</ul>
Jquery Script
<script>
$(document).ready(function() {
$('li').click(function(event) {
$(this).toggleClass('red');
});
});//end doc ready
</script>
CSS
<style>
.red{
color: red;
}
</style>
So, I'm struggling here. I want to make an on click even that when I click on a navigation, it opens nested list and add class to parent list.
That part almost works, problem is that it adds that class to all elements from parent list.
<ul>
<li><div><p class="hidden">Test 1</p>
<ul class="shown">
<li>
<p>Inner 1</p>
</li>
</ul>
</div>
</li>
<li><div><p class="hidden">Test 2</p>
<ul class="shown">
<li>
<p>Inner 2</p>
</li>
</ul>
</div>
</li>
</ul>
<ul>
jque
$(document).ready(function () {
$('.shown').hide();
$('.hidden').click(function () {
var $answer = $(this).next('.shown');
if ($answer.is(':hidden')) {
$answer.show();
$('.hidden').addClass('color1');
} else {
$answer.hide();
$('.hidden').removeClass('color1');
}
});
});
css
.color1{
background:red;
}
jsfiddle
https://jsfiddle.net/Lc5n8k81/1/
here while adding and removing color1 class change $('.hidden') to $(this).. as $('.hidden') will add class to all element with .hidden class
Jsfiddle: https://jsfiddle.net/6moznpbr/
$(document).ready(function () {
$('.shown').hide();
$('.hidden').click(function () {
var $answer = $(this).next('.shown');
if ($answer.is(':hidden')) {
$answer.show();
$(this).addClass('color1');
} else {
$answer.hide();
$(this).removeClass('color1');
}
});
});
Inside your click handler, you want to refer to $(this) not $('.hidden') - the latter means all elements with class hidden:
$('.hidden').click(function () {
var $answer = $(this).next('.shown');
if ($answer.is(':hidden')) {
$answer.show();
$(this).addClass('color1');
} else {
$answer.hide();
$(this).removeClass('color1');
}
});
https://jsfiddle.net/Lc5n8k81/2/