Javascript counter for big and small numbers - javascript

I have been working on a counter for a webpage and I had been stuck with this function that I can't solve.
I have a counter for 4 divs and since two of them are small numbers and the other two are big numbers the first ones run soo fast that I can't see them to the function.
Someone knows how to set the js function so that they can run at a different speed, and finish at the same time?
let section_counter = document.querySelector('#section_counter');
let counters = document.querySelectorAll('.counter-item .counter');
// Scroll Animation
let CounterObserver = new IntersectionObserver(
(entries, observer) => {
let [entry] = entries;
if (!entry.isIntersecting) return;
let speed = 1000;
counters.forEach((counter, index) => {
function UpdateCounter() {
const targetNumber = +counter.dataset.target;
const initialNumber = +counter.innerText;
const incPerCount = targetNumber / speed;
if (initialNumber < targetNumber) {
counter.innerText = Math.ceil(initialNumber + incPerCount);
setTimeout(UpdateCounter, 50);
}
}
UpdateCounter();
if (counter.parentElement.style.animation) {
counter.parentElement.style.animation = '';
} else {
counter.parentElement.style.animation = `slide-up 0.3s ease forwards ${
index / counters.length + 0.5
}s`;
}
});
observer.unobserve(section_counter);
},
{
root: null,
threshold: window.innerWidth > 768 ? 0.4 : 0.3,
}
);
CounterObserver.observe(section_counter);
<section id="section_counter">
<div class="container">
<h1 class="section-heading">For every set, you purchase of our sustainable wear, you are helping the world save: </h1>
</div>
<div class="container">
<div class="counter-grid">
<div class="counter-item">
<h1 class="counter" data-target="15">0</h1>
<h2 class="counter-heading">Plastic bottles</h2>
<div class="counter-text">Which takes up to 150 years to decompose</div>
</div>
<div class="counter-item">
<h1 class="counter" data-target="22">0</h1>
<h2 class="counter-heading">KW of energy</h2>
<div class="counter-text">Equivalent to 1-day household consumption</div>
</div>
<div class="counter-item">
<h1 class="counter" data-target="5900">0</h1>
<h2 class="counter-heading">Liters of water</h2>
<div class="counter-text">Equivalent to the daily consumption of 16 persons (Mexico average)</div>
</div>
<div class="counter-item">
<h1 class="counter" data-target="9000">0</h1>
<h2 class="counter-heading">Grams of Co2 emissions</h2>
<div class="counter-text">Equivalent to a 90 km car consumption</div>
</div>
</div>
</div>
</section>

Try this solution with using additional attribute data-count. The logic is a simple: we store the calculation with the decimal value in data-count and put only an integer inside, remove data-count at the end.
let section_counter = document.querySelector('#section_counter');
let counters = document.querySelectorAll('.counter-item .counter');
// Scroll Animation
let CounterObserver = new IntersectionObserver(
(entries, observer) => {
let [entry] = entries;
if (!entry.isIntersecting) return;
let speed = 1000;
counters.forEach((counter, index) => {
const targetNumber = +counter.dataset.target;
// Find the unit for one counter step
const count = targetNumber / speed;
// Set data attribute for accurate calculation with decimal
counter.setAttribute('data-count', 0);
function UpdateCounter() {
const initialNumber = +counter.innerText;
// Get decimal number to calculate
const countNumber = +counter.dataset.count;
// Getting an integer value with Math.floor()
const integer = Math.floor(countNumber);
if (initialNumber < targetNumber) {
// Set decimal number / toFixed() with speed length, to increase accuracy
counter.setAttribute('data-count', (countNumber + count).toFixed(`${speed}`.length));
// Set integer number
counter.innerText = integer;
setTimeout(UpdateCounter, 50);
} else {
// remove additional data attribute
counter.removeAttribute('data-count');
}
}
UpdateCounter();
if (counter.parentElement.style.animation) {
counter.parentElement.style.animation = '';
} else {
counter.parentElement.style.animation = `slide-up 0.3s ease forwards ${
index / counters.length + 0.5
}s`;
}
});
observer.unobserve(section_counter);
}, {
root: null,
threshold: window.innerWidth > 768 ? 0.4 : 0.3,
}
);
CounterObserver.observe(section_counter);
<section id="section_counter">
<div class="container">
<h1 class="section-heading">
For every set, you purchase of our sustainable wear, you are helping the world save:
</h1>
</div>
<div class="container">
<div class="counter-grid">
<div class="counter-item">
<h1 class="counter" data-target="15">0</h1>
<h2 class="counter-heading">Plastic bottles</h2>
<div class="counter-text">Which takes up to 150 years to decompose</div>
</div>
<div class="counter-item">
<h1 class="counter" data-target="22">0</h1>
<h2 class="counter-heading">KW of energy</h2>
<div class="counter-text">Equivalent to 1-day household consumption</div>
</div>
<div class="counter-item">
<h1 class="counter" data-target="5900">0</h1>
<h2 class="counter-heading">Liters of water</h2>
<div class="counter-text">
Equivalent to the daily consumption of 16 persons (Mexico average)
</div>
</div>
<div class="counter-item">
<h1 class="counter" data-target="9000">0</h1>
<h2 class="counter-heading">Grams of Co2 emissions</h2>
<div class="counter-text">Equivalent to a 90 km car consumption</div>
</div>
</div>
</div>
</section>

