Changing className after insertAdjacentHTML - javascript

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.

Related

Toggle span text with i tag

How can i make my code above change the span text without removing the 'i' tag?
function toggle(e) {
let txt = e.innerText;
e.innerText = txt == 'Modo escuro' ? 'Modo claro' : 'Modo escuro';
}
<a onclick="toggle(this)" id="theme-toggle" href="#" class="nav__link" >
<i class='bx bx-bulb nav__icon' ></i>
<span class="nav__name">Modo escuro</span>
</a>
live demo here: https://pauletatv.netlify.app
Includes it
Just add your tags into your .innerHTML element.
let modo = 0;
function toggle(e) {
if (modo == 0) {
e.innerHTML = "<i class='bx bx-bulb nav__icon' ></i><span class='nav__name'>Modo claro</span>";
modo = 1;
} else {
e.innerHTML = "<i class='bx bx-bulb nav__icon' ></i><span class='nav__name'>Modo escuro</span>";
modo = 0;
}
}
<a onclick="toggle(this)" id="theme-toggle" href="#" class="nav__link" >Click</a>
In alternative
You can check user theme preference cookies, in this way:
let modo = 0;
if (document.cookie.indexOf("theme=1") !== -1) {
modo = 1;
}
function toggle(e) {
if (modo == 0) {
e.innerHTML = "<i class='bx bx-bulb nav__icon' ></i><span class='nav__name'>Modo claro</span>";
modo = 1;
} else {
e.innerHTML = "<i class='bx bx-bulb nav__icon' ></i><span class='nav__name'>Modo escuro</span>";
modo = 0;
}
}
<a onclick="toggle(this)" id="theme-toggle" href="#" class="nav__link" >Click</a>

how to toggle between icons when a button is clicked?

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>';
}

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>

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>

How to modify the class attribute in ng-repeat module?

Here is my plunker.enter link description here
I'm a newer to AngularJS and I want to modify the class style of the star to show if it's marked.
<div class="col-sm-6 col-md-4 col-lg-4 cell-project" ng-repeat="project in projects">
<div class="panel panel-primary panel-project">
<div class="panel-heading" ng-switch="project.PermissionStatus">
<span ng-bind="project.ProjectName"></span>
<i class="fa fa-gear i-setup" ng-switch-when="1"></i>
<div ng-switch-when="0" ng-switch="project.CollectionStatus">
<i class="fa fa-star i-setup" ng-switch-when="1" ng-click="updateCol(0)"></i>
<i class="fa fa-star-o i-setup" ng-switch-when="0" ng-click="updateCol(1)"></i>
</div>
</div>
</div>
</div>
And here is the updateCol function:
$scope.updateCol = function(collectionStatus){
if (1 === collectionStatus) {
console.log("marked");
//$(this).removeClass("fa fa-star-o i-setup ng-scope");
//$(this).addClass("fa fa-star i-setup ng-scope");
//do something to change its class from "fa-star-o" to "fa-star"
}
else if (0 === collectionStatus) {
console.log("unmarked");
//do something to change its class from "fa-star" to "fa-star-o"
}};
How to solve this? When I use id selector, all the classes are changed, not the one that I want to modify. Please help me.
in the click handler just update the value of CollectionStatus
<i class="fa fa-star i-setup" ng-switch-when="1" ng-click="project.CollectionStatus = 0"></i>
<i class="fa fa-star-o i-setup" ng-switch-when="0" ng-click="project.CollectionStatus = 1"></i>
Demo: Plunker
Using ng-class
<div class="panel-heading" ng-switch="project.PermissionStatus">
<span ng-bind="project.ProjectName"></span>
<i class="fa fa-gear i-setup" ng-switch-when="1"></i>
<i class="fa i-setup" ng-class="{'fa-star': project.CollectionStatus == 1, 'fa-star-o': project.CollectionStatus == 0 }" ng-click="updateStatus(project)"></i>
</div>
then
$scope.updateStatus = function(project){
project.CollectionStatus = project.CollectionStatus == 0 ? 1 : 0;
//do your ajax here
if (1 === project.CollectionStatus) {
console.log("marked");
//$(this).removeClass("fa fa-star-o i-setup ng-scope");
//$(this).addClass("fa fa-star i-setup ng-scope");
//do something to change its class from "fa-star-o" to "fa-star"
}
else if (0 === project.CollectionStatus) {
console.log("unmarked");
//do something to change its class from "fa-star" to "fa-star-o"
}
};
Demo: Plunker
1 === collectionStatus is not equal to true === collectionStatus, so you should use 1 == collectionStatus or simply collectionStatus
$scope.updateCol = function(collectionStatus){
if (collectionStatus) {
console.log("marked");
//$(this).removeClass("fa fa-star-o i-setup ng-scope");
//$(this).addClass("fa fa-star i-setup ng-scope");
//do something to change its class from "fa-star-o" to "fa-star"
}
else{
console.log("unmarked");
//do something to change its class from "fa-star" to "fa-star-o"
}};

Categories

Resources