JS Counter starts on scroll - javascript

I ran into a problem with my Counter on website which Im building. I made Counter and it's working perfect, the problem is that it works constantly, not when scrolling to the section where it is located. So I want just make it to start count when it comes section where he is. Hope you guys understand me, and I would be grateful to anyone who wants to help me. Here is my JavaScript code:
var pacijenti = setInterval(pacijenata, 300);
var procenat = setInterval(procenatIzlecenosti, 60);
var klinika = setInterval(klinike, 400);
let count1 = 0;
let count2 = 0;
let count3 = 0;
function pacijenata() {
count1 = count1 += 1000;
document.querySelector("#number1").innerHTML = count1 + "+";
if( count1 === 10000 ) {
clearInterval(pacijenti);
}
}
function procenatIzlecenosti() {
count2++;
document.querySelector("#number2").innerHTML = count2 + "%";
if( count2 === 70 ) {
clearInterval(procenat);
}
}
function klinike() {
count3++;
document.querySelector("#number3").innerHTML = count3;
if( count3 === 4 ) {
clearInterval(klinika);
}
}
<section id="brojac">
<div class="counterContainer">
<ul>
<li>
<i class="fas fa-hospital-user"></i>
<p id="number1" class="number">10000</p>
<p>Pacijenata</p>
</li>
<li>
<i class="fas fa-universal-access"></i>
<p id="number2" class="number">70</p>
<p>Procenat izlečenosti</p>
</li>
<li>
<i class="fas fa-clinic-medical"></i>
<p id="number3" class="number">4</p>
<p>Klinike</p>
</li>
</ul>
</div>
</section>

What you need is a way to start the counter when a certain element comes into view:
You can use this custom code for that (adapted from this answer):
const counterSection = document.getElementById("brojac");
let counterStarted = false;
const counterScrolledIntoView = () => {
const docViewTop = window.scrollTop;
const docViewBottom = docViewTop + window.height();
const counterSectionTop = counterSection.offset().top;
const counterSectionBottom = counterSection + counterSection.height();
return ((counterSectionBottom <= docViewBottom) && (counterSectionTop >= docViewTop));
}
Then you need to attach an event listener for scroll events:
document.addEventListener('scroll', () => {
const counterInView = counterScrolledIntoView();
if (!counterStarted && counterInView) {
// The element just got scrolled into view, (re)start the counter
counterStarted = true;
/*
var pacijenti = setInterval(pacijenata, 300);
var procenat = setInterval(procenatIzlecenosti, 60);
var klinika = setInterval(klinike, 400);
let count1 = 0;
let count2 = 0;
let count3 = 0;
*/
} else if (!counterInView) {
counterStarted = false;
}
})

let count1 = 0;
let count2 = 0;
let count3 = 0;
var pacijenti = setInterval(pacijenata, 300);
var procenat = setInterval(procenatIzlecenosti, 60);
var klinika = setInterval(klinike, 400);
let scrolldown = false;
document.getElementById('brojac').addEventListener('scroll', function(e) {
scrolldown = true;
if( count1 === 10000 ) { clearInterval(pacijenti); }
if( count2 === 70 ) { clearInterval(procenat); }
if( count3 === 4 ) { clearInterval(klinika); }
setTimeout(function(){ scrolldown = false; },250);
});
function pacijenata() {
if( scrolldown === true ){
count1 += 10;
document.querySelector("#number1").innerHTML = count1 + "+";
}
}
function procenatIzlecenosti() {
if(scrolldown === true){
count2 += 1;
document.querySelector("#number2").innerHTML = count2 + "%";
}
}
function klinike() {
if( scrolldown === true ){
count3 += 1;
document.querySelector("#number3").innerHTML = count3;
}
}
#brojac{
height:100px;
overflow:scroll;
}
<section id="brojac">
<div class="counterContainer">
<ul>
<li>
<i class="fas fa-hospital-user"></i>
<p id="number1" class="number">0</p>
<p>Pacijenata</p>
</li>
<li>
<i class="fas fa-universal-access"></i>
<p id="number2" class="number">0</p>
<p>Procenat izlečenosti</p>
</li>
<li>
<i class="fas fa-clinic-medical"></i>
<p id="number3" class="number">0</p>
<p>Klinike</p>
</li>
</ul>
</div>
</section>