Related

Creating a flip card with multiple faces using Javascript

I was trying to create a flipcard with multiple faces but Im not entirely sure how to make the change whenever I click the card. When I'm on the console I can see that the class was added but the face is still the same. I want it to be grey background, Name: Jane, grey background, Name: John. Thats the pattern I am trying to create. I have janeCard and johnCard at the end since I'm not 100% sure how to toggle between them.
Here is the link to my codepen if anyone wants to see. https://codepen.io/heidibonilla/pen/abyRrBg
<section class="card-area">
<div class="card">
<div class="inner-card jane" id="clicks">
<div class="front"></div>
</div>
</div>
// Card will flip on click
const flipCard = document.querySelector('.inner-card');
flipCard.addEventListener('click', function() {
flipCard.classList.toggle('is-flipped');
})
// Set a var to count the clicks
let clicks = document.getElementById('clicks');
let count = 0;
clicks.onclick = function() {
count += 1;
console.log(count);
if(count % 2 == 0) {
// show front of card
console.log('even');
} else {
// switch between john or jane
janeCard.classList.toggle('john');
console.log('odd');
console.log(janeCard)
}
}
const janeCard = document.querySelector('.jane');
const johnCard = document.querySelector('.john');
janeCard.innerHTML = `<div class="front">
</div>
<div class="back">
<div class="back-info">
<h2>Jane Doe</h2>
<p><strong>Title:</strong> Web Developer</p>
<p><strong>Email:</strong> example#example.com</p>
<p><strong>Phone:</strong> (999) 999 - 9999</p>
</div>
</div>`
johnCard.innerHTML = `<div class="back">
<div class="back-info">
<h2>John Doe</h2>
<p><strong>Title:</strong> iOS Developer</p>
<p><strong>Email:</strong> example#example.com</p>
<p><strong>Phone:</strong> (999) 999 - 9999</p>
</div>
</div>`

Automate a slider with pause and resume functions

I have a slider and I would like to automate it with pause and resume functions. I found this great snippet of code that allows me to pause and resume, however, it only allows me to pause once.
I am struggling to figure out how to make it so the user can pause as many times as they like.
here is the complete code:
$s = 1000; // slide transition speed (for sliding carousel)
$d = 5000; // duration per slide
$w = $('.slide').width(); // slide width
function IntervalTimer(callback, interval) {
var timerId, startTime, remaining = 0;
var state = 0; // 0 = idle, 1 = running, 2 = paused, 3= resumed
this.pause = function () {
if (state != 1) return;
remaining = interval - (new Date() - startTime);
window.clearInterval(timerId);
state = 2;
$('.timer').stop(true, false)
};
this.resume = function () {
if (state != 2) return;
state = 3;
window.setTimeout(this.timeoutCallback, remaining);
$('.timer').animate({"width":$w}, remaining);
$('.timer').animate({"width":0}, 0);
};
this.timeoutCallback = function () {
if (state != 3) return;
callback();
startTime = new Date();
timerId = window.setInterval(callback, interval);
state = 1;
};
startTime = new Date();
timerId = window.setInterval(callback, interval);
state = 1;
}
var starttimer = new IntervalTimer(function () {
autoSlider()
}, $d);
timer();
$('.slider-content').hover(function(ev){
starttimer.pause()
}, function(ev){
starttimer.resume()
});
function timer() {
$('.timer').animate({"width":$w}, $d);
$('.timer').animate({"width":0}, 0);
}
Any help is greatly appreciated.
UPDATE:
Here is the HTML
<div class="slider-content">
<div class="timer"></div>
<div class="slide 1">
<div class="hero-container">
<div class="header-content-container">
<h1 class="entry-title"></h1>
<hr>
<div class="flex-container">
<div class="col1"></div>
<div class="col2"></div>
</div>
<div class="post-link"></div>
</div>
</div>
</div>
<div class="slide 2">
<div class="hero-container">
<div class="header-content-container">
<h1 class="entry-title"></h1>
<hr>
<div class="flex-container">
<div class="col1"></div>
<div class="col2"></div>
</div>
<div class="post-link"></div>
</div>
</div>
</div>
<div class="slide 3">
<div class="hero-container">
<div class="header-content-container">
<h1 class="entry-title"></h1>
<hr>
<div class="flex-container">
<div class="col1"></div>
<div class="col2"></div>
</div>
<div class="post-link"></div>
</div>
</div>
</div>
<div class="slide 4">
<div class="hero-container">
<div class="header-content-container">
<h1 class="entry-title"></h1>
<hr>
<div class="flex-container">
<div class="col1"></div>
<div class="col2"></div>
</div>
<div class="post-link"></div>
</div>
</div>
</div>
</div>

