Can't set css property to an object property in javascript - 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!

Related

How to save budget list in local storage?

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

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.

Query user input - API

smarters! I'm working on a weather app and I'm failing to get user input. I tried creating a variable and assigning the input value to it and changing the part of the url that it's supposed to be dynamic. Sorry if I'm not being very clear, I'm a beginner. But here's my code and my attempt
HTML
<form class="search">
<input type="text" name="search-city" id="search-city" />
<button class="search-btn">Search</button>
</form>
<div class="container">
<div class="box">
<span class="main"></span>
<span class="name"></span>
<span class="temp"></span>
<span class="desc"></span>
<span class="feel"></span>
<span class="min"></span>
<span class="max"></span>
</div>
<div class="toggle">
<input type="checkbox" name="toggle" class="checkbox" id="checkbox" />
<label for="checkbox" class="label">
<div class="ball"></div>
<p>C</p>
<p>F</p>
</label>
</div>
</div>
JS
const name = document.querySelector('.name');
const temperature = document.querySelector('.temp');
const main = document.querySelector('.main');
const desc = document.querySelector('.desc');
const feel = document.querySelector('.feel');
const minTemp = document.querySelector('.min');
const maxTemp = document.querySelector('.max');
const searchBtn = document.querySelector('.search-btn');
let api = 'http://api.openweathermap.org/data/2.5/weather?q=';
let city = 'Los Angeles';
const API_KEY = '&appid=78f46276c074c96c7cc3e739da828101';
const getWeather = async () => {
const unit = document.querySelector('.checkbox').value;
const searchCity = document.querySelector('.search-city');
let units = `${unit}`;
let url = api + city + '&units=' + units + API_KEY;
const response = await fetch(url, { mode: 'cors' });
const data = await response.json();
displayWeather(data);
};
searchBtn.addEventListener('click', (e) => {
e.preventDefault();
});
const displayWeather = async (data) => {
name.textContent = data.name;
temperature.textContent = parseInt(data.main.temp) + '°';
main.textContent = data.weather[0].main;
desc.textContent = 'Description: ' + data.weather[0].description;
feel.textContent = 'Feels like: ' + parseInt(data.main.feels_like) + '°';
console.log(data);
minTemp.textContent = 'Min: ' + parseInt(data.main.temp_min) + '°';
maxTemp.textContent = 'Max: ' + parseInt(data.main.temp_max) + '°';
};
const toggleUnit = document.querySelector('.checkbox');
toggleUnit.addEventListener('click', (e) => {
if (e.target.value === 'imperial') {
e.target.value = 'metric';
getWeather();
} else {
e.target.value = 'imperial';
getWeather();
}
});
getWeather();
My Attempt
const getWeather = async () => {
const unit = document.querySelector('.checkbox').value;
const searchCity = document.querySelector('.search-city');
let searchTem = searchCity.value; // created a variable and assigned the user input to it
if (!searchTem) {
searchTerm = 'Detroit';
}
let units = `${unit}`;
let url = api + searchTerm + '&units=' + units + API_KEY; // here I replaced city for that variable I just created
const response = await fetch(url, { mode: 'cors' });
const data = await response.json();
displayWeather(data);
};
searchBtn.addEventListener('click', (e) => {
e.preventDefault();
});
I appreciate any help. I've been struggling with this for a day already :/
Thanks
You are querying the the input node from the document incorrectly.
As per your code
const searchCity = document.querySelector('.search-city');
will try to get a node with class search-city. Whereas, in your shared code, you are passing an id called search-city on the input element.
To fix this update your query statement
const searchCity = document.querySelector('#search-city');
Also, there is a typo in the naming of searchTerm variable. You are trying to assign input value to variable named searchTem and in your dynamic url referencing variable named searchTerm.
/**
* query all your required element once since this is costly
*
**/
const searchBtn = document.querySelector('.search-btn');
const unit = document.querySelector('.checkbox')
const searchCity = document.querySelector('#search-city');
const api = 'http://api.openweathermap.org/data/2.5/weather?q=';
const city = 'Los Angeles';
const API_KEY = '&appid=78f46276c074c96c7cc3e739da828101';
const getWeather = async () => {
let searchTerm = searchCity.value;
if (!searchTerm) {
searchTerm = 'Detroit';
}
let units = `${unit.value}`;
// here I replaced city for that variable I just created
let url = api + searchTerm + '&units=' + units + API_KEY;
const response = await fetch(url, { mode: 'cors' });
const data = await response.json();
displayWeather(data);
};
searchBtn.addEventListener('click', (e) => {
e.preventDefault();
// call the fetch handling method on submit click
getWeather();
});
<form class="search">
<input type="text" name="search-city" id="search-city" />
<button class="search-btn">Search</button>
</form>
<div class="container">
<div class="box">
<span class="main"></span>
<span class="name"></span>
<span class="temp"></span>
<span class="desc"></span>
<span class="feel"></span>
<span class="min"></span>
<span class="max"></span>
</div>
<div class="toggle">
<input type="checkbox" name="toggle" class="checkbox" id="checkbox" />
<label for="checkbox" class="label">
<div class="ball"></div>
<p>C</p>
<p>F</p>
</label>
</div>
</div>

