/    Sign up×
Community /Pin to ProfileBookmark

js multiple incremental counters

Hi, as you can see from the code, I have 3 counters, one for blue, one for red, and one for yellow. I want to optimize the js code and make it less redundant. I am also going to add more color counters as well so I’d like the code to be “scalable”. Is there a more efficient way to do this?

`<!DOCTYPE html>
<!–[if lt IE 7]> <html class=”no-js lt-ie9 lt-ie8 lt-ie7″> <![endif]–>
<!–[if IE 7]> <html class=”no-js lt-ie9 lt-ie8″> <![endif]–>
<!–[if IE 8]> <html class=”no-js lt-ie9″> <![endif]–>
<!–[if gt IE 8]><!–> <html class=”no-js”> <!–<![endif]–>
<head>
<meta charset=”utf-8″>
<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>
<title></title>
<meta name=”description” content=””>
<meta name=”viewport” content=”width=device-width, initial-scale=1″>
<link rel=”stylesheet” href=””>
</head>
<body>
<!–[if lt IE 7]>
<p class=”browsehappy”>You are using an <strong>outdated</strong> browser. Please <a href=”#”>upgrade your browser</a> to improve your experience.</p>
<![endif]–>
<div>
<button id=”subtractBlue”>-</button>
<input type =”number” value=”0″ id=”inputBlue”>
<button id=”addBlue”>+</button>
<button id=”resetBlue”>R</button>
blue
</div>
<div>
<button id=”subtractRed”>-</button>
<input type =”number” value=”0″ id=”inputRed”>
<button id=”addRed”>+</button>
<button id=”resetRed”>R</button>
red
</div>
<div>
<button id=”subtractYellow”>-</button>
<input type =”number” value=”0″ id=”inputYellow”>
<button id=”addYellow”>+</button>
<button id=”resetYellow”>R</button>
yellow
</div>
<p></p>
<div>
Blue has
<input type=”number” id=”blueFinal”>
</div>
<div>
Red has
<input type=”number” id=”redFinal”>
</div>
<div>
Yellow has
<input type=”number” id=”yellowFinal”>
</div>

<script>
// blue
let btnAddBlue = document.querySelector(‘#addBlue’);
let btnSubtractBlue = document.querySelector(‘#subtractBlue’);
let btnResetBlue = document.querySelector(‘#resetBlue’);
let inputBlue = document.querySelector(‘#inputBlue’);
let blueFinal = document.querySelector(‘#blueFinal’);

btnAddBlue.addEventListener(‘click’, () => {
inputBlue.value = parseInt(inputBlue.value) + 1;
blueFinal.value = parseInt(inputBlue.value)
});

btnSubtractBlue.addEventListener(‘click’, () => {
inputBlue.value = parseInt(inputBlue.value) – 1;
blueFinal.value = parseInt(inputBlue.value)
});

btnResetBlue.addEventListener(‘click’, () => {
inputBlue.value = “0”;
blueFinal.value = parseInt(inputBlue.value)
});

// red
let btnAddRed = document.querySelector(‘#addRed’);
let btnSubtractRed = document.querySelector(‘#subtractRed’);
let btnResetRed = document.querySelector(‘#resetRed’);
let inputRed = document.querySelector(‘#inputRed’);
let redFinal = document.querySelector(‘#redFinal’);

btnAddRed.addEventListener(‘click’, () => {
inputRed.value = parseInt(inputRed.value) + 1;
redFinal.value = parseInt(inputRed.value)
});

btnSubtractRed.addEventListener(‘click’, () => {
inputRed.value = parseInt(inputRed.value) – 1;
redFinal.value = parseInt(inputRed.value)
});

btnResetRed.addEventListener(‘click’, () => {
inputRed.value = “0”;
redFinal.value = parseInt(inputRed.value)
});

// yellow Yellow
let btnAddYellow = document.querySelector(‘#addYellow’);
let btnSubtractYellow = document.querySelector(‘#subtractYellow’);
let btnResetYellow = document.querySelector(‘#resetYellow’);
let inputYellow = document.querySelector(‘#inputYellow’);
let yellowFinal = document.querySelector(‘#yellowFinal’);

btnAddYellow.addEventListener(‘click’, () => {
inputYellow.value = parseInt(inputYellow.value) + 1;
yellowFinal.value = parseInt(inputYellow.value)
});

btnSubtractYellow.addEventListener(‘click’, () => {
inputYellow.value = parseInt(inputYellow.value) – 1;
yellowFinal.value = parseInt(inputYellow.value)
});

btnResetYellow.addEventListener(‘click’, () => {
inputYellow.value = “0”;
yellowFinal.value = parseInt(inputYellow.value)
});
</script>

</body>
</html>`

to post a comment
JavaScript

2 Comments(s)

Copy linkTweet thisAlerts:
@SempervivumAug 07.2020 — Hi daveyedgar and welcome to the forum.

Try this code: &lt;div id="colcont"&gt;&lt;/div&gt;
&lt;script&gt;
const colors = ['red', 'green', 'blue', 'yellow', 'turquoise'];
const outerCont = document.getElementById('colcont');
colors.forEach((color) =&gt; {
const cont = document.createElement('div');
const subtractBtn = document.createElement('button');
subtractBtn.textContent = '-';
subtractBtn.id = 'subtract' + color;
subtractBtn.addEventListener('click', changeIt);
cont.appendChild(subtractBtn);
const input = document.createElement('input');
input.id = 'input' + color;
cont.appendChild(input);
const addBtn = document.createElement('button');
addBtn.textContent = '+';
addBtn.id = 'add' + color;
addBtn.addEventListener('click', changeIt);
cont.appendChild(addBtn);
const resetBtn = document.createElement('button');
resetBtn.textContent = '0';
resetBtn.id = 'reset' + color;
resetBtn.addEventListener('click', changeIt);
cont.appendChild(resetBtn);
content = document.createTextNode(color);
cont.appendChild(content);

<i> </i> outerCont.appendChild(cont);
<i> </i> function changeIt(event) {
<i> </i> switch (event.target.textContent) {
<i> </i> case '-':
<i> </i> if (input.value &gt; 0) input.value--;
<i> </i> break;
<i> </i> case '+':
<i> </i> input.value++;
<i> </i> break;
<i> </i> case '0':
<i> </i> input.value = 0;
<i> </i> break;
<i> </i> }
<i> </i> }
<i> </i> })
<i> </i>&lt;/script&gt;
Copy linkTweet thisAlerts:
@rpg2009Aug 07.2020 — Had a go at this as well:)

