Retrieve array of objects from local storage - javascript

Trying to make to-do list but I have difficulties with local storage. First i don't understand why does local storage returns [object Object] instead of actual text. Secondly at some point local storage becomes empty and then begins to fill in from the beginning. That's so confusing for me
function addTask() {
let addTaskButton = document.getElementById('add-task-button')
let list = document.getElementById('task-list');
let li = document.createElement('li');
let checkbox = document.createElement('input');
let taskText = document.createElement('span');
let delButton = document.createElement('button');
let btnText = document.createTextNode('Delete task');
checkbox.type = 'checkbox';
checkbox.className = 'checkbox';
taskText.innerText = document.getElementById('input-task').value;
taskText.className = 'task';
delButton.className = 'delete-btn';
delButton.addEventListener('click', deleteTask)
delButton.addEventListener('click', updateStorage)
addTaskButton.addEventListener('click', updateStorage);
delButton.appendChild(btnText);
li.appendChild(checkbox);
li.appendChild(taskText);
li.appendChild(delButton);
list.appendChild(li);
document.getElementById('input-task').value = '';
taskList.push({
text: taskText.innerText,
checked: false
});
}
let taskList = [];
function updateStorage() {
localStorage.setItem('tasks', JSON.stringify(taskList));
console.log(taskList)
}
function deleteTask () {
this.parentNode.remove();
}
document.getElementById('add-task-button').addEventListener('click', addTask);
function loadList() {
document.querySelector('ul').innerHTML = JSON.parse(localStorage.getItem('tasks')) || [];
}
window.addEventListener('load', loadList);

this way:
const
inputTask = document.querySelector('#input-task')
, addTaskBt = document.querySelector('#add-task-button')
, taskList = document.querySelector('#task-list')
, tasks = JSON.parse(localStorage.getItem('tasks') || '[]')
, savTasks =_=> localStorage.setItem('tasks',JSON.stringify(tasks))
;
tasks.forEach( newLItask )
addTaskBt.onclick =_=>
{
if (inputTask.value.trim()==='') return
let taskElm = { txt: inputTask.value.trim(), checking:false }
tasks.push( taskElm )
newLItask( taskElm )
savTasks()
inputTask.value = ''
inputTask.focus()
}
taskList.onclick = ({target}) => // event delegayion for all buttons & checkboxes
{
if (!target.matches('button.delete-btn, input[type=checkbox]')) return
let taskIndex = tasks.findIndex(task => task===target.closest('li').ref )
if (target.matches('input[type=checkbox]'))
tasks[taskIndex].checking = target.checked
else // delete
{
tasks.splice(taskIndex,1)
target.closest('li').remove()
}
savTasks()
}
function newLItask( taskElm )
{
taskList
.appendChild(Object.assign(document.createElement('li'), {ref:taskElm} ))
.innerHTML = `
<input type="checkbox" class="checkbox" ${taskElm.checking ? 'checked': ''}>
<span class="task"> ${taskElm.txt} </span>
<button class="delete-btn">Delete task</button>`
}
for testing:
#task-list {
padding : 0;
list-style-type : none;
}
#task-list li {
margin : .4em 0;
}
#task-list li > span {
display : inline-block;
width : 20em;
border-bottom : 1px solid lightsteelblue;
margin : 0 .6em 0 0;
}
#task-list input[type=checkbox]:checked + span {
text-decoration : line-through ;
text-decoration-style : wavy;
text-decoration-color : orangered;
}
<input type="text" id="input-task" placeholder="input task" size="26">
<button id="add-task-button" >add task</button>
<ul id="task-list"></ul>

I made this a comment on the original post, but I think this might qualify as the answer...
The JSON.parse gets you an object, and when you try to use that object as a string (setting the innerHTML of an element), you'll get the "[object Object]" text. What's stored in localStorage is a string already that represents your JSON. Just set the innerHTML to what comes back from your localStorage.getItem('tasks') call.

Related

How many people are from each city ? (Javascript Object)

