Why isn't this code save data in local storage (undefined) - javascript

When creating new div with data from input form, the first div save the data that i inputed, but next, when i input new data, div display undefined value.
first attempt second attempt
0: {name: "Milk", amount: "30"}
name: "Milk"
amount: "30"
1: "expense"
2: "expense"
3: "expense"
document.getElementById('expenseInput').addEventListener('submit', saveExpense);
function saveExpense(e) {
let expenseName = document.getElementById('expenseNameInput').value,
expenseAmount = document.getElementById('expenseAmountInput').value;
let expenseStorage = {
name: expenseName,
amount: expenseAmount,
}
if (localStorage.getItem('expenses') == null) {
let expenses = [];
expenses.push(expenseStorage);
localStorage.setItem('expenses', JSON.stringify(expenses));
} else {
let expenses = JSON.parse(localStorage.getItem('expenses'));
expenses.push('expenseStorage');
localStorage.setItem('expenses', JSON.stringify(expenses));
}
document.getElementById('expenseInput').reset();
fetchExpense();
e.preventDefault();
}
function fetchExpense() {
let expenses = JSON.parse(localStorage.getItem('expenses')),
expensesList = document.getElementById('expensesList');
expensesList.innerHTML = '';
for (let i = 0; i < expenses.length; i++) {
let name = expenses[i].name,
amount = expenses[i].amount;
expensesList.innerHTML += '<div class="well" id="expense-item">' +
'<h3>' + name + '</h3>' +
'<h3>' + amount + '</h3>' +
'Delete' +
'</div>';
}
}
I'm rewriting code many times but it doesnt's work.

Try replacing expenses.push('expenseStorage') to expenses.push(expenseStorage).
So your code will look like this:
document.getElementById('expenseInput').addEventListener('submit', saveExpense);
function saveExpense(e) {
let expenseName = document.getElementById('expenseNameInput').value,
expenseAmount = document.getElementById('expenseAmountInput').value;
let expenseStorage = {
name: expenseName,
amount: expenseAmount,
}
if (localStorage.getItem('expenses') == null) {
let expenses = [];
expenses.push(expenseStorage);
localStorage.setItem('expenses', JSON.stringify(expenses));
} else {
let expenses = JSON.parse(localStorage.getItem('expenses'));
expenses.push(expenseStorage);
localStorage.setItem('expenses', JSON.stringify(expenses));
}
document.getElementById('expenseInput').reset();
fetchExpense();
e.preventDefault();
}
function fetchExpense() {
let expenses = JSON.parse(localStorage.getItem('expenses')),
expensesList = document.getElementById('expensesList');
expensesList.innerHTML = '';
for (let i = 0; i < expenses.length; i++) {
let name = expenses[i].name,
amount = expenses[i].amount;
expensesList.innerHTML += '<div class="well" id="expense-item">' +
'<h3>' + name + '</h3>' +
'<h3>' + amount + '</h3>' +
'Delete' +
'</div>';
}
}

Related

How to make a leaderboard ranking scores JavaScript

Currently, my code shows the score of the user that's logged in. I want to show the highest score obtained by each user on the leaderboard until the top 10.
js from index.html
<script>
loadRankingTable();
window.onload = () => {
//Check login
if (sessionStorage.loggedInUser !== undefined) {
let oldData = localStorage.getItem(sessionStorage.loggedInUser);
console.log(JSON.parse(oldData))
if (oldData) {
oldData = JSON.parse(oldData);
oldData.topScore = highscore;
localStorage.setItem(sessionStorage.loggedInUser, JSON.stringify(oldData));
}
document.getElementById("Greeting").innerHTML = sessionStorage.loggedInUser;
}
}
</script>
prac.js
function loadRankingTable(){
let str = "<table><tr><th>Rank</th><th>Name</th><th>Score</th></tr>";
for(let key of Object.keys(localStorage)){
let usr = JSON.parse(localStorage[key]);
str += "<tr><td>" + "1" + "</td><td>" + sessionStorage.loggedInUser + "</td><td>" + highscore + "</td></tr>";
}
str += "</table>";
document.getElementById("Ranking").innerHTML = str;
}
The highscore gets stored in the local storage, but I want the logged in user's highscore shown next to their name on the leaderboard, up till the top 10.
Try this: (others have permission to copy and edit this)
function load(){
var userscores = {
"ex1": 10,
"noncy": 40,
"del3tus": 24,
"the_r0ck": 8,
"MONSTER_OSITY": 120
};
var max = 0;
var sorted = [];
for(var prop in userscores){
if(userscores[prop] >= max){
max = userscores[prop];
}
}
var cur = max;
for(var i = max; i > 0; i--){
for(var prop in userscores){
if(userscores[prop] == i){
sorted.push(prop);
}
}
}
var html = "";
for(var i = 0; i < sorted.length; i++){
html = "<tr><td>" + (i + 1) + "</td><td>" + sorted[i] + "</td><td>" + userscores[sorted[i]] + "</td></tr>";
document.getElementById("leaderboard").innerHTML += html;
}
}
<button onclick="load();">Load leaderboard</button>
<table id="leaderboard" border="1" cellSpacing="0px"><tr><th>#</th><th>Name</th><th>Points</th></tr></table>
If that doesn't work, let me know. You can also change it to make it fit better.