JavaScript arrays adding last element instead of recently added input

Good evening. I am new to JavaScript and I need help with my mini-project and I have only one issue here and it is in the this.Add = function ().
It works properly when I enter a duplicate value from my list therefore it displays an alert that no dupes are allowed. But... when I enter a unique value, it only adds up the last element present (Wash the dishes) from myTasks list. instead of the one I recently entered and the list goes on adding the same ones. Did I just misplace something?
This is my final activity yet and I want to finish it to move to the next function. Thank you in advance.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Tasks CRUD</title>
<style>
#tasks{
display: none;
}
</style>
</head>
<body>
<center>
<form action="javascript:void(0);" method="POST" onsubmit="app.Add()">
<input type="text" id="add-task" placeholder="Add another card">
<input type="submit" value="Add">
</form>
<div id="tasks" role="aria-hidden">
<form action="javascript:void(0);" method="POST" id="saveEdit">
<input type="text" id="edit-task">
<input type="submit" value="Edit" /> <a onclick="CloseInput()" aria-label="Close">✖</a>
</form>
</div>
<p id="counter"></p>
<table>
<tr>
<th>Name</th>
</tr>
<tbody id="myTasks">
</tbody>
</table>
</center>
<script>
var app = new function() {
this.el = document.getElementById('myTasks');
this.myTasks = ['Clean the bathroom', 'Wash the dishes'];
this.Count = function(data) {
var el = document.getElementById('counter');
var name = 'task';
if (data) {
if (data > 1) {
name = 'Things To DO';
}
el.innerHTML = data + ' ' + name ;
} else {
el.innerHTML = 'No ' + name;
}
};
this.FetchAll = function() {
var data = '';
if (this.myTasks.length > 0) {
for (i = 0; i < this.myTasks.length; i++) {
data += '<tr>';
data += '<td>' + this.myTasks[i] + '</td>';
data += '<td><button onclick="app.Edit(' + i + ')">Edit</button></td>';
data += '<td><button onclick="app.Delete(' + i + ')">Delete</button></td>';
data += '</tr>';
}
}
this.Count(this.myTasks.length);
return this.el.innerHTML = data;
};
this.Add = function () {
el = document.getElementById('add-task');
// Get the value
var task = el.value;
if (task ) {
for(task of this.myTasks)
{
var ctr = 0;
if(document.getElementById("add-task").value == task){
ctr = 1;
break;
}
}
if(ctr == 1)
{
window.alert("Duplicates not allowed.");
}else{
// Add the new value
this.myTasks.push(task.trim());
// Reset input value
el.value = '';
// Dislay the new list
this.FetchAll();
}
}
};
this.Edit = function (item) {
var el = document.getElementById('edit-task');
// Display value in the field
el.value = this.myTasks[item];
// Display fields
document.getElementById('tasks').style.display = 'block';
self = this;
document.getElementById('saveEdit').onsubmit = function() {
// Get value
var task = el.value;
if (task) {
// Edit value
self.myTasks.splice(item, 1, task.trim());
// Display the new list
self.FetchAll();
// Hide fields
CloseInput();
}
}
};
this.Delete = function (item) {
// Delete the current row
this.myTasks.splice(item, 1);
// Display the new list
this.FetchAll();
};
}
app.FetchAll();
function CloseInput() {
document.getElementById('tasks').style.display = 'none';
}
</script>
</body>
</html>
In your for loop:
for (task of this.myTask) {
}
You are not declaring a new task variable, but instead assigning to the outer task variable, hence the repeated addition of tasks already in your list.
You can declare a new variable in the for scope like so:
for (const task of this.myTask) {
}
Your HTML as it is.
And your Javascript goes like below. You have a bug while checking if the task already exists in the array. As you're comparing string value either use simple for loop with triple equals or do as i have attached below.
var app = new function() {
this.el = document.getElementById('myTasks');
this.myTasks = ['Clean the bathroom', 'Wash the dishes'];
this.Count = function(data) {
var el = document.getElementById('counter');
var name = 'task';
if (data) {
if (data > 1) {
name = 'Things To DO';
}
el.innerHTML = data + ' ' + name ;
} else {
el.innerHTML = 'No ' + name;
}
};
this.FetchAll = function() {
var data = '';
if (this.myTasks.length > 0) {
for (i = 0; i < this.myTasks.length; i++) {
data += '<tr>';
data += '<td>' + this.myTasks[i] + '</td>';
data += '<td><button onclick="app.Edit(' + i + ')">Edit</button></td>';
data += '<td><button onclick="app.Delete(' + i + ')">Delete</button></td>';
data += '</tr>';
}
}
this.Count(this.myTasks.length);
console.log(this.myTasks.length);
return this.el.innerHTML = data;
};
this.Add = function () {
el = document.getElementById('add-task');
// Get the value
var task = el.value;
console.log(task);
if (task ){
var arrayContainsTask = (this.myTasks.indexOf(task) > -1);
if(arrayContainsTask == true){
window.alert("Duplicates not allowed.");
}else{
// Add the new value
this.myTasks.push(task);
// Reset input value
el.value = '';
}
// Dislay the new list
this.FetchAll();
}
}
}