You can use Intersection Observer API to initiate the countdown when your target element is visible or intersected in the view port .

Related

How to make value become 0 in textbox?

I am making a dice game where you roll dice. When you roll a number that number adds to your total score. But when you roll a 1 you lose your total score and it switches to the other player. You can also hold to switch player.
As it is right now it become 0 after getting a 1 the first time. My problem is that when you switch back to the original starter player the score that was there before comes back. Like it does not stay the value of 0 but only looks like it.
var swithcing = false;
var current1 = 0;
var total1 = 0;
var current2 = 0;
var total2 = 0;
function roll() {
var randomnumber = Math.floor(Math.random() * 6) + 1;
var player1score = document.querySelector('.player1total');
var player1curent = document.querySelector('.player1');
var player2score = document.querySelector('.player2total')
var player2curent = document.querySelector('.player2')
if (randomnumber == 1) {
swithcing = !swithcing;
player1score.innerHTML = 0;
player1curent.innerHTML = 0;
player2curent.innerHTML = 0;
}
if (randomnumber == 1 && swithcing == false) {
player2score.innerHTML = 0;
}
if (swithcing == true) {
current2 += randomnumber;
player2score.innerHTML = current2;
player2curent.innerHTML = randomnumber;
}
if (swithcing == false) {
current1 += randomnumber;
player1score.innerHTML = current1;
player1curent.innerHTML = randomnumber;
}
}
function hold() {
swithcing = !swithcing;
}
<h1>Player 1</h1>
<h2 class="player1"></h2>
<h3 class="player1total"></h3>
<h1>Player 2</h1>
<h2 class="player2"></h2>
<h3 class="player2total"></h3>
<input type="button" onclick="roll()" value="Roll Dice!" />
<input type="button" onclick="hold()" value="Hold!" />
I think your code should look something like this
let switching = false;
let current1 = 0;
let total1 = 0;
let current2 = 0;
let total2 = 0;
let randomnumber = 0
const player1score = document.querySelector('.player1total');
const player1current = document.querySelector('.player1');
const player2score = document.querySelector('.player2total');
const player2current = document.querySelector('.player2');
function roll() {
randomnumber = Math.floor(Math.random() * 6) + 1;
//console.log(randomnumber);
//logic for normal rolls
if(randomnumber > 1){
if(switching==true){
current2=randomnumber;//set to number rolled
total2+=randomnumber;//sum to total score
} else {
current1=randomnumber;//set to number rolled
total1+=randomnumber;//sum to total score
}
}
//logic if player loses
if (randomnumber == 1) {
//switch
switching = !switching;
//if switches to player 2
current1=0;//reset
current2=0;//reset
if(switching==true){
//console.log("Player 2 selected");
total2+=total1//total becomes player 1 previous total
total1=0;//player 1 total resets
} else {
//console.log("Player 1 selected");
total1+=total2//total becomes player 2 previous total
total2=0;//player 2 total resets
}
}
player1score.textContent = total1;
player1current.textContent = current1;
player2current.textContent = current2;
player2score.textContent = total2;
}
function hold() {
switching = !switching;
player1score.textContent = total1;
player1current.textContent = 0;
player2current.textContent = 0;
player2score.textContent = total2;
}
<h1>Player 1</h1>
<h2 class="player1"></h2>
<h3 class="player1total"></h3>
<h1>Player 2</h1>
<h2 class="player2"></h2>
<h3 class="player2total"></h3>
<input type="button" onclick="roll()" value="Roll Dice!" />
<input type="button" onclick="hold()" value="Hold!" />

Shopping Cart Update Total Function doesnt work

