isNaN doesnt verify if the fields are filled - javascript

var result;
var gasoline = document.getElementById("gasolina").value
var alcohol = document.getElementById("alcool").value
var converte = parseInt(gasolina)
function calculo(){
valor = document.getElementById("text")
var calculando = function calculando(){
var divisao = newAlcool % newGasolina
if(divisao > 0.75){
result = "Gasoline is better"
valor.innerHTML = `${result}`
}else{
result = "alcohol is better"
valor.innerHTML = `${result}`
}
}
if(!alcohol || !gasoline || isNaN(alcohol) || isNaN(gasoline)){
result = "Please fill in the required field"
valor.innerHTML = `${result}`
}else{
newGasolina = parseInt(gasoline)
newAlcool = parseInt(alcohol)
calculando()
}
}
*{
background-image: url('img/Background.png');
background-size: 100%;
font-family: 'Prompt', sans-serif;
color: black;
}
.txtmenor{
font-size: 15px;
}
div{
text-align: center;
border:none;
background: transparent;
outline: none;
}
.logo{
width: 150px;
background: transparent;
}
h1{
background: transparent;
align-items: center;
text-align: center;
font-size: 18px;
margin-bottom: 0px;
}
.calcular{
margin-top: 15px;
align-items: center;
text-align: center;
background: transparent;
padding: 0;
border: none;
background: none;
}
.calcularimg{
width: 150px;
text-align: center;
background: transparent;
border-radius: 10px;
}
input{
margin: 0;
color: #314591;
background: white;
text-align: center;
background-image: none;
margin-right: 10px;
}
a{
text-align: center;
border:none;
background: transparent;
outline: none;
}
p{
background: transparent;
}
<!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">
<title>Alcool ou Gasolina</title>
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Prompt:wght#300&display=swap" rel="stylesheet">
<script src="main.js"></script>
</head>
<body>
<header id="header">
<!--<div><img src="img/Logo App.png" alt="Alcool Ou Gasolina" class="logo"></div>-->
<h1>Vamos Comparar qual e o melhor para o seu carro entre alcool e gasolina </h1>
<h1 class="txtmenor"><div>Alcool Gasolina</div> </h1>
<div><input type="number" name="" id="gasolina" placeholder="Ex:0.00" min="0">
<input type="number" name="" id="alcool" placeholder="Ex:0.00" min="0"><br></div>
<a hidden href="http://127.0.0.1:5500/calcular.html"> <p> Entenda o calculo </p></a>
<div><button onclick="calculo()" class="calcular" id="calcular">calculo</button></div>
<h1 id="text"></h1>
</header>
</body>
</html>
I tried many ways to this code work but doesnt work
my objective is calculate what is better alcohol or gasoline but my isNaN doesnt verify if the fields are empty.still doesnt work it keeps showing "Please fill in the required" field regardless of whether it is filled.
and my function maybe doesnt work im not sure
my code:
var result;
var gasoline = document.getElementById("gasolina").value
var alcohol = document.getElementById("alcool").value
var converte = parseInt(gasolina)
function calculo(){
valor = document.getElementById("text")
var calculando = function calculando(){
var divisao = newAlcool % newGasolina
if(divisao > 0.75){
result = "Gasoline is better"
valor.innerHTML = `${result}`
}else{
result = "alcohol is better"
valor.innerHTML = `${result}`
}
}
if(!alcohol || !gasoline || isNaN(alcohol) || isNaN(gasoline)){
result = "Please fill in the required field"
valor.innerHTML = `${result}`
}else{
newGasolina = parseInt(gasoline)
newAlcool = parseInt(alcohol)
calculando()
}
}

If checking isNaN you want, then update your if condition
if(!alcohol || !gasoline || isNaN(alcohol) || isNaN(gasoline)) {
}
and update your code, because your not getting value, you are only getting HTML element.
var gasoline = document.getElementById("gasolina").value;
var alcohol = document.getElementById("alcool").value;
because isNaN("") will always be false.

Related

Javascript: Form Validation remove error messages

