How to save budget list in local storage? - javascript

I know local storage is not a secure solution for this, but for now, I am doing it this way for practice.
I think I am on the right track here, I want my created list for the budget app to store, this method seems to store the first created list.
/*----Store Stored budget list----*/
function storedEntry(){
const saveData = makeNewBudget();
const myJSON = JSON.stringify(saveData);
window.localStorage.setItem(STORAGE_KEY, myJSON);
}
I think what needs to happen is get that same method to work for the array.
let budgetArray = [];
I tried this method, but gives a JSON error, sop for some reason it's not converted to JSON
let budgetArray = JSON.parse(window.localStorage.getItem(STORAGE_KEY) ?? "[]");
End result should be set local storage for array in its own function and get the stored information when checking the array.
I put the entire JS code so you can see what is going on
/*----Generate ID----*/
const createId = () =>`${Math.floor(Math.random() * 10000)}$(new Date().getTime())}`;
/*----Get current Date----*/
function createdDate() {
let currentDate = new Date();
let day = String(currentDate.getDate()).padStart(2, '0');
let month = String(currentDate.getMonth() + 1).padStart(2, '0');
let year = currentDate.getFullYear();
currentDate = month + '/' + day + '/' + year;
console.log(currentDate)
return currentDate;
}
/*----Variable Objects----*/
const el = {
list: document.querySelector(".list"),
cashflow: document.querySelector("#cashflow"),
catagory: document.querySelector(".catagory"),
label: document.querySelector(".label"),
number: document.querySelector(".number"),
};
/*----Array with local Storage----*/
let budgetArray = [];
/*----Budget list Object----*/
function makeNewBudget(){
const data = {
id: createId(),
cashflowNew: el.cashflow.value,
catagoryNew: el.catagory.value,
labelNew: el.label.value,
dateNew: createdDate(),
numberNew: el.number.value,
};
return data;
}
/*----Render Budget List----*/
function renderList(){
el.list.innerHTML = budgetArray.map(function (data,i) {
return `<div class="entry">
<div class="list">
<button onclick="deleteItem(event, ${i})" class="Archive" data-id="${data.id}">
<img src="../resources/Images/archive.png" alt="Archive">
</button>
<button onclick="editItem(event, ${i})" class = "edit" data-id="${data.id}" class = "edit" data-id="${data.id}">
<img src="../resources/Images/edit.png" alt="Edit">
</button>
<div class="input" data-id="${data.id}"></div>
<label class="dateNew">${data.dateNew}</label>
<label class="cashflowNew">${data.cashflowNew}</label>
<label class="catagoryNew">${data.catagoryNew}</label>
<label class="labelNew">${data.labelNew}</label>
<label class="numberNew">${data.numberNew}</label>
</div>
</div>
<label class="total"></label>`;
});
}
/*----form validation----*/
let budgetButton = document.querySelector(".budget-button");
let label = document.querySelector(".label");
let num = document.querySelector(".number");
let entry = document.querySelector(".entry")
budgetButton.addEventListener("click", () => {
if (!label.value || !num.value) {
alert("please make sure all inputs are filled");
}
budgetArray.push(makeNewBudget())
renderList();
storedEntry();
});
/*----Archive list----*/
function deleteItem(event, i){
}
/*----Store Stored budget list----*/
function storedEntry(){
const saveData = makeNewBudget();
const myJSON = JSON.stringify(saveData);
window.localStorage.setItem(STORAGE_KEY, myJSON);
}

Related

Going through each child in a div generated from API in javascript

