Creating Javascript countdown from currentvalue to targetvalue and change numbers every sec - javascript

currentValue = 708295;
targetValue = 0;
function count() {
if (currentValue > targetValue) {
currentValue -= 1
} else if (currentValue < targetValue) {
currentValue += 1
}
document.getElementById('timeTo').innerHTML =
'Total wordcount:'+ currentValue.toString();
changeTime = 1000;
if (Math.abs(currentValue - targetValue) <0) {
changeTime = 1000 - Math.abs(currentValue - targetValue);
}
setTimeout(count,changeTime/1);
}
count()
<h1 id="timeTo">Starting</h1>
any help will be very useful, i m trying to learn javascricpt and i want to create count down.
I want number to go down every sec but so far i have created the function to count the number but its counting too fast
ANy help or any suggestions
Thanks

setTimeout second argument is miliseconds value, it should be set to 1000 if you want to tick every second.

Related

While loop not stoping with random number

i'm trying to generate random number between 0 and 10, but loop is not stops when it came to 10
function testNumber () {
let i = (Math.floor(Math.random() * 10)+1)
while (i < 10) {
setInterval(() => {
document.write("Random number: " + (Math.floor(Math.random() * 10)+1)
)},1000)
return i;
}
}
function test() {
testNumber();
}
I'm not sure I understood your question, but if I did, you want to keep generating random numbers less or equal to 10, until you get 10 and show them in HTML. This is the solution for that:
HTML:
<div class="num"> </div>
JS:
const num = document.querySelector('.num');
function testNumber () {
let i = (Math.floor(Math.random() * 11)
while (i !== 10) {
num.innerHTML = `${num.innerHTML}Random number: ${i}<br>`
i = (Math.floor(Math.random() * 11)
}
}
If you want to "stop generating random numbers when you get 10", you'll probably want something like this:
function testNumber() {
let counter = 0
while (counter < 10) {
setInterval(() => {
document.write("Random number: " + (Math.floor(Math.random() * 11))
)},1000)
counter++;
}
}
testNumber();
Your loop condition is currently your random number, that's why it will run until the number is 10 by chance. You need to initialize a separate counter variable which gets incremented in each iteration of your loop.
Also your current calculation Math.floor(Math.random() * 10) + 1 would only return numbers from 1 to 10 (excluding 0).
And read about the setInterval function. I'm not sure if that's what you actually want to achieve.
I think you never change i in loop.
this works:
function testNumber () {
let i=(Math.floor(Math.random() * 10)+1)
const interval=
setInterval( () => {
i=(Math.floor(Math.random() * 10)+1)
document.write("Random number: " +i.toString())
if(i==10) clearInterval(interval)},1000)
}
function test () {
testNumber()
}
test()
clearInterval(interval) allows you to exit interval.

Increment value in time

I am looking to increment the value of "time" with 0.01 each 10 miliseconds until it gets to the desired value. Right now it just increases it instantly to the conditioned value.
var time = 0;
function animate() {
decreaseIncrement = -0.78;
increaseIncrement = 0.78;
if (
(document.getElementById("but5").onclick = function () {
if (time < increaseIncrement) {
do {
time += 0.01;
} while (time < increaseIncrement);
}
})
)
if (
(document.getElementById("but3").onclick = function () {
if (decreaseIncrement < time) {
do {
time -= 0.01;
} while (decreaseIncrement < time);
}
})
)
increaseIncrement = time + increaseIncrement;
decreaseIncrement = time + decreaseIncrement;
}
https://jsfiddle.net/2epqg1wc/1/
You can solve that problem using setInterval which repeatedly runs a task every x milliseconds until you cancel it. Below code reduces the value to 0 in 0.01 steps with a step performed every 10 milliseconds.
var value = 1.0;
var decrement = 0.01;
function decreaseAnimation() {
var interval = setInterval(() => {
value -= decrement;
console.log(value);
if (value <= 0) {
clearInterval(interval);
}
}, 10);
}
decreaseAnimation();
You have 3 options:
requestAnimationFrame (rAF)
setTimeout/setInterval (sTo)
messageChannel
The first 2 options are more straightforward but they will lack the precision, because rAF fires every 17 milliseconds (assuming 60Hz) and sTO will fire at most 4ms after 4 successive recursions. Usually rAF is preferred over sTo because of better reliability in timing of firing these callbacks. Use sTO as a fallback if rAF is not supported.
Here is an implementation from a library for similar purposes:
var rafx = require("rafx");
rafx.async({ //create a ledger object to store values
curr_time:0,
desired:Math.random(),
frames:0
}).animate(function(obj){
//obj is the ledger above
//increment obj.frames here if you want to
return obj;
},).until(function(obj){
obj.frames++;
obj.curr_time = obj.frames * 17 / 10 * 0.01;
return obj.curr_time >= obj.desired;
}).then(function(obj){
console.log("sequence ended with values:" + JSON.stringify(obj));
});
You can copy paste the code above here and test it.
The last option uses MessageChannel to post message between ports, which gives extremely high precision because it is fired at the next event loop. You can combine this with performance.now to determine whether to increment your time or not.
Disclosure: I am the author of the aforementioned lib.

NaN in the context of a recursive for loop

I am trying to understand a solution I found for a problem: "You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin."
My question is, if I run the function with change(3,[2]), why does it spit out 0. I am having trouble with comprehending how after a single recursive call currentCoin becomes undefined, and then when the program reaches the for loop in that call, it doesn't call the change function again with total += change(amount - 0 * undefined, coins.slice(0, -1)). Why does it not crash with either an infinite recursive call with change(NaN,[]) or coins.slice(0,-1) being used on an empty array. It seems to ignore that on the for loop.
Am I misunderstanding how a for-loop works?
var change = function(amount, coins) {
if(amount == 0) return 1;
let currentCoin = coins[coins.length - 1];
let total = 0;
for(let qty = 0; qty * currentCoin <= amount; qty++){
total += change(amount - qty * currentCoin, coins.slice(0, -1))
}
return total;
};
console.log(change(3,[2]))
There are a couple things going on here.
First is the behavior of coins[coins.length - 1]. In Javascript, when you access an element of a list at an index that doesn't exist in that list, the indexer will return undefined instead of crashing with an IndexOutOfBoundsException or the like.
Second is qty * currentCoin <= amount. In the case that currentCoin is undefined (due to the above), qty * currentCoin will be NaN. In Javascript, any comparison of NaN with another number will return false by design. (e.g. NaN <= anything is false).
Put this all together and you see that, on the first recursion, the coins array will be empty which makes currentCoin NaN. This causes qty * currentCoin <= currentAmount to be false, which causes the loop to short circuit (so slice never gets called on an empty list). Since the loop never executes, total will still be 0, which is what gets returned. This continues until qty * currentCoin <= amount becomes true in the outermost recursion, and that loop exits with total still equalling 0 (since it only ever added 0).
If you intersperse console.log calls in strategic places about the function, it becomes clearer what is happening:
var change = function(amount, coins) {
console.log(amount, coins);
if(amount == 0) return 1;
let currentCoin = coins[coins.length - 1];
console.log(':', currentCoin, amount);
let total = 0;
for(let qty = 0; qty * currentCoin <= amount; qty++){
total += change(amount - qty * currentCoin, coins.slice(0, -1))
console.log('=', total);
}
console.log('recdone');
return total;
};
console.log(change(3,[2]))
not crash because a NaN in comparison with a number is every false...
NaN < number or NaN > number and so on produce false... so the
qty * currentCoin <= amount
is evaluate false and will exit from the for.
So, if you need to check the NaN you must before the for
let totalCoin = qty * currentCoin;
let check = isNaN(totalCoin);
if(check) {
// return you sentinel value;
}
var change = function(amount, coins) {
if(amount == 0) return 1;
let currentCoin = coins[coins.length - 1]; // firstpass 1-1 = 0, second pas 0-1=-1 => coins[-1] = undefined
let total = 0;
// this will 0*0<=3, second pass 0*undefined => null which is false hence never execute
for(let qty = 0; qty * currentCoin <= amount; qty++){
total += change(amount - qty * currentCoin, coins.slice(0, -1))
}
return total;
};
console.log(change(3,[2]))
In second pass when coins.length = 0 then
let currentCoin = coins[0 - 1]; // = undefined
Later in for loop you will 0 * undefined ( qty * currentCoin) which results NaN which is Not a number
There is no need for recursion in this case. One can use a bottom-up dynamic programming approach. Let ways[i] denote the number of ways to get to i dollars with the given coins and coins[i] represent the value of the ith coin. Then, ways[i] is the sum of all ways[i - coins[j]] for all j from 1 to the number of coins.
var change = function(amount, coins) {
const ways = Array(amount + 1);
ways[0] = 1;
for(const coin of coins){
for(let i = coin; i <= amount; i++){
ways[i] = (ways[i] ?? 0) + ways[i - coin] ?? 0;
}
}
return ways[amount];
};
console.log(change(5,[1,2,3,4,5]))

Is there a minimum possible size change in CSS?

I wrote some JavaScript code to animate CSS properties of elements. I pass the following arguments to the function: amount, interval, and duration; amount being the change in the property (for example 200 could mean add 200 pixels to the element's width), interval being the time between two consecutive changes, and duration being the total duration of the animation.
The code works fine unless I pass the arguments in a way that the change in each interval becomes very small (like a tiny fraction of a pixel).
I know the code is working fine theoretically, as I get the change in console.
Any ideas about the problem?
Cheers.
UPDATE: the code:
function handleTimer (amount, interval, duration, execute, element) {
let i = 0;
let current = 0;
let stepsCount = countSteps(interval, duration);
let stepLength = calcStepLength(stepsCount, amount);
let count = setTimeout(function addOneMore () {
if ( i < stepsCount -1 ){
i++;
current += stepLength;
execute(stepLength, element);
if (current < amount) {
count = setTimeout(addOneMore, interval)
}
} else {
current = amount;
execute(amount - (stepsCount -1) * stepLength, element);
}
}, interval)
}
function countSteps (interval, duration) {
let remainder = duration % interval;
let stepsCount;
if (remainder) {
stepsCount = Math.floor(duration / interval) + 1;
} else {
stepsCount = duration / interval;
}
return stepsCount;
}
function calcStepLength(stepsCount, amount) {
return amount / stepsCount;
}
function resizeWidth (amount, element) {
let widthSTR = $(element).css('width');
let width = parseInt( widthSTR.substr( 0 , widthSTR.length - 2 ) );
$(element).css('width', `${width + amount}px`);
}
So this:
handleTimer(218, 5, 200, resizeWidth, '.box');
works fine, but this:
handleTimer(218, 5, 2000, resizeWidth, '.box');
doesn't.
UPDATE 2:
I know browsers are super accurate with pixels, like when you use percentages. Of course the value will be rounded before rendering since displays cant display half pixels, but the value is still calculated accurately.
I don't know at what decimal the rounding occurs.
This happens because parseInt is rounding your number up.
Pay attention to this line:
let width = parseInt( widthSTR.substr( 0 , widthSTR.length - 2 ) );
if width is a decimal number, like 22.5px, it will be rounded up to 22.
If amount is less than 1, it won't reach 23 and when you round up the number again, you'll get 22 again and it becomes a loop.
You have two solutions:
Use another variable to save the width value, avoiding to writing and reading it from CSS:
let initialWidth = $(element).css('width');
let savedWidth = widthSTR.substr(0, initialWidth, initialWidth.length - 2 ) );
function resizeWidth (amount, element) {
savedWidth += amount;
$(element).css('width', `${savedWidth}px`);
}
Just use parseFloat in place of parseInt to don't round your number up:
let width = parseFloat( widthSTR.substr( 0 , widthSTR.length - 2 ) );

Javascript countdown then count-up from a prompted variable?

Please Help! I'm new to Javascript, so there's probably an easier solution to this. Basically, I need it to prompt for a number and then count down from that number to zero. Once it reaches zero, I need it to count-up and stop at the same prompted number.
I got it to count down at first, then I completely butchered it, I have no clue what to do.
<script type="text/javascript">
// get number from user
var startNum = parseInt(prompt("Input a number to start counting down from.",""));
var counter = setInterval(timer, 1000);
console.log(startNum);
function timer() {
startNum--; // reduce number by 1
console.log(startNum);
if (startNum <= 0) {
clearInterval(counter);
}
}
var counter = setInterval(timer2, 1000);
var endNum = 0
function timer2() {
console.log(endNum)
endNum++; // add number by 1
console.log(endNum);
if (endNum >= startNum) {
clearInterval(counter);
}
}
</script>
You've got a couple issues here. the first one was pointed out by Rob in the comments. You're running both functions at the same time.
The other issue you have is that you're never storing the number. You're just subtracting and adding to nothing essentially.
So -
<script type="text/javascript">
// get number from user
var startNum = parseInt(prompt("Input a number to start counting down from.",""));
var currentNum = startNum;
var counter = setInterval(timer, 1000);
function timer() {
console.log(currentNum);
currentNum -= 1; // reduce number by 1
console.log(currentNum);
if (currentNum == 0) {
clearInterval(counter);
counter = setInterval(timer2, 1000);
}
}
function timer2() {
console.log(currentNum)
currentNum += 1; // add number by 1
console.log(currentNum);
if (currentNum == startNum) {
clearInterval(counter);
}
}
</script>
Something like this should do the trick. Basically creating another variable to hold your start number and consider that the current number and the value that is going to change.
here's a fiddle - http://jsfiddle.net/w5FM6/
cheers

Categories