Remove all Groups and children in a nodeJS app - javascript

i need help with my little nodeJS app. i need to create a function which will delete nested groups in a tree.
iv'e debugged my tree search recursion and it works great.
but my delete function not deleting anything.
i need to get to the parent and delete it from the array.
tree looks like that:
class Group {
constructor(name, parent) {
this.name = name;
this.parent = parent || null;
this.children = [];
this.users = new users || null;
}
}
class groups {
constructor() {
this.root = new Group('root');
}
}
working tree search function (feel free to use!)
and non functioning delete function
findGroupByName(name) {
if (!name)
return null;
return this._findGroupByNameInternal(this.root, name);
}
_findGroupByNameInternal(group, name) {
if (!group)
return null;
if (group.name === name)
return group;
for (const g of group.children) {
const result = this._findGroupByNameInternal(g, name);
if (!result)
continue;
return result;
}
}
removeByName(name) {
if (!this.children)
return;
const groupToRemove = this.findGroupByName(name);
if (groupToRemove) {
this.children = this.children.filter(g => g !== groupToRemove);
}
}
menu handler
function removeGroup(callback) { //need fixing
rl.question('Enter group name to delete: \n', (groupName) => {
let parentGroup = programdata.groups.findGroupByName(groupName);
programdata.groups.removeByName(groupName)
console.log(parentGroup);
callback()
})
}
function showGroups(callback) {
callback()
}

This isn't working for you because the group returned by _findGroupByNameInternal() isn't necessarily a child of the instance you called removeByName() on. So when you try to filter() the instance children, it may not be there — it may be a grandchild or deeper. You need to remove the group when you find it and still know the parent. There's a lot of way to do that, but here's a simple one:
class Groups {
constructor() {
this.root = new Group('root');
}
removeByName(name){
this.root.removeByName(name)
}
}
class Group {
constructor(name, parent) {
this.name = name;
this.parent = parent || null;
this.children = [];
}
removeByName(name){
// is name in children?
let index = this.children.findIndex(g => g.name === name)
if (index > -1) {
// delete it
this.children.splice(index, 1)
console.log(`removed ${name} from ${this.name}`)
} else {
// otherwise recurse on children
this.children.forEach(child => child.removeByName(name))
}
}
}
Here's a full snippet:
class Group {
constructor(name, parent) {
this.name = name;
this.parent = parent || null;
this.children = [];
}
removeByName(name){
let index = this.children.findIndex(g => g.name === name)
if (index > -1) {
this.children.splice(index, 1)
console.log(`removed ${name} from ${this.name}`)
} else {
this.children.forEach(child => child.removeByName(name))
}
}
}
class Groups {
constructor() {
this.root = new Group('root');
}
removeByName(name){
this.root.removeByName(name)
}
}
let groups = new Groups()
// Make some nested groups
for (let j=0; j < 5; j++){
let parent = groups.root
let group = new Group(`group_${j}`, parent )
parent.children.push(group)
parent = group
for (let i=0; i < 5; i++){
let group = new Group(`group_${j}_${i}`, parent )
parent.children.push(group)
}
}
// Delete the second second of group 3 (group_3_1)
groups.removeByName('group_3_1')
// Make sure group_3_1 is gone
console.log(groups.root.children[3].children.map(c => c.name))

Related

Problems when printing a circular singly linked list

