how to toggle between icons when a button is clicked? - javascript

I want to switch between a moon and a sun when the dark mode is enabled or disabled.
Now I have it that I can change once, but after that it stays as a moon.
How do I fix this this?
function darkmode() {
document.body.classList.toggle('dark-mode');
document.getElementById('toggleknop').innerHTML = '<i class="fas fa-moon fa-2x" id="maan" style="color:#737eac;"></i>';
}
<button onclick="darkmode()" id="Knop">
<span id="toggleknop"><i class="fas fa-sun fa-2x" id="zon" style="color:#d8c658;"></i></span>
</button>

You can change/toggle easily Drak <=> Light only using CSS.
just use 'document.body.classList.toggle('dark-mode');' code only for toggle. show icon depend on the parent class. please see the snippet here:
function darkmode() {
document.body.classList.toggle('dark-mode');
}
.dark-mode button {
background: black;
color: white;
}
.dark-mode .sun-icon,
.moon-icon {
display: none;
}
.dark-mode .moon-icon {
display: inline;
}
<button onclick="darkmode()" id="Knop">
click
<span class="sun-icon">
sun <i class="fas fa-sun fa-2x" id="zon" style="color:#d8c658;"></i>
</span>
<span class="moon-icon">
moon <i class="fas fa-moon fa-2x" id="maan" style="color:#737eac;"></i>
</span>
</button>
Maybe it helps to solve your problem.
Thank you

var currentTheme = 'dark';
function changeTheme() {
document.body.classList.toggle('dark-mode');
if (currentTheme === 'dark') {
document.getElementById('toggleknop').innerHTML = '<i class="fas fa-sun fa-2x" id="zon" style="color:#d8c658;"></i>';
currentTheme = 'sun';
}else {
document.getElementById('toggleknop').innerHTML = '<i class="fas fa-moon fa-2x" id="maan" style="color:#737eac;"></i>';
currentTheme = 'dark';
}
}

You need to remember whether you are in dark mode with a variable stored outside the function:
var inDarkMode = false;
function toggleDarkMode() {
if (inDarkMode) {
document.body.classList.remove('dark-mode');
document.getElementById('toggleknop').innerHTML =
'<i class="fas fa-moon fa-2x" id="maan" style="color:#737eac;"></i>';
inDarkMode = false;
} else {
document.body.classList.add('dark-mode');
document.getElementById('toggleknop').innerHTML =
'<i class="fas fa-sun fa-2x" id="zon" style="color:#d8c658;"></i>';
inDarkMode = true;
}
}