I'm trying to access and delete the child in a div generated when I press the "submit" button, the individual divs inside will be generated because there are some functions running with the click, but when I press refresh to delete them nothing happened.
For more clarification here's the src: https://github.com/espnal/wdd230-final-project/blob/main/javascript/js.js
(This is my first post here if you have any suggestions I'm open)
const refresh = document.querySelector("#refresh");
const form = document.querySelector("#form-1");
const contentDiv = document.querySelector(".contentdiv");
const input = document.querySelector("#form-1 input");
//There're another two function like this one below
function firstItemF(list, city) {
let firstItem = list[0]
let dayweather = "Sunday"
const icon = `https://openweathermap.org/img/wn/${firstItem.weather[0]["icon"]}#2x.png`;
let individualDiv = document.createElement("Div")
individualDiv.className = "individual"
let description = document.createElement("p")
description.innerHTML = firstItem.weather[0].description;
let day = document.createElement("h4")
day.innerHTML = dayweather
let temperature = document.createElement("p")
let kelvin = firstItem.main.temp.toFixed(0);
let f = 9 / 5 * (kelvin - 273) + 32;
temperature.innerHTML = `Current temperature: ${f}℉`
let hum = document.createElement("p")
hum.innerHTML = `${firstItem.main.humidity}%`
let img = document.createElement('img');
img.setAttribute('src', icon);
img.setAttribute('alt', "icon");
img.setAttribute('loading', 'lazy');
individualDiv.appendChild(img);
individualDiv.appendChild(day);
individualDiv.appendChild(description);
individualDiv.appendChild(temperature);
individualDiv.appendChild(hum);
contentDiv.appendChild(individualDiv);
}
form.addEventListener("submit", e => {
e.preventDefault();
const inputVal = input.value;
const urlForecast = `https://api.openweathermap.org/data/2.5/forecast?q=${inputVal}&appid=${myKey}`;
fetch(urlForecast)
.then((response) => response.json())
.then((object) => {
console.log(object);
const {
city,
list
} = object;
let title = document.createElement("h3");
title.innerHTML = `${city.name}, ${city.country}`
titleDiv.appendChild(title);
//im using this one for the example
firstItemF(list, city)
SecondItemF(list, city)
ThirdItemF(list, city)
})
});
//Here is the problem
refresh.addEventListener("click", (e) => {
contentDiv.classList.remove("individual");
})
<form id="form-1">
<button type="submit">SUBMIT</button>
<i id="refresh" class="fa-solid fa-arrow-rotate-right"></i>
<input id="input-s2" type="text" placeholder="Search for a city" autofocus>
<div class="cards-container">
<div class="contentdiv">
</div>
</div>
</form>
You need to use a linter like this one: https://jshint.com Your code needs a ton of semi-colons and you're missing a bracket and parenthesis }) that .fetch() or submit handler needs. I edited your question just so it doesn't irritate anyone trying to answer the question. You'll see the comment at the bottom of this example showing where I added it, but I guessed because there's no way to test it since there's no key for the API (but not expecting one, so worries there).
Besides that problem, the solution for the problem addressed in the question is the following:
Remove:
contentDiv.classList.remove("individual");
And add:
contentDiv.replaceChildren();
Removing a class doesn't remove the actual elements (well normally unless there's some very convoluted logic going on). .replaceChildren(); without a parameter will remove everything within contentDiv, but if you nee to just remove .individual do the following:
document.querySelector('.individual').remove();
const refresh = document.querySelector("#refresh");
const form = document.querySelector("#form-1");
const contentDiv = document.querySelector(".contentdiv");
const input = document.querySelector("#form-1 input");
//There're another two function like this one below
function firstItemF(list, city) {
let firstItem = list[0];
let dayweather = "Sunday";
const icon = `https://openweathermap.org/img/wn/${firstItem.weather[0].icon}#2x.png`;
let individualDiv = document.createElement("Div");
individualDiv.className = "individual";
let description = document.createElement("p");
description.innerHTML = firstItem.weather[0].description;
let day = document.createElement("h4");
day.innerHTML = dayweather;
let temperature = document.createElement("p");
let kelvin = firstItem.main.temp.toFixed(0);
let f = 9 / 5 * (kelvin - 273) + 32;
temperature.innerHTML = `Current temperature: ${f}℉`;
let hum = document.createElement("p");
hum.innerHTML = `${firstItem.main.humidity}%`;
let img = document.createElement('img');
img.setAttribute('src', icon);
img.setAttribute('alt', "icon");
img.setAttribute('loading', 'lazy');
individualDiv.appendChild(img);
individualDiv.appendChild(day);
individualDiv.appendChild(description);
individualDiv.appendChild(temperature);
individualDiv.appendChild(hum);
contentDiv.appendChild(individualDiv);
}
form.addEventListener("submit", e => {
e.preventDefault();
const inputVal = input.value;
const urlForecast = `https://api.openweathermap.org/data/2.5/forecast?q=${inputVal}&appid=${myKey}`;
fetch(urlForecast)
.then((response) => response.json())
.then((object) => {
console.log(object);
const {
city,
list
} = object;
let title = document.createElement("h3");
title.innerHTML = `${city.name}, ${city.country}`;
titleDiv.appendChild(title);
//im using this one for the example
firstItemF(list, city);
SecondItemF(list, city);
ThirdItemF(list, city);
});
});// <= This is missing
//Here is the problem
refresh.addEventListener("click", (e) => {
contentDiv.replaceChildren();
});
<form id="form-1">
<button type="submit">SUBMIT</button>
<i id="refresh" class="fa-solid fa-arrow-rotate-right"></i>
<input id="input-s2" type="text" placeholder="Search for a city" autofocus>
<div class="cards-container">
<div class="contentdiv">
</div>
</div>
</form>

