React: How to totally and completely clear state - javascript

In this React Javascript Calculator, decimal points are able to be added to numbers, but only after a complete browser refresh, and not after clicking the clear button which triggers the clear() function. How can state be completely and totally reset in the clear() function so that state becomes as if a browser refresh had been done. Any help would be greatly appreciated.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './style.css';
const initState = {
text: '0',
operators:['+']
}
class JavascriptCalculator extends React.Component {
constructor(props) {
super(props);
this.state = initState;
this.display = this.display.bind(this);
this.clear = this.clear.bind(this);
this.calculate = this.calculate.bind(this);
}
display(text){
// if display is zero, remove the leading zero from the text.
if(this.state.text == 0){
this.state.text = '';
}
let regex = /[*/+-]/;
// if text is not an operator
if (!regex.test(text)){
let displayed = this.state.text
// start by adding text
displayed += text;
// disallow multiple decimal points in a number
// if attempt at more than one decimal point remove last one.
let array = displayed.split('');
let count = 0;
for (let i = 0; i < array.length; i++){
if (array[i] === '.'){
count++;
}
}
// one decimal point is allowed per operator.
// thus to allow the first decimal point,
// this.state.operators must be initialized
// to length of 1.
if(count > this.state.operators.length){
array.pop();
}
displayed = array.join('');
this.setState({ text: displayed});
}
// if text is an operator
if (regex.test(text)){
// add the text to the array
// so that repeated decimal points are prevented
let array = this.state.operators;
array.push(text);
this.setState({ operators: array});
let displayed = this.state.text
displayed += text;
this.setState({ text: displayed});
}
// if text is equals sign, run the calculate function.
if (text === '='){
let displayed = this.state.text.split('');
displayed.push('=');
console.log(displayed);
this.calculate(displayed);
}
}
calculate(displayed){
let regex = /[*/+-]/;
let text = '';
let length = displayed.length;
let operators = [];
//console.log(this.state.array);
// capture numbers longer than one digit by adding them to a string
// and adding a comma in place of the operators, so the string
// can be split into an array at the operators.
for (let i = 0; i < length; i++){
// put numbers into a string
if (displayed[i].match(/[\d.]/)) {
text+=displayed[i];
}
// add commas to string in place of operators
if (displayed[i].match(regex)){
text+=',';
// add operators to their own array
operators.push(displayed[i]);
}
if (displayed[i] === '='){
break;
}
}
//console.log(operators);
// create the numbers array
let numbers = text.split(',');
//console.log(numbers);
// initialize answer with first number
let answer = numbers[0];
let func = undefined;
// Start with second number
for (let i = 1; i < numbers.length; i++){
func = returnFunc(operators.shift());
answer = func(answer, numbers[i]);
this.setState({text: answer})
}
function returnFunc(val) {
switch (val) {
case '+':
return function sum(a,b) { return Number(a)+Number(b)};
case '-':
return function subtract(a,b) { return Number(a)-Number(b)};
case '*':
return function multiply(a,b) { return Number(a)*Number(b)};
case '/':
return function divide(a,b) { return Number(a)/Number(b)};
default:
throw new Error("Called with unknown operator " + val);
}
}
}
clear(){
this.setState({text:'0', operators:'+'});
}
render() {
return (
<div id="javascript-calculator">
<h1 id="title">Javascript Calculator</h1>
<div id="display">{this.state.text}</div>
<hr/>
<div>
<button id="clear" onClick={e => this.clear()}> clear </button>
<button id="equals" onClick={e => this.display("=")}> = </button>
<button id="zero" onClick={e => this.display("0")}> 0 </button>
<button id="one" onClick={e => this.display("1")}> 1 </button>
<button id="two" onClick={e => this.display("2")}> 2 </button>
<button id="three" onClick={e => this.display("3")}> 3 </button>
<button id="four" onClick={e => this.display("4")}> 4 </button>
<button id="five" onClick={e => this.display("5")}> 5 </button>
<button id="six" onClick={e => this.display("6")}> 6 </button>
<button id="seven" onClick={e => this.display("7")}> 7 </button>
<button id="eight" onClick={e => this.display("8")}> 8 </button>
<button id="nine" onClick={e => this.display("9")}> 9 </button>
<button id="add" onClick={e => this.display("+")}> + </button>
<button id="subtract" onClick={e => this.display("-")}> - </button>
<button id="multiply" onClick={e => this.display("*")}> * </button>
<button id="divide" onClick={e => this.display("/")}> / </button>
<button id="decimal" onClick={e => this.display(".")}> . </button>
</div>
</div>
);
}
}
ReactDOM.render(<JavascriptCalculator />, document.getElementById("app"));
index.js
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Javascript Calculator</title>
<style>
</style>
</head>
<body>
<main>
<div id="app"></app>
</main>
</body>
</html>