I am building an eCommerce store website, and I am facing an issue. The function updateCartTotal doesn't work at all. The script is also added to the bottom of the HTML body.
Thanks in advance.
HTML:
<span class="material-symbols-outlined" id="cart-icon">
shopping_cart
</span>
<div class="cart">
<h2 class="cart-title">Your Shopping Cart</h2>
<div class="cart-content">
<div class="cart-box">
<img src="/Monn-Homme/images/tie1.jpg" class="cart-image">
<div class="detail-box">
<div class="cart-product-title">
Tie
</div>
<div class="cart-price"> £10.99</div>
<input type="number" value="1" class="cart-qty">
</div>
<span class="material-symbols-outlined" id="cart-remove">
delete
</span>
</div>
</div>
<div class="total">
<div class="total-title">Total</div>
<div class="total-price">£10.99</div>
</div>
<button type="button" class="buy-btn">Buy Now</button>
<span class="material-symbols-outlined" id="close-cart">
close
</span>
</div>
</div>
Javascript:
let cartIcon = document.getElementById("cart-icon");
let cart = document.querySelector(".cart");
let CloseCart = document.querySelector("#close-cart");
cartIcon.onclick = () => {
cart.classList.add("active");
};
CloseCart.onclick = () => {
cart.classList.remove("active");
};
if (document.readyState == "loading") {
document.addEventListener("DOMContentLoaded", ready);
} else {
ready();
}
function ready() {
var removeCartButtons = document.getElementsByClassName("material-symbols-outlined");
for (var i = 0; i < removeCartButtons.length; i++) {
var button = removeCartButtons[i];
button.addEventListener("click", removeCartItem)
}
// Quantity Change //
var quantitInputs = document.getElementsByClassName("cart qty");
for (var i = 0; i < quantitInputs.length; i++) {
var input = quantitInputs[i];
input.addEventListener("change", quantityChanged);
}
}
function removeCartItem(event) {
var buttonClicked = event.target;
buttonClicked.parentElement.remove();
updateCartTotal();
}
quantityChanged = (event) => {
var input = event.target;
if (isNaN(input.value) || input.value <= 0) {
input.value = 1;
}
updateCartTotal();
}
function updateCartTotal() {
var cartContainer = document.getElementsByClassName("cart-content")[0];
var cartBox = cartContainer.getElementsByClassName("cart-box");
var total = 0
for (var i = 0; i < cartBox.length; i++) {
var cartBox = cartBox[i]
var priceElement = cartBox.getElementsByClassName("cart-price")[0]
var quantityElement = cartBox.getElementsByClassName("cart-qty")[0]
price = parseFloat(priceElement.innerText.replace("£", ""))
quantity = quantityElement.value
total = total + (price * quantity)
}
document.getElementsByClassName("total-price")[0].innerText = total
}
i am expecting the total to update as the quantity changes, and the function to work
You have the following mistakes-
There is no element with the class name cart qty.
var quantitInputs = document.getElementsByClassName("cart qty");
quantityChanged function should have a function keyword.
You are using the same name variable cartBox in updateCartTotal function which is creating confusion-
var cartBox = cartContainer.getElementsByClassName("cart-box");
for (var i = 0; i < cartBox.length; i++) {
var cartBox = cartBox[i]
}
Now, after fixing these mistakes, your code will look like the below which is working.
Note- I moved all the declarations to the top and I replaced those two methods-
getElementsByClassName() = querySelectorAll()
getElementsByClassName()[0] = querySelector()
let cartIcon = document.querySelector("#cart-icon");
let cart = document.querySelector(".cart");
let CloseCart = document.querySelector("#close-cart");
var quantitInputs = document.querySelectorAll(".cart-qty");
var removeCartButtons = document.querySelectorAll(".material-symbols-outlined");
var cartContainer = document.querySelector(".cart-content");
var cartBox = cartContainer.querySelectorAll(".cart-box");
var totalEl = document.querySelector(".total-price")
cartIcon.onclick = () => {
cart.classList.add("active");
};
CloseCart.onclick = () => {
cart.classList.remove("active");
};
if (document.readyState == "loading") {
document.addEventListener("DOMContentLoaded", ready);
} else {
ready();
}
function ready() {
for (var i = 0; i < removeCartButtons.length; i++) {
var button = removeCartButtons[i];
button.addEventListener("click", removeCartItem);
}
// Quantity Change //
for (var i = 0; i < quantitInputs.length; i++) {
var input = quantitInputs[i];
input.addEventListener("change", quantityChanged);
}
}
function removeCartItem(event) {
var buttonClicked = event.target;
buttonClicked.parentElement.remove();
updateCartTotal();
}
function quantityChanged(event) {
var input = event.target;
if (isNaN(input.value) || input.value <= 0) {
input.value = 1;
}
updateCartTotal();
};
function updateCartTotal() {
var total = 0;
for (var i = 0; i < cartBox.length; i++) {
var cartBoxEl = cartBox[i];
var priceElement = cartBoxEl.querySelector(".cart-price");
var quantityElement = cartBoxEl.querySelector(".cart-qty");
price = parseFloat(priceElement.innerText.replace("£", ""));
quantity = quantityElement.value;
total = total + price * quantity;
}
if (totalEl) {
totalEl.innerText = total;
}
}
<div>
<span class="material-symbols-outlined" id="cart-icon">
shopping_cart
</span>
<div class="cart">
<h2 class="cart-title">Your Shopping Cart</h2>
<div class="cart-content">
<div class="cart-box">
<img src="/Monn-Homme/images/tie1.jpg" class="cart-image">
<div class="detail-box">
<div class="cart-product-title">
Tie
</div>
<div class="cart-price"> £10.99</div>
<input type="number" value="1" class="cart-qty">
</div>
<span class="material-symbols-outlined" id="cart-remove">
delete
</span>
</div>
</div>
<div class="total">
<div class="total-title">Total</div>
<div class="total-price">£10.99</div>
</div>
<button type="button" class="buy-btn">Buy Now</button>
<span class="material-symbols-outlined" id="close-cart">
close
</span>
</div>
</div>