How would you use JavaScript to create a toggle button that unhides/ hides content?

I am trying to hide content that is revealed when the button is clicked.
This is my starting HTML:
<div class="sunrise-section" id="hide-show">
<h3>SUNRISE</h3>
<p class="sunrise">5:40 A.M.</p>
</div>
<div class="sunset-section" id="hide-show">
<h3>SUNSET</h3>
<p class="sunset">8:05 P.M.</p>
</div>
<div class="navbar-bottom">
<button onclick="onClick"><img src="https://image.flaticon.com/icons/svg/892/892499.svg" alt="click for details" height="18px" id="navbar-bottom-button"></button>
</div>
This is my starting JavaScript (The onClick function is last; I included everything to show context):
window.addEventListener('load', ()=> {
let long;
let lat;
let locationTimeZone = document.querySelector('.location-timezone');
let temperatureDegree = document.querySelector('.temperature-degree');
let humidity = document.querySelector('.humidity');
let todayDate = document.querySelector('.today-date');
let windSpeed = document.querySelector('.wind-speed');
let visibility = document.querySelector('.visibility');
let pressure = document.querySelector('.pressure');
let sunrise = document.querySelector('.sunrise');
let sunset = document.querySelector('.sunset');
let myDate = new Date();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(position => {
long = position.coords.longitude;
lat = position.coords.latitude;
const proxy = 'https://cors-anywhere.herokuapp.com/';
const api = `${proxy}https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=d5f88bf8e740a9d82677f46f346f0a33&units=Imperial`;
fetch(api)
.then(response => {
return response.json();
})
.then(data => {
console.log(data);
// Set Sunrise
let sunriseDate = new Date(data.sys.sunrise * 1000);
let sunriseHours = sunriseDate.getHours();
let sunriseMinutes = sunriseDate.getMinutes();
// Set Sunset
let sunsetDate = new Date(data.sys.sunset * 1000);
let sunsetHours = sunsetDate.getHours();
let sunsetMinutes = sunsetDate.getMinutes();
// Add 0 Before Minutes if Less than 10
if(sunsetMinutes.toString().length < 2)
sunsetMinutes = "0" + sunsetMinutes
if(sunriseMinutes.toString().length < 2)
sunriseMinutes = "0" + sunsetMinutes
// Set DOM Elements from the API
locationTimeZone.textContent = data.name;
temperatureDegree.textContent = Math.round(data.main.temp);
humidity.textContent = data.main.humidity + '%';
todayDate.textContent = myDate.format('l F d') + 'th, ' + myDate.format('Y');
windSpeed.textContent = data.wind.speed + ' MPH';
visibility.textContent = Math.round(data.visibility / 1609) + '+ Mi';
pressure.textContent = data.main.pressure + ' mb';
sunrise.textContent = sunriseHours + ":" + sunriseMinutes + " A.M.";
sunset.textContent = (sunsetHours - 12) + ":" + sunsetMinutes + " P.M.";
// Set Icon
let iconCode = data.weather[0].icon;
let iconUrl = "http://openweathermap.org/img/wn/" + iconCode + "#2x.png";
$('#weather-icons').attr('src', iconUrl);
// Toggle Hide / Unhide Button
function onClick() {let x = document.getElementById("hide-show");
if (x.style.display === "none") {
x.style.display = "block";}
else {x.style.display = "none";}
}
} )
});
}
});
I've tried to change .getElementById("hide-show") to document.querySelectorAll('[id=hide-show]') and nothing changes.
I appreciate any input that can help me better understand this problem!
I think the onClick function is never called if you have your javascript in a separate file.
Here is a simple way to do this, it's called event delegation, it's better to have a single listener than multiple in a loop.
let elements = document.querySelectorAll('.hide-show');
document.addEventListener('click', e => {
if (e.target.closest('button')) {
elements.forEach(el => {
el.classList.contains('hidden') ? el.classList.remove('hidden') : el.classList.add('hidden');
})
}
})
.hidden {
display: none
}
<div class="sunrise-section hide-show" id="one">
<h3>SUNRISE</h3>
<p class="sunrise">5:40 A.M.</p>
</div>
<div class="sunset-section hide-show" id="two">
<h3>SUNSET</h3>
<p class="sunset">8:05 P.M.</p>
</div>
<div class="navbar-bottom">
<button><img src="https://image.flaticon.com/icons/svg/892/892499.svg" alt="click for details" height="18px" id="navbar-bottom-button"></button>
</div>

Categories

Resources