Fontawesome can't change the class because of invalid string characters - javascript

const toggleDarkOrLight = document.getElementsByTagName('i')[0];
var toggled = false;
const toggle = () => {
if (toggled === false) {
toggleDarkOrLight.classList.remove('fa fa-toggle-off');
toggleDarkOrLight.classList.add('fa fa-toggle-on');
} else {
toggleDarkOrLight.classList.remove('fa fa-toggle-on');
toggleDarkOrLight.classList.add('fa fa-toggle-off');
}
}
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<i class="fa fa-toggle-off" onclick="toggle()"></i>
</body>
<html>
Why can't I change the class? Is it because of the "-" character
What should I try instead then?
Also, how can I make the toggle on and off like a smooth animation (or I can't?)

It's the space( ) thats interfering!
Since your adding, and removing the fa class, just let it be.
That said, consider using classList.contains to check witch class you want to toggle.
const toggleDarkOrLight = document.getElementsByTagName('i')[0];
const toggle = () => {
if (toggleDarkOrLight.classList.contains('fa-toggle-off')) {
toggleDarkOrLight.classList.remove('fa-toggle-off');
toggleDarkOrLight.classList.add('fa-toggle-on');
} else {
toggleDarkOrLight.classList.remove('fa-toggle-on');
toggleDarkOrLight.classList.add('fa-toggle-off');
}
}
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<i class="fa fa-toggle-off" onclick="toggle()"></i>
</body>
<html>

No, it's the space. classList.add/.remove expect a single class name and a class name may not contain a space. In order to add/remove multiple classes, but them in separate arguments:
toggleDarkOrLight.classList.remove('fa', 'fa-toggle-off');
toggleDarkOrLight.classList.add('fa', 'fa-toggle-on');
(Or just leave faout, since you are both adding and removing it.)

You don't actually want to toggle the fa part at all. You only want to toggle the fa-toggle-off/on part. Here is how your code should look:
const toggleDarkOrLight = document.getElementsByTagName("i")[0];
var toggled = false;
const toggle = () => {
if (toggled === false) {
toggleDarkOrLight.classList.remove("fa-toggle-off");
toggleDarkOrLight.classList.add("fa-toggle-on");
toggled = true;
} else {
toggleDarkOrLight.classList.remove("fa-toggle-on");
toggleDarkOrLight.classList.add("fa-toggle-off");
toggled = false;
}
};
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<i class="fa fa-toggle-off" onclick="toggle()"></i>
</body>
<html>

Related

todos list with a saved array and then retrieve it stuck?

i started an app todoslist , after creating first code simply of adding new todos in DOM
now my task is this :
addtodo :
// grab todo value
// pu tit in the array
// tell the draw method to redraw the todos
drawtodo :
grab the array
for each text add a todo entry in the documen
the array
my html code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="style.css">
<title>TodoList</title>
</head>
<body>
<div class="todolist_box">
<h3> To Do List </h3>
<div class="input">
<input type="text" id ="inp" placeholder="Add new Task">
<button onclick="newTodo()" ><i> enter </i></button>
<button onclick="newTodo()" ><i> save </i></button>
<button onclick="drawtodo()" ><i> load </i></button>
</div>
<ul id="myUL">
</ul>
</div>
<script src="script.js" type="application/javascript"></script>
</body>
</html>
and this is my javascript code
function newElement() {
// this code doesn't work, but it gives you an idea
const li = document.createElement("li")
const newEntry = document.getElementById("inp").value
const u = document.createTextNode(newEntry)
li.appendChild(u)
document.getElementById("myUL").appendChild(li)
document.getElementById("inp").value = "Nothing"
// something like thi
let todos = []
function newTodo() {
let inpvalue = document.getElementById('inp').value
todos.push(inpvalue)
// trigger draw event
}
function drawtodo() {
for (var i = todos.length - 1; i >= 0; i--) {
let li = document.createElement('li')
let newlist = li.appendChild(document.createTextNode(todos[i]))
inpvalue.appendChild(newlist)
}
}
document.onload = function() {
// this will excute when the document loads
}
}
Try using Javascript event listener instead of onclick attribute in html.
HTML:
<button id="load" ><i> load </i></button> // Removed onclick attribute
JS:
document.getElementById("load").addEventListener("click", drawtodo, false);
same with enter and save buttons, when click triggers the newTodo function.

Range addEventListner Input Updating too frequently

I am new to JavaScript for context.
I want to have a web page where the user has a base number, which is an input and can have unlimited subtractors, or "sources", that will bring the number down. It's like the user is listing all of his or her sources to pay for something expensive. Each source will have a name and a range, which goes from -100 to 100.
The problem with it is that it takes every change in input as a potential source, but I want only the value of the ranges to be sourced. In other words, if the user has added five ranges, then I only want there to be five subtractors/sources.
Is there anything I could do to make this change happen? It also may be helpful to know that when I change the event listener to 'mouseDown' the same thing happens.
Here is everything I have written.
const addBtn = document.querySelector(".solvePlusLogo")
function addSolvr() {
solvContain = document.querySelector('.solveContainer')
const solvDiv= document.createElement('div');
solvContain.appendChild(solvDiv);
const solvLabel = document.createElement('input');
solvDiv.appendChild(solvLabel);
const solvRange = document.createElement('input');
solvRange.type = "range";
solvRange.className = "range"
solvDiv.appendChild(solvRange);
}
addBtn.addEventListener('click', addSolvr)
let full = document.querySelector("#numInput").value
document.addEventListener('input', function(event) {
if(event.target.matches(".range")) {
const subtractors = []
subtractors.push(event.target.value)
for(let x of subtractors) {
full -= x
}
document.querySelector("#numDisplay").innerHTML = full
}
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<input type="number" id="numInput">
<h3 id="numDisplay">
$0
</h3>
<div class="solveContainer" style="font-family: 'IBM Plex Mono', momnospace;">
<div class="solveIntro">
<button class="solvePlusLogo">Add Source
</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Every time the range changes, you're subtracting its current value from full. But full has previously had a different range value subtracting, so these subtractions are accumulating.
You need to get the current value of #numInput and subtract the range value from it.
Your subtractors array will just contain the value of the current range input. You need to loop over all the ranges and combine them.
const addBtn = document.querySelector(".solvePlusLogo")
function addSolvr() {
solvContain = document.querySelector('.solveContainer')
const solvDiv = document.createElement('div');
solvContain.appendChild(solvDiv);
const solvLabel = document.createElement('input');
solvDiv.appendChild(solvLabel);
const solvRange = document.createElement('input');
solvRange.type = "range";
solvRange.className = "range"
solvDiv.appendChild(solvRange);
}
addBtn.addEventListener('click', addSolvr)
document.addEventListener('input', function(event) {
if (event.target.matches(".range")) {
let full = document.querySelector("#numInput").value
const subtractors = document.querySelectorAll(".range");
subtractors.forEach(subtractor => full -= subtractor.value)
document.querySelector("#numDisplay").innerHTML = full
}
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<input type="number" id="numInput">
<h3 id="numDisplay">
$0
</h3>
<div class="solveContainer" style="font-family: 'IBM Plex Mono', momnospace;">
<div class="solveIntro">
<button class="solvePlusLogo">Add Source
</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>

Countdown clicker - JS

I'm totally lost as to where to begin here, how would I create a countdown button so that each time my button is clicked, it prints out the global variable and reduce it by 1 in the innerHTML and when it hits 0 it says BOOM?
I know I have to declare the variable outside but not sure what to do afterwards
JS:
var i = 20
function myFunction()
{
i = i--; // the value of i starting at 20
}
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- link to external JS file. Note that <script> has an
end </script> tag -->
<meta charset="utf-8">
<title> Task 6 </title>
<link href="style.css" type="text/css" rel="stylesheet">
<script src="task6.js" type="text/javascript"></script>
</head>
<body>
<!-- Create a paragraph with id mydata -->
<div id="box">
<p id="mydata"> Count Down </p>
<p> <button onclick="myFunction();"> Click </button></p>
</div>
</body>
</html>
I tryed this code and works fine
var i = 20;
function myFunction() {
myData = document.getElementById("mydata");
i = i - 1;
myData.textContent = i;
if(i <= 0) {//with <=0 the user if click again,after zero he sees only BOOM
myData.textContent = "BOOM!"
}
}
html code
<!DOCTYPE html>
<html lang="en">
<head>
<!-- link to external JS file. Note that <script> has an
end </script> tag -->
<meta charset="utf-8">
<title> Task 6 </title>
<link href="style.css" type="text/css" rel="stylesheet">
<script src="task6.js" type="text/javascript"></script>
</head>
<body>
<!-- Create a paragraph with id mydata -->
<div id="box">
<p id="mydata"> Count Down </p>
<p> <button onclick="myFunction();"> Click </button></p>
</div>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- link to external JS file. Note that <script> has an
end </script> tag -->
<meta charset="utf-8">
<title> Task 6 </title>
<link href="style.css" type="text/css" rel="stylesheet">
<script type="text/javascript">
var i = 20;
function myFunction() {
var myData = document.getElementById("mydata");
i = i - 1;
myData.textContent = i;
if(i <= 0) {
myData.textContent = "BOOM!"
}
}
</script>
</head>
<body>
<!-- Create a paragraph with id mydata -->
<div id="box">
<p id="mydata"> Count Down </p>
<p> <button onclick="myFunction();"> Click </button></p>
</div>
</body>
</html>
It's good practice to not inline JS in the HTML so I'll provide an extra example to show how to separate it out using a couple of DOM selection methods:
let count = 20;
// grab the element with the mydata id
const mydata = document.getElementById('mydata');
// grab the button and attach an click event listener to it -
// when the button is clicked the `handleClick` function is called
const button = document.querySelector('button');
button.addEventListener('click', handleClick, false);
function handleClick() {
if (count === 0) {
mydata.textContent = 'Boom';
} else {
mydata.textContent = count;
}
count--;
}
<body>
<p id="mydata">Countdown</p>
<button>Click</button>
<script src="task6.js" type="text/javascript"></script>
</body>
Reference
getElementById
querySelector
addEventListener
I'll assume you want to show the variable output and the BOOM at the <p id="mydata"> Count Down </p>, if I am mistaken correct me. So, something like this:
let i = 20;
const myData = document.querySelector("#mydata");
function myFunction() {
i = i - 1;
myData.textContent = i;
if(i === 0) {
myData.textContent = "BOOM!"
}
}
You almost got it whole,only missed the textContent and if part. If this is what you wanted to achieve. If this isn't what you were looking for, hit me up so I can correct it. Cheers :)
You need some way of displaying the number inside of your variable. One of the simplist ways to do this would be to set text to your paragraph tag using getElementById() and inner HTML. For example, after running your deincrement, on the next line you would do something like...
function myFunction()
{
i = i--; // the value of i starting at 20
document.getElementById("mydata").innerHTML = i;
}
This code simply grabs your "mydata" paragraph from the DOM and injects the number into the tag as html.

Navigation between pages - html

I trying to navigate between 3 pages which contain the same header and footer but each page has different content.
I want to load different contents html on hash change.
The problem is that when I click on the same page again, the content.html loaded again.
How can I use the content without loading the html again and again, using java script/html/jquery?
Code example:
Navigationbar.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Navigation Bar</title>
<link rel="stylesheet" type="text/css" href="css/navigationbar.css">
</head>
<body>
<nav>
<img id="navigation-bar-logo" class="logo" src='images/flybryceLogo.png'>
<ul class="navigation-bar-ul">
<li class="navigation-bar-li"><a id="navigation-bar-contact-page-tab" href="#contact.html">CONTACT</a></li>
<li class="navigation-bar-li"><a id="navigation-bar-about-us-page-tab" href="#aboutus.html">ABOUT US</a></li>
<li class="navigation-bar-li"><a id="navigation-bar-home-page-tab" href="#home.html">HOME</a></li>
</ul>
</nav>
</body>
</html>
initial.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>One Page Test</title>
<link rel="stylesheet" type="text/css" href="css/homepage.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<div id="main-container" class="main-container">
<div id="header" class="header">
</div>
<div id="content" class="content"></div>
<div id="footer" class="bot"></div>
</div>
<script>
document.onreadystatechange = function(){
if (document.readyState == 'complete') {
window.onhashchange=hash_change;
window.onload=hash_change;
if(window.location.hash==''){
//default hash
window.location.replace('#home.html');
}
//load the header
$("#header").load("fragments/navigationbar.html");
//load the footer
$("#footer").load("fragments/footer.html");
}
}
function hash_change()
{
//get the new hash
var newHashCode = window.location.hash.substring(1);
if (newHashCode === "home.html"){
$("#content").load("home.html");
} else if (newHashCode === "aboutus.html") {
$("#content").load("aboutus.html");
} else if (newHashCode === "contact.html"){
$("#content").load("contact.html");
}
}
</script>
</body>
</html>
A longer but suitable solution would be to build a content cache on your own.
For example asking to the server just once the html and then setting it to the $('#content') element. You can use this helper function.
var contentsCache = {};
var getAndCache = function(url, callback) {
var cachedContents = contentsCache[url];
if (!cachedContents) {
$.get(url, function(serverContents) {
cachedContents = serverContents;
contentsCache[url] = cachedContents;
callback(cachedContents);
});
} else {
callback(cachedContents);
}
};
And then replace the $('#content').load calls by calls to this new asynchronous way.
function hash_change()
{
var fillContentCb = function(s) {
$('#content').html(s);
};
//get the new hash
var newHashCode = window.location.hash.substring(1);
if (newHashCode === "home.html"){
getAndCache("home.html", fillContentCb);
} else if (newHashCode === "aboutus.html") {
getAndCache("aboutus.html", fillContentCb);
} else if (newHashCode === "contact.html"){
getAndCache("content.html", fillContentCb);
}
}
As suggested in some comments, consider using native HTML navigation instead. Another suggestion is to use a client-side JS framework which supports routing if this application is likely to grow.
Add an if condition that checks whether the current hash location matches with the one that's been clicked on, and if it does just return. You'd have to store it in a global JS variable, and set it every time you navigate.

adding .className to object is not working

I am attempting to set a className to my nav element and it isn't working as intended. When I manually add the class to my HTML it puts a border around the unordered list items and the buttons. When I use js to add it, it shows that the nav tag has the attribute in the inspector but it does not add the border so I do not believe it is working. What am I doing wrong? I have linked to the bootstrap cdn and jquery cdn in the file.
HTML
<!doctype html>
<html lang="en-us">
<head>
<title>Exercise 5.9</title>
<meta charset="UTF-8">
<meta equiv="X-UA-Compatible" content="IE=Edge">
</head>
<body id="content">
<!-- Latest compiled and minified CSS -->
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<nav>
<div>
<ul>
<li>Home</li>
<li>Our Policies</li>
<li>How you can help</li>
<li>What we have accomplished</li>
<button type="button">Donate $10.00</button>
<button type="button">Donate $50.00</button>
<button type="button">Donate $100.00</button>
</ul>
</div>
</nav>
<p>If you would to offer financial support, please choose the buttons above</p>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="exercise-5.9.js"></script>
</body>
</html>
JS
var nav = document.getElementsByTagName("nav");
nav.className = "navbar navbar-default";
console.log(nav);
Instead of using .className = try just setting the attribute of class to whatever you want. The main reason why it's not working, however, is because .getElementsByTagName() returns an array (nodeList) so you need to make sure when you set the class, it's properly indexed.
Using .setAttribute("atr", "value")
var button = document.getElementById("btnGo");
button.onclick = function () {
var nav = document.getElementsByTagName("nav");
for (var i = 0; i < nav.length; i++) {
nav[i].setAttribute("class", "myClassName");
}
};
Using .className
var button = document.getElementById("btnGo");
button.onclick = function () {
var nav = document.getElementsByTagName("nav");
for (var i = 0; i < nav.length; i++) {
nav[i].className = "myClass";
}
};
getElementsByTagName() return an array, you should write document.getElementsByTagName('nav')[0];

Categories

Resources