Create a variable containing the initial state, then use it to replace the current state when you want to clear, like the below example:
const initState = {
text: '0',
array: [],
operators:['+']
}
...
constructor(props) {
super(props);
this.state = initState;
this.display = this.display.bind(this);
this.clear = this.clear.bind(this);
this.calculate = this.calculate.bind(this);
}
...
clear(){
this.setState(initState);
}

Related

Javascript calculator stringing multiple operators

I'm working on The Odin Project curriculum at the moment, and the calculator is the final project of the foundations. I have a mostly working app, but I just can't seem to be able to chain multiple operators without having to press the equals button in between. To clarify, I should be able to do 5+5+5 etc. At the moment however, it does nothing after the first 5+5. I have been stuck on this for quite a while, and am getting frustrated.
Any help is greatly appreciated.
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Calculator</title>
</head>
<body>
<div class="calculator">
<div class="output">
<div class="previous"></div>
<div class="operator-display"></div>
<div class="current"></div>
</div>
<button class="span-two clear">Clear</button>
<button class="span-two delete">Delete</button>
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button class="operator">+</button>
<button class="number">4</button>
<button class="number">5</button>
<button class="number">6</button>
<button class="operator">-</button>
<button class="number">7</button>
<button class="number">8</button>
<button class="number">9</button>
<button class="operator">*</button>
<button class="decimal">.</button>
<button class="number">0</button>
<button class="equals">=</button>
<button class="operator">/</button>
</div>
</body>
<script src="script.js"></script>
</html>
javascript:
const numberBtns = document.querySelectorAll(".number");
const operationBtns = document.querySelectorAll(".operator");
const equalsBtn = document.querySelector(".equals");
const clearBtn = document.querySelector(".clear");
const deleteBtn = document.querySelector(".delete");
const previous = document.querySelector(".previous");
const current = document.querySelector(".current");
const operatorDisplay = document.querySelector(".operator-display");
let decimalBtn = document.querySelector(".decimal");
let firstNumber = 0;
let secondNumber = 0;
let result;
//function to clear output screen
function clearOutput(){
previous.innerText = "";
current.innerText = "";
operatorDisplay.innerText = "";
}
//calls function to clear screen on a click
clearBtn.addEventListener("click", ()=>{
clearOutput();
})
//add number to screen on click
numberBtns.forEach(button => {
button.addEventListener('click', ()=>{
current.innerText += button.innerText;
})
})
decimalBtn.addEventListener('click', ()=>{
addDecimal();
})
//when pressing an operator button, the current operand is moved to the previous operand //place
operationBtns.forEach(button =>{
button.addEventListener('click', ()=>{
if (operatorDisplay.innerText != "") {
operate();
}
else{
previous.innerText = current.innerText;
firstNumber = previous.innerText;
current.innerText = "";
operatorDisplay.innerText = button.innerText;
}
})
})
//calculates result based on chosen operator
equalsBtn.addEventListener('click', ()=>{
secondNumber = current.innerText;
operate();
//Display error message if user tries to divide by 0
if (secondNumber === "0" && operatorDisplay.innerText === "/") {
errorMessage();
}
//pressing equals button does nothing if either operand is empty
if (current.innerText != "" && previous.innerText != "") {
displayResult();
}
})
//deletes last number of the current operand on click
deleteBtn.addEventListener('click', ()=>{
current.innerText = current.innerText.slice(0, -1);
})
//displays result
function displayResult(){
clearOutput();
//rounds the result in case of a ridiculous number of decimals
current.innerText = Math.round(result * 10000) / 10000;
}
function operate(){
if (operatorDisplay.innerText === "+") {
result = parseFloat(firstNumber) + parseFloat(secondNumber);
}
if (operatorDisplay.innerText === "-") {
result = parseFloat(firstNumber) - parseFloat(secondNumber);
}
if (operatorDisplay.innerText === "*") {
result = parseFloat(firstNumber) * parseFloat(secondNumber);
}
if (operatorDisplay.innerText === "/") {
result = parseFloat(firstNumber) / parseFloat(secondNumber);
}
}
function errorMessage(){
clearOutput();
result = "Division by 0 impossible";
}
//adds decimal point
function addDecimal(){
if (!current.innerText.includes(".")) {
current.innerText += ".";
}
}