Not saying this is the way to go, but I find it is helpful to get the html in shape first. Having some helpful attribute names can make it a lot easier for targeting elements on the page.

The amended html
``<i>
</i> &lt;form id='colour-inputs'&gt;
&lt;div id='redColour'&gt;
&lt;button class='subtractColour'&gt;-&lt;/button&gt;
&lt;input type ='number' id='redValue' class='colourValue' name='red' value='0'&gt;
&lt;button class='addColour'&gt;+&lt;/button&gt;
&lt;button class='resetColour'&gt;Reset&lt;/button&gt;
&lt;label for='redValue'&gt;Red&lt;/label&gt;
&lt;/div&gt;
&lt;div id='greenColour'&gt;
&lt;button class='subtractColour'&gt;-&lt;/button&gt;
&lt;input type ='number' id='greenValue' class='colourValue' name='green' value='0'&gt;
&lt;button class='addColour'&gt;+&lt;/button&gt;
&lt;button class='resetColour'&gt;Reset&lt;/button&gt;
&lt;label for='greenValue'&gt;Green&lt;/label&gt;
&lt;/div&gt;
&lt;div id='blueColour'&gt;
&lt;button class='subtractColour'&gt;-&lt;/button&gt;
&lt;input type ='number' id='blueValue' class='colourValue' name='blue' value='0'&gt;
&lt;button class='addColour'&gt;+&lt;/button&gt;
&lt;button class='resetColour'&gt;Reset&lt;/button&gt;
&lt;label for='blueValue'&gt;Blue&lt;/label&gt;
&lt;/div&gt;
&lt;/form&gt;
&lt;!-- form outputs --&gt;
&lt;div class='colourValues'&gt;
&lt;p&gt;Red has &lt;span class='redFinalValue'&gt;0&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Green has &lt;span class='greenFinalValue'&gt;0&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Blue has &lt;span class='blueFinalValue'&gt;0&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;<i>
</i>
`</CODE>
The javascript
<CODE>
`<i>
</i>document.addEventListener('DOMContentLoaded', event =&gt; {
// names of the methods on changeColour are the same as the button classNames
const changeColour = {
subtractColour: elem =&gt; {
const newColour = parseInt(elem.value, 10) - 1
return (newColour &gt; 0) ? newColour : 0
},
addColour: elem =&gt; {
const newColour = parseInt(elem.value, 10) + 1
return (newColour &lt; 255) ? newColour : 255
},
resetColour: () =&gt; {
return 0
}
}

const colourHandler = event =&gt; {
event.preventDefault()
const elem = event.target

if (elem.nodeName &amp;&amp; elem.nodeName === 'BUTTON') {
// from the parent 'div' of the button look for the input element
const colourInput = elem.parentNode.querySelector('.colourValue')

// the 'name' attribute of the input holds the name of colour we want in our output div.
// Using a template string we can then build a query
const colourOutput = document.querySelector(
.colourValues .${colourInput.name}FinalValue)

// the className of the button should be the same as the changeColour method we want e.g. subtract, add, reset
const colourAction = elem.className

if (changeColour[colourAction]) {
// e.g. changeColour['addColour'](colourInput)
const newColour = changeColour[colourAction](colourInput)
colourInput.value = newColour
colourOutput.textContent = newColour
}
}
}

const form = document.querySelector('#colour-inputs')
// add the eventListener to the form instead and
// check which child element has been clicked in the handler
form.addEventListener('click', colourHandler)
})<i>
</i>
`</CODE>
un-commented

<CODE>
`<i>
</i>document.addEventListener('DOMContentLoaded', event =&gt; {
const changeColour = {
subtractColour: elem =&gt; {
const newColour = parseInt(elem.value, 10) - 1
return (newColour &gt; 0) ? newColour : 0
},
addColour: elem =&gt; {
const newColour = parseInt(elem.value, 10) + 1
return (newColour &lt; 255) ? newColour : 255
},
resetColour: () =&gt; 0
}

const colourHandler = event =&gt; {
event.preventDefault()
const elem = event.target

if (elem.nodeName &amp;&amp; elem.nodeName === 'BUTTON') {
const colourInput = elem.parentNode.querySelector('.colourValue')
const colourOutput = document.querySelector(
.colourValues .${colourInput.name}FinalValue)
const colourAction = elem.className

if (changeColour[colourAction]) {
const newColour = changeColour[colourAction](colourInput)
colourInput.value = newColour
colourOutput.textContent = newColour
}
}
}

const form = document.querySelector('#colour-inputs')
form.addEventListener('click', colourHandler)
})<i>
</i>
``


Where the above falls down, is you can manually enter a number into the colour input boxes and this won't be reflected in the outputs. The way around this off the top of my head would be to add an onchange or 'change' listener for those inputs. These would then change the Red has, Blue has values.
×

Success!

Help @daveyedgar spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 4.26,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,

tipper: @Samric24,
tipped: article
amount: 1000 SATS,
)...