How can I compare data from two links with Ajax?

I want to compare and print genre_ids in the first link and id in the other link.
Sample:
genre_ids: [
18,
878,
]
{
id: 18,
name: "Drama",
},
{
id: 878,
name: "Science Fiction",
}
Result: Drama, Science Fiction
$(document).ready(function () {
var url = "http://api.themoviedb.org/3/discover/movie?api_key=7196f61181cb7f5b0a28020cd3f603fb&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1&item_count=14";
var categories = "https://api.themoviedb.org/3/genre/movie/list?api_key=7196f61181cb7f5b0a28020cd3f603fb&language=en-EN";
$.ajax({
url: url,
method: 'GET',
success: function (data) {
$.ajax({
url: categories,
method: 'GET',
success: function (cat) {
$('#Movies').html(ListMovies(data, cat));
}
});
}
});
function ListMovies(data, cat) {
var card = "";
var cats = "";
for (var i = 0; i < 12; i++) {
card += "<div class='col-sm-3'><div class='card'><img src='https://image.tmdb.org/t/p/w1280" + data.results[i].backdrop_path + "' height='250px' class='card-img-top'><div class='card-body'><h5 class='card-title'>" + data.results[i].original_title + " <span>" + data.results[i].vote_average + "</span></h5><p class='card-text'>" + result should be here + "</p></div></div></div>";
}
return card;
}
});
What about this:
function ListMovies(data, cat) {
var card = "";
for (let i = 0; i < 12; i++) {
let cats = [];
cat.genres.forEach(elem=>{
if(data.results[i].genre_ids.includes(elem.id)) cats.push(elem.name)
})
card += "<div class='col-sm-3'><div class='card'><img src='https://image.tmdb.org/t/p/w1280" + data.results[i].backdrop_path + "' height='250px' class='card-img-top'><div class='card-body'><h5 class='card-title'>" + data.results[i].original_title + " <span>" + data.results[i].vote_average + "</span></h5><p class='card-text'>" + cats.join(", ") + "</p></div></div></div>";
}
return card;
}

DOM createElement() dynamically with click event to div specific url element