In Svelte, is there a way to undo invalid user input, without changing the state?

In Svelte, is there a way to undo invalid user input, without triggering a momentarily fake property change for state?
For example (try it online), when user types in 123a in the input box, I want to covert it to a number and assign it counter.
For that, I have to introduce a temporary and redundant change to counter (using Number.NaN below). Otherwise, counter won't change, and 123a will remain inside the input box, while I want to revert it back to 123:
<script>
let count = 0;
const handleClick = () => count++;
const handleChange = async e => {
const userValue = e.target.value;
let newValue = userValue? parseInt(userValue): 0;
if (isNaN(newValue)) newValue = count;
count = Number.NaN;
await Promise.resolve();
count = newValue;
};
</script>
Count: <button on:click={handleClick}>{count}</button>
<br />
A: <input value={count} on:input={handleChange} />
<br />
Is there a better way of doing it? Essentially, I want trigger a manual re-render for a part of my Svetle component, without changing the state.
Of course, in the event handler I could undo the change just by modifying e.target.value directly:
const handleChange = async e => {
const userValue = e.target.value;
let newValue = userValue? parseInt(userValue): 0;
if (isNaN(newValue)) newValue = count;
if (newValue == count)
e.target.value = count;
else
count = newValue;
};
But I wonder if there's a way to tell Svelte to re-render the whole <input>?
To compare, here's how I could do it in React (try it online):
function App() {
let [count, setCount] = useState(0);
const handleClick = () => setCount((count) => count + 1);
const handleChange = (e) => {
const userValue = e.target.value;
let newValue = userValue ? parseInt(userValue) : 0;
if (isNaN(newValue)) newValue = count;
setCount(newValue);
};
return (
<>
Count: <button onClick={handleClick}>{count}</button>
<br />
A: <input value={count} onInput={handleChange} />
<br />
</>
);
}
You simply need to bind count to the value of the input. REPL
<script>
let count = 0;
const handleClick = () => count++;
const handleChange = (e) => {
const userValue = e.target.value;
const newValue = userValue ? parseInt(userValue, 10) : 0;
count = isNaN(newValue) ? count : newValue;
};
</script>
Count: <button on:click={handleClick}>{count}</button>
<br />
A: <input bind:value={count} on:input={handleChange} />
<br />
Note: Remember to always pass a radix to parseInt(), it does not default to 10.

React: How to force setState()?