I'm trying to list an object in the following format but I can't figure out how to enumarade the li or put them inside their own ol any help??
It looks like your post is mostly code; please add some more details.
It looks like your post is mostly code; please add some more details.
let myObj = [
{
name:"Pablo",
age:"39",
job:"retired",
city:"LA",
},
{
name:"Ernesto",
age:"20",
job:"student",
city:"LA",
},
{
name:"Katrina",
age:"25",
job:"lawyer",
city:"LA",
},
{
name:"Mario",
age:"55",
job:"doctor",
city:"Lancaster",
},
{
name:"Luigi",
age:"50",
job:"Server",
city:"Lancaster",
},
{
name:"Peach",
age:"10",
job:"street",
city:"Labrea",
}
];
let target = document.getElementById('target');
let cityName = null;
for(i=0;i<myObj.length;i++){
if (cityName == null && myObj[i].city){
target.innerHTML += `<h3 class="cityTitle">${myObj[i].city}</h3>`;
}
if (cityName && cityName != myObj[i].city){
if (cityName) {
target.innerHTML += `<h3 class="cityTitle">${myObj[i].city}</h3>`;
}
target.innerHTML += `<li>${myObj[i].name}</li>`;
} else {
target.innerHTML += `<li>${myObj[i].name}</li>`;
}
cityName = myObj[i].city;
}
.cityTitle{
border: 1px solid black;
}
h3{
margin: 0;
padding: 0px 10px;
background-color: rgb(245, 185, 185);
}
<div id="target"></div>
Expected:
LA
Pablo
Ernesto
Katrina
Lancaster
Mario
Luigi
Labrea
Peach
get unduplicated cities first, then do the loop to render.
// get unduplicated cities
const cities = [...new Set(data.map(person => person.city))];
//render html
cities.forEach(city => {
//get persons in city
const persons = data.filter(person => person.city === city);
target.innerHTML += `<h3 class="cityTitle">${city}</h3>`;
target.innerHTML += persons.map(p => `<li>${p.name}</li>`).join('');
});

Display slider when you hover over array elements and give value to the array elements