Use hasClass to check if it contains class.
function darkmode() {
document.body.classList.toggle('dark-mode');
var toggleknop= document.getElementById('toggleknop');
if(toggleknop.hasClass('fa-sun')
{
toggleknop.classList.remove('fa-sun');
toggleknop.classList.add('fa-moon');
//Your styling
}
else if(toggleknop.hasClass('fa-moon') {
toggleknop.classList.remove('fa-moon');
toggleknop.classList.add('fa-sun');//Your styling
}

function darkmode() {
document.body.classList.toggle('dark-mode');
document.getElementById('toggleknop').innerHTML = document.body.classList.contains('dark-mode') ? '<i class="fas fa-moon fa-2x" id="maan" style="color:#737eac;"></i>' : '<i class="fas fa-sun fa-2x" id="zon" style="color:#d8c658;"></i>';
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css" rel="stylesheet"/>
<button onclick="darkmode()" id="Knop">
<span id="toggleknop"><i class="fas fa-sun fa-2x" id="zon" style="color:#d8c658;"></i></span>
</button>
function darkmode() {
document.body.classList.toggle('dark-mode');
document.getElementById('toggleknop').innerHTML = document.body.classList.contains('dark-mode') ? '<i class="fas fa-moon fa-2x" id="maan" style="color:#737eac;"></i>' : '<i class="fas fa-sun fa-2x" id="zon" style="color:#d8c658;"></i>';
}

Related

jQuery Remember toggleClass status in list

I have a function:
function toggle(event) {
$(`#${event.target.id}`).toggleClass('fa-power-on fa-power-off');
}
I also have a list of buttons:
<i id="id1" onclick="toggle($event)"></i>
<i id="id14" onclick="toggle($event)"></i>
<i id="id12" onclick="toggle($event)"></i>
<i id="id17" onclick="toggle($event)"></i>
<i id="id18" onclick="toggle($event)"></i>
<i id="id1w" onclick="toggle($event)"></i>
I need the status of the toggleClass icon to be remembered for each.
Either by localStorage or id's and status all in an object and then saved on localstorage or other.
The <i></i> list is dynamic so I cannot hardcode it.
How can I do this?
Consider the following example.
$(function() {
function toggle(el) {
$(el).toggleClass("fa-power-on fa-power-off");
}
function getPowerStatus(selector) {
var results = [];
$(selector).each(function(i, el) {
var key = $(el).attr("id");
var val = $(el).hasClass("fa-power-on");
var item = {};
item[key] = val;
results.push(item);
});
return results;
}
function saveStatus(stats) {
localStorage.setItem("status", JSON.stringify(stats));
}
function getStatus() {
return JOSN.parse(localstorage.getItem("status"));
}
$("i[id^='id']").click(function(e) {
toggle(this);
var status = getPowerStatus("i[id^='id']");
console.log(status);
saveStatus(status);
});
});
.fa-power-off {}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<i id="id1" class="fas fa-power-off"></i>
<i id="id14" class="fas fa-power-off"></i>
<i id="id12" class="fas fa-power-off"></i>
<i id="id17" class="fas fa-power-off"></i>
<i id="id18" class="fas fa-power-off"></i>
<i id="id1w" class="fas fa-power-off"></i>
This created functions to toggle, gather the status of each, set, and get those status to Local Storage.
Not sure what Icon Set you're using, but Font-Awesome does not have a fa-power-on. Which would mean you'd want to toggle a different class.
$(function() {
function toggle(el) {
$(el).toggleClass("on");
}
function getPowerStatus(selector) {
var results = [];
$(selector).each(function(i, el) {
var key = $(el).attr("id");
var val = $(el).hasClass("on");
var item = {};
item[key] = val;
results.push(item);
});
return results;
}
function saveStatus(stats) {
localStorage.setItem("status", JSON.stringify(stats));
}
function getStatus() {
return JOSN.parse(localstorage.getItem("status"));
}
$("i[id^='id']").click(function(e) {
toggle(this);
var status = getPowerStatus("i[id^='id']");
console.log(status);
saveStatus(status);
});
});
.fa-power-off {
border-radius: 50%;
}
.fa-power-off.on {
background: black;
color: white;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<i id="id1" class="fas fa-power-off"></i>
<i id="id14" class="fas fa-power-off"></i>
<i id="id12" class="fas fa-power-off"></i>
<i id="id17" class="fas fa-power-off"></i>
<i id="id18" class="fas fa-power-off"></i>
<i id="id1w" class="fas fa-power-off"></i>
Now you can Click them on or off. Each time click event happens, it toggle the class and updates the saved status. You can then get the status when the page loads and re-apply the on class as needed.

Changing className after insertAdjacentHTML

I am trying to change my className after the insertAdjacentHTML() function. I am using an AJAX request for this and the route /reviewcombine is from my backend JavaScript codes.
My codes:
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
.checked {
color: orange;
}
</style>
<script>
function getTestByID() {
var request = new XMLHttpRequest();
//The "/reviewcombine" here is the route from my backend JavaScript
request.open("GET", "/reviewcombine", true);
request.setRequestHeader("Content-Type", "application/json");
request.onload = function () {
var tests = JSON.parse(request.responseText);
var exampleID = 1
var totalTests = tests.length;
var testlistings = document.getElementById("testListings");
for (var testCount = 0; testCount < totalTests; testCount++) {
if (tests[testCount].reviewResId == exampleID) {
var username = tests[testCount].username;
var rating = tests[testCount].rating;
var testItem = '<div class="eachtest">\
<h5 style="padding:6px; background-color: #E1ECF4; display: inline-block">#'+ username + '</h5>\
<div style="margin-top: 1px; padding-left: 3px;">\
<p style="color: rgb(255, 136, 0); font-size: 16px; display: inline;">'+ rating + '</p> \
<span class="fa fa-star" id="test_1"></span>\
<span class="fa fa-star" id="test_2"></span>\
<span class="fa fa-star" id="test_3"></span>\
<span class="fa fa-star" id="test_4"></span>\
<span class="fa fa-star" id="test_5"></span>\
\
</div>\
</div>';
// insertAdjacentHTML() to insert the HTML codes.
testlistings.insertAdjacentHTML('beforeend', testItem);
//cant change after insertAdjacentHTML????????????????????
var star = tests[testCount].rating
if (star == 0) {
return;
}
else if (star == 1) {
document.getElementById('test_1').className = "fa fa-star checked"
}
else if (star == 2) {
document.getElementById('test_1').className = "fa fa-star checked"
document.getElementById('test_2').className = "fa fa-star checked"
}
else if (star == 3) {
document.getElementById('test_1').className = "fa fa-star checked"
document.getElementById('test_2').className = "fa fa-star checked"
document.getElementById('test_3').className = "fa fa-star checked"
}
else if (star == 4) {
document.getElementById('test_1').className = "fa fa-star checked"
document.getElementById('test_2').className = "fa fa-star checked"
document.getElementById('test_3').className = "fa fa-star checked"
document.getElementById('test_4').className = "fa fa-star checked"
}
else {
document.getElementById('test_1').className = "fa fa-star checked"
document.getElementById('test_2').className = "fa fa-star checked"
document.getElementById('test_3').className = "fa fa-star checked"
document.getElementById('test_4').className = "fa fa-star checked"
document.getElementById('test_5').className = "fa fa-star checked"
}
}
}
}
request.send();
}
</script>
</head>
<body onload="getTestByID()">
<div id="testListings"></div>
</body>
</html>
Here, I am trying to change my stars to orange and display it based on the ratings value.
However, doing this after the insertAdjacentHTML function just changes the classNames permanently. The subsequent loops are using the fa fa-star checked class instead of the fa fa-star class that they should be using. (Doing it before the insertAdjacentHTML function is also not possible)
This is an example of the output I am getting:
Can someone please help me to identify what is the error here? Any relevant sources would also be a big help. Thanks a lot!
Inside the loop you are assigning a hard-coded id:
<span class="fa fa-star" id="test_1"></span>
document.getElementById('test_1") is only going to return the first instance of it, because id is supposed to be unique. Try making the id dynamically.

How can I get two different events with "querySelectorAll" for each element?

I have a probleme with my code. Now if I click the first element, all elements will become red, if I click second time they will become green. I would like have two independent events for each element with class fa-heart. I will explain better: If I click the first time the first element DOM, only this element will become red, and if I click it second time, it will become green, and so for all the others. I apologize if my request is not clear. Thank you so much for your help.
<script src="https://kit.fontawesome.com/a1d70a0cda.js"></script>
<a onclick="change()"><i class="fas fa-heart"></i></a>
<a onclick="change()"><i class="fas fa-heart"></i></a>
<a onclick="change()"><i class="fas fa-heart"></i></a>
<script>
function change(){
var a = document.querySelectorAll('.fa-heart');
var qty = a.length;
var i = 0;
for(i; i<qty; i++){
if(a[i].style.color !== 'red'){
a[i].style.color = 'red';
}else{
a[i].style.color='green';
}
}
}
</script>
Add an individual listener to each <i> instead, and in the listener, check the current .style of the clicked element to figure out what to assign next:
document.querySelectorAll('.fa-heart').forEach((i) => {
i.addEventListener('click', () => {
i.style.color = i.style.color !== 'red'
? 'red'
: 'green';
});
});
<script src="https://kit.fontawesome.com/a1d70a0cda.js"></script>
<a><i class="fas fa-heart"></i></a>
<a><i class="fas fa-heart"></i></a>
<a><i class="fas fa-heart"></i></a>
Or, with event delegation:
document.addEventListener('click', (e) => {
if (!e.target.matches('.fa-heart')) {
return;
}
e.target.style.color = e.target.style.color !== 'red'
? 'red'
: 'green';
});
console.log('start');
setTimeout(() => {
console.log('adding dynamic elements');
document.body.innerHTML += `<a><i class="fas fa-heart"></i></a>
<a><i class="fas fa-heart"></i></a>
<a><i class="fas fa-heart"></i></a>`;
}, 1000);
<script src="https://kit.fontawesome.com/a1d70a0cda.js"></script>
If you must use inline handlers (which you shouldn't), pass the this (the clicked element) to the listener:
function change(i) {
i.style.color = i.style.color !== 'red'
? 'red'
: 'green';
}
<script src="https://kit.fontawesome.com/a1d70a0cda.js"></script>
<a onclick="change(this)"><i class="fas fa-heart"></i></a>
<a onclick="change(this)"><i class="fas fa-heart"></i></a>
<a onclick="change(this)"><i class="fas fa-heart"></i></a>
Here you go. This will change the clicked one to green and others to red.
function change(clicked) {
document.querySelectorAll('a').forEach(el => el.setAttribute("style", "color:red"));
clicked.style.cssText ="color:green;";
}
<script src="https://kit.fontawesome.com/a1d70a0cda.js"></script>
<a onclick="change(this)"><i class="fas fa-heart"></i></a>
<a onclick="change(this)"><i class="fas fa-heart"></i></a>
<a onclick="change(this)"><i class="fas fa-heart"></i></a>

JavaScript convert string into HTML element

I have javascript string with HTML elements. I want to display these elements on page but not in string form.
var stars = a;
if (stars == 5){
return '<i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i>'
}
So how it is possible to convert this string?
Use the innerHTML property of an element.
E.g.
let element = document.getElementById('myElement');
element.innerHTML = "<i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i>"
Use the innerHTML property to add the string as elements to the document. And you have to use the correct quotes in the string. Your string is not valid.
var stars = 5;
if (stars == 5) {
document.getElementById('body').innerHTML += '<i class="fas fa-star">a</i><i class="fas fa-star">a</i><i class="fas fa-star">a</i><i class="fas fa-star">a</i><i class="fas fa-star">a</i>'
}
.fas
{
background-color:green
}
<body id="body"></body>
you can use insertAdjacentHTML
const divInString = '<div class="todo">Stuff</div>'
const parentOfDiv = document.querySelector(".parent")
parentOfDiv.insertAdjacentHTML("beforeEnd",divInString)
I was looking for a solution for this problem as well and this is what solved my issue.

color icons upto the hover position

I have 10 circles (Fontawesome icons) horizontally placed. I want to fill colors to them when the user hover on any icon. For ex: if the user hovers on the 5th circle, all the circles upto the 5th circle should fill in color. (Something like in a rating system) How can i do it?
Following is the code which i render 10 circles.
export const RatePersonalityCard = ({}) => {
for (let score = 1; score < 11; score++) {
let scoreList = [];
scoreList.push(
<div className="trait_vote_single tooltip" style={{fontSize:'40px',color:'gray'}} onClick={() => handleClick(score)}>
{/*<div className="trait_vote_circle"></div>*/}
<i className="fa fa-circle-thin" aria-hidden="true"></i>
<a className="trait_value" style={{marginTop:'-34px',marginLeft:'-1px'}}>{score}</a>
<span className="tooltiptext2 unchange_div" style={{marginLeft: '-40px'}}>{starvalue}</span>
</div>
)
}
return (
<div className="">
<div className="single_trait_rate width_100 text_align_center">{userTraits.trait_name}</div>
<div className="trait_vote_div">
{scoreList}
</div>
</div>
);
};
You could create a hover event for each for every score list item that adds a class to the currently hovered item and everything prior. Then add a blur event to every item to remove the class.
function handleHover(e) {
let index = scoreList.indexOf(e.target);
for (let i = 0; i <= index; i++) {
scoreList[index].classList.add('highlight');
}
}
function handleBlur(e) {
scoreList.forEach(function(item) {
item.classList.remove('highlight');
});
}
No CSS example. I don't see great value in adding any JS to something that can simply done via CSS. If you also need a click event, it's as simple as 1 class on 1 span. I'd also recommend reading:
Decoupling Your HTML, CSS, and JavaScrip which my code does not do.
span .fa-star{
display: none;
}
span:hover > .fa-star{
color: yellow;
display: inline-block;
color: red;
}
span:hover > .fa-star-o{
display: none;
}
span { cursor: pointer }
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<span>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<span>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<span>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<span>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<span>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
</span>
</span>
</span>
</span>
</span>

Categories

Resources