I am attempting to build a 9 divs (cards) dynamically containing information about store branch locations. Each card has a unique URL associated with it that links to each branches specific URL.
This approach, within the function, appends the first (0) URL to all the cards:
$("div").click(function() {
window.location = $(this).find("a").attr("href");
return false;
});
This approach appends the last URL (8) to all the cards:
branch.addEventListener("click", function(e){
e.preventDefault();
window.open(prop.pages_url);
})
Code I'm working with:
function buildLocationList(data) {
for (i = 0; i < 9; i++) {
var currentFeature = data.features[i];
var prop = currentFeature.properties;
//Create Card
var branches = document.getElementById('branches');
var url = branches.appendChild(document.createElement('a');
url.setAttribute('href', prop.pages_url);
)
var branch = branches.appendChild(document.createElement('div'));
branch.className = 'card';
branch.id = "branch-" + i;
branch.url = prop.pages_url;
branch.addEventListener("click", function(e){
e.preventDefault();
window.open(prop.pages_url);
})
//Append Branch Card Details
v
var company = branch.appendChild(document.createElement('h5'));
company.innerHTML = prop.name + '<br />';
var distancePhone = branch.appendChild(document.createElement('p'));
if (prop.distance) {
var roundedDistance = Math.round(prop.distance * 100) / 100;
distancePhone.innerHTML = '<span class="miles">Approx. ' + roundedDistance + ' miles</span>' + '<span class="location-phone">' + prop.phone_number + '</span>';
}
else {
distancePhone.innerHTML = prop.phone_number;
}
var address = branch.appendChild(document.createElement('p'));
if (prop.address_line_2) {
address.innerHTML += prop.address_line_1 + ', ' + prop.address_line_2 + '<br />';
}
else {
address.innerHTML += prop.address_line_1 + '<br />';
};
address.innerHTML += prop.address_city + ', ' + prop.address_state + ' ' +prop.address_postal_code + '</p>';
}
}
I would like the card to be clickable with a redirect to each branch's unique URL.
You're storing the URL on the card element:
branch.url = prop.pages_url
All you need to do in the click handler is access the property:
branch.addEventListener("click", function(e){
e.preventDefault();
window.open(e.currentTarget.url);
})
In the context of the event handler, e.currentTarget is the element to which the handler is attached. If you were interested in which element fired the event, you'd use e.target.
Here's your code snippet modified below. I don't think the links will open on here though due to the sandboxed iframe.
function buildLocationList(data) {
for (i = 0; i < data.features.length; i++) {
var currentFeature = data.features[i];
var prop = currentFeature.properties;
//Create Card
var branches = document.getElementById('branches');
var url = branches.appendChild(document.createElement('a'));
url.setAttribute('href', prop.pages_url);
var branch = branches.appendChild(document.createElement('div'));
branch.className = 'card';
branch.id = "branch-" + i;
branch.url = prop.pages_url;
branch.addEventListener("click", function(e){
e.preventDefault();
console.log(e.currentTarget.url);
window.open(e.currentTarget.url);
})
//Append Branch Card Details
var company = branch.appendChild(document.createElement('h5'));
company.innerHTML = prop.name + '<br />';
var distancePhone = branch.appendChild(document.createElement('p'));
if (prop.distance) {
var roundedDistance = Math.round(prop.distance * 100) / 100;
distancePhone.innerHTML = '<span class="miles">Approx. ' + roundedDistance + ' miles</span>' + '<span class="location-phone">' + prop.phone_number + '</span>';
}
else {
distancePhone.innerHTML = prop.phone_number;
}
var address = branch.appendChild(document.createElement('p'));
if (prop.address_line_2) {
address.innerHTML += prop.address_line_1 + ', ' + prop.address_line_2 + '<br />';
}
else {
address.innerHTML += prop.address_line_1 + '<br />';
};
address.innerHTML += prop.address_city + ', ' + prop.address_state + ' ' +prop.address_postal_code + '</p>';
}
}
buildLocationList({features:[{
properties: {
distance: 100,
name: 'Google',
pages_url: 'https://www.google.com',
phone_number: '123-456-7890',
address_line_1: '1234 Street',
address_city: 'Citytown',
address_state: 'State',
address_postal_code: '12345'
}
},{
properties: {
distance: 200,
name: 'Microsoft',
pages_url: 'https://www.microsoft.com',
phone_number: '123-456-7890',
address_line_1: '1234 Street',
address_city: 'Citytown',
address_state: 'State',
address_postal_code: '12345'
}
}]})
.card {
border: 1px solid #ccc;
padding: 10px;
max-width: 50%;
margin: 10px;
}
<div id="branches"></div>
<div>
w3schools
</div>
<script>
$("div").click(function() {
window.location = $(this).find("a").data("value");
});
</script>

How do I remove just the current instance of the array, not all instances of the array?

