How to change style of a button in javascript? [duplicate] - javascript

This question already has answers here:
How can I change an element's class with JavaScript?
(33 answers)
Closed 2 years ago.
I have a button whose original style is display: none, and after activating a function i want to change his style to an appear using style of defined class style.
I have the pause button as follows:
<li><button className="pause_button"
onClick={() =>{this.props.pause_resume();}}>
</button>
</li>
and the styles
.sortButton {
background-color: ivory;
color: black;
padding: 10px 25px;
border-radius: 3px;
margin: 5px;
font-size: 16px;
opacity: 1;
}
.sortButton:hover {
background-color: dodgerblue;
color: white;
opacity: 1;
}
.pause_button {
display: none;
}
I am trying to change the style of pause_button to be the style of sortButton
Here is what i tried, but unfortunately no change appears.
const pause_button = document.getElementsByClassName("pause_button");
pause_button.style = "sortButton";
In a different part of my code I'm using the same way and it does make changes to the button.
const buttons = Array.from(document.getElementsByClassName("sortButton"));
buttons.forEach(button => {
button.style = "sortButton";
})
The last bit of code happens after I have changed the buttons style in this way.
const buttons = Array.from(document.getElementsByClassName("sortButton"));
buttons.forEach(button => {
if(button.innerText !== text){
button.style.backgroundColor = 'grey';
button.style.opacity= 0.2;
}
})
All the changes except from the pause button appearing works,

Two things: style is an object, not a string. You need to change the element's class instead. And getElementsByClassName returns a collection of elements. In your code:
const pause_button = document.getElementsByClassName("pause_button");
pause_button.style = "sortButton";
pause_button is an HTMLCollection. You can use Array.from() like you did in the other example, or you can iterate over it directly using for...of.
const buttons = getElementsByClassName("pause_button");
for (button of buttons) {
button.className = "sortButton";
}

You have to use Element.className on the DOM Node to associate a class to a particular node. To apply the class "sortButton" you have to do the following:
const buttons = Array.from(document.getElementsByClassName("sortButton"));
buttons.forEach(button => { button.className = "sortButton" });

Related

JS Variable Cannot Change Element Properties