How to find/remove last text portion of innerHTML

I have a <div> element that contains both html elements and text. I want to find/remove the last or the last nth or the nth text only portion of it.
So for example
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
If I had a method to delete the last text character, the first call would delete z and the second call would delete g. Or if I had a method to find the 4th character, it would return d.
It sounds like you only care about the text nodes, so probably something like this so you can just delete the nth character:
var div = document.getElementById("foo");
const getTextNodes = (el, nodes) => {
nodes = nodes || [];
for (var i = 0; i < el.childNodes.length; i++) {
var curNode = el.childNodes[i];
if (curNode.nodeName === "#text") {
if (curNode.textContent.trim().length) {
nodes.push(curNode);
}
} else {
getTextNodes(curNode, nodes);
}
}
return nodes;
}
console.log(getTextNodes(div).map((el) => el.textContent));
const deleteNthCharacter = (el, n) => {
n--; // since we want to be "1 indexed"
const nodes = getTextNodes(el);
let len = 0;
for (let i = 0; i < nodes.length; i++) {
const curNode = nodes[i];
if (len + curNode.textContent.length > n) {
curNode.textContent = curNode.textContent.substring(0, n - len) + curNode.textContent.substring(n + 1 - len);
break;
} else {
len += curNode.textContent.length;
}
}
}
deleteNthCharacter(div, 2);
deleteNthCharacter(div, 7);
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
If I understood your question correctly this should do the trick:
function deleteLastChar(targetId){
const target = document.getElementById(targetId);
let lastWithText = -1;
//find last child that has text set
target.childNodes.forEach((child, iter) => {
if(child.innerText != undefined && child.innerText.length > 0){
lastWithText = iter;
}
});
// exit if no valid text node was found
if(lastWithText === -1)
return;
const lastNode = target.childNodes[lastWithText];
lastNode.innerText = lastNode.innerText.slice(0, -1);
}
deleteLastChar("foo")
deleteLastChar("foo")
deleteLastChar("foo")
deleteLastChar("foo")
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
If I understand the question this is probably what you're looking for
let x = document.getElementById('foo').children;
function erase() {
for (let i = x.length - 1; i >=0; i--) {
if(x[i].textContent.length > 0) {
const textC = x[i].textContent;
x[i].textContent = textC.substring(0, textC.length - 1);
return;
}
}
}
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
<button onclick="erase()">Erase</button>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="foo">
<span id="bar">abcdefg</span><br>
<span id="baz">z</span><br><br>
<div id="result"></div>
<div id="result2"></div>
</div>
<script type="text/javascript">
var s = function(x){
return document.querySelector(x)
}
log = console.log;
var span1 = s("#bar")
var span2 = s("#baz")
var result = s("#result")
var result2 = s("#result2")
var res = span1.innerText.charAt(4)
// with the charAt method
result.innerText = " Result is : " +res+"\n\n"
// with regular Expression
var reg = /e/
result2.innerText = " Result2 is : " +span1.innerText.match(reg)
</script>
</body>
</html>