I have a circular singly linked list code:
class Node{
constructor(value){
this.value = value;
this.next = null;
}
}
class LinkdeList{
constructor(){
this.first = null;
this.last = null;
}
empty(){
return this.first === null
}
insert(value){
let newest = new Node(value);
if (this.empty()) {
this.first = this.last = newest;
this.last.next = this.first;
}else{
newest.next = this.first;
this.first = newest;
this.last.next = this.first;
}
}
traverse(){
let aux = this.first;
while (aux.next != this.first) {
console.log(aux.value);
aux = aux.next;
}
}
}
let linked = new LinkdeList();
linked.insert("David");
linked.insert("John");
linked.insert("Adam")
linked.insert("Bob");
linked.traverse();
And when I tried to print the list, I just get in console 3 names:
Bob
Adam
John
And as you can see I push 4 names in my linked list. I tried to print the values of my list in the traverse method, but It didn´t work because I don´t get in console:
Bob
Adam
John
David
The loop stops one step too early. This is a good case for a do ... while loop. You should also protect it from failing when the list is empty
traverse() {
if (this.empty()) return; // <---
let aux = this.first;
do {
console.log(aux.value);
aux = aux.next;
} while (aux != this.first);
}
Some other remarks on your code:
As in a non-empty circular list it is always true that the head follows after the tail, it is actually not needed to maintain a first reference. Just keep a last reference, knowing that you can always get the head of the list via last.next.
console.log should not be used in a class method for anything else than debugging. Give your traverse method more flexibility by making it a generator. That way you leave the decision of what to do with the values to the caller of that method.
As in a circular list a node should never have a next property with a null value, don't assign null in the Node constructor. Instead give it a self-reference.
Name the empty method isEmpty as it more clearly indicates that this will not empty the list, but will return whether it is empty.
Fix a typo in the class name: LinkedList
class Node {
constructor(value) {
this.value = value;
this.next = this; // self-reference
}
}
class LinkedList {
constructor() {
this.last = null; // No need for a `first`
}
isEmpty() {
return this.last === null;
}
insert(value) {
const newest = new Node(value);
if (!this.isEmpty()) {
newest.next = this.last.next;
this.last.next = newest;
}
this.last = newest;
}
*traverse() { // Generator
if (this.isEmpty()) return; // Guard
let aux = this.last;
do {
aux = aux.next;
yield aux.value; // Don't print. Yield instead.
} while (aux != this.last);
}
}
const linked = new LinkedList();
linked.insert("David");
linked.insert("John");
linked.insert("Adam")
linked.insert("Bob");
// Caller of traverse can decide what to do: we want to print:
for (const name of linked.traverse()) console.log(name);
Your code works perfectly fine! You just need to tweak your traversal() method because the while loop breaks before it gets a chance to log the last node.
You can try something like this:
traverse(){
let aux = this.first;
while (true) {
console.log(aux.value);
aux = aux.next;
if (aux == this.first) {
break;
}
}
}
I will expand an attribute (count)
constructor() {
...
this.count = 0;
}
Calculate it when insert is called
insert(value) {
...
this.count = this.count + 1;
}
If there is an extension removal method later, remember to calculate it
remove() {
...
this.count = this.count - 1;
}
And adjust the conditional expression of traverse,
replace while (aux.next != this.first) with for (let i = this.count; i > 0; i--)
I prefer trincot's answer, my answer is aimed at a small scope of
code changes.
In practice I will design it with a similar structure(trincot's answer).
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkdeList {
constructor() {
this.count = 0;
this.first = null;
this.last = null;
}
empty() {
return this.first === null
}
insert(value) {
let newest = new Node(value);
if (this.empty()) {
this.first = this.last = newest;
this.last.next = this.first;
} else {
newest.next = this.first;
this.first = newest;
this.last.next = this.first;
}
this.count = this.count + 1;
}
traverse() {
let aux = this.first;
for (let i = this.count; i > 0; i--) {
console.log(aux.value);
aux = aux.next;
}
}
}
let linked = new LinkdeList();
linked.insert("David");
linked.insert("John");
linked.insert("Adam")
linked.insert("Bob");
linked.traverse();

(Deep?) copy Map in JavaScript [duplicate]

This question already has answers here:
Shallow-clone a Map or Set
(6 answers)
Closed 2 years ago.
How can I deep copy a map object to another map ? I'm trying to use ES6 method but this return Map(0){} empty object. My first try was send a map object to function and assign this to a new value in this class. But on next() method I'm removing one property from this map and this change map in unit test file
creatureTurnQueue.js
export default class CreatureTurnQueue {
constructor() {
this.creatureMap = new Map();
this.creatureArray = [];
this.observersArray = [];
}
initQueue(list = {}) {
this.creatureMap = Object.assign({}, list)
this.creatureMap = list //<=old method
list.forEach(val => this.creatureArray.push(val));
}
getActiveCreature() {
let [first] = this.creatureArray.filter(el => el);
return first;
}
next(list = {}) {
this.creatureMap.delete(this.creatureMap.keys().next().value);
if (this.creatureMap.size == 0) {
this.notifyObserver();
this.initQueue(list);
return true;
}
}
addObserver(_observer) {
this.observersArray.push(_observer)
}
removeObserver(_observer) {
this.observersArray.pull(_observer)
}
notifyObserver() {
this.observersArray.forEach(item => item.resetCounterAttack())
}
}
creatureTurnQueueTest.js
import Creature from "../creature.js";
import CreatureTurnQueue from "../creatureTurnQueue.js";
import Point from './../point';
export default class CreatureTurnQueueTest {
queueShoulChangeActiveCreature() {
let creatureTurnQueue = new CreatureTurnQueue();
let creture1 = new Creature("aaaa", 1, 1, 1, 1);
let creture2 = new Creature("bbbb", 1, 1, 1, 1);
let creture3 = new Creature("cccc", 1, 1, 1, 1);
let point1 = new Point(1, 0)
let point2 = new Point(2, 0)
let point3 = new Point(3, 0)
let creatureMap = new Map();
creatureMap.set(point1, creture1);
creatureMap.set(point2, creture2);
creatureMap.set(point3, creture3);
creatureTurnQueue.initQueue(creatureMap);
console.log("~ creatureMap", creatureMap) <= map have 2 elements
creatureMap.forEach(item => { <= creatureMap return 2 elements becouse this one value is removed
if (item !== creatureTurnQueue.getActiveCreature()) {
console.log("~ item", item)
console.log("~ creatureTurnQueue.getActiveCreature()", creatureTurnQueue.getActiveCreature())
throw `Exception: => Kolejka nie dziala poprawnie zwracana aktywna creatura jest inna`;
}
if (creatureTurnQueue.next(creatureMap)) {
throw `Exception: => Kolejka nie dziala poprawnie w momecie wywolania funkcji next()`;
}
});
}
}
The rest of a classes
point.js
export default class Point {
constructor(_x, _y) {
this.x = _x;
this.y = _y;
}
}
creature.js
import CreatureStatistics from "./creatureStatistics.js";
export default class Creature {
constructor(_name, _attack, _armor, _maxHp, _moveRange) {
this.stats = this.createCreature(_name, _attack, _armor, _maxHp, _moveRange);
this.stats.currentHp = this.stats.maxHp;
this.stats.wasCounterAttack = false;
}
createCreature(_name, _attack, _armor, _maxHp, _moveRange) {
return new CreatureStatistics(
_name || "Smok",
_attack || 1,
_armor || 1,
_maxHp || 100,
_moveRange || 10
);
}
setDefaultStats() {
// this.stats.wasCounterAttack == true ? this.stats.wasCounterAttack = false : this.stats.wasCounterAttack = true
this.stats.currentHp = this.stats.currentHp != undefined ? this.stats.currentHp : this.stats.maxHp;
}
// popraw counter atack
attack(_defender) {
_defender.setDefaultStats();
this.setDefaultStats();
if (_defender.isAlive()) {
_defender.stats.currentHp = this.calculateDamage(_defender);
if (_defender.isAlive() && !_defender.stats.wasCounterAttack) {
_defender.stats.wasCounterAttack = true;
this.stats.currentHp = _defender.calculateDamage(this);
}
}
}
calculateDamage(attackedCreature) {
return attackedCreature.stats.currentHp - this.stats.getAttack() + attackedCreature.stats.getArmor() > attackedCreature.stats.getMaxHp()
? attackedCreature.stats.currentHp
: attackedCreature.stats.currentHp - this.stats.getAttack() + attackedCreature.stats.getArmor();
}
isAlive() {
if (this.stats.currentHp > 0) {
return true;
}
}
getCurrentHp() {
return this.stats.currentHp;
}
resetCounterAttack() {
this.stats.wasCounterAttack = false;
}
canCounterAttack() {
return !this.stats.wasCounterAttack
}
}
creatureStatistics.js
export default class CreatureStatistics {
constructor(_name, _attack, _armor, _maxHp, _moveRange) {
this.name = _name;
this.attack = _attack;
this.armor = _armor;
this.maxHp = _maxHp;
this.moveRange = _moveRange;
}
getName() {
return this.name;
}
getAttack() {
return this.attack;
}
getArmor() {
return this.armor;
}
getMaxHp() {
return this.maxHp;
}
getMoveRange() {
return this.moveRange;
}
}
The map was in fact a reference of the creatureMap from unit test script. Modifying the map inside your class will modify the creatureMap in unit test. You can try to create a new Map and copy over all values:
// Start class CreateTurnQueue
initQueue(list = {}) {
const newMap = new Map();
// Both Object and Map has entries method although the order is different
const iterator = list.entries();
for(const item of iterator) {
const [point, creature] = item;
newMap.set(point, creature);
this.creatureArray.push(creature);
}
this.creatureMap = newMap;
}
// End class CreateTurnQueue
Now you don't have a reference to the creatureMap from the unit test script and modify this.creatureMap will not affect the one you passed to the initQueue method as argument.

Javascript: Add player to a specific object in an array

I'm making an application where a user can create a team and add players to it, to track team stats.
In my code, I have an array of teams, a function to create a team and a function to create a player.
I want createNewPlayer() to accept a team variable, so it adds the player to the wright team.
Now, the function returns the "Team does not exist", while I created a team with that exact name before running the function.
Any idea how to fix this problem?
const Teams = []
// Team Class
class Team {
constructor(name, players) {
this.name = name;
this.players = [];
}
}
// Player class
class Player {
constructor(name, lastName, team, goal, assist, yellowCard, redCard, minPlayed) {
this.name = name;
this.lastName = lastName;
this.team = team;
this.goal = 0;
this.assist = 0;
this.yellowCard = 0;
this.redCard = 0;
this.minPlayed = 0;
}
}
// Create new team
const createNewTeam = (name) => {
if (typeof name === "string") {
let newTeam = new Team(name);
Teams.push(newTeam);
} else {
console.log("Something went wrong.");
}
}
//Create new player
const createNewPlayer = (name, lastName, team) => {
let newPlayer = new Player(name, lastName, team);
for (i = 0; i < Teams.length; i++) {
if (Teams[i].name === team) {
Teams[i].players.push(newPlayer);
} else {
console.log("Team does not exist!")
}
}
}
You loop over all the teams, and in every iteration in which the team name does not match, you log the error.
You should try something like this:
let teamFound = false;
for (i = 0; i < Teams.length; i++) {
if (Teams[i].name === team) {
Teams[i].players.push(newPlayer);
teamFound = true;
break;
}
}
if (!teamFound) {
console.log("Team does not exist!")
}
I think you have to check for Teams[i].name == team.name instead.
I would try something like this:
const createNewPlayer = (name, lastName, teamName) => {
let newPlayer = new Player(name, lastName, teamName);
let team = Teams.find((Team) => Team.name === teamName)
if(team !== undefined) {
team.players.push
} else {
console.log("Team does not exist!")
}
return newPlayer
}

given an array representing a hierachy, output data into a tree form in JS

Given a data file which has an array representing a hierarchy. Create a tree data structure by writing a script in Javascript. Output the data in tree form:
Data file:
["transportation.cars.Mazda",
"transportation.cars.Honda",
"transportation.cars.Toyota",
"transportation.train.lightRail",
"transportation.train.rapidTransit",
"transportation.waterVehicle.ferry",
"transportation.waterVehicle.boats"
...]
Output in tree form:
root
transportation
cars
Mazda
Honda
Toyota
train
lightRail
rapidTransit
waterVehicle
ferry
boats
My attempt:
var root = new Node('root');
var arr = ["transportation.cars.Mazda",
"transportation.cars.Honda",
"transportation.cars.Toyota",
"transportation.train.lightRail",
"transportation.train.rapidTransit",
"transportation.waterVehicle.ferry",
"transportation.waterVehicle.boats"
]
for(var i of arr){
var res=i.split(".");
root.addChild(new Node(res[0]));
res[0].addChild(new Node(res[1]));
res[1].addChild(new Node(res[2]));
}
this.addChild = function(node) {
node.setParentNode(this);
this.children[this.children.length] = node;
}
console.log(root);
I am trying to create a tree structure using JavaScript, but it does not has the same function as in Java (i.e. it does not have class method unless using Typescript. )
You can use something similar to a trie tree. The way you add a node would have to be much more specific. But it's possible with something like this.
function Node(word)
{
this.value = word;
this.children = {};
}
function AddDotChain(chain)
{
let arr = chain.split('.');
let currentNode = this;
function recurse(currentIndex)
{
if(currentIndex === arr.length)
{
return;
}
let currentWord = arr[currentIndex];
if(currentNode.children[currentWord])
{
currentNode = currentNode[currentWord];
return recurse(currentIndex + 1);
}
let child = new Node(currentWord);
currentNode.children[currentWord] = child;
currentNode = child;
return recurse(currentIndex + 1);
}
}
Where you just slap the entire chain in there without splitting it. There's probably a flaw in my logic somewhere but the overall idea should work. This can also be done iteritavely if you wanna reduce the overhead of recursion. Forgive the messiness, Tried to type this as fast as possible.
Here's a sloppy sloppy implementation on repl.it.
You can do it, with a data structure as Tree, you only need loop over the array of string that contains the data and split them by dot and then add each item to the tree instance that will be created when you execute the function that take your array and output as a Tree data structure.
this code can help you
var arr = ["transportation.cars.Mazda",
"transportation.cars.Honda",
"transportation.cars.Toyota",
"transportation.train.lightRail",
"transportation.train.rapidTransit",
"transportation.waterVehicle.ferry",
"transportation.waterVehicle.boats"
];
function Node(data) {
this.data = data;
this.children = [];
}
function Tree(data) {
this.root = null;
}
Tree.prototype.contains = function(data) {
return this.find(data) ? true : false;
}
Tree.prototype.add = function(data, node) {
const newNode = new Node(data);
if (!this.root) {
this.root = newNode;
return;
}
const parent = node ? this.find(node) : null;
if (parent) {
if (!this.contains(data)) {
parent.children.push(newNode);
}
}
}
Tree.prototype.find = function(data) {
if (this.root) {
const queue = [this.root];
while(queue.length) {
const node = queue.shift();
if (node && node.data === data) {
return node;
}
for(var i = 0; i < node.children.length; i++) {
const child = node.children[i];
queue.push(child);
}
}
}
return null;
}
function createTreeOfTransportation(arr) {
const tree = new Tree();
for(var i = 0; i < arr.length; i++) {
const element = arr[i];
const nodes = element.split('.');
for (var j = 0; j < nodes.length; j++) {
const currentNode = nodes[j];
const parent = nodes[j-1];
console.log(j, parent);
tree.add(currentNode, parent);
}
}
return tree;
}
console.log(createTreeOfTransportation(arr));

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