Quick question here, I encountered this problem today while practicing some JS. I wanted to create a basic prototype to loop through a "div" background-color array on click, but I realized that assigning the element property to a variable (instead of using the event target) impedes me to change the actual values.
This is the JS code:
let colors = ["blue", "yellow", "orange", "red"]
let n = 1;
document.querySelectorAll('div').forEach(occurence => {
occurence.addEventListener('click', (e) => {
let classes = e.target.className;
classes = colors[n];
n++;
console.log(classes);
if (n >= 4) {n = 0;}
});
});
So, changing the actual e.target.className works just fine, but trying to change the assigned "classes" variable does nothing. I feel like this may be a matter of specificity, or JS being unable to access the actual property values, or some akin beginner mistake.
e.target.className passes by value when you have let classes = e.target.className, so classes contains a copy of its data. Changing classes just changes the copy, rather than what's stored in e.target.classname.
Actually, you are not changing the value of e.target.className. What you do, is assigning the value of e.target.className to the variable/let-binding classes. To assign one of the color values to the className property, the assignment has to be the other way around:
e.target.className = colors[n];
let classes = e.target.className will assign the current string value of className to classes. And while you can assign a new colour value to classes that won't assign the new colour value to the className property of the element. For that you want to explicitly assign it: e.target.className = colors[i].
You may also want to remove the need to add a event listener to all the elements. Event delegation allows you to add one listener to a parent element which captures events from its child elements as they "bubble up" the DOM.
Here's an over-wrought example:
const colors = ['blue', 'yellow', 'orange', 'red'];
// Cache the elements first, and add a listener to
// the container
const counter = document.querySelector('.index');
const container = document.querySelector('.container');
container.addEventListener('click', handleClick);
let count = 0;
function handleClick(e) {
// Check to see if the element that was clicked
// was a div element
if (e.target.matches('.container div')) {
// Update the counter element, the `className` value,
// and the `textContent of the "box", and then update
// the count value
counter.textContent = `Color index: ${count}`;
e.target.className = colors[count];
e.target.textContent = colors[count];
count = count < colors.length - 1 ? ++count : 0;
}
}
.container { display: grid; gap: 0.4em; grid-template-columns: repeat(2, 50px); }
.container div { display: flex; justify-content: center; align-items: center; height: 50px; width: 50px; border: 1px solid lightgray; }
.container div:hover { cursor: pointer; border: 1px solid darkgray; }
.blue { background-color: lightblue; }
.yellow { background-color: #ffff00; }
.orange { background-color: darkorange; }
.red { background-color: red; }
.index { margin-top: 0.5em; }
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="index">Color index:</div>

How to toggle elements' class from an `onClick` event (from jQuery to pure JS)?

I want to toggle a css class on all elements with the same class, on click of another element.
I had it working with jQuery but need to switch to pure JavaScript.
The jQuery version that works:
$(function() {
$("#logo").click(function() {
$(".grey").toggleClass("white", 1000);
$(".red").toggleClass("orange", 1000);
});
});
When you click on the element with id="logo", everything with class="grey" toggles white class and everything with class="red" toggles orange.
Update with new problem!
I'm using #Vektor's code which works well — except on the iPhone 5 where nothing happens. (It works in my iPhone 12 and 7.) Simplified code for trials:
<body>
<div id="logo" class="grey"><p class="red">Hello.</p>
</div>
<script>
const logo = document.getElementById('logo');
logo.addEventListener('click', () => {
const grey = document.querySelectorAll('.grey');
const red = document.querySelectorAll('.red');
grey.forEach(e => e.classList.toggle('white'));
red.forEach(e => e.classList.toggle('orange'));
}, false);
</script>
</body>
body{background-color: #000000;}
div#logo{
position:fixed;
top:0;
left:0;
height: 100vh;
width:30vw;
cursor: pointer;
}
.red{background-color:#4C0000;}
.orange{background-color:#d69215}
.grey{background-color:#485055;}
.white{background-color:white;}
I read adding cursor:pointer would fix JavaScript not functioning on non-traditional clickable elements for older iPhone browsers. It didn't.
first grab the "id". Then Listen for a "click" event on that. When click occurs grab the all "white" class elements first. "queryselectorAll" returns an array-like NodeList, so you can use "forEach" array method on that. Then iterate the all elements one by one. Same logic goes for "red" class elements.
let logo = document.getElementById('logo');
logo.addEventListener('click', ()=>{
let grey = document.querySelectorAll('.grey');
grey.forEach((e)=>{
e.classList.toggle('white')
})
let red = document.querySelectorAll('.red');
red.forEach((e)=>{
e.classList.toggle('orange')
})
})
Firstly, select the logo element by its id attribute. Register a click event listener on it to trigger the procedure. The event handler function will select all the elements containing the grey & red class names producing a list of nodes, iterate over them, and for each of those elements, toggle the white & orange class names in the list of classes.
const logo = document.getElementById('logo');
logo.addEventListener('click', () => {
const grey = document.querySelectorAll('.grey');
const red = document.querySelectorAll('.red');
grey.forEach(e => e.classList.toggle('white'));
red.forEach(e => e.classList.toggle('orange'));
}, false);
body {
background-color: #666;
}
.grey {
color: #bbb;
}
.red {
color: red;
}
.white {
color: white;
}
.orange {
color: orange;
}
<button id="logo">LOGO!</button>
<p class="grey">Hello World</p>
<p class="red">Hello World</p>
<p class="grey">Hello World</p>
<p class="red">Hello World</p>
<p class="grey">Hello World</p>
I hope this solves your problem.
Update
As per request by OP, I've added these updates to address the issue regarding the click event not being fired on older iPhone versions (namely the iPhone 5) in the above solution. Because I don't have access to those devices, I can't guarantee the viability of the following suggestions.
LOGO1!
LOGO2!
LOGO3!
const handleClick = function handleClick() {
const grey = document.querySelectorAll('.grey');
const red = document.querySelectorAll('.red');
grey.forEach(e => e.classList.toggle('white'));
red.forEach(e => e.classList.toggle('orange'));
}
You can get an element by its class and then operate on it:
document.getElementById('logo').addEventListener('click', function(){
var redElements = document.getElementsByClassName('red');
Array.from(redElements).forEach(el => el.classList.toggle('orange'));
var greyElements = document.getElementsByClassName('grey');
Array.from(greyElements).forEach(el => el.classList.toggle('white'));
});
simplification of javascript is jquery so dont need to do it in hard way friend.
var grey = document.getElementByClassName("grey");
grey.classList.toggle("white");

JavaScript onclick change image and increase the counter

I try to make a simple like/dislike function to my page. The image changing is working but the counter not and I do not know why. Any idea how to make it workable?
By the way I have read a bunch of questions about like/dislike system with JS but its not really works for me.
const imageChange = document.querySelector('.likeClassQ')
var countL = 0;
var buttonLike = document.getElementById("likeButton");
var displayLike = document.getElementById("likes");
buttonLike.addEventListener('click', () => {
imageChange.classList.toggle('likeClassFilled')
})
buttonLike.onclick = function() {
if (buttonLike.classList == 'likeClass') {
countL++;
buttonLike.classList.add = "likeClassFilled";
} else if (buttonLike.classList == "likeClassFilled") {
countL--;
buttonLike.classList.add = "likeClass";
}
displayLike.innerHTML = countL;
}
.likeClass {
background-color: red;
background-repeat: no-repeat;
background-size: contain;
padding: 10px;
border: none;
}
.likeClassFilled {
background-color: green;
}
<span><span id="likes">0</span> Likes</span><br>
<button id="likeButton" class="likeClass likeClassQ">Like</button>
There is no need to assign a function to onclick and use addEventListener. Just use one and stick to it.
Your CSS classes are all over the place. Use one for the general styling and another one for your state. Or better yet, use the data attribute if the element or maybe even a stylized checkbox for that. Mixing CSS classes and business logic is a slippery slope.
classList has methods like toggle, add and includes, but you have to use those fields as methods and not as simple fields. Also, you can not use the comparison operator (==) with objects. You would only use that on simple values like strings or numbers. You execute functions/methods by writing brackets after the method/function name and passing any parameters in those. When you use the assignment operator (=), you are not calling anything.
Your logic about saving the state and deriving the current state is flawed. I changed it to toggle a class on each click. Hence you will not find any classes being added or removed within the condition.
const imageChange = document.querySelector('.likeClassQ')
var countL = 0;
var buttonLike = document.getElementById("likeButton");
var displayLike = document.getElementById("likes");
buttonLike.onclick = function() {
if (buttonLike.classList.contains('likeClassFilled')) {
countL--;
} else {
countL++;
}
buttonLike.classList.toggle("likeClassFilled");
displayLike.innerHTML = countL;
}
.likeClass {
background-color: red;
background-repeat: no-repeat;
background-size: contain;
padding: 10px;
border: none;
}
.likeClassFilled {
background-color: green;
}
<span><span id="likes">0</span> Likes</span><br>
<button id="likeButton" class="likeClass likeClassQ">Like</button>

Toggle add and remove class in JavaScript with if condition

I have a element with an id="caretToggle" and a button with onclick="caretToggle()". This fires a function that adds a class to invert the caret on the button.
I am successful in running:
function caretToggle() {
var caretElement = document.getElementById("caretToggle");
caretElement.classList.add("dropup");
}
But This leaves the caret inverted after the collapse is closed. I want to toggle the caret once the button is clicked again.
This is my condition code that I have failed to get working:
function caretToggle() {
var caretElement = document.getElementById("caretToggle");
if (caretElement.classList.contains("dropup")) {
caretElement.classList.remove("dropup");
} else {
caretElement.classList.add("dropup");
}
}
Thank you in advance for any help you may provide!
You dont need to check wheter contains or not.
What you can do simply use toggle function on classList :)
function caretToggle() {
var caretElement = document.getElementById("caretToggle");
caretElement.classList.toggle("dropup");
}
And also there is a conditional toggle like:
caretElement.classList.toggle("dropup", counter < 10)
Check here from MDN
If you want to toggle class simply do it like this
let caretElement = document.getElementById("caretToggle");
function caretToggle() {
caretElement.classList.toggle("dropup");
console.log('class attribute contains: ', caretElement.className)
}
span {
margin:10px;
}
.dropup {
background-color: purple;
padding: 1em;
border-radius: 10px;
color: white;
}
<span id="caretToggle">HTMLElement</span>
<br/>
<br/>
<br/>
<br/>
<button onclick="caretToggle()">Click</button>

How do you get the style of focussed HTML element using JavaScript?

I would like to get the computed style of an element when it is focussed. I am using puppeteer and I would like to compare the CSS before focus to the CSS after focus. I can successfully get focus on an element using element.focus() and can confirm it's focussed by checking the active element (document.activeElement). However, the computed style (getComputedStyle()) for this element is the same as before focus, which is not what I expected.
Is there a way to get the CSS of the element after focus?
To be clear, I am writing a JavaScript tool which can scrape any website to check if the outline or border of an element under focus has sufficient contrast with the background on the page (such that it conforms with accessibility guidelines https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast.html). To do this I need to be able to get the colour of the outline/border when the element is under focus. Normally a focus outline would be defined in the CSS under :focus { ... } so this is what I wish to retrieve for any element.
you need to pay attention to the order of code in the script. if you change the style before the getComputedStyle() you'll get the change.
exmple:
document.querySelector("input").addEventListener("focus", (e) => {
console.log(window.getComputedStyle(e.target, null).color);
e.target.style.color = "red";
console.log(window.getComputedStyle(e.target, null).color);
e.target.style.color = "blue";
})
<input type="text" style="color: blue;">
As getComputedStyle returns a live CSSStyleDeclaration, you have to record the CSS styles by yourself manually to keep the CSS before focus.
Here's a working example:
let allInputs = document.querySelectorAll('input')
let beforeFocusStyles = Array.from(allInputs).reduce(function(final, elem) {
final[elem.dataset.identifier] = (function() {
let liveStyle = window.getComputedStyle(elem)
let value = {}
for (let key in liveStyle) {
value[key] = liveStyle[key]
}
return value
})()
return final
}, {})
Array.from(allInputs).forEach(elem => {
elem.onfocus = function() {
let afterFocusStyle = window.getComputedStyle(elem)
let differenceInStyle = (function() {
let beforeFocusStyle = beforeFocusStyles[elem.dataset.identifier]
let differences = []
for (let key in afterFocusStyle) {
if (beforeFocusStyle[key] !== afterFocusStyle[key]) {
differences.push([key, beforeFocusStyle[key], afterFocusStyle[key]])
}
}
return differences
})()
differenceInStyle.forEach(difference => {
console.log(difference[0], difference[1], difference[2])
})
}
})
.type1 {
outline: 1px solid black;
border: none;
}
.type1:focus {
outline: 2px solid red;
border: none;
}
.type2 {
outline: 1px solid blue;
border: none;
}
.type2:focus {
outline: 2px solid green;
border: none;
}
<input type="text" class="type1" data-identifier="1">
<input type="text" class="type2" data-identifier="2">

Categories