How to save the preferences in Local Storage (JavaScript)

I got 2 radio buttons and each one have a function (change the weather from celsius to fahrenheit)
The wearher data is from an API.
<p>
<label>
Celsius
<input
type="radio"
name="weather"
value="celsius"
class="celsius"
onclick="weatherC()"
/>
</label>
</p>
<p>
<label>
Fahrenheit
<input
type="radio"
name="weather"
value="fahrenheit"
class="fahrenheit"
onclick="weatherF()"
/>
</label>
</p>
Those are the functions in JavaScript:
function weatherC() {
fetch("http://api.openweathermap.org/data/2.5/weather?q=Azuga&units=metric&appid=cbf24ef0d0428af6ca69c8320756cbf5")
.then(handleResponse)
.then((data) => {
const maxTemp = document.querySelector(".max-temp");
maxTemp.innerText = Math.ceil(data.main["temp_max"]) + "\u2103";
const minTemp = document.querySelector(".min-temp");
minTemp.innerText = Math.ceil(data.main["temp_min"]) + "\u2103";
const currentTemp = document.querySelector(".current-temp");
currentTemp.innerText = Math.ceil(data.main["temp"]) + "\u2103";
const feelsLike = document.querySelector(".feels-like");
feelsLike.innerText = Math.ceil(data.main["feels_like"]) + "\u2103";
const city = document.querySelector(".city");
city.innerText = data["name"];
const statusIcon = document.querySelector(".iconClass");
const iconFromApi = data.weather[0].icon;
const icon = `http://openweathermap.org/img/wn/${iconFromApi}#2x.png`;
statusIcon.innerHTML = `<img src="${icon}">`;
});
}
function weatherF() {
fetch("http://api.openweathermap.org/data/2.5/weather?q=Azuga&units=fehrenheit&appid=cbf24ef0d0428af6ca69c8320756cbf5")
.then(handleResponse)
.then((data) => {
const maxTemp = document.querySelector(".max-temp");
maxTemp.innerText = Math.ceil(data.main["temp_max"]) + "\u2109";
const minTemp = document.querySelector(".min-temp");
minTemp.innerText = Math.ceil(data.main["temp_min"]) + "\u2109";
const currentTemp = document.querySelector(".current-temp");
currentTemp.innerText = Math.ceil(data.main["temp"]) + "\u2109";
const feelsLike = document.querySelector(".feels-like");
feelsLike.innerText = Math.ceil(data.main["feels_like"]) + "\u2109";
const city = document.querySelector(".city");
city.innerText = data["name"];
const statusIcon = document.querySelector(".iconClass");
const iconFromApi = data.weather[0].icon;
const icon = `http://openweathermap.org/img/wn/${iconFromApi}#2x.png`;
statusIcon.innerHTML = `<img src="${icon}">`;
});
}
weatherC();
how can i make it that when i refresh the page the selected radio button to remain the same?(I m new to js so an example would be awesome :D)
In the weatherF and the weatherC functions you need to put in a localStorage.setItem call
And then in the page load you need to do a check if localStorage.getItem() return null
If local storage is new to you set up a few small apps where you test out the locaStorage.setItem(key, value) and localStorage.getItem(key)
If you set up the localStorage functions and you can’t get it to work post again and can take a look at it. You really should do a bit more of the code though before positing.