JavaScript not further executed once a button is disabled

I am using next and prev buttons so one question will be shown at a time, however, once next or prev buttons are disabled, the other button doesn't work anymore either. Here's my code:
var showing = [1, 0, 0, 0];
var questions = ['q0', 'q1', 'q2', 'q3'];
function next() {
var qElems = [];
for (var i = 0; i < questions.length; i++) {
qElems.push(document.getElementById(questions[i]));
}
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == showing.length - 1) {
document.getElementById("next").disabled = true;
} else {
console.log(i);
qElems[i + 1].style.display = 'block';
qElems[i].style.display = 'none';
showing[i + 1] = 1;
}
break;
}
}
}
function prev() {
var qElems = [];
for (var i = 0; i < questions.length; i++) {
qElems.push(document.getElementById(questions[i]));
}
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == showing.length - 4) {
document.getElementById("prev").disabled = true;
} else {
qElems[i - 1].style.display = 'block';
qElems[i].style.display = 'none';
showing[i - 1] = 1;
}
break;
}
}
}
I think you want this simplified script
I had to guess the HTML, but there is only one function.
window.addEventListener("load", function() {
let showing = 0;
const questions = document.querySelectorAll(".q");
questions[showing].style.display = "block";
const next = document.getElementById("next");
const prev = document.getElementById("prev");
document.getElementById("nav").addEventListener("click", function(e) {
var but = e.target, dir;
if (but.id === "prev") dir = -1;
else if (but.id === "next") dir = 1;
else return; // not a button
questions[showing].style.display = "none"; // hide current
showing += dir; // up or down
next.disabled = showing === questions.length-1;
if (showing <= 0) showing = 0;
prev.disabled = showing === 0
questions[showing].style.display = "block";
})
})
.q { display:none }
<div class="q" id="q0">Question 0</div>
<hr/>
<div class="q" id="q1">Question 1</div>
<hr/>
<div class="q" id="q2">Question 2</div>
<hr/>
<div class="q" id="q3">Question 3</div>
<hr/>
<div id="nav">
<button type="button" id="prev" disabled>Prev</button>
<button type="button" id="next">Next</button>
</div>
Since this is a quiet interesting java script task, Im doing my own solution.
Hope this matches the requirement.
I have created 4 divs of which first one is only displayed at first. Remaining divs are placed hidden. On clicking next, the divs are displayed according to index. Once the last and first indexes are interpreted, the respective next and previous buttons are enabled and disabled.
var showing = [1, 0, 0, 0];
var questions = ['q0', 'q1', 'q2', 'q3'];
var qElems = [];
function initialize() {
for (var i = 0; i < questions.length; i++) {
qElems.push(document.getElementById(questions[i]));
}
}
function updatevisibilitystatus(showindex, hideindex) {
qElems[showindex].style.display = 'block';
qElems[hideindex].style.display = 'none';
showing[showindex] = 1;
}
function next() {
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == showing.length - 2) {
document.getElementById("next").disabled = true;
}
updatevisibilitystatus(i + 1, i);
document.getElementById("prev").disabled = false;
break;
}
}
}
function prev() {
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == 1) {
document.getElementById("prev").disabled = true;
}
updatevisibilitystatus(i - 1, i);
document.getElementById("next").disabled = false;
break;
}
}
}
<body onload="initialize()">
<div id="q0" style="display: block;">Q0</div>
<div id="q1" style="display: none;">Q1</div>
<div id="q2" style="display: none;">Q2</div>
<div id="q3" style="display: none;">Q3</div>
<button id="prev" disabled onclick="prev()">Prev</button>
<button id="next" onclick="next()">Next</button>
</body>

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