In this React Javascript Calculator this.setState({ array: displayed}); is supposed to update the array in state, but it doesn't. Is there a way to force it? Any help would be greatly appreciated.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './style.css';
class JavascriptCalculator extends React.Component {
constructor(props) {
super(props);
this.state = {
text: 0,
array: [],
operators:['+']
}
this.display = this.display.bind(this);
this.clear = this.clear.bind(this);
this.calculate = this.calculate.bind(this);
}
display(text){
// if display is zero, remove the leading zero from the text.
if(this.state.text == 0){
this.state.text = ''
}
let regex = /[*/+-]/;
// if text is not an operator
if (!regex.test(text)){
let displayed = this.state.text
// disallow consecutive decimal points
if (text == '.' && displayed.slice(-1) == '.'){
return;
}
// start by adding text
displayed = this.state.text += text;
// disallow multiple decimal points in a number
// if attempt at more than one decimal point remove last one.
let array = displayed.split('');
let count = 0;
for (let i = 0; i < array.length; i++){
if (array[i] == '.'){
count++;
}
}
// one decimal point is allowed per operator.
// thus to allow the first decimal point,
// this.state.operators must be initialized
// to length of 1.
if(count > this.state.operators.length){
array.pop();
}
displayed = array.join('');
this.setState({ text: displayed});
}
// if text is an operator
if (regex.test(text)){
// add the text to the array
// so that repeated decimal points are prevented
let array = this.state.operators;
array.push(text);
this.setState({ operators: array});
// add the text to the text
let displayed = this.state.text += text;
this.setState({ text: displayed});
}
// if text ends in equals sign, run the calculate function.
if (text == '='){
let displayed = this.state.text.split('');
console.log(displayed);
this.setState({ array: displayed});
//this.state.array = displayed;
this.calculate();
}
}
calculate(){
let regex = /[*/+-]/;
let text = '';
let length = this.state.array.length;
let operators = [];
//console.log(this.state.array);
// capture numbers longer than one digit by adding them to a string
// and adding a comma in place of the operators, so the string
// can be split into an array at the operators.
for (let i = 0; i < length; i++){
// put numbers into a string
if (this.state.array[i].match(/[\d.]/)) {
text+=this.state.array[i];
}
// add commas to string in place of operators
if (this.state.array[i].match(regex)){
text+=',';
// add operators to their own array
operators.push(this.state.array[i]);
}
if (this.state.array[i] == '='){
break;
}
}
//console.log(operators);
// create the numbers array
let numbers = text.split(',');
//console.log(numbers);
// initialize answer with first number
let answer = numbers[0];
let func = undefined;
// Start with second number
for (let i = 1; i < numbers.length; i++){
func = returnFunc(operators.shift());
console.log(func);
answer = func(answer, numbers[i]);
}
this.display(answer);
function returnFunc(val) {
switch (val) {
case '+':
return function sum(a,b) { return Number(a)+Number(b)};
case '-':
return function subtract(a,b) { return Number(a)-Number(b)};
case '*':
return function multiply(a,b) { return Number(a)*Number(b)};
case '/':
return function divide(a,b) { return Number(a)/Number(b)};
default:
throw new Error("Called with unknown operator " + val);
}
}
}
clear(id){
this.setState({ text: id });
this.setState({ array: [] });
this.setState({ operators: [] });
}
render() {
return (
<div id="javascript-calculator">
<h1 id="title">Javascript Calculator</h1>
<div id="display">{this.state.text}</div>
<hr/>
<div>
<button id="clear" onClick={e => this.clear("0")}> clear </button>
<button id="equals" onClick={e => this.display("=")}> = </button>
<button id="zero" onClick={e => this.display("0")}> 0 </button>
<button id="one" onClick={e => this.display("1")}> 1 </button>
<button id="two" onClick={e => this.display("2")}> 2 </button>
<button id="three" onClick={e => this.display("3")}> 3 </button>
<button id="four" onClick={e => this.display("4")}> 4 </button>
<button id="five" onClick={e => this.display("5")}> 5 </button>
<button id="six" onClick={e => this.display("6")}> 6 </button>
<button id="seven" onClick={e => this.display("7")}> 7 </button>
<button id="eight" onClick={e => this.display("8")}> 8 </button>
<button id="nine" onClick={e => this.display("9")}> 9 </button>
<button id="add" onClick={e => this.display("+")}> + </button>
<button id="subtract" onClick={e => this.display("-")}> - </button>
<button id="multiply" onClick={e => this.display("*")}> * </button>
<button id="divide" onClick={e => this.display("/")}> / </button>
<button id="decimal" onClick={e => this.display(".")}> . </button>
</div>
</div>
);
}
}
ReactDOM.render(<JavascriptCalculator />, document.getElementById("app"));
index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Javascript Calculator</title>
<style>
</style>
</head>
<body>
<main>
<div id="app"></app>
</main>
</body>
</html>
setState is async. It won't work how you're using it. In your case, you should just pass the displayed array to the calculate function.

How to add attribute name and attribute value dynamically in React

I want to set value="a" depending on the condition it meets. Button has no value attribute currently. How do I write this?I want like this <button value="a"> One </button>
const buttonValues = ["a", "b"]
const addingValuesToButtons = () => {
for (var i = 0; i < buttonValues.length; i++) {
if(buttonValues[i] === "a") {
//add attribute name and value to first two buttons
}
if(buttonValues[i] === "b"){
//add attribute name and value to first three buttons
}
};
return(
<div>
<button> One </button>
<button> Two </button>
<button> Three </button>
<button> Four </button>
</div>
)
}
const buttonValues = ["a", "b"]
const addingValuesToButtons = () => {
const buttons = [];
for (var i = 0; i < buttonValues.length; i++) {
if(buttonValues[i] === "a") {
buttons.push({attr: 'foo', name: 'bar'});
}
if(buttonValues[i] === "b"){
buttons.push({attr: 'baz', name: 'bar2'})
}
};
return(
<div>
{buttons.map(button => {
return <button attr={button.attr}>{button.name}</button>;
})}
</div>
)
}
It will go like this:
<button value={this.buttonValues[0] == 'a'?this.buttonValues[0]:null}> One </button>
another netter approach is :
const buttonValues = [{value:"a",name:"One"}, {value:"b",name:"two"}]
this.buttonValues.map(value => {<button value={value.value == 'a'? value.value:null}>{value.name}</button>}) ;

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