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>
Related
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.
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>';
}
I usually write in Python on the back-end and am not seasoned on JS. This code looks pretty nasty to me as it repeats itself a lot. If I were writing in Python I think I would make a list of objects then loop over the list of objects to add the active class if one of the objects matches the URL.
Can I do that with JS? Or what is a good way to optimize this from someone who writes on the front-end normally?
JS:
var url = window.location.pathname;
var overview = document.getElementById("overview");
var cats = document.getElementById("categories");
var videos = document.getElementById("videos");
var tests = document.getElementById("tests");
var memos = document.getElementById("memos");
var overviewBtm = document.getElementById("overview-btm");
var videosBtm = document.getElementById("videos-btm");
var testsBtm = document.getElementById("tests-btm");
var memosBtm = document.getElementById("memos-btm");
var profileBtm = document.getElementById("profile-btm");
var superUsersBtm = document.getElementById("super-users-btm");
var superResultsBtm = document.getElementById("super-results-btm");
var superNewBtm = document.getElementById("super-new-btm");
var superInviteBtm = document.getElementById("super-invite-btm");
var superProfileBtm = document.getElementById("super-profile-btm");
if (url == '/overview/'){
console.log(url);
if (overview){
overview.classList.add('nav-active');
} else if (overviewBtm){
overviewBtm.classList.add('nav-active');
}
} else if (url == '/categories/'){
console.log(url);
if (cats){
cats.classList.add('nav-active');
}
} else if (url == '/videos/'){
console.log(url);
if (videos){
videos.classList.add('nav-active');
} else if (videosBtm){
videosBtm.classList.add('nav-active');
}
} else if (url == '/tests/'){
console.log(url);
if (tests){
tests.classList.add('nav-active');
} else if(testsBtm){
testsBtm.classList.add('nav-active');
}
} else if (url == '/memos/'){
console.log(url);
if (memos){
memos.classList.add('nav-active');
} else if (memosBtm){
memosBtm.classList.add('nav-active');
}
} else if (url == '/profile/'){
console.log(url);
if (profileBtm){
profileBtm.classList.add('nav-active');
} else if (superProfileBtm){
superProfileBtm.classList.add('nav-active');
}
} else if (url == '/tests/results/'){
console.log(url);
if (superResultsBtm){
superResultsBtm.classList.add('nav-active');
}
} else if (url == '/accounts/'){
console.log(url);
if (superUsersBtm){
superUsersBtm.classList.add('nav-active');
}
} else if (url == '/invite/'){
console.log(url);
if (superInviteBtm){
superInviteBtm.classList.add('nav-active');
}
} else if (url == null){
// pass
}
Edit:
Snippet of HTML in the base.html:
<div class="header-icon-container d-xs-none">
<a class="nav-item nav-link d-xs-none" href="{% url 'overview' %}" id="
<i class="fas fa-home fa-2x"></i>
<span>Home</span>
</a>
</div>
<div class="header-icon-container">
<a class="nav-item nav-link" href="#" id="drills">
<i class="fas fa-dumbbell fa-2x"></i>
<span>Drills</span>
</a>
</div>
<div class="header-icon-container d-xs-none">
<a class="nav-item nav-link" href="{% url 'tests' %}" id="tests">
<i class="fas fa-graduation-cap fa-2x"></i>
<span>Testing</span>
</a>
</div>
<div class="header-icon-container">
<a class="nav-item nav-link" href="{% url 'videos' %}" id="videos">
<i class="fas fa-video fa-2x"></i>
<span>Videos</span>
</a>
</div>
<div class="header-icon-container">
<a class="nav-item nav-link" href="{% url 'memos' %}" id="memos">
<i class="fas fa-paper-plane fa-2x"></i>
<span>Memos</span>
</a>
</div>
Well, im not sure what are these overview-btm, super-profile-btm and stuff. But for the links, it is simple:
const links = document.querySelectorAll('.nav-item.nav-link');
links.forEach((link) => {
if (link.pathname === window.location.pathname) {
link.classList.add('nav-active');
}
})
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>
Problem
I can select a player by clicking btn--add, but when I click btn--reset to reset my picks and then try to add players again, the text in the list of spans does not change to reflect the player of the last name clicked.
Update #1: Yes, I'm calling both functions at the bottom of scripts.js (it is just not shown in the code snippet)
scripts.js
function countPlayers(){
var playerName = null;
var player = null;
var pickedF = null;
var pickedD = null;
var pickedG = null;
$(".player").click(function(){
// Select the current player
player = $(this);
// Count number of players of each position that have been clicked
pickedF = $(".player--forward.is-selected").length;
pickedD = $(".player--defenseman.is-selected").length;
pickedG = $(".player--goalie.is-selected").length;
// Grab the name of the player last clicked
playerName = player.find(".player__name").text();
// Use regex to replace spaces with hypens and then lowercase the text
// window.location.hash will append #playerName onto the URL
var playerNameHypenate = playerName.replace(/\s+/g, '-').toLowerCase();
window.location.hash = playerNameHypenate;
});
$(".btn--add").click(function(){
// Ensures names don't match
var playerExists = $('.player__pick:contains("'+playerName+'")').length;
// Changes the opacity of a picked player to 0.5
player.addClass("is-selected");
if (player.hasClass("player--forward")) {
if (!playerExists) {
$(".player__pick--forward.is-empty").eq(0).html(playerName);
$(".player__pick--forward.is-empty").eq(0).removeClass("is-empty");
if (pickedF < 2) {
pickedF++;
}
console.log(pickedF);
if (pickedF === 2) {
$(".player--forward").not(".is-selected").css("pointer-events", "none");
console.log("Locked forwards");
} else {
$(".player--forward").css("pointer-events", "auto");
}
}
}
if (player.hasClass("player--defenseman")) {
if (!playerExists) {
$(".player__pick--defenseman.is-empty").eq(0).html(playerName);
$(".player__pick--defenseman.is-empty").eq(0).removeClass("is-empty");
if (pickedD < 3) {
pickedD++;
}
console.log(pickedD);
if (pickedD === 3) {
$(".player--defenseman").not(".is-selected").css("pointer-events", "none");
console.log("Locked defensemen");
} else {
$(".player--defenseman").css("pointer-events", "auto");
}
}
}
if (player.hasClass("player--goalie")) {
if (!playerExists) {
$(".player__pick--goalie.is-empty").eq(0).html(playerName);
$(".player__pick--goalie.is-empty").eq(0).removeClass("is-empty");
if (pickedG < 1){
pickedG++;
}
console.log(pickedG);
if (pickedG === 1) {
$(".player--goalie").not(".is-selected").css("pointer-events", "none");
console.log("Locked goalie");
} else {
$(".player--goalie").css("pointer-events", "auto");
}
}
}
});
$(".btn--remove").click(function(){
player.removeClass("is-selected");
// This refers to each element with a class of `player__pick--forward`
// Then we are seeing if this element in the `player__pick--forward` array matches
if (player.hasClass("player--forward")) {
$(".player__pick--forward").each(function(index) {
if ( $(this).text() === playerName ) {
pickedF--;
$(this).html("Pick a Forward");
$(this).addClass("is-empty");
console.log(pickedF);
}
})
}
if (player.hasClass("player--defenseman")) {
$(".player__pick--defenseman").each(function(index) {
if ( $(this).text() === playerName ) {
pickedD--;
$(this).html("Pick a Defenseman");
$(this).addClass("is-empty");
console.log(pickedD);
}
})
}
if (player.hasClass("player--goalie")) {
$(".player__pick--goalie").each(function(index) {
if ( $(this).text() === playerName ) {
pickedG--;
$(this).html("Pick a Goalie");
$(this).addClass("is-empty");
console.log(pickedG);
}
})
}
});
}
// // Clear all picks
function clearPicks() {
$(".btn--reset").click(function(){
// Deselect players
$(".player").removeClass("is-selected");
// Change pointer events back to auto
$(".player").css("pointer-events", "auto");
// Revert text back to defaults
$(".player__pick--forward").html("Pick a Forward");
$(".player__pick--defenseman").html("Pick a Defenseman");
$(".player__pick--goalie").html("Pick a Goalie");
pickedF = 0;
pickedD = 0;
pickedG = 0;
console.log(pickedF, pickedD, pickedG);
});
}
index.html
<div class="popup clearfix">
<div class="icon-container">
<i class="fa fa-times" aria-hidden="true"></i>
</div>
<img src="" alt="" class="popup__picture animated">
<div class="popup__text">
<p class="popup__position">tk-position</p>
<p class="popup__name">tk-name</p>
<p class="popup__years">tk-years</p>
<p class="popup__description">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sequi ad dicta sunt unde, sed quae nihil inventore voluptates nulla voluptate laudantium nesciunt quo, aspernatur deleniti quod harum, nisi error doloribus.</p>
<div class="popup__stats">
<p>tk-stats</p>
</div>
<div class="buttons">
<button class="btn--add">Add to team</button>
<button class="btn--remove">Remove from team</button>
</div>
</div>
</div>
<ul class="">
<li><span class="player__pick player__pick--forward is-empty"><i class="fa fa-long-arrow-right" aria-hidden="true"></i> Pick a forward</span></li>
<li><span class="player__pick player__pick--forward is-empty"><i class="fa fa-long-arrow-right" aria-hidden="true"></i> Pick a forward</span></li>
<li><span class="player__pick player__pick--defenseman is-empty"><i class="fa fa-long-arrow-right" aria-hidden="true"></i> Pick a defenseman</span></li>
<li><span class="player__pick player__pick--defenseman is-empty"><i class="fa fa-long-arrow-right" aria-hidden="true"></i> Pick a defenseman</span></li>
<li><span class="player__pick player__pick--defenseman is-empty"><i class="fa fa-long-arrow-right" aria-hidden="true"></i> Pick a defenseman</span></li>
<li><span class="player__pick player__pick--goalie is-empty"><i class="fa fa-long-arrow-right" aria-hidden="true"></i> Pick a goalie</span></li>
</ul>
<button class="btn--reset">Clear all picks</button>
All of you click event binding functions are nested inside the functions countPlayers and clearPicks. Those functions are never called so the click events are never attached to the DOM.