How to create a proper start button on typing game using vanilla javascript

I'm trying to create a start button for my Javascript game that starts the and when the game is over resets the game. As of right now, the button I have starts the game but when it's "Game Over" the timer doesn't reset or start. The words change but not the timer or score. I tried using the reload.location and it didn't do anything.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css"> -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css">
<title>One Piece WordBeater</title>
</head>
<body>
<body class="bg-dark text-white">
<header class="bg-secondary text-center p-3 mb-5">
<h1>One Piece Word Beater</h1>
</header>
<div class="container text-center">
<!--Word & Input-->
<div class="row">
<div class="col-md-3 mx-auto">
<p class="lead">Current Level: <span class="text-info" id="levels"></span></p>
</div>
<div class="col-md-6 mx-auto">
<p class="lead">Type the Given Word Within <span class="text-success" id="seconds">5</span> Seconds. </p>
<h2 class="display-2 mb-5" id="current-word">luffy</h2>
<input type="text" class="form-control form-control-lg" placeholder="Start Typing..." id="word-input" autofocus>
<h4 class="mt-3" id="message"></h4>
<br>
<div class="btn-group">
<button type="button" class="btn btn-warning mr-5" id="start"><b>Let's Play!</b></button>
<button type="button" class="btn btn-danger" id="reset"><b>Reset Game</b></button>
</div>
</div>
<div class="col-md-3 mx-auto">
<p class="lead">High Score: <span class="text-info" id="highsocre"></span></p>
</div>
</div>
<!--Time and Columns-->
<div class="row mt-5">
<div class="col md-6">
<h3>Time left: <span id="time">0</span></h3>
</div>
<div class="col md-6">
<h3>Score: <span id="score"> 0 </span></h3>
</div>
</div>
<!--Instructions-->
<div class="row mt-5">
<div class="col md-12">
<div class="card card-body bg-secondary text-white">
<h5>Instructions</h5>
<p>Type each word in the given amount of seconds to score. To play again, just type the current word. Your score
will reset</p>
</div>
</div>
</div>
<!--Level Selector-->
<div class = "row mt-5">
<div class="col md-12">
<div class="card card-body bg-secondary text-white">
<h5>Select the Difficulty</h5>
<div class="row mt-5">
<div class="col md-12">
<div class="btn-group">
<button type="button" class="btn btn-success mr-2" id="easy">Easy</button>
<button type="button" class="btn btn-primary mr-2" id="medium">Medium</button>
<button type="button" class="btn btn-danger" id="hard">Hard</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/js/bootstrap.min.js"></script>
<script src="index.js"></script>
</body>
</html>
JavaScript:
window.addEventListener('load', init,);
//Avaible levels
const levels = {
easy: 5,
medium: 3,
hard: 2,
}
//to cchange level
const currentLevel = levels.easy;
let time = currentLevel;
let score = 0;
let isPLaying;//initalzies game...true if game is on false if game is off
/*function resetGame(){
const resetBtn = document.getElementById('reset')
resetBtn.onclick = function() {
let time = currentLevel;
let score = 0;
let isPLaying; //Show number of seconds
}
}*/
//DOM Elements
const wordInput = document.querySelector('#word-input');
const currentWord = document.querySelector('#current-word');
const scoreDisplay = document.querySelector('#score');
const timeDisplay = document.querySelector('#time');
const message = document.querySelector('#message');
const seconds = document.querySelector('#seconds');
const levelDisplay = document.querySelector('#levels');
const words = [
'luffy',
'zoro',
'shanks',
'nami',
'brook',
'chooper',
'sanji',
'franky',
'jinbe',
'carrot',
'pekoms',
'ace',
'sabo',
'robin',
'bellamy',
'crocodile',
'merry',
'yonko',
'camie',
'nefertari',
'raizo',
'momo',
'law',
'dracule',
'boa',
'buggy',
'golroger',
'bigmom',
'smoker',
'kaido'
];
//initialize Game
/*function init() {
// //Show number of seconds
seconds.innerHTML = currentLevel;
// //load a word from array
showWord(words);
// //Start Matching on word input
wordInput.addEventListener('input', startMatch);
// //Call countdown every second
setInterval(countdown, 1000);
// //Check status
setInterval(checkStatus, 50)
} */
function init() {
//start button
const startBtn = document.getElementById('start')
startBtn.onclick = function() {
//Show number of seconds
seconds.innerHTML = currentLevel;
//load a word from array
showWord(words);
//Start Matching on word input
wordInput.addEventListener('input', startMatch);
//Call countdown every second
setInterval(countdown, 1000);
//Check status
setInterval(checkStatus, 50)
}
}
//level Buttons
//Easy Mode
// document.getElementById('easy').addEventListener('click', easyMode);
// function easyMode(levels) {
// }
//Start Match
//converts words to lowercase
function startMatch() {
if(matchWords()){
isPLaying = true;
time = currentLevel + 1;
showWord(words);
wordInput.value='';
score++;
}
//if score negative -1 display 0
if(score === -1){
scoreDisplay.innerHTML = 0;
}else{
scoreDisplay.innerHTML = score;
}
}
//Match Current Word to word imput
function matchWords(){
if(wordInput.value.toLowerCase() === currentWord.innerHTML) {
message.innerHTML = 'Correct!!!';
return true;
} else {
message.innerHTML = '';
return false;
}
}
//Pick & Show random word
function showWord(words) {
//Generate random array index
const randIndex = Math.floor(Math.random() * words.length);
//Output random word
currentWord.innerHTML = words[randIndex];
}
//Countdown Timer
function countdown() {
//Make sure time is not run out
if(time > 0) {
//Decrease time
time--;
}else if(time === 0) {
//Game Over
isPLaying = false;
}
//Show time
timeDisplay.innerHTML = time;
}
//Check game Status
function checkStatus() {
if(!isPLaying && time === 0){
message.innerHTML = 'Game Over!!';
score = -1;
}
}
Your timer doesn't reset because you didn't stop it with the clearInterval function. The score doesn't reset because you didn't change it in HTML.
First Of all to understang what is wrong with your timer add this code inside your checkStatus() function and open the developer console of your navigator. You will see that your timer continue even if the game is over.
console.log("The game is over but the timer continue...");
OK now, to fix you issue: add this to your code to keep a reference and use it later:
let countDownInterval;
let checkStatusCountDown;
modify your init() function with:
countDownInterval = setInterval(countdown, 1000);
checkStatusCountDown = setInterval(checkStatus, 50);
Now when the game is over we will clear the time interval and reset the score:
function checkStatus() {
if(!isPLaying && time === 0){
message.innerHTML = 'Game Over!!';
score = -1;
scoreDisplay.innerHTML = 0; // reset score in html
clearInterval(checkStatusCountDown); // clear interval
clearInterval(countDownInterval); // clear interval
}
}