I'm doing a Contact form and when I'm using the error messages when the infos aren't correct it works but I can't remove the messages once it's corrected.
What's wrong/missing in my code please?
Here's my code :
// Get Data
const nom = document.querySelector("#nom");
const prenom = document.querySelector("#prenom");
const email = document.querySelector("#email");
const message = document.querySelector("#message");
const success = document.querySelector("#success");
const errorNodes = document.querySelectorAll(".error");
// Validate Data
clearMessages ();
let errorFlag = false;
function validateForm(){
errorNodes[0].innerText = "";
errorNodes[1].innerText = "";
if(nom.value.length < 1){
errorNodes[0].innerText = "Le nom ne peut pas être vide.";
errorFlag = true;
}
if(prenom.value.length < 1){
errorNodes[1].innerText = "Le prénom ne peut pas être vide.";
errorFlag = true;
}
if(!errorFlag){
success.innerText = "Message envoyé!";
}
}
// Clear error / success messages
function clearMessages(){
for (let i = 0; i < errorNodes.length; i++){
errorNodes[i].innerText = "";
}
success.innerText = "";
}
// Check if email is valid
function emailIsValid(email){
let pattern = /\S+#\S+\.\S+/;
return pattern.test(email);
}
* {
font-family: Arial;
font-size: 16px;
}
body {
background: #5a8cdb;
}
form {
max-width: 550px;
width: 90%;
background: white;
margin: 90px auto 0 auto;
padding: 40px;
border-radius: 10px;
box-sizing: border-box;
}
h1 {
font-size: 32px;
margin: 0;
text-align: center;
}
.item label {
display: block;
margin: 20px 0;
}
.item input, textarea {
width: 100%;
padding: 10px;
box-sizing: border-box;
outline: none;
resize: none;
border: none;
border-bottom: 1px solid #d3d3d3;
}
input[type="text"]:focus, textarea:focus {
border-bottom: 1px solid #5a8cdb;
}
textarea::-webkit-scrollbar {
width: 3px;
}
textarea::-webkit-scrollbar-thumb {
background-color: #5a8cdb;
}
.center {
text-align: center;
}
input[type="submit"] {
margin-top: 30px;
width: 90%;
max-width: 200px;
border-radius: 5px;
background: #5a8cdb;
color: white;
font-size: 16px;
cursor: pointer;
}
input[type="submit"]:hover {
background: #3F73C5;
}
.error {
display: block;
margin: 5px 0;
color: red;
}
.error-border {
border-bottom: 1px solid red;
}
#success {
color: green;
}
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Formulaire de Contact</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<form onsubmit="event.preventDefault(); validateForm()">
<h1>Contactez-nous</h1><br>
<div class="item">
<label for="nom">Nom</label>
<input type="text" id="nom" placeholder="Votre nom">
<small class="error"></small>
<label for="prenom">Prénom</label>
<input type="text" id="prenom" placeholder="Votre prénom">
<small class="error"></small>
<div class="center">
<input type="submit" value="Envoyez">
<p id="success"></p>
</div>
</form>
<script src="script.js"></script>
</body>
</html>
..........................................................................
.........................................................................
well you have to call 'clearMessages()' after editing input somehow. or during editing.
add this to js file:
nom.addEventListener('change', clearMessages);
prenom.addEventListener('change', clearMessages);
nom.addEventListener('focus', clearMessages);
prenom.addEventListener('focus', clearMessages);
EDIT :
change code in clear message to :
errorFlag = false;
for (let i = 0; i < errorNodes.length; i++){
errorNodes[i].innerText = "";
}
success.innerText = "";
and also edit this :
let errorFlag = false;
clearMessages ();
You don't have necessary code when everything is correct within validateForm method. So either add statement that if everything is okay, will remove the the error messages with innerHTML = '' or instead of calling the validation on formSubmit you can:
nom.addEventListener('keyup', (e) => {
if(e.target.value < 1)
//show error code
else //remove error
})
This can be added to every input you want to validate.
When you call the validateForm(), clear them before it does anything else
function validateForm(){
errorNodes[0].innerText = "";
errorNodes[1].innerText = "";
Then the rest of your code and add this
if(!errorFlag){
errorNodes[0].innerText = "";
errorNodes[1].innerText = "";
success.innerText = "Message envoyé!";
}
Easiest way
It is because the code didn't call the 'clearMessages()' after checking the form is validated.
Move the 'clearMessages()' insdie the 'if(!errorFlag)' condition block so the function will call 'clearMessages()' once the form is submit with no error.
if(!errorFlag){
success.innerText = "Message envoyé!";
clearMessages ();
}

Input event listener not working at times

I have made a simple API based project wherein whenever the user enter some number in the input, the div below it with the output becomes visible and when the input field is empty the div gets hidden again as it was in the initial state. The problem is whenever I clear the input field gradually the setup works as expected but if I clear it quickly the div doesn't hide the div at all. Below given is the reference code for the same
let input = document.querySelector("#number-input");
let fact = document.querySelector(".fact-content");
input.addEventListener("input", getFact);
function getFact() {
let number = input.value;
if (number != "") {
let xhr = new XMLHttpRequest();
xhr.open("GET", "http://numbersapi.com/" + number);
xhr.onload = function () {
if (this.status == 200) {
fact.innerText = this.responseText;
fact.style.display = "block";
}
};
xhr.send();
}
else{
fact.innerText = "";
fact.style.display = "none";
}
}
#import url('https://fonts.googleapis.com/css2?family=Varela+Round&display=swap');
*{
margin: 0;
padding: 0;
font-family: 'Varela Round', sans-serif;
box-sizing: border-box;
}
body{
background-color: #9AD0EC;
}
main{
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.container{
width: 40%;
margin: auto;
line-height: 1.6;
background-color: #1572A1;
color: #eee;
padding: 2rem;
min-width: 500px;
border-radius: 5px;
}
.container h1{
font-size: 1.5em;
}
.container h4{
font-size: 1.2rem;
}
input{
padding: 0.5rem;
border-radius: 5px;
border: none;
margin: 10px 0;
width: 50%;
}
.fact-content{
display: none;
}
<!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" href="style.css" />
<title>Number Fact</title>
</head>
<body>
<main>
<div class="container">
<h1>Get random fact based on numbers</h1>
<h4>Enter a number and get a random fact</h4>
<input
type="number"
id="number-input"
placeholder="Enter a number..."
/>
<p class="fact-content"></p>
</div>
</main>
</body>
</html>
Consider the case when you have two characters in your input. You delete one character, and initiate an AJAX request for the remaining character. Before that AJAX request completes, you delete the remaining character.
When you delete the final character, the event handler clears and hides the element. But then the previous AJAX request completes, and displays the outdated response in the element.
There are two things you can do here:
When the AJAX request completes, check that the input value is still the same as the number variable. If it's not, discard the response to the AJAX request.
Switch to using the fetch API, and use an AbortController instance to abort the in-flight request when the input value changes.
let input = document.querySelector("#number-input");
let fact = document.querySelector(".fact-content");
let abortToken = null;
input.addEventListener("input", getFact);
async function getFact() {
if (abortToken) {
abortToken.abort("Input changed");
abortToken = null;
}
let number = input.value;
if (!number) {
fact.innerText = "";
fact.style.display = "none";
return;
}
const url = `http://numbersapi.com/${number}`;
abortToken = new AbortController();
const { signal } = abortToken;
try {
const response = await fetch(url, { signal });
if (input.value !== number) {
// The input has been modified.
return;
}
if (!response.ok){
const errorMessage = await response.text();
console.error(response.status, response.statusText, errorMessage);
fact.innerText = "# ERROR #";
fact.style.display = "block";
return;
}
const text = await response.text();
fact.innerText = text;
fact.style.display = "block";
} catch {
}
}
#import url('https://fonts.googleapis.com/css2?family=Varela+Round&display=swap');
*{
margin: 0;
padding: 0;
font-family: 'Varela Round', sans-serif;
box-sizing: border-box;
}
body{
background-color: #9AD0EC;
}
main{
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.container{
width: 40%;
margin: auto;
line-height: 1.6;
background-color: #1572A1;
color: #eee;
padding: 2rem;
min-width: 500px;
border-radius: 5px;
}
.container h1{
font-size: 1.5em;
}
.container h4{
font-size: 1.2rem;
}
input{
padding: 0.5rem;
border-radius: 5px;
border: none;
margin: 10px 0;
width: 50%;
}
.fact-content{
display: none;
}
<!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" href="style.css" />
<title>Number Fact</title>
</head>
<body>
<main>
<div class="container">
<h1>Get random fact based on numbers</h1>
<h4>Enter a number and get a random fact</h4>
<input
type="number"
id="number-input"
placeholder="Enter a number..."
/>
<p class="fact-content"></p>
</div>
</main>
</body>
</html>

Can't access JavaScript method in different "class"

So I'm making a calculator in JavaScript as a way to learn JavaScript. I'd like to add some sort of Object Orientated into the project.
My HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>The Unconventional Calculator</title>
<link
href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="assets/styles/app.css" />
</head>
<body>
<header>
<h1>The Unconventional Calculator</h1>
</header>
<section id="calculator">
<input type="number" id="input-number" />
<div id="calc-actions">
<button type="button" id="btn-add">+</button>
<button type="button" id="btn-subtract">-</button>
<button type="button" id="btn-multiply">*</button>
<button type="button" id="btn-divide">/</button>
<button type="button" id="btn-equals">=</button>
</div>
</section>
<section id="results">
<h2 id="current-calculation">0</h2>
<h2>Result: <span id="current-result">0</span></h2>
</section>
<section class="credit">
<h1>Check out my code on GitHub
<br>Type your number, press enter, repeat until you're done and then press enter.</h1>
</section>
<!-- So the site loads first then the js runs -->
<script src="assets/scripts/vendor.js"></script>
<script src="assets/scripts/app.js"> </script>
</body>
</html>
MY CSS
* {
box-sizing: border-box;
}
html {
font-family: 'Roboto', open-sans;
}
body {
margin: 0;
}
header {
background: #6d0026;
color: white;
padding: 1rem;
text-align: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
width: 100%;
}
#results,
#calculator {
margin: 2rem auto;
width: 40rem;
max-width: 90%;
border: 1px solid #6d0026;
border-radius: 10px;
padding: 1rem;
color: #6d0026;
}
#results {
text-align: center;
}
#calculator input {
font: inherit;
font-size: 3rem;
border: 2px solid #6d0026;
width: 10rem;
padding: 0.15rem;
margin: auto;
display: block;
color: #6d0026;
text-align: center;
}
#calculator input:focus {
outline: none;
}
#calculator button {
font: inherit;
background: #6d0026;
color: white;
border: 1px solid #6d0026;
padding: 1rem;
cursor: pointer;
}
#calculator button:focus {
outline: none;
}
#calculator button:hover,
#calculator button:active {
background: #6d2d1b;
border-color: #6d2d1b;
}
#calc-actions button {
width: 4rem;
}
#calc-actions {
margin-top: 1rem;
text-align: center;
}
.credit {
margin: 70px 0 0 0;
text-align: center;
}
app.js
// Base Variables
let result = 0;
let number = 0;
//Store equation as string
let calculationDescription = "";
//Event listeners
document.querySelector("#btn-add").addEventListener('click', sumNumbs);
document.querySelector("#btn-subtract").addEventListener('click', subtractNumbs);
document.querySelector("#btn-multiply").addEventListener('click', multiplyNumbs);
document.querySelector("#btn-divide").addEventListener('click', divideNumbs);
document.querySelector("#btn-equals").addEventListener('click', equals);
document.querySelector('#input-number').addEventListener('keypress', numbersInput);
function numbersInput(e) {
if(e.key === 'Enter' && userInput !== null) {
number = e.target.value;
e.target.value = '';
calculationDescription += number + " ";
console.log(calculationDescription);
}
}
function sumNumbs() {
calculationDescription += "+ ";
}
function subtractNumbs() {
calculationDescription += "- ";
}
function multiplyNumbs() {
calculationDescription += "x ";
}
function divideNumbs() {
calculationDescription += "/ ";
}
function equals() {
let finalCalculation = calculationDescription.split(" ");
//Goes to errorHandler to remove whitespace and make array ready for equation
errorHandler.removeWhiteSpace(finalCalculation);
}
errorHandler.js
class errorHandler {
static removeWhiteSpace(arraySplit) {
return console.log(arraySplit);
}
}
vendor.js(this one isn't to important for the solution)
const userInput = document.getElementById('input-number');
const addBtn = document.getElementById('btn-add');
const subtractBtn = document.getElementById('btn-subtract');
const multiplyBtn = document.getElementById('btn-multiply');
const divideBtn = document.getElementById('btn-divide');
const equalsBtn = document.getElementById('btn-equals');
const currentResultOutput = document.getElementById('current-result');
const currentCalculationOutput = document.getElementById('current-calculation');
function outputResult(result, text) {
currentResultOutput.textContent = result;
currentCalculationOutput.textContent = text;
}
So in my equals method I'd like to send the array finalCalculation which is in the app.js class into the removeWhiteSpace method that's in my errorHandler.js
This is the error I keep getting
app.js:44 Uncaught ReferenceError: errorHandler is not defined
at HTMLButtonElement.equals (app.js:44)
I've tried turning both of them into classes and then creating a constructor with an instance variable for errorHandler to take in the array, but that doesn't seem to work.

Stop underline from getting bigger

I'm creating a currency converter app using html,css and javascript, and when text is entered into the <input> on the left, the converted value will appear in the input element on the right: <p id = "converted">.
I want to keep the underline(border-bottom) the same length on the <p id = "converted">. Currently, when you enter text into the input element on the left, the one on the right increases in size and makes the underline larger. I want the underline to stay the same as when there is no text in the element.
I am currently styling the <p id = "converted"> element like so:
padding-right: 40%;
border-bottom: 0.5vh solid white;
I do not think the API I am using will work correctly with the stack overflow snippets, but I will include a link to a codepen: https://codepen.io/oliknight/pen/XLvQow
let currlet currencyArr = [];
let ratesArr = [];
window.addEventListener("load", () => {
const api = "https://api.exchangeratesapi.io/latest?base=GBP";
fetch(api)
.then(response => {
return response.json();
})
.then(data => {
for (currency in data.rates) {
currencyArr.push(currency);
ratesArr.push(data.rates[currency]);
// create 'option' element here
var optionLeft = document.createElement("option");
var optionRight = document.createElement("option");
optionLeft.textContent = currency;
optionRight.textContent = currency;
document.querySelector("#left-select").appendChild(optionLeft);
document.querySelector("#right-select").appendChild(optionRight);
}
document.querySelector("#input").addEventListener("keyup", convert);
function convert() {
const input = document.querySelector("#input");
let leftSelectValue = document.querySelector("#left-select").value;
let convertedNumber = document.querySelector("#converted");
for (let i = 0; i < currencyArr.length; i++) {
if (leftSelectValue === currencyArr[i]) {
convertedNumber.textContent = ratesArr[i].toFixed(4) * input.value;
}
}
}
});
});
encyArr = [];
let ratesArr = [];
window.addEventListener("load", () => {
const api = "https://api.exchangeratesapi.io/latest?base=GBP";
fetch(api)
.then(response => {
return response.json();
})
.then(data => {
for (currency in data.rates) {
currencyArr.push(currency);
ratesArr.push(data.rates[currency]);
// create 'option' element here
var optionLeft = document.createElement("option");
var optionRight = document.createElement("option");
optionLeft.textContent = currency;
optionRight.textContent = currency;
document.querySelector("#left-select").appendChild(optionLeft);
document.querySelector("#right-select").appendChild(optionRight);
}
document.querySelector("#input").addEventListener("keyup", convert);
function convert() {
const input = document.querySelector("#input");
let leftSelectValue = document.querySelector("#left-select").value;
let convertedNumber = document.querySelector("#converted");
for (let i = 0; i < currencyArr.length; i++) {
if (leftSelectValue === currencyArr[i]) {
convertedNumber.textContent = ratesArr[i].toFixed(4) * input.value;
}
}
}
});
});
html {
font-family: "Lato", sans-serif;
font-weight: thin;
background-image: linear-gradient(to right top, #90d0ff, #008ef7);
color: white;
height: 100vh;
overflow: hidden;
}
h1 {
text-align: center;
font-size: 5em;
position: absolute;
left: 0;
right: 0;
margin: auto;
}
.container {
width: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.container p {
font-size: 8em;
display: inline-block;
padding-right: 40%;
border-bottom: 0.5vh solid white;
max-width: 50%;
}
.parent {
display: flex;
justify-content: center;
height: 100vh;
align-items: center;
}
.container select {
background: transparent;
color: white;
padding: 20px;
width: 80px;
height: 60px;
border: none;
font-size: 20px;
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.5);
-webkit-appearance: button;
outline: none;
margin-left: 10%;
}
.original {
background: transparent;
border: none;
border-bottom: 0.5vh solid white;
font-size: 8em;
max-width: 50%;
outline: none;
font-family: "Lato", sans-serif;
font-weight: thin;
color: white;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Currency Converter</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="main.css" />
<link href="https://fonts.googleapis.com/css?family=Lato:300&display=swap" rel="stylesheet" />
</head>
<body>
<h1>Currency Converter</h1>
<div class="parent">
<div class="container">
<input type="text" class="original" id="input" />
<select id="left-select"> </select>
</div>
<div class="container" id="ctn">
<p id="converted">0</p>
<select id="right-select"> </select>
</div>
</div>
<script src="main.js"></script>
</body>
</html>
Thanks!
If you replace max-width with width in your css, the percentage (e.g. 50%) width will stay the same, regardless of how long the converted number is. However this poses a problem regarding your overflow.
You could remove the padding, but you could still run into issues whereby only half a digit is showing at the end, depending on how big the device is:
So you may want to either reduce the font size or experiment with width percentages (maybe 49 or 51 .. ) , or both ..
If you knew exactly how many decimal digits there would be in the returned converted number, this would help determine an adequate size font.
Good luck, and hope this helps

How can I save and retrieve an entire <div> using HTML5's Web Storage API

I want to save and retrieve some content of html after adding them from javascript and not losing them after refreshing
// hide/show the header
$("#icon").click(function(){
$("#add-new-todo").fadeToggle();
});
// delete a todo onclick
$("#todo").on("click", ".delete", function(event) {
$(this).parent().fadeOut(500, function() {
$(this).remove();
});
event.stopPropagation();
});
//function that scratch the finished todo
$("#todo").on("click", ".todoList", function() {
$(this).toggleClass("completed");
});
// format date to: weekday - year - month - day - time
function formatDate()
{
var event = new Date();
var options = { weekday: 'long', year: 'numeric', month: 'long',
day: 'numeric', hour: 'numeric', minute: 'numeric'};
return event.toLocaleDateString('en-US', options);
}
// clear the input field after adding a todo
function clearAll() {
let title = document.getElementById('todoTitle');
let content = document.getElementById('todoContent');
title.value = "";
content.value = "";
}
// add a new todo
function addNewToDo()
{
let title = document.getElementById('todoTitle');
let content = document.getElementById('todoContent');
if ((title.value == null || title.value == "") ||
(content.value == null || content.value == "")) {
alert("Please fill all the required fields!");
// clearAll();
return false;
}
let parentDiv = document.getElementById('todo');
let newDiv = document.createElement("div");
newDiv.className = "todoList";
let conDiv = document.createElement("div");
conDiv.className = "content";
let delDiv = document.createElement("div");
delDiv.className = "delete";
delDiv.innerHTML = "<i class='fas fa-times'></i>";
let header = document.createElement("h2");
header.innerHTML = title.value;
let dateContent = document.createElement("p");
dateContent.className = "date";
let date = formatDate();
dateContent.innerHTML = "added: " + date;
let subject = document.createElement("p");
subject.className = "subject";
subject.innerHTML = content.value;
conDiv.appendChild(header);
conDiv.appendChild(dateContent);
conDiv.appendChild(subject);
newDiv.appendChild(delDiv);
newDiv.appendChild(conDiv);
// newDiv.appendChild(delDiv);
parentDiv.appendChild(newDiv);
clearAll();
}
body {
background: #2BC0E4; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, #EAECC6, #2BC0E4); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #EAECC6, #2BC0E4); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
#container {
font-family: 'Roboto', sans-serif;
width: 400px;
margin: 150px auto;
background: #f7f7f7;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.1);
border-radius: 3%;
}
#todo {
padding-bottom: 5px;
}
#title {
background-color: #2980b9;
color: white;
margin: 0;
text-transform: uppercase;
font-size: 18px;
text-align: center;
}
#items-title {
margin: 10px auto;
padding-left: 20px;
}
form {
margin: 10px auto;
padding-left: 20px;
}
.form-lines:first-child input {
border-radius: 5%;
}
.form-lines:first-child input[type="text"] {
width: 62%;
height: 35px;
padding-left: 20px;
box-sizing: border-box;
background-color: #f7f7f7;
border: 2px solid rgba(0,0,0,0.2);
word-wrap: break-word;
}
#todoButton {
width: 28%;
height: 30px;
background-color: #2980b9;
color: #fff;
border: none;
}
#todoButton:hover {
background-color: #206592;
font-size: 19px;
}
.form-lines:nth-child(2) input {
margin: 5px auto 0;
width: 92%;
height: 60px;
border-radius: 5%;
padding-left: 20px;
box-sizing: border-box;
word-wrap: break-word;
background-color: #f7f7f7;
border: 2px solid rgba(0,0,0,0.2);
}
.form-lines input[type="text"]:focus {
border: 2px solid #2980b9;
background-color: #fff;
}
#icon {
float: right;
padding-right: 20px;
}
hr {
width: 50%;
margin: 0px auto 5px;
}
.todoList {
width: 93%;
border: 2px solid rgba(0,0,0,0.2);
border-radius: 5%;
margin: auto auto 5px;
padding-left: 20px;
box-sizing: border-box;
}
.delete {
float: right;
padding: 10px 15px;
margin: 40px 10px 0px;
background-color: red;
color: white;
font-size: 25px;
border-radius: 10%;
}
.content h2 {
margin: 10px 0;
font-size: 30px;
text-transform: capitalize;
word-wrap: break-word;
}
.content .date {
font-size: 13px;
color: rgba(0,0,0,0.75);
margin: 0;
width: 77%;
word-wrap: break-word;
}
.conten .subject {
margin: 15px auto;
font-size: 23px;
color: black;
padding-top: 10px;
padding-right: 3px;
word-wrap: break-word;
}
.completed {
color: gray;
text-decoration: line-through;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<link rel="stylesheet" href="css/normalize.min.css">
<link rel="stylesheet" href="css/main.css">
<script src="js/vendor/modernizr-2.8.3.min.js"></script>
</head>
<body>
<div id="container">
<div id="header">
<div id="title">
<div>
<h1>
SEF Todo List<span id="icon"><i class="fas fa-minus"></i></span>
</h1>
</div>
</div>
<div id="add-new-todo">
<div id="items-title">
<h1>Item</h1>
</div>
<form>
<div class="form-lines">
<input type="text" name="todoTitle" placeholder="Enter title" id="todoTitle">
<input type="button" name="todoButton" value="Add" id="todoButton" onclick="addNewToDo()">
</div>
<div class="form-lines">
<input type="text" name="todoContent" placeholder="Enter what To Do" id="todoContent">
</div>
</form>
</div>
</div>
<hr>
<div id="todo"></div>
</div>
<!--[if lt IE 8]>
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>
<![endif]-->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.11.2.min.js"><\/script>')</script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
e=o.createElement(i);r=o.getElementsByTagName(i)[0];
e.src='//www.google-analytics.com/analytics.js';
r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
ga('create','UA-XXXXX-X','auto');ga('send','pageview');
</script>
</body>
</html>
here is my code with all the files, the project is about building a small todo webapp that should use the storage of the browser
I was trying to use localStorage but it saves the div as an object without the content
The new divs are inserted in the using javascript addNewToDo()
I want store all the appended divs in that div to retrieve them upon reloading of the page
thanks in advance
UPDATE:
after asking the instructor for more details, he said that we should not store the whole div tag, what we are interested in is the content it contains
So here's my solution, feel free to give your feedback I would appreciate it
// initialize the itemsArray to [] or to the existing previous todos
let itemsArray = localStorage.getItem('items') ? JSON.parse(localStorage.getItem('items')) : [];
localStorage.setItem('items', JSON.stringify(itemsArray));
var data = JSON.parse(localStorage.getItem('items'));
// hide/show the header
$("#icon").click(function(){
$("#add-new-todo").fadeToggle();
});
// delete a todo onclick
$("#todo").on("click", ".delete", function(event) {
$(this).parent().fadeOut(500, function() {
let idxDel = $(this).index();
// call the function that deletes the div from the localStorage
deleteFromStorage(idxDel);
$(this).remove();
});
event.stopPropagation();
});
//function that scratch the finished todo
$("#todo").on("click", ".todoList", function() {
$(this).toggleClass("completed");
});
// format date to: weekday - year - month - day - time
function formatDate()
{
var event = new Date();
var options = { weekday: 'long', year: 'numeric', month: 'long',
day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false};
return event.toLocaleDateString('en-US', options);
}
// clear the input field after adding a todo
function clearAll() {
let title = document.getElementById('todoTitle');
let content = document.getElementById('todoContent');
title.value = "";
content.value = "";
}
// add a new todo
function addNewToDo()
{
let title = document.getElementById('todoTitle');
let content = document.getElementById('todoContent');
if ((title.value == null || title.value == "") ||
(content.value == null || content.value == "")) {
alert("Please fill all the required fields!");
return false;
}
let parentDiv = document.getElementById('todo');
let newDiv = document.createElement("div");
newDiv.className = "todoList";
let conDiv = document.createElement("div");
conDiv.className = "content";
let delDiv = document.createElement("div");
delDiv.className = "delete";
delDiv.innerHTML = "<i class='fas fa-times'></i>";
let header = document.createElement("h2");
header.innerHTML = title.value;
let dateContent = document.createElement("p");
dateContent.className = "date";
let date = formatDate();
dateContent.innerHTML = "added: " + date;
let subject = document.createElement("p");
subject.className = "subject";
subject.innerHTML = content.value;
conDiv.appendChild(header);
conDiv.appendChild(dateContent);
conDiv.appendChild(subject);
newDiv.appendChild(delDiv);
newDiv.appendChild(conDiv);
addToLocalStorage(title.value, "added: " + date, content.value);
parentDiv.appendChild(newDiv);
clearAll();
}
// save the added todo to the localStorage
function addToLocalStorage (title, date, subject)
{
obj = {"title" : String(title),
"date": String(date),
"subject": String(subject)};
itemsArray.push(obj);
// add the new item added to data array to be available for other functions
data = itemsArray;
localStorage.setItem('items', JSON.stringify(itemsArray));
}
// retrieve all the todos from the localStorage
function retrieveToDo()
{
let parentDiv = document.getElementById('todo');
for (let i = 0; i < data.length; i++) {
let newDiv = document.createElement("div");
newDiv.className = "todoList";
let conDiv = document.createElement("div");
conDiv.className = "content";
let delDiv = document.createElement("div");
delDiv.className = "delete";
delDiv.innerHTML = "<i class='fas fa-times'></i>";
let header = document.createElement("h2");
header.innerHTML = data[i].title;
let dateContent = document.createElement("p");
dateContent.className = "date";
dateContent.innerHTML = data[i].date;
let subject = document.createElement("p");
subject.className = "subject";
subject.innerHTML = data[i].subject;
conDiv.appendChild(header);
conDiv.appendChild(dateContent);
conDiv.appendChild(subject);
newDiv.appendChild(delDiv);
newDiv.appendChild(conDiv);
parentDiv.appendChild(newDiv);
}
}
// delete a specific todo from the localStorage
function deleteFromStorage(idxDel)
{
data.splice(idxDel, 1);;
localStorage.setItem('items', JSON.stringify(data));
}
I think it's better save json to map;But if you want use html,you can save todoList after append newDIV,like this:
parentDiv.appendChild(newDiv);
storage.setItem('originList', parentDiv.innerHTML);
and in the page ,you should init addNewToDo function. like this:
if (type) {
var originListHtml = storage.getItem('originList');
if (!parentDiv.innerHTML) {
parentDiv.innerHTML = originListHtml;
}
return;
}
above can ok; Please see the following example,Hope can help you :)
// hide/show the header
$("#icon").click(function() {
$("#add-new-todo").fadeToggle();
});
// delete a todo onclick
$("#todo").on("click", ".delete", function(event) {
$(this).parent().fadeOut(500, function() {
$(this).remove();
});
event.stopPropagation();
});
//function that scratch the finished todo
$("#todo").on("click", ".todoList", function() {
$(this).toggleClass("completed");
});
// format date to: weekday - year - month - day - time
function formatDate() {
var event = new Date();
var options = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric'
};
return event.toLocaleDateString('en-US', options);
}
// clear the input field after adding a todo
function clearAll() {
let title = document.getElementById('todoTitle');
let content = document.getElementById('todoContent');
title.value = "";
content.value = "";
}
// add a new todo
function addNewToDo(type) {
let title = document.getElementById('todoTitle');
let content = document.getElementById('todoContent');
// 判断初始化的时候显示之前localStorage的内容
if (type) {
var originListHtml = storage.getItem('originList');
if (!parentDiv.innerHTML) {
parentDiv.innerHTML = originListHtml;
}
return;
}
if ((title.value == null || title.value == "") ||
(content.value == null || content.value == "")) {
alert("Please fill all the required fields!");
// clearAll();
return false;
}
let parentDiv = document.getElementById('todo');
let newDiv = document.createElement("div");
newDiv.className = "todoList";
let conDiv = document.createElement("div");
conDiv.className = "content";
let delDiv = document.createElement("div");
delDiv.className = "delete";
delDiv.innerHTML = "<i class='fas fa-times'></i>";
let header = document.createElement("h2");
header.innerHTML = title.value;
let dateContent = document.createElement("p");
dateContent.className = "date";
let date = formatDate();
dateContent.innerHTML = "added: " + date;
let subject = document.createElement("p");
subject.className = "subject";
subject.innerHTML = content.value;
conDiv.appendChild(header);
conDiv.appendChild(dateContent);
conDiv.appendChild(subject);
newDiv.appendChild(delDiv);
newDiv.appendChild(conDiv);
// newDiv.appendChild(delDiv);
parentDiv.appendChild(newDiv);
// 存储todoList
storage.setItem('originList', parentDiv.innerHTML);
clearAll();
}
//初始化todoList
addNewToDo('init');
body {
background: #2BC0E4;
/* fallback for old browsers */
background: -webkit-linear-gradient(to right, #EAECC6, #2BC0E4);
/* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #EAECC6, #2BC0E4);
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
#container {
font-family: 'Roboto', sans-serif;
width: 400px;
margin: 150px auto;
background: #f7f7f7;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.1);
border-radius: 3%;
}
#todo {
padding-bottom: 5px;
}
#title {
background-color: #2980b9;
color: white;
margin: 0;
text-transform: uppercase;
font-size: 18px;
text-align: center;
}
#items-title {
margin: 10px auto;
padding-left: 20px;
}
form {
margin: 10px auto;
padding-left: 20px;
}
.form-lines:first-child input {
border-radius: 5%;
}
.form-lines:first-child input[type="text"] {
width: 62%;
height: 35px;
padding-left: 20px;
box-sizing: border-box;
background-color: #f7f7f7;
border: 2px solid rgba(0, 0, 0, 0.2);
word-wrap: break-word;
}
#todoButton {
width: 28%;
height: 30px;
background-color: #2980b9;
color: #fff;
border: none;
}
#todoButton:hover {
background-color: #206592;
font-size: 19px;
}
.form-lines:nth-child(2) input {
margin: 5px auto 0;
width: 92%;
height: 60px;
border-radius: 5%;
padding-left: 20px;
box-sizing: border-box;
word-wrap: break-word;
background-color: #f7f7f7;
border: 2px solid rgba(0, 0, 0, 0.2);
}
.form-lines input[type="text"]:focus {
border: 2px solid #2980b9;
background-color: #fff;
}
#icon {
float: right;
padding-right: 20px;
}
hr {
width: 50%;
margin: 0px auto 5px;
}
.todoList {
width: 93%;
border: 2px solid rgba(0, 0, 0, 0.2);
border-radius: 5%;
margin: auto auto 5px;
padding-left: 20px;
box-sizing: border-box;
}
.delete {
float: right;
padding: 10px 15px;
margin: 40px 10px 0px;
background-color: red;
color: white;
font-size: 25px;
border-radius: 10%;
}
.content h2 {
margin: 10px 0;
font-size: 30px;
text-transform: capitalize;
word-wrap: break-word;
}
.content .date {
font-size: 13px;
color: rgba(0, 0, 0, 0.75);
margin: 0;
width: 77%;
word-wrap: break-word;
}
.conten .subject {
margin: 15px auto;
font-size: 23px;
color: black;
padding-top: 10px;
padding-right: 3px;
word-wrap: break-word;
}
.completed {
color: gray;
text-decoration: line-through;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<link rel="stylesheet" href="css/normalize.min.css">
<link rel="stylesheet" href="css/main.css">
<script src="js/vendor/modernizr-2.8.3.min.js"></script>
</head>
<body>
<div id="container">
<div id="header">
<div id="title">
<div>
<h1>
SEF Todo List<span id="icon"><i class="fas fa-minus"></i></span>
</h1>
</div>
</div>
<div id="add-new-todo">
<div id="items-title">
<h1>Item</h1>
</div>
<form>
<div class="form-lines">
<input type="text" name="todoTitle" placeholder="Enter title" id="todoTitle">
<input type="button" name="todoButton" value="Add" id="todoButton" onclick="addNewToDo()">
</div>
<div class="form-lines">
<input type="text" name="todoContent" placeholder="Enter what To Do" id="todoContent">
</div>
</form>
</div>
</div>
<hr>
<div id="todo"></div>
</div>
<!--[if lt IE 8]>
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>
<![endif]-->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/vendor/jquery-1.11.2.min.js"><\/script>')
</script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
(function(b, o, i, l, e, r) {
b.GoogleAnalyticsObject = l;
b[l] || (b[l] =
function() {
(b[l].q = b[l].q || []).push(arguments)
});
b[l].l = +new Date;
e = o.createElement(i);
r = o.getElementsByTagName(i)[0];
e.src = '//www.google-analytics.com/analytics.js';
r.parentNode.insertBefore(e, r)
}(window, document, 'script', 'ga'));
ga('create', 'UA-XXXXX-X', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

Categories