I have done the part where you have to generate the array elements when you enter them from textbox, what I struggle with now is to display a slider on hover over each array element and give the array element a value, also what I struggle with is to delete each generated array element individually, my delete function deletes the entire array on click not just the single element I click.
Here is how it should look like:
enter image description here
Here is my code so far:
let names = [];
let nameInput = document.getElementById("name");
let messageBox = document.getElementById("display");
function insert ( ) {
names.push( nameInput.value );
clearAndShow();
}
function remove()
{
var element = document.getElementById("display");
element.parentNode.removeChild(element);
}
function clearAndShow () {
let printd=""
nameInput.value = "";
messageBox.innerHTML = "";
names.forEach(function(element){
if(element != ''){
var _span = document.createElement('span');
_span.style.borderStyle = "solid"
_span.style.borderColor = "blue"
_span.style.width = '50px'
_span.style.marginLeft = "5px"
_span.appendChild(document.createTextNode(element))
messageBox.appendChild(_span)
printd +="''" + element + "''" + "," + " ";
document.getElementById("labelprint").innerHTML=(printd)
}
})
}
h3 {
color: rgb(0, 174, 255);
}
.container {
border: solid 2px;
display: block;
margin-left: 200px;
margin-right: 200px;
margin-top: 50px;
}
<div class="container">
<form>
<h1>Enter Search</h1>
<input id="name" type="text" />
<input type="button" value="Search" onclick="insert()" />
</form>
<br/>
<div onclick="remove(this)" id="display"></div>
<br/>
<label >You have Selected: </label>
<h3 id="labelprint"></h3>
</div>
I am not being rude I just got confused on how you stated your message but what I think you are saying is to do this:
var names = [];
var nameInput = document.getElementById("name");
var messageBox = document.getElementById("display");
function insert ( ) {
names.push( nameInput.value );
// add value to array val: names[names.length - 1] = PutValueHere
clearAndShow();
}
function remove(this){
document.getElementById("display").parentNode.firstChild.remove(); // If you want it to remove the last child with the id 'display' then do .parentNode.lastChild.remove()
//if you are trying to remove the last val in the array do this: names.splice(names.length-1,1) for the first do this names.splice(0,1)
}
function clearAndShow () {
var printd=""
nameInput.value = "";
messageBox.innerHTML = "";
names.forEach(function(element){
if(element != ''){
var _span = document.createElement('span');
_span.id = '_spanId'
$('_spanId').css('border-style',solid');
$('_spanId').css('border-color',blue');
$('_spanId').css('width',50+'px');
$('_spanId').css('margin-left',5+'px');
_span[0].appendChild(document.createTextNode(element))
messageBox[0].appendChild(_span)
printd += "''" + element + "'', ";
document.getElementById("labelprint").innerHTML = printd
}
})
}
I have tried to implement something that i hope it's close to what are you looking for:
HTML:
<div class="container">
<form>
<h1>Add new slider</h1>
<input id="sliderName" type="text" />
<input type="button" value="Add" onclick="insertSlider()" />
</form>
<div id="display"></div>
</div>
CSS:
h3 {
color: rgb(0, 174, 255);
}
.container {
border: solid 2px;
display: block;
margin-left: 200px;
margin-right: 200px;
margin-top: 50px;
}
JS:
let messageBox = document.getElementById("display");
function deleteFn(id) {
const element = document.getElementById(id)
if(element) element.outerHTML="";
}
function onChangeSlideId(id){
const elementSlide = document.getElementById('slider-'+id+'')
if(elementSlide){
const value = elementSlide.value
const elementSlideText = document.getElementById('slider-value-'+id+'')
elementSlideText.innerText = '('+value+')'
}
}
function insertSlider(){
const name = document.getElementById("sliderName")
const nameValue = name.value
const newLabel = document.createElement('label')
newLabel.setAttribute('for',nameValue)
newLabel.innerText = nameValue
const newSlider = document.createElement('input')
newSlider.setAttribute('id','slider-'+nameValue+'')
newSlider.setAttribute('type','range')
newSlider.setAttribute('name',nameValue)
newSlider.setAttribute('onchange','onChangeSlideId("'+nameValue+'")')
const sliderValue = document.createElement('span')
sliderValue.setAttribute('id','slider-value-'+nameValue+'')
sliderValue.innerText = '('+newSlider.value+')'
const newContainer = document.createElement('div')
newContainer.setAttribute('id',nameValue)
newContainer.setAttribute('style','display: grid')
newContainer.appendChild(newSlider)
newContainer.appendChild(newLabel)
newContainer.appendChild(sliderValue)
const newDeleteButton = document.createElement('input')
newDeleteButton.setAttribute('type', 'button')
newDeleteButton.setAttribute('value', 'Delete ' + nameValue + '')
newDeleteButton.setAttribute('onclick', 'deleteFn("'+nameValue+'")')
newContainer.appendChild(newDeleteButton)
messageBox.appendChild(newContainer)
}
You can try it by yourself in this codepen

How to update created elements?

I have this simple function that will create a paragraph.
function appendElements() {
const input = document.getElementById("myInput");
const createDiv = document.createElement("div");
createDiv.classList.add("myDiv");
const createP = document.createElement("P");
createP.classList.add("myParagraph");
createP.innerHTML = input.value;
createDiv.appendChild(createP);
const div = document.getElementById("examplediv");
div.appendChild(createDiv);
}
And another function that will sum the innerHTML of the divs, and create a div element for the result.
function calculateSum() {
let div = document.getElementsByClassName("myParagraph");
let array = new Array;
for (var i = 0; i <div.length; i++) {
array.push(div[i].innerHTML);
}
let numberedArray = array.map((i) => Number(i));
const sumArray = numberedArray.reduce(function(a, b){
return a + b;
}, 0);
const createElement = document.createElement("div");
createElement.innerHTML = sumArray;
document.getElementById("divForAvg").appendChild(createElement);
}
And the last function that will change the innerHTML of the paragraph element when clicked.
function editELement() {
const input2 = document.getElementById("myInput2")
let items = document.getElementsByClassName("myParagraph");
for(var i = 0; i < items.length; i++){
items[i].onclick = function(){
items[i].innerHTML = input2.value;
}
}
}
So basically when I create some paragraphs and execute the second function, the second function will calculate the sum of the paragraphs and create a div with the sum inside.
What I want is when I remove one of the paragraph elements or edit them, I want the previously created divs to update(recalculate the sum), I have literally no idea on how to do this.
Let's try this using event delegation. I have interpreted what I think you are looking for (note: it's exemplary, but it may give you an idea for your code) and reduced your code a bit for the example. Note the 2 different ways to create new elements (insertAdjacentHTML and Object.assign).
You can play with the code #Stackblitz.com.
document.addEventListener("click", handle);
function handle(evt) {
if (evt.target.id === "create") {
return appendInputValueElement();
}
if (evt.target.classList.contains("remove")) {
return removeThis(evt.target);
}
if (evt.target.id === "clear") {
document.querySelector("#accumulated ul").innerHTML = "";
return true;
}
}
function appendInputValueElement() {
const input = document.querySelector(".myInput");
const div = document.querySelector("#exampleDiv");
exampleDiv.insertAdjacentHTML("beforeEnd", `
<div class="myDiv">
<button class="remove">remove</button>
<span class="myParagraph">${input.value || 0}</span>
</div>
`);
calculateSum();
}
function removeThis(elem) {
elem.closest(".myDiv").remove();
calculateSum();
}
function calculateSum() {
const allParas = [...document.querySelectorAll(".myParagraph")];
const sum = allParas.reduce( (acc, val) => acc + +val.textContent, 0);
document.querySelector("#accumulated ul")
.append(Object.assign(document.createElement("li"), {textContent: sum}));
document.querySelector(".currentSum").dataset.currentSum = sum;
if (sum < 1) {
document.querySelector("#accumulated ul").innerHTML = "";
}
}
.currentSum::after {
content: ' 'attr(data-current-sum);
color: green;
font-weight: bold;
}
.myParagraph {
color: red;
}
.accSums, .currentSum, .myDiv {
margin-top: 0.3rem;
}
<div>
A number please: <input class="myInput" type="number" value="12">
<button id="create">create value</button>
</div>
<div class="currentSum" data-current-sum="0">*Current sum</div>
<p id="exampleDiv"></p>
<div id="accumulated">
<div class="accSums">*Accumulated sums</div>
<ul></ul>
<button id="clear">Clear accumulated</button>
</div>
i've changed calculateSum you can call it when you edited paragraph. If summParagraph doesn't exists then we create it.
function calculateSum() {
let div = document.getElementsByClassName("myParagraph");
let array = new Array;
for (var i = 0; i <div.length; i++) {
array.push(div[i].innerHTML);
}
let numberedArray = array.map((i) => Number(i));
const sumArray = numberedArray.reduce(function(a, b){
return a + b;
}, 0);
if (!document.getElementById("summParagraph")) {
const createElement = document.createElement("div");
createElement.setAttribute("id", "summParagraph");
document.getElementById("divForAvg").appendChild(createElement);
}
document.getElementById("summParagraph").innerHTML = summArray;
}

Remove Active Element With JavaScript

I'm trying to add some validation on something I'm working on. Basically if no input is processed, it would return a red paragraph telling you to enter something and return false. The problem I'm having is how to remove it when a valid value is processed.
var input = document.getElementById('input'),
button = document.getElementById('add')
function removeItem() {
var item = this.parentNode
var parent = item.parentNode
parent.removeChild(item)
}
button.addEventListener('click', function (e) {
if (input.value === '') {
var p = document.querySelector('p')
p.style.display = 'block'
return false
} else if (!input.value === '') {
p.style.display = ''
return true
}
var userInput = document.createTextNode(input.value)
var li = document.createElement('li')
var ul = document.getElementById('todo')
var remove = document.createElement('button')
remove.innerHTML = 'Remove'
remove.addEventListener('click', removeItem);
ul.insertBefore(li, ul.childNodes[0])
li.appendChild(userInput)
li.appendChild(remove)
})
<input type="text" id="input"/>
<button id="add">Add</button>
<p>plz add</p>
<div class="container">
<ul id="todo"></ul>
</div>
p {
display: none;
color: #f00;
}
Some issues:
You return in both if ... else cases, which (if it would work) makes the rest of the code unreachable.
The else if condition is unnecessary (since the if condition was already false), but is also wrong: ! has precedence over ===, so better use !==. Anyway, it is not needed at all.
Here is the corrected code:
var input = document.getElementById('input'),
button = document.getElementById('add');
function removeItem() {
var item = this.parentNode;
var parent = item.parentNode;
parent.removeChild(item);
}
button.addEventListener('click', function(e) {
var p = document.querySelector('p');
if (input.value.trim() === '') {
p.style.display = 'block';
return false;
}
p.style.display = '';
var remove = document.createElement('button');
remove.textContent = 'Remove';
remove.addEventListener('click', removeItem);
var li = document.createElement('li');
li.appendChild(document.createTextNode(input.value));
li.appendChild(remove);
todo.insertBefore(li, todo.childNodes[0]);
});
p {
display: none;
color: #f00;
}
<input type="text" id="input"/>
<button id="add">Add</button>
<p>plz add</p>
<div class="container">
<ul id="todo"></ul>
</div>
add an id to the error element. Then :
var el = document.getElementById('theidyouset')
el.parentNode.removeChild( el );
or you could hide it
el.className += " classhiddenwithcss";
Use CSS classes and simply add or remove the class from the class list as needed.
Also, because you are using return in both of your if/else cases, the code will stop processing and not continue on to do the rest of the work. Move the if/else to the end of the code so that return is the last thing you do.
And, use semi-colons at the end of your statements.
var input = document.getElementById('input'),
button = document.getElementById('add')
function removeItem() {
var item = this.parentNode;
var parent = item.parentNode;
parent.removeChild(item);
}
button.addEventListener('click', function(e) {
var p = document.querySelector('p')
var userInput = document.createTextNode(input.value)
var li = document.createElement('li')
var ul = document.getElementById('todo')
var remove = document.createElement('button')
remove.innerHTML = 'Remove'
remove.addEventListener('click', removeItem);
ul.insertBefore(li, ul.childNodes[0])
li.appendChild(userInput)
li.appendChild(remove)
if (input.value === '') {
p.classList.remove("hidden");
return false;
} else {
p.classList.add("hidden");
return true;
}
})
p {
color: #f00;
}
.hidden {
display:none;
}
<input type="text" id="input"/>
<button id="add">Add</button>
<p class="hidden">plz add</p>
<div class="container">
<ul id="todo"></ul>
</div>

How to beat a JavaScript condition riddle?

I am using a foreach loop in php to load data from a mysql table. I'm using the data ID's loaded from the data base and applying it to the button values.
The buttons come in two colors, green and white. The buttons represent likes for liking comments or posts.
The total existing number of likes starts at 6 (div id="total")
white buttons
If button 1 has color of white and you click it, total likes (6) will increase by 1. If you click button 1 again, total likes (7) will decrease by 1.
If button 1, button 2, and button three are clicked, total likes (6) increases by 3 ( 1 for each button). If button 1, button 2 and button 3 are clicked again, the total likes (9) will decrease by 3.
The Puzzle
Green buttons
How do I make it so, When a green button is clicked, the total (6) decrease by 1, and if the button is clicked again, it should increase by 1. Unlike white buttons.
If Green button 3, 5 and 6 are clicked, the total (6) should decease by 3. if the same buttons are clicked again, total (6) increases by 3.
Here is my code
var colorcode = "rgb(116, 204, 49)";
var buttonid = str;
var elem = document.getElementById(buttonid);
var theCSSprop = window.getComputedStyle(elem, null).getPropertyValue("background-color");
var initialtotal = parseInt(document.getElementById("total").innerHTML, 10);
var likes = new Array();
function showUser(str) {
////// 1st condition /////
if (theCSSprop == colorcode) {
if (likes[value] == 0 || !likes[value]) {
likes[value] = 1;
} else {
likes[value] = 0;
}
var sum = 0;
for (i = 0; i < likes.length; i++) {
if (likes[i] == 1) {
sum--
}
}
}
////// 2nd condition /////
else {
if (likes[str] == 0 || !likes[str]) {
likes[str] = 1;
} else {
likes[str] = 0;
}
var sum = 0;
for (i = 0; i < likes.length; i++) {
if (likes[i] == 1) {
sum++
}
}
}
var tot = initialtotal + sum;
document.getElementById("total").innerHTML = tot;
}
<div id="total" style="width:100px;padding:50px 0px; background-color:whitesmoke;text-align:center;">6 </div>
<!---------------------------------------------------------------------------------------------------------------------->
<button id="5" value="5" onclick="showUser(this.value)">LIKE </button>
<button id="346" value="346" onclick="showUser(this.value)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="128" value="128" onclick="showUser(this.value)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="687" value="687" onclick="showUser(this.value)">LIKE </button>
<button id="183" value="183" onclick="showUser(this.value)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="555" value="555" onclick="showUser(this.value)">LIKE </button>
<!---------------------------------------------------------------------------------------------------------------------->
Instead of passing this.value to showUser(), just pass this. That way, the function can get the value and the style directly, without having to call getElementById() (you're not passing the ID). Then you need to set theCSSprop inside the function, so it's the property of the current button.
To make green buttons alternate direction from increment to decrement, you need a global variable that remembers what it did the last time the function was called.
Also, you don't need to write if(likes[str] == 0 || !likes[str]), since 0 is faley. Just write if(!likes[str]).
var colorcode = "rgb(116, 204, 49)";
var likes = new Array();
var greenIncr = -1;
function showUser(elem) {
var initialtotal = parseInt(document.getElementById("total").innerHTML, 10);
////// 1st condition /////
var str = elem.value;
var theCSSprop = window.getComputedStyle(elem, null).getPropertyValue("background-color");
if (theCSSprop == colorcode) {
if (!likes[str]) {
likes[str] = 1;
} else {
likes[str] = 0;
}
var sum = 0;
for (i = 0; i < likes.length; i++) {
if (likes[i] == 1) {
sum += greenIncr;
}
}
greenIncr = -greenIncr; // revese the direction of green button
}
////// 2nd condition /////
else {
if (!likes[str]) {
likes[str] = 1;
} else {
likes[str] = 0;
}
var sum = 0;
for (i = 0; i < likes.length; i++) {
if (likes[i] == 1) {
sum++
}
}
}
var tot = initialtotal + sum;
document.getElementById("total").innerHTML = tot;
}
<div id="total" style="width:100px;padding:50px 0px; background-color:whitesmoke;text-align:center;">6 </div>
<!---------------------------------------------------------------------------------------------------------------------->
<button id="5" value="5" onclick="showUser(this)">LIKE </button>
<button id="346" value="346" onclick="showUser(this)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="128" value="128" onclick="showUser(this)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="687" value="687" onclick="showUser(this)">LIKE </button>
<button id="183" value="183" onclick="showUser(this)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="555" value="555" onclick="showUser(this)">LIKE </button>
<!---------------------------------------------------------------------------------------------------------------------->
First naive implementation can look like this
class Counter {
constructor(initial) {
this.initial = initial
this.white = [false, false, false]
this.green = [false, false, false]
}
changeGreen(index) {
this.green[index] = !this.green[index]
}
changeWhite(index) {
this.white[index] = !this.white[index]
}
get total() {
return this.initial + this.white.reduce((total, current) => total + current, 0) + this.green.reduce((total, current) => total - current, 0)
}
}
let counter = new Counter(6)
const render = counter => {
document.querySelector('#total').innerHTML = counter.total
}
render(counter)
;['#first', '#second', '#third'].map((selector, index) => {
document.querySelector(selector).addEventListener('click', e => {
e.target.classList.toggle('pressed')
counter.changeWhite(index)
render(counter)
})
})
;['#fourth', '#fifth', '#sixth'].map((selector, index) => {
document.querySelector(selector).addEventListener('click', e => {
e.target.classList.toggle('pressed')
counter.changeGreen(index)
render(counter)
})
})
.green {
background: #00aa00
}
.pressed {
border-style: inset
}
<div id="total">0</div>
<p>
<button id="first">First</button>
<button id="second">Second</button>
<button id="third">Third</button>
<button id="fourth" class="green">Fourth</button>
<button id="fifth" class="green">Fifth</button>
<button id="sixth" class="green">Sixth</button>
</p>
But after all I've finished with something like
class Counter {
constructor(initial, strategy) {
this.initial = initial;
this.elements = [];
this.strategy = typeof strategy === 'function' ? strategy : () => {}
}
addElement(content, type, next) {
const element = {
content: content,
type: type,
state: false
};
this.elements.push(element);
return next(element, this.elements.length - 1);
}
toggleElementState(index) {
this.elements[index].state = !this.elements[index].state
}
get total() {
return this.strategy(this.initial, this.elements)
}
}
const initialize = () => {
Counter.WHITE = Symbol('white');
Counter.GREEN = Symbol('green');
const counter = new Counter(6, (initial, buttons) => {
return initial +
buttons.filter(button => button.type === Counter.WHITE).reduce((total, current) => total + Number(current.state), 0) +
buttons.filter(button => button.type === Counter.GREEN).reduce((total, current) => total - Number(current.state), 0)
});
const render = counter => {
document.querySelector('#total').innerHTML = counter.total
};
const createButton = (element, index) => {
const button = document.createElement('button');
button.setAttribute('data-id', index);
button.classList.add(element.type === Counter.GREEN ? 'green' : 'none');
button.textContent = element.content;
document.querySelector('#buttons').appendChild(button)
};
const addButton = (type, ...selectors) => {
selectors.forEach(selector => counter.addElement(selector, type, createButton));
};
render(counter);
addButton(Counter.WHITE, '#first', '#second', '#third');
addButton(Counter.GREEN, '#fourth', '#fifth', '#sixth');
addButton(Counter.WHITE, '#first', '#second', '#third');
document.querySelector('#buttons').addEventListener('click', function(e) {
e.target.classList.toggle('pressed');
counter.toggleElementState(parseInt(e.target.dataset.id));
render(counter)
})
};
document.addEventListener('DOMContentLoaded', initialize);
.green {
background: #00aa00
}
.pressed {
border-style: inset
}
<div id="total">0</div>
<p id="buttons">
</p>

Categories

Resources