How do I remove just the current instance of the array, not all instances of the array?
var persons = [];
showAllButton.onclick = function() {
while (showList.firstChild)showList.removeChild(showList.firstChild);
Created new node instances.
for (var l in persons) {
var listNode = document.createElement("LI");
var btn = document.createElement("BUTTON");
btn.innerHTML = "Remove";
showList.appendChild(listNode);
showList.appendChild(btn);
Displays pushed instances correctly.
listNode.innerHTML =
'<p><b>Full Name:</b> ' + persons[l].firstName +' ' + persons[l].lastName + '</p>' +
'<p><b>Phone:</b> ' + persons[l].phone + '</p>' +
'<p><b>Address:</b> ' + persons[l].address + '</p>'
}
Tried a few variations of the following function but just empties the array, or at least wont return the amended array.
btn.onclick = function() {
var index = Array.indexOf(persons[l]);
persons.splice(index, 1);
return persons;
}
if (showAllButton.value=="Show Contacts") {
showAllButton.value = "Hide Contacts";
showList.style.display = "block";
}
else if (showAllButton.value = "Hide Contacts") {
showAllButton.value = "Show Contacts";
showList.style.display = "none";
}
}
probably bind l, remove the element at index l, then redraw the dom somehow.:
btn.onclick = function(l) { //take over the bound l
persons.splice(l, 1);
//some kind of redraw
showAllButton.click();
}.bind(null,l);//bind l
Something like this should work as expected (sorry, blind coding, have no time to test now)
var persons = [];
function removePerson(index) {
persons.splice(index, 1);
renderList();
}
function clearList() {
while (showList.firstChild) {
showList.removeChild(showList.firstChild);
}
}
function renderItem(person, index) {
var item = showList.appendChild(document.createElement("LI"));
var label = item.appendChild(document.createElement("SPAN"));
label.innerHTML = persons[i];
var btn = item.appendChild(document.createElement("BUTTON"));
btn.innerHRML = "Remove";
btn.onclick = removePerson.bind(null, index);
}
function renderList() {
clearList();
persons.forEach(renderItem);
}
Not a kind of best practices, but seems to be working.
Final Working Code, thank you!
showAllButton.onclick = function() {
while (showList.firstChild)showList.removeChild(showList.firstChild);
for (var l in persons) {
var list = showList.appendChild(document.createElement("LI"));
list.innerHTML =
'<p><b>Full Name:</b> ' + persons[l].firstName +' ' + persons[l].lastName + '</p>' +
'<p><b>Phone:</b> ' + persons[l].phone + '</p>' +
'<p><b>Address:</b> ' + persons[l].address + '</p>';
var btn = showList.appendChild(document.createElement("BUTTON"));
btn.innerHTML = "Remove";
btn.onclick = function(l) {
persons.splice(l, 1);
showAllButton.click();
}.bind(null,l);
}

Only show objects in array that contain a specific string

I was trying to make something where you can type a string, and the js only shows the objects containing this string. For example, I type Address1 and it searches the address value of each one then shows it (here: it would be Name1). Here is my code https://jsfiddle.net/76e40vqg/11/
HTML
<input>
<div id="output"></div>
JS
var data = [{"image":"http://www.w3schools.com/css/img_fjords.jpg","name":"Name1","address":"Address1","rate":"4.4"},
{"image":"http://shushi168.com/data/out/114/38247214-image.png","name":"Name2","address":"Address2","rate":"3.3"},
{"image":"http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg","name":"Name3","address":"Address3","rate":"3.3"}
];
var restoName = [], restoAddress = [], restoRate = [], restoImage= [];
for(i = 0; i < data.length; i++){
restoName.push(data[i].name);
restoAddress.push(data[i].address);
restoRate.push(data[i].rate);
restoImage.push(data[i].image);
}
for(i = 0; i < restoName.length; i++){
document.getElementById('output').innerHTML += "Image : <a href='" + restoImage[i] + "'><div class='thumb' style='background-image:" + 'url("' + restoImage[i] + '");' + "'></div></a><br>" + "Name : " + restoName[i] + "<br>" + "Address : " + restoAddress[i] + "<br>" + "Rate : " + restoRate[i] + "<br>" + i + "<br><hr>";
}
I really tried many things but nothing is working, this is why I am asking here...
Don't store the details as separate arrays. Instead, use a structure similar to the data object returned.
for(i = 0; i < data.length; i++){
if (data[i].address.indexOf(searchedAddress) !== -1) { // Get searchedAddress from user
document.getElementById("output").innerHTML += data[i].name;
}
}
Edits on your JSFiddle: https://jsfiddle.net/76e40vqg/17/
Cheers!
Here is a working solution :
var data = [{"image":"http://www.w3schools.com/css/img_fjords.jpg","name":"Name1","address":"Address1","rate":"4.4"},
{"image":"http://shushi168.com/data/out/114/38247214-image.png","name":"Name2","address":"Address2","rate":"3.3"},
{"image":"http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg","name":"Name3","address":"Address3","rate":"3.3"}
];
document.getElementById('search').onkeyup = search;
var output = document.getElementById('output');
function search(event) {
var value = event.target.value;
output.innerHTML = '';
data.forEach(function(item) {
var found = false;
Object.keys(item).forEach(function(val) {
if(item[val].indexOf(value) > -1) found = true;
});
if(found) {
// ouput your data
var div = document.createElement('div');
div.innerHTML = item.name
output.appendChild(div);
}
});
return true;
}
<input type="search" id="search" />
<div id="output"></div>

Categories