LocalStorage set and get using select2 multiple - javascript

I'm having a trouble on how can I save and get multiple list in localStorage and retain data to my select. I tried to set and get the item but when the page reload the data does not retain in my select. I also tried printing the list through console.log as you can see in the image the localStorage contain list value . The only problem I encountered , it does not retain the multiple data in my select when reloads. It would be great if anybody could figure out where I am doing something wrong. thank you so much in advance!
References:link1
let data = [{"id":1,"name":"USA","parentid":0},
{"id":2,"name":"Japan","parentid":0},
{"id":3,"name":"Europe","parentid":0},
{"id":4,"name":"California","parentid":1},
{"id":5,"name":"Oklahoma","parentid":1},
{"id":6,"name":"Arizona","parentid":1},
{"id":7,"name":"Kantô","parentid":2},
{"id":8,"name":"Kansai","parentid":2},
{"id":9,"name":"Chügoku","parentid":2},
{"id":10,"name":"France","parentid":3},
{"id":11,"name":"Deutschland","parentid":3},
{"id":12,"name":"Espana","parentid":3},
{"id":13,"name":"Sacramento","parentid":4},
{"id":14,"name":"Los Angeles","parentid":4},
{"id":15,"name":"San Diego","parentid":4},
{"id":16,"name":"Tulsa","parentid":5},
{"id":17,"name":"Oklahoma City","parentid":5},
{"id":18,"name":"Lawton","parentid":5},
{"id":19,"name":"Phoenix","parentid":6},
{"id":20,"name":"Flagstaff","parentid":6},
{"id":21,"name":"Tucson","parentid":6},
{"id":21,"name":"Tokyo","parentid":7},
{"id":22,"name":"Chiba","parentid":7},
{"id":23,"name":"Tochigi","parentid":7},
{"id":24,"name":"Kyoto","parentid":8},
{"id":25,"name":"Osaka","parentid":8},
{"id":26,"name":"Nara","parentid":8},
{"id":27,"name":"Tottori","parentid":9},
{"id":28,"name":"Hirochima","parentid":9},
{"id":29,"name":"Okayama","parentid":9},
{"id":30,"name":"Quimper","parentid":10},
{"id":31,"name":"Toulouse","parentid":10},
{"id":32,"name":"Nancy","parentid":10},
{"id":33,"name":"Dusseldorf","parentid":11},
{"id":34,"name":"Leipzig","parentid":11},
{"id":35,"name":"Munchen","parentid":11},
{"id":36,"name":"Barcelona","parentid":12},
{"id":37,"name":"Sevilla","parentid":12},
{"id":38,"name":"Guernica","parentid":12}]
function populateList(list, props) {
if(props[0].value != -1){
let l = document.getElementById(list);
l.innerHTML = "";
let topItem = document.createElement("option");
topItem.value = -1;
topItem.text = "--Select--";
l.appendChild(topItem);
for(let i=0; i< props.length; i++){
let newOptGroup = document.createElement("optgroup");
let item = props[i];
let items = data.filter(it => it.parentid == item.value);
items.forEach(function(it){
let newItem = document.createElement("option");
newItem.value = it.id;
newItem.text = it.name;
if(props.length>0 && props[0].value !=0){
newOptGroup.label= item.key
newOptGroup.appendChild(newItem)
}
else l.appendChild(newItem);
})
if(props.length>0 && props[0].value !=0 && props[0].value !=-1){
l.appendChild(newOptGroup)
}
}
}
}
function updateList(selList, thisList) {
let values = [];
for(let i=0;i<thisList.selectedOptions.length; i++) values.push({
key: thisList.selectedOptions[i].label,
value: parseInt(thisList.selectedOptions[i].value)
})
if (values.length>0 && values[0] != 0) {
populateList(selList, values);
} else {
let s = document.getElementById(selList);
s.value = "";
triggerEvent(s, "onchange");
let sCopy = s.cloneNode(false);
let p = s.parentNode;
p.replaceChild(sCopy, s);
}
}
function triggerEvent(e, trigger)
{
if ((e[trigger] || false) && typeof e[trigger] == 'function')
{
e[trigger](e);
}
}
function loadList1() {
populateList("province[]", [{key: '', value: 0}]);
}
window.onload = loadList1;
function reload_and_saveLocalStorage(){
savedlocalStorage();
gettingLocalStorage();
//reload page
window.location.reload(true);
}
function savedlocalStorage(){
//province setting item to LocalStorage
const province_options = document.getElementById('province[]').options;
var prov_selected = [];
Array.from(province_options).map((option) => {
if (option.selected) {
prov_selected.push(option.value);
}
});
localStorage.setItem("province_localstorage", JSON.stringify(prov_selected));
//municipality setting item to LocalStorage
const muni_options = document.getElementById('municipality[]').options;
var muni_selected = [];
Array.from(muni_options).map((option) => {
if (option.selected) {
muni_selected.push(option.value);
}
});
localStorage.setItem("muni_localstorage", JSON.stringify(muni_selected));
//barangay setting item to LocalStorage
const barangay_options = document.getElementById('barangay[]').options;
var barangay_selected = [];
Array.from(barangay_options).map((option) => {
if (option.selected) {
barangay_selected.push(option.value);
}
});
localStorage.setItem("barangay_localstorage", JSON.stringify(barangay_selected));
}
function gettingLocalStorage(){
//Province getting item to Localstorage and display to select
var province_selected = JSON.parse(localStorage.getItem("province_localstorage"));
const province_options = document.getElementById('province[]').options;
Array.from(province_options).map((option) => {
if(province_selected.indexOf(option.value) !== -1) {
option.setAttribute("selected", "selected");
}
});
$(".prov").change();
//Municipality getting item to Localstorage and display to select
var muni_selected = JSON.parse(localStorage.getItem("muni_localstorage"));
const muni_options = document.getElementById('municipality[]').options;
Array.from(muni_options).map((option) => {
if(muni_selected.indexOf(option.value) !== -1) {
option.setAttribute("selected", "selected");
}
});
$(".muni").change();
//barangay getting item to Localstorage and display to select
var barangay_selected = JSON.parse(localStorage.getItem("barangay_localstorage"));
const barangay_options = document.getElementById('barangay[]').options;
Array.from(barangay_options).map((option) => {
if(barangay_selected.indexOf(option.value) !== -1) {
option.setAttribute("selected", "selected");
}
});
$(".brgy").change();
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
Region: <select class = "prov" id="province[]" onchange="updateList('municipality[]', this);" multiple="multiple"></select>
Sub-region:<select class="muni" id="municipality[]" onchange="updateList('barangay[]', this);" multiple="multiple"></select>
Location:<select class="brgy" id="barangay[]" multiple="multiple"></select>
<button onclick="reload_and_saveLocalStorage()">SAVE AND RELOAD </button>

Can't execute the snippet beacuse is not secure envolving localStorage, but my advice is to try
$(".brgy").val(option.value);
Instead of setting the "selected" attribute on the option.
That should work.

Related

Uncaught TypeError: Cannot read property 'done' of undefined Javascript

Been trying to solve this issue for the past few days. Surprisingly, my checkbox and Localstorage all works but in console, it displays an error "Uncaught TypeError: Cannot read property 'done' of undefined". I have tried my best to solve this issue to make the error go away but no luck. I know I am trying to call the ".done" property that doesn't exist but how do I solve this issue? I have google'd and read all similar questions on SO.
I don't think it's acceptable to ignore this error in console right? Can somebody please guide/help me? Please just JavaScript, no jQuery. Thanks!
The error comes from the function checkAll() and uncheckAll().
function checkAll() {
var getInputs = document.getElementsByTagName("input");
for (var i = 0, max = getInputs.length; i < max; i++) {
if (getInputs[i].type === 'checkbox')
getInputs[i].checked = true;
items[i].done = true;
localStorage.setItem('items', JSON.stringify(items));
}
}
and
function uncheckAll() {
var getInputs = document.getElementsByTagName("input");
for (var i = 0, max = getInputs.length; i < max; i++) {
if (getInputs[i].type === 'checkbox')
getInputs[i].checked = false;
items[i].done = false;
localStorage.setItem('items', JSON.stringify(items));
}
}
My code below:
<script>
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const items = JSON.parse(localStorage.getItem('items')) || [];
function addItem(e) {
e.preventDefault();
const text = (this.querySelector('[name=item]')).value;
const item = {
text,
done: false
};
items.push(item);
populateList(items, itemsList);
localStorage.setItem('items', JSON.stringify(items));
this.reset();
}
function populateList(plates = [], platesList) {
platesList.innerHTML = plates.map((plate, i) => {
return `
<li>
<input type="checkbox" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''} />
<label for="item${i}">${plate.text}</label>
</li>
`;
}).join('');
}
function toggleDone(e) {
if(!e.target.matches('input')) return; //skip unless its an input
const el = e.target;
const index = el.dataset.index;
items[index].done = !items[index].done;
localStorage.setItem('items', JSON.stringify(items));
populateList(items, itemsList);
}
addItems.addEventListener('submit', addItem);
itemsList.addEventListener('click', toggleDone);
populateList(items, itemsList);
// Challenge: Button: clear all, check all, uncheck all
function checkAll() {
var getInputs = document.getElementsByTagName("input");
for (var i = 0, max = getInputs.length; i < max; i++) {
if (getInputs[i].type === 'checkbox')
getInputs[i].checked = true;
items[i].done = true;
localStorage.setItem('items', JSON.stringify(items));
}
}
function uncheckAll() {
var getInputs = document.getElementsByTagName("input");
for (var i = 0, max = getInputs.length; i < max; i++) {
if (getInputs[i].type === 'checkbox')
getInputs[i].checked = false;
items[i].done = false;
localStorage.setItem('items', JSON.stringify(items));
}
}
function clearItem() {
localStorage.clear();
var element = document.getElementById("plates");
element.parentNode.removeChild(element);
location.reload();
console.log('Items cleared in localStorage');
}
</script>
Because you are initializing the array to empty, if there are no items set in localstorage
const items = JSON.parse(localStorage.getItem('items')) || [];
It is possible that your items[i] could be undefined.
You need to change
items[i].done = false; //similarly for true
to
items[i] = items[i] || {};
items[i].done = false; //or true

Save change in custom list display using local storage

I am trying to create a customizable list with links that can be hidden using a class if you click in a button. Also the list have a sortable option that you can move the links on the list, which saves to localstorage.
The problem is that I don't know how to save the class change with the list order in the localstorage if you click the "add/remove" button on each li.
Also, if anyone can help me improve the code I will be grateful, I am a newbie with localstorage and only managed this with a lot of reading in tutorials and documentation.
Here's a working example:
http://codepen.io/RogerHN/pen/EgbOzB
var list = document.getElementById('linklist');
var items = list.children;
var itemsArr = [];
for (var i in items) {
itemsArr.push(items[i]);
}
// localStorage
var ls = JSON.parse(localStorage.getItem('userlist') || '[]');
for (var j = 0; j < ls.length; j++) {
for (i = 0; i < itemsArr.length; ++i) {
if(itemsArr[i].dataset !== undefined){
if (ls[j] === itemsArr[i].dataset.id) {
list.appendChild(itemsArr[i]);
}
}
}
}
$('.list-block.sortable').on('sort', function () {
var newIdsOrder = [];
$(this).find('li').each(function(){
newIdsOrder.push($(this).attr('data-id'));
});
// store in localStorage
localStorage.setItem('userlist', JSON.stringify(newIdsOrder));
});
You want something like this:
var myApp = new Framework7({
swipePanel: 'left'
});
// Export selectors engine
var $$ = Dom7;
var mainView = myApp.addView('.view-main');
var list = document.getElementById('linklist');
var items = list.children;
var itemsArr = [];
for (var i in items) {
itemsArr.push(items[i]);
}
// localStorage
var ls = JSON.parse(localStorage.getItem('userlist') || '[]');
var classes = JSON.parse(localStorage.getItem('classes') || '["","","","","","","","","",""]');
for (var j = 0; j < ls.length; j++) {
for (i = 0; i < itemsArr.length; ++i) {
if(itemsArr[i].dataset !== undefined){
if (ls[j] === itemsArr[i].dataset.id) {
itemsArr[i].className = classes[i];
list.appendChild(itemsArr[i]);
// handle [add/remove] thing
if (classes[i] != "") {
$(itemsArr[i]).find(".checky").removeClass("selected");
}
}
}
}
}
$('.list-block.sortable').on('sort', saveInfo);
$(".restore").click(function(e) {
$(".confirm").show();
$(".shadow").show();
});
$(".no,.shadow").click(function(e) {
$(".confirm").hide();
$(".shadow").hide();
});
$(".yes").click(function(e) {
$(".confirm").hide();
});
$(".lbl").click(function(e) {
$(".toggle-text").toggleClass("blue");
$(".restore").toggle();
$(".checky").toggle();
$("li.hidden").toggleClass("visible");
});
$('.checky').click(function() {
if (!$(this).hasClass("selected")) {
$(this).parent().removeClass("hidden").addClass("visible");
}
else {
$(this).parent().addClass("hidden visible");
}
$(this).toggleClass("selected");
saveInfo();
});
function saveInfo() {
var newUserList = [];
var newClassList = [];
$("#linklist").find('li').each(
function() {
newUserList.push($(this).attr('data-id'));
if ($(this).hasClass("hidden")) {
newClassList.push("hidden");
}
else {
newClassList.push("");
}
});
// store in localStorage
localStorage.setItem('userlist', JSON.stringify(newUserList));
localStorage.setItem('classes', JSON.stringify(newClassList));
console.log("saved.");
}
function reset() {
console.log("Removing data from local storage.");
localStorage.setItem('userlist', '["1","2","3","4","5","6","7","8","9","10"]');
localStorage.setItem('classes', '["","","","","","","","","",""]');
window.location.reload(true);
};
Codepen
Technically, I should've added explanation...

Sort only array elements JavaScript which has a CSS property

I want to create an unordered list. The order should be given by their id (Which is a number. The smallest is at the bottom.)
BUT if a certain li does not have a a CSS property (text-decoration:line-through in my case.) Then they should be at the bottom anyway.
I am trying to make a To Do list, where checked elements are at the bottom, but when you uncheck them, they jump back to place.
http://codepen.io/balazsorban44/pen/Gjzwbp
const inputArea = document.getElementById('todo-input');
const list = document.getElementById('tasks');
tasks = [];
function loaded() {
inputArea.focus();
}
function enter() {
if (event.keyCode == 13) {
addTask()
}
}
function refresh(array) {
var task = document.createElement('li');
const checkBox = document.createElement('input');
checkBox.setAttribute('type', 'checkbox');
checkBox.setAttribute('onclick', 'toggleCheckBox()');
task.appendChild(checkBox);
task.appendChild(document.createTextNode(array[array.length - 1].task));
task.id = array[array.length - 1].timestamp.getTime()
list.appendChild(task);
return list;
}
function addTask() {
if (inputArea.value != '') {
tasks.push({
timestamp: new Date(),
task: inputArea.value
});
inputArea.value = '';
inputArea.focus();
refresh(tasks);
doneOrUndone();
inputArea.placeholder = 'Click + or press Enter.'
} else {
inputArea.placeholder = 'Write something'
}
}
function doneOrUndone() {
var done = 0
const out = document.getElementById('out')
for (var i = 0; i < tasks.length; i++) {
if (document.getElementsByTagName('li')[i].style.textDecoration != '') {
done++
}
}
out.value = parseInt(done) + '/' + parseInt(tasks.length) + ':'
}
function toggleCheckBox() {
const task = event.target.parentNode
if (task.style.textDecoration == '') {
task.style.textDecoration = 'line-through';
list.appendChild(task)
doneOrUndone()
} else {
task.style.textDecoration = ''
for (var i = 0; i < tasks.length; i++) {
if (task.id < tasks[i].timestamp.getTime() && list.childNodes[0].style.textDecoration == 'line-through') {
if (task.id > list.childNodes[0].id) {
list.insertBefore(task, list.childNodes[0]);
break;
}
} else {
list.insertBefore(task, list.childNodes[i]);
break
}
}
doneOrUndone()
}
}
I think the real problem is that when setting style.textDecoration to line-through, the actual property that is set is textDecorationLine.
Your line if (task.style.textDecoration == '') is therefore always true.
You can replace textDecoration with textDecorationLine and it should work.
http://codepen.io/anon/pen/bwzzkP
The underlying cause of this problem is, in my opinion, that you're using an element's style attribute to monitor state. I'd advice to either:
Store state in javascript, or
Store state in a class, or
Store state in a custom data- attribute
For example:
const task = event.target.parentNode;
const isDone = task.getAttribute("data-done");
task.style.textDecoration = !isDone ? 'line-through' : '';
task.setAttribute("data-done", !isDone);

How to parse the JSON data from PHP to JS with Mysql?

I have a JS that generate automatically the select html tag and cascade the 3 dropdowns. Now, I'm trying to get the data of the dropdowns will be filled thru Mysql database with json_encode but I have no luck.
How to parse thejson_encode properly from PHP to JS to fill the dropdown automatically with Mysql?
Please help me.
PHP:
$result_region = $wpdb->get_results('SELECT DISTINCT state, city, avenue FROM tablename', OBJECT);
foreach($output as $rows){
$data[] = array('state'=> $rows->state, 'city' => $rows->city,'avenue'=> $rows->avenue);
}
echo json_encode($data);
Working example of manually encoded data JS:
var data = getData();
var container = document.querySelector("#sl_form");
// initialize select-boxes with data
initSelect(data);
// reads the data and creates the DOM elements (select-boxes and their relevant options)
function initSelect(data) {
var p, select, option, input, filteredOptions;
for (var key in data) {
p = document.createElement("p");
p.innerHTML = key;
select = document.createElement("select");
select.name = key;
container.appendChild(p);
container.appendChild(select);
filteredOptions = optionFilter(data[key].availableOptions, data[data[key].parent], data[key]);
input = document.querySelector('select[name="' + key + '"');
input.setAttribute("onchange", "updateSelect(this)");
for (var i = 0; i < filteredOptions.length; i++) {
option = document.createElement("option");
option.value = filteredOptions[i].value;
option.innerHTML = filteredOptions[i].value;
input.appendChild(option);
}
input.options.selectedIndex = getSelectedIndex(filteredOptions, data[key]);
input.setAttribute('model', data[key].selectedOption.value);
}
}
// this function will be called on change of select-box
function updateSelect(element) {
var input, option;
setSelectedOption(element);
for (var key in data) {
filteredOptions = optionFilter(data[key].availableOptions, data[data[key].parent], data[key]);
input = document.querySelector('select[name="' + key + '"');
while (input.firstChild) {
input.removeChild(input.firstChild);
}
for (var i = 0; i < filteredOptions.length; i++) {
option = document.createElement("option");
option.value = filteredOptions[i].value;
option.innerHTML = filteredOptions[i].value;
input.appendChild(option);
}
input.options.selectedIndex = getSelectedIndex(filteredOptions, data[key]);
input.setAttribute('model', data[key].selectedOption.value);
}
}
// set the selected-option of select-box when it's changed
function setSelectedOption(element) {
var inputName = element.getAttribute("name");
var inputValue = getSelectedText(element);
var inputItem = data[inputName];
var selectedOption, filteredOptions;
// setting selected option of changed select-box
for (var i = 0; i < inputItem.availableOptions.length; i++) {
if (inputValue === inputItem.availableOptions[i].value) {
inputItem.selectedOption = inputItem.availableOptions[i];
break;
}
}
// setting child object selected option now
for (var key in data) {
if (data[key].parent === inputName) {
filteredOptions = optionFilter(data[key].availableOptions, data[data[key].parent], data[key]);
data[key].selectedOption = filteredOptions[0];
}
}
}
// get the text of select-box
function getSelectedText(element) {
if (element.selectedIndex == -1) {
return null;
}
return element.options[element.selectedIndex].text;
}
function getSelectedIndex(options, self) {
var index;
for (var i = 0; i < options.length; i++) {
if (self.selectedOption.value === options[i].value) {
index = i;
break;
}
}
return index;
}
// get filtered options based on parent's selected value
function optionFilter(items, parent, self) {
var result = [];
if (typeof parent !== "undefined") {
for (var i = 0; i < items.length; i++) {
if (typeof parent.selectedOption !== "undefined") {
if (parent.selectedOption !== null && items[i].parentValue === parent.selectedOption.value) {
result.push(items[i]);
}
}
}
if (typeof self.selectedOption === "undefined") {
self.selectedOption = null;
}
if (self.selectedOption === null) {
self.selectedOption = result[0];
}
return result;
} else {
return items;
}
}
Change your foreach loop as below. It will return all value. You were overriding values in foreach loop.
foreach($result_region as $row){
$data[] = ['sl_region'=> $row->sl_region,
'sl_city' => $row->sl_city,'sl_mall'=> $row->sl_mall];
}
if your php version is lower then 5.4 then use
foreach($result_region as $row){
$data[] = array('sl_region'=> $row->sl_region,
'sl_city' => $row->sl_city,'sl_mall'=> $row->sl_mall);
}

How do I iterate through all the id's?

Check out the api --> https://api.icndb.com/jokes/random/10
Everytime when the user clicks on a specific joke, it will be added to the favorite list.
To keep the code concise I will only show the function itself:
(function() {
"use strict";
const getJokesButton = document.getElementById('getData');
getJokesButton.addEventListener('click', getData);
loadLocalStorage();
function loadLocalStorage() {
let storage = JSON.parse(localStorage.getItem('favoList')) || [];
let listOfFavorites = document.getElementById("favorites");
let emptyArray = '';
if(storage.length > 0) {
for(let i = 0; i < storage.length; i++) {
let idNumberJoke = storage[i].id;
emptyArray +=
`<li><input type="checkbox" id='${idNumberJoke}'/> User title: ${storage[i].joke}</li>`;
listOfFavorites.innerHTML = emptyArray;
}
} else {
return false;
}
}
// fetch data from api
function getData() {
let listOfJokes = document.getElementById("list-of-jokes");
fetch('https://api.icndb.com/jokes/random/10')
.then(function(res) {
return res.json();
}).then(function(data) {
// variable is undefined because it is not initialized. Therefore at some empty single quotes
let result = '';
console.log(data.value);
data.value.forEach((joke) => {
result +=
`<li><input type="checkbox" class='inputCheckbox' id='${joke.id}'/> User title : ${joke.joke}</li>`;
listOfJokes.innerHTML = result;
});
bindCheckbox();
}).catch(function(err) {
console.log(err);
});
}
function clickedButton() {
getJokesButton.setAttribute('disabled', 'disabled');
getJokesButton.classList.add('opacity');
}
function bindCheckbox() {
let inputCheckbox = document.querySelectorAll('input[type=checkbox]');
let elems = document.getElementById('list-of-jokes').childNodes;
let favoriteList = document.getElementById('favorites');
let fav = JSON.parse(localStorage.getItem('favoList'))|| [];
if(elems.length > 0) {
inputCheckbox.forEach(function(element, index) {
inputCheckbox[index].addEventListener('change', function() {
let joke = this;
if(joke.checked && joke.parentNode.parentNode.id === 'list-of-jokes') {
joke.checked = false;
favoriteList.appendChild(joke.parentNode);
addFavorite(joke.id, joke.parentNode.innerText, fav);
}
if(joke.checked && joke.parentNode.parentNode.id === 'favorites') {
joke.checked = false;
removeFavorite(joke, index);
}
});
});
}
clickedButton();
}
function removeFavorite(favorite, index) {
let favoriteCheckBox = favorite;
let i = index;
// convert iterable object to an array, otherwise splice method would give an error.
let favoriteListItem = Array.from(favoriteCheckBox.parentNode);
favoriteListItem.splice(i, 1);
document.getElementById('list-of-jokes').appendChild(favorite.parentNode);
localStorage.setItem('favoList', JSON.stringify(favoriteListItem));
}
// store favorites in localStorage
function addFavorite(jokeId, jokeText, fav) {
let norrisJoke = {
id: jokeId,
joke: jokeText
};
let favorites = fav;
for (let i = 0; i < favorites.length; i++) {
if(favorites[i].id !== norrisJoke.id) {
favorites.push(norrisJoke);
}
}
// favorites[i].id !== norrisJoke.id
// always get the object before the push method and pass it into stringify
localStorage.setItem('favoList', JSON.stringify(favorites));
}
// function which will randomly add one joke to favorite list every 5 seconds
// function need a button which allows you to turn on and off this auto add function
})();
<div class="inner-body">
<button id="getData">GET Jokes</button>
<div class='inner-block'>
<h2>Chuck Norris Jokes</h2>
<ul class='unordered-list' id="list-of-jokes">
</ul>
</div>
<div class='inner-block'>
<h2>Favorites</h2>
<ul class='unordered-list' id="favorites">
</ul>
</div>
</div>
The keys and values would not be pushed into localStorage, the only thing I see is an empty [] in localStorage. The norrisJoke object literal will be dynamically changed. So how could I make this function works?
Too complex, but click on the link below and scroll down to the bottom:
https://codepen.io/chichichi/pen/Gyzzvb
You are trying to run through an empty list here
for (let i = 0; i < favorites.length; i++) {
if(favorites[i].id !== norrisJoke.id) {
favorites.push(norrisJoke);
}
}
This means that nothing will ever be pushed. You can reduce your list to an array of id, then check if the joke exists in the list.
const favIds = favorites.reduce((sum, element) => {
return sum.concat(element.id);
},
[]);
Now you can check if the joke doesn't exists in favorites
if(!favIds.includes(jokeId)){
favorites.push(norrisJoke);
}
The problem is the for loop, the first time it's executed favorites will be an empty array so it's length will be 0, so it will never enter the loop
Something like this should work:
favorites = favorites.filter(joke => joke.id !== norrisJoke.id).concat(norrisJoke);
let favorites = JSON.parse(localStorage.getItem('favoList'))|| {};
favorites[norrisJoke.id] =norrisJoke.joke
Why don't you use a map in place of an array?
Also as #fl9 points out your for loop will never start off! because favorites.length is 0 to begin with
But I want to check duplicates before the joke will be pushed into favorite list
By definition a hash will not allow duplicate entries, so no need to worry about duplications
Run localStorage.getItem('favoList') in the console of this fiddle :
(function() {
"use strict";
const getJokesButton = document.getElementById('getData');
getJokesButton.addEventListener('click', getData);
loadLocalStorage();
function loadLocalStorage() {
let storage = JSON.parse(localStorage.getItem('favoList')) || [];
let listOfFavorites = document.getElementById("favorites");
let emptyArray = '';
if(storage.length > 0) {
for(let i = 0; i < storage.length; i++) {
let idNumberJoke = storage[i].id;
emptyArray +=
`<li><input type="checkbox" id='${idNumberJoke}'/> User title: ${storage[i].joke}</li>`;
listOfFavorites.innerHTML = emptyArray;
}
} else {
return false;
}
}
// fetch data from api
function getData() {
let listOfJokes = document.getElementById("list-of-jokes");
fetch('https://api.icndb.com/jokes/random/10')
.then(function(res) {
return res.json();
}).then(function(data) {
// variable is undefined because it is not initialized. Therefore at some empty single quotes
let result = '';
console.log(data.value);
data.value.forEach((joke) => {
result +=
`<li><input type="checkbox" class='inputCheckbox' id='${joke.id}'/> User title : ${joke.joke}</li>`;
listOfJokes.innerHTML = result;
});
bindCheckbox();
}).catch(function(err) {
console.log(err);
});
}
function clickedButton() {
getJokesButton.setAttribute('disabled', 'disabled');
getJokesButton.classList.add('opacity');
}
function bindCheckbox() {
let inputCheckbox = document.querySelectorAll('input[type=checkbox]');
let elems = document.getElementById('list-of-jokes').childNodes;
let favoriteList = document.getElementById('favorites');
let fav = JSON.parse(localStorage.getItem('favoList'))|| [];
if(elems.length > 0) {
inputCheckbox.forEach(function(element, index) {
inputCheckbox[index].addEventListener('change', function() {
let joke = this;
if(joke.checked && joke.parentNode.parentNode.id === 'list-of-jokes') {
joke.checked = false;
favoriteList.appendChild(joke.parentNode);
addFavorite(joke.id, joke.parentNode.innerText, fav);
}
if(joke.checked && joke.parentNode.parentNode.id === 'favorites') {
joke.checked = false;
removeFavorite(joke, index);
}
});
});
}
clickedButton();
}
function removeFavorite(favorite, index) {
let favoriteCheckBox = favorite;
let i = index;
// convert iterable object to an array, otherwise splice method would give an error.
let favoriteListItem = Array.from(favoriteCheckBox.parentNode);
favoriteListItem.splice(i, 1);
document.getElementById('list-of-jokes').appendChild(favorite.parentNode);
localStorage.setItem('favoList', JSON.stringify(favoriteListItem));
}
// store favorites in localStorage
function addFavorite(jokeId, jokeText, fav) {
let norrisJoke = {
id: jokeId,
joke: jokeText
};
let favorites = fav;
for (let i = 0; i < favorites.length; i++) {
if(favorites[i].id !== norrisJoke.id) {
favorites.push(norrisJoke);
}
}
// favorites[i].id !== norrisJoke.id
// always get the object before the push method and pass it into stringify
localStorage.setItem('favoList', JSON.stringify(favorites));
}
// function which will randomly add one joke to favorite list every 5 seconds
// function need a button which allows you to turn on and off this auto add function
})();

Categories

Resources