Calculate percent of each element

I've the following code to calculate the percentage of each element (like poll voting system):
$(document).ready(function() {
$("#percentage").click(function() {
var number, sumNumbers = 0, newPercent;
$(".item").each(function() {
number = $(this).children(".itemNum").text();
number = +number;
sumNumbers += number;
if(sumNumbers != 0) {
newPercent = (number / sumNumbers) * 100;
} else {
newPercent = 0;
}
$(this).children(".percentage").text(newPercent+"%");
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item">
<span class="itemNum">0</span> <span class="percentage"></span>
</div>
<div class="item">
<span class="itemNum">2</span> <span class="percentage"></span>
</div>
<div class="item">
<span class="itemNum">1</span> <span class="percentage"></span>
</div>
<button id="percentage">Calculate Percentage!</button>
But, the result is:
0 0%
2 100%
1 33.33333333333333%
So, how to calculate return the following result?
0 0%
2 66.66666666666667%
1 33.33333333333333%
I need these results to do a progress bar on my poll system, so, how to do this?
You need to parse the text to integer via parseInt() function.
And you need first to sum numbers and then you can calculate percentage.
For one loop question:
You can't count percentage in one loop. Explained here
$(document).ready(function() {
$("#percentage").click(function() {
var number, sumNumbers = 0, newPercent;
$(".item").each(function(){
number = $(this).children(".itemNum").text();
sumNumbers += parseInt(number);
});
$(".item").each(function() {
number = parseInt($(this).children(".itemNum").text());
if(sumNumbers != 0) {
newPercent = (number / sumNumbers) * 100;
} else {
newPercent = 0;
}
$(this).children(".percentage").text(newPercent+"%");
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item">
<span class="itemNum">0</span> <span class="percentage"></span>
</div>
<div class="item">
<span class="itemNum">2</span> <span class="percentage"></span>
</div>
<div class="item">
<span class="itemNum">1</span> <span class="percentage"></span>
</div>
<button id="percentage">Calculate Percentage!</button>

Get dollar total of all elements with class using jQuery

I have the following html:
<div class="balance">
<div class="heading">
<p class="total"><span>00</span></p>
</div>
<div class="instance withdrawal">
<h3>Random</h3>
<p>desc</p>
<p class="amount">$350.<span>00</span></p>
</div>
<div class="instance deposit">
<h3>Added in</h3>
<p>desc</p>
<p class="amount">$1,250.<span>00</span></p>
</div>
<div class="instance withdrawal">
<h3>Bill</h3>
<p>desc</p>
<p class="amount">$50.<span>00</span></p>
</div>
</div>
<!--end wallet-container left-->
How can i use jQuery to add take total deposits, subtract the withdrawals and append it to the p.total?
Try this fiddle.
Edited to take floating points into account.
JS
$(function() {
var total = 0;
// Check each instance
$('.instance').each(function() {
var
$this = $(this),
clone = $this.find('.amount').clone(),
amount = 0,
floating = 0;
// Get floating point
floating = parseFloat('0.' + clone.find('span').text());
clone.find('span').remove();
// Get integer amount
amount = parseInt(clone.text().replace(/\D+/gim, ''), 10);
if (!isNaN(amount) && amount > 0) {
if ($this.is('.deposit')) total += (amount + floating); // Deposit
else if ($this.is('.withdrawal')) total -= (amount + floating); // Withdrawal
}
});
// Format total with commas
var formatted = ('' + parseInt(total, 10)).split('').reverse().join('');
formatted = formatted.replace(/(\d{3})/gim, '$1,');
formatted = formatted.split('').reverse();
if (formatted[0] == ',') formatted.shift();
formatted = formatted.join('');
$('.total').text('$' + parseInt(formatted, 10) + '.');
var decimal = (total - parseInt(total, 10)) * 100;
$('.total').append('<span>' + decimal + '</span>')
});
Try adjusting html slightly by placing $ character before first span element containing whole number including second sibling span element containing decimal number as descendants of .deposit , .withdrawal elements; utilizing data-* attribute to reference object containing withdrawal , deposit, total properties; Array.prototype.reduce() ; Number() ; String.prototype.replace() for comma , character ; .each()
var res = {
deposit: 0,
withdrawal: 0,
total: 0
};
function calculate(el) {
return el.get().reduce(function(a, b) {
return Number(a.textContent.replace(/,/g, "")) + Number(b.textContent)
})
}
$(".deposit, .withdrawal").each(function(i, el) {
res[$(el).data().type] += calculate($("span", el))
})
res.total = res.deposit - res.withdrawal;
$(".total span").html(res.total);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div class="balance">
<div class="heading">
<p class="total" data-type="total"><span>00</span>
</p>
</div>
<div class="instance withdrawal" data-type="withdrawal">
<h3>Random</h3>
<p>desc</p>
<p class="amount">$<span>350</span><span>.00</span>
</p>
</div>
<div class="instance deposit" data-type="deposit">
<h3>Added in</h3>
<p>desc</p>
<p class="amount">$<span>1,250</span><span>.00</span>
</p>
</div>
<div class="instance withdrawal" data-type="withdrawal">
<h3>Bill</h3>
<p>desc</p>
<p class="amount">$<span>50</span><span>.00</span>
</p>
</div>
</div>
<!--end wallet-container left-->

Categories