How to populate multiple HTML DOM elements with local storage values

I want to display contents in the last <div> element when a click event occurs but now it only shows 1st 2 elements. Is there something I am not doing right somewhere?
Here is my code so far:
JS
const iname = document.getElementById("name");
const iemail = document.getElementById("email");
const iphone = document.getElementById("phone");
const submit = document.getElementById("submit");
const storage = document.getElementById("storage");
submit.onclick = function () {
const name = iname.value;
const email = iemail.value;
const phoneno = iphone.value;
if (name && email && phoneno) {
localStorage.setItem(name, "");
localStorage.setItem(email, "");
localStorage.setItem(phoneno, "");
location.reload();
}
};
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = localStorage.getItem(key);
storage.innerHTML += `Name : ${key}<br />Email : ${value}`;
}
localStorage.clear()
HTML
<p>Name</p>
<input id="name" autocomplete="off">
<p>Email</p>
<input id="email" autocomplete="off">
<p>Phone no</p>
<input id="phone" autocomplete="off">
<button id="submit">Let's go</button>
<div id="storage" class="box">
<h1>Is this correct?</h1></div>
I think you are setting the values in localstorage the wrong way.
The syntax for storing stuff in there is localstorage.setItem(keyName, keyValue).
And your code is setting the keyName argument to the value you are getting from the form and keyValue argument to an empty string; not what you need.
Make the following changes and you should be good to go (see comments):
submit.onclick = function () {
const name = iname.value;
const email = iemail.value;
const phoneno = iphone.value;
if (name && email && phoneno) {
// set local storage values
localStorage.setItem("name", name); // modified
localStorage.setItem("email", email); // modified
localStorage.setItem("phoneno", phoneno); // modified
location.reload();
}
console.log(localStorage); // new (maybe unnecessary)
};
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = localStorage.getItem(key);
storage.innerHTML += `${upFirst(key)}: ${value}<br>`; // modified
}
localStorage.clear();
/**
* new: making the first letter an upper case (for labels in the output div).
* See usage in 'for loop' above.
*/
function upFirst(stringValue) {
return stringValue.slice(0, 1).toUpperCase() + stringValue.slice(1);
}

Can't set css property to an object property in javascript

I'm trying to change the color of the product(object) title based on the current year.
I mean if the product's year is the same as the current year it should change the title color.
Whenever I save, I get an Error in DevTools:
" Uncaught TypeError: Cannot set property 'color' of undefined ".
<form id="theForm">
<div>
<input type="text" id="title" placeholder="Type title...">
</div>
<div>
<input type="date" id="date">
</div>
<button type="submit" id="sub">Add</button>
</form>
<section class="result">
<div id="addedProducts"></div>
</section>
const theForm = document.getElementById("theForm");
theForm.addEventListener("submit", saveProduct);
function saveProduct(evt){
const proTitle = document.getElementById("title").value;
const proDate = document.getElementById("date").value;
const product = {
title: proTitle,
date: proDate
}
if(localStorage.getItem("products") === null){
const products = []; //initialized
products.push(product);// add a new Product
//to local localStorage
localStorage.setItem("products", JSON.stringify(products));
} else {
// get products from localStorage
const products = JSON.parse(localStorage.getItem("products"));
// add product to products
products.push(product);
// set again to localStorage
localStorage.setItem("products", JSON.stringify(products));
}
theForm.reset();
fetchProducts();
evt.preventDefault()
}
function fetchProducts(){
const products = JSON.parse(localStorage.getItem("products"));
const addedProducts = document.getElementById("addedProducts");
addedProducts.innerHTML = "";
products.forEach(addProduct);
function addProduct(product) {
const title = product.title;
const date = product.date;
const splitDate = date.split("");
const splittedYear = splitDate.slice(0, 4);
const splittedMonth = splitDate.slice(5, 7);
const splittedDay = splitDate.slice(8);
const jYear = splittedYear.join("");
const jMonth = splittedMonth.join("");
const jDay = splittedDay.join("");
const jDate = jMonth +"/"+ jDay +"/"+
jYear;
// Parsed Date attributes
const pYear = parseInt(jYear, 10);
const pMonth = parseInt(jMonth, 10);
const pDay = parseInt(jDay, 10);
// current Date
const cDate = new Date();
const cDay = cDate.getDate();
const cMonth = cDate.getMonth() + 1;
const cYear = cDate.getFullYear();
//Here's the problem!!!
if(pYear == cYear){
// The next line broke every thing
/* Uncaught TypeError: Cannot
set property 'color' of undefined*/
title.style.color = "#159";
console.log("yes");//that works fine
} else {
console.log("not");// So da that one
}
addedProducts.innerHTML += '<div class="res">'+
'<span class="title">' + title +'</span>' +
" " + '<span class="dateClass">' + jDate +'</span>'+
'<button onclick="deletePro(\'' + title + '\',\'' + date + '\')" id="remove">Delete</button>' +
'</div>';
}
}
Sorry if it's a long code. I've been so confused!

How to create multiple variables dynamically that can be summed up

I have a variable that gets its value once an ID is clicked, via .innerText
var currentID = e.target.id;
I need the value of this variable, currentID, to be stored in a new variable which is named just like the ID of which it got its value.
So, if a user clicks an element with the ID price1, and the price is 200.
A new variable with the name price1 with value 200 should be created.
Then, I want to sum up the new variables: price1+price2+price3 etc = totalprice.
This is what I'm doing right now:
$('div.unselected-option').click(function(e) {
$(this).toggleClass("selected-option unselected-option")
if ($(this).hasClass("selected-option")) {
var currentID = e.target.id;
console.log(currentID);
var price1 = document.getElementById(currentID).innerText
var finalprice
finalprice = +price1;
document.getElementById("showprice2").innerHTML = finalprice
Here's an image of the design:
I can't seem to figure this out... What I'm doing right now just results in having 1 variable which means I cannot sum anything up... I would love your view on this issue!
Your use case is pretty strange I hope your backend is secured and well made.
Here is a potential solution:
<div id="a1" onclick="handleProductClick">20</div>
<div id="a2" onclick="handleProductClick">40</div>
<div id="b1" onclick="handleProductClick">20</div>
<div id="b2" onclick="handleProductClick">60</div>
...
<div id="total-price">0</div>
...
const basket = {}
function addToBasket(event) {
const { id, innerText } = event.target
const price = parseInt(innertText, 10)
const product = basket[id]
const count = product.count || 1
basket[id] = {
price,
count
}
}
function getBasketTotalPrice = () => {
return Object.keys(basket)
.reduce((total, product) => total + product.count * product.price, 0)
}
function handleProductClick = (event) => {
addToBasket(event)
const totalPrice = getBasketTotalPrice()
document.querySelector('#total-price').innerHTML = totalPrice
}

Categories

Resources