FlipClock.js : ease-in to initial value - javascript

I'm a PHP developer and I want to make FlipClock's inital value ease-in. I think it can be done by:
Making clock.incerement()'s interval value flexible, Based on how close is current value, to initial value.
Make a break when the current value was equal to initial value.
I changed this code:
var clock;
var initial = 5000;
$(document).ready(function() {
clock = new FlipClock($('.clock'), 0, {
clockFace: 'Counter',
});
setTimeout(function() {
setInterval(function() {
if(clock.getTime().time >= initial) {
clock.stop();
} else {
clock.increment();
}
}, 100);
});
});
to this one:
var clock;
var initial = 5000;
$(document).ready(function() {
clock = new FlipClock($('.clock'), 0, {
clockFace: 'Counter',
});
setTimeout(function() {
setInterval(function() {
if(clock.getTime().time >= initial) {
clock.stop();
} else {
clock.increment();
}
}, function() {
if ((initial - clock.getTime().time) > 1000) {
return 1;
} else if ((initial - clock.getTime().time) > 100) {
return 10;
} else {
return 1000;
}
});
});
});
But did not worked. What i have to do?!
Thank you.

The interval value is supposed to a time in milliseconds, not a function.
One other way to do it is that you calculate the timeout value is as such
setTimeout(function(){
var x = CalculateCurrentInterval(clock);
setInterval(function() {
if(clock.getTime().time >= initial) {
clock.stop();
} else {
clock.increment();
}
}, x);
})
var CalculateCurrentInverval = function(clock) {
if ((initial - clock.getTime().time) > 1000) {
return 1;
} else if ((initial - clock.getTime().time) > 100) {
return 10;
} else {
return 1000;
}
}
I have not tried it but it should work.
Problem is that you are sending in a function where a number is expected

Related

Countdown timer stops when switching tabs

So basically when I switch tabs, the countdown timer on a specific page just stops counting down and resumes when you return to the tab. Is there anyway to mitigate that so that it counts in the background or it accounts for the time you spend on another tab?
This is basically what I have for js:
document.getElementById('timer').innerHTML =
05 + ":" + 01;
startTimer();
function startTimer() {
var presentTime = document.getElementById('timer').innerHTML;
var timeArray = presentTime.split(/[:]+/);
var m = timeArray[0];
var s = checkSecond((timeArray[1] - 1));
if(s==59){m=m-1}
if(m<0){
return
} else if (m == 0 && s == 0) {
location.reload();
}
document.getElementById('timer').innerHTML =
m + ":" + s;
setTimeout(startTimer, 1000);
}
function checkSecond(sec) {
if (sec < 10 && sec >= 0) {sec = "0" + sec};
if (sec < 0) {sec = "59"};
return sec;
}
Any ideas whether the time could be done server side or something so that it can't be modified client side? If not, then whatever, but mainly just want to figure out how to make the countdown still work (or account for the time spent) when on another tab.
We can store the variable m and s values either globally or use the local storage to set the values after setting the inner HTML and get the stored values back whenever tabs were switched as:
Set values:
window.localStorage.setItem('minutes', m.toString()); //same for the seconds
Get values:
window.localStorage.getItem('minutes'); //same for the seconds
Hope this answers your questions.
Just a simple solution:
Add this piece of code.
<html>
<head>
<script>
(function() {
var $momentum;
function createWorker() {
var containerFunction = function() {
var idMap = {};
self.onmessage = function(e) {
if (e.data.type === 'setInterval') {
idMap[e.data.id] = setInterval(function() {
self.postMessage({
type: 'fire',
id: e.data.id
});
}, e.data.delay);
} else if (e.data.type === 'clearInterval') {
clearInterval(idMap[e.data.id]);
delete idMap[e.data.id];
} else if (e.data.type === 'setTimeout') {
idMap[e.data.id] = setTimeout(function() {
self.postMessage({
type: 'fire',
id: e.data.id
});
// remove reference to this timeout after is finished
delete idMap[e.data.id];
}, e.data.delay);
} else if (e.data.type === 'clearCallback') {
clearTimeout(idMap[e.data.id]);
delete idMap[e.data.id];
}
};
};
return new Worker(URL.createObjectURL(new Blob([
'(',
containerFunction.toString(),
')();'
], {
type: 'application/javascript'
})));
}
$momentum = {
worker: createWorker(),
idToCallback: {},
currentId: 0
};
function generateId() {
return $momentum.currentId++;
}
function patchedSetInterval(callback, delay) {
var intervalId = generateId();
$momentum.idToCallback[intervalId] = callback;
$momentum.worker.postMessage({
type: 'setInterval',
delay: delay,
id: intervalId
});
return intervalId;
}
function patchedClearInterval(intervalId) {
$momentum.worker.postMessage({
type: 'clearInterval',
id: intervalId
});
delete $momentum.idToCallback[intervalId];
}
function patchedSetTimeout(callback, delay) {
var intervalId = generateId();
$momentum.idToCallback[intervalId] = function() {
callback();
delete $momentum.idToCallback[intervalId];
};
$momentum.worker.postMessage({
type: 'setTimeout',
delay: delay,
id: intervalId
});
return intervalId;
}
function patchedClearTimeout(intervalId) {
$momentum.worker.postMessage({
type: 'clearInterval',
id: intervalId
});
delete $momentum.idToCallback[intervalId];
}
$momentum.worker.onmessage = function(e) {
if (e.data.type === 'fire') {
$momentum.idToCallback[e.data.id]();
}
};
window.$momentum = $momentum;
window.setInterval = patchedSetInterval;
window.clearInterval = patchedClearInterval;
window.setTimeout = patchedSetTimeout;
window.clearTimeout = patchedClearTimeout;
})();
</script>
</head>
</html>

How to create timer in javascript with fixed intervals? and option to start from a number?

I am using the solution in this answer to create an accurate javascript timer. The code works fine. But I want it to have a fixed interval option. like it need to output 100, 200, 300, so on..,
Math.round(timer.getTime() / 1000); this code rounds the value to the nearest second so timer goes 1, 2, 3, 4, 5...
I tried adjusting the duration of setInterval to 50 and rounding to nearest 100, it works almost fine to my needs. but it is repeating numbers and sometimes skips few numbers.
And also I need some timer to start from a specific number, say from 400 to 10000. the class has 0 as default. How do I go about implementing that?
please find the codepen for more code and details:
https://codepen.io/gurgoon32/pen/KKzYYKG
class Timer {
constructor() {
this.isRunning = false;
this.startTime = 0;
this.overallTime = 0;
}
_getTimeElapsedSinceLastStart() {
if (!this.startTime) {
return 0;
}
return Date.now() - this.startTime;
}
start() {
if (this.isRunning) {
return console.error('Timer is already running');
}
this.isRunning = true;
this.startTime = Date.now();
}
stop() {
if (!this.isRunning) {
return console.error('Timer is already stopped');
}
this.isRunning = false;
this.overallTime = this.overallTime + this._getTimeElapsedSinceLastStart();
}
reset() {
this.overallTime = 0;
if (this.isRunning) {
this.startTime = Date.now();
return;
}
this.startTime = 0;
}
getTime() {
if (!this.startTime) {
return 0;
}
if (this.isRunning) {
return this.overallTime + this._getTimeElapsedSinceLastStart();
}
return this.overallTime;
}
}
let the_interval;
function round_nearest_hundred(num) {
return Math.round(num / 100) * 100;
}
function onUpdateTimer(duration) {
const timeInSeconds = Math.round(timer.getTime() / 1000);
document.getElementById('time').innerText = timeInSeconds;
document.getElementById('accTime').innerText = round_nearest_hundred(timer.getTime());
console.log(round_nearest_hundred(timer.getTime()));
if (round_nearest_hundred(timer.getTime()) >= duration) {
document.getElementById('status').innerText = 'complete';
timer.stop();
timer_manager(false);
}
}
function timer_manager(flag, updateFunction, time, duration) {
if (flag) {
the_interval = setInterval(function() {
updateFunction(duration);
}, time);
} else {
clearInterval(the_interval);
}
}
const timer = new Timer();
//timer.start();
timer_manager(true, onUpdateTimer, 50, 10000);
document.getElementById('start').addEventListener('click', function() {
timer.start();
});
document.getElementById('stop').addEventListener('click', function() {
timer.stop();
});
document.getElementById('restart').addEventListener('click', function() {
timer_manager(true, onUpdateTimer, 100, 10000);
timer.reset();
timer.start();
});
<p>Elapsed time: <span id="time">0</span>s</p>
<p id="accTime"></p>
<p id="status"></p>
<button id="start">start</button>
<button id="stop">pause</button>
<button id="restart">restart</button>
Give this a try:
class Timer {
constructor () {
this.isRunning = false;
this.startTime = 0;
this.overallTime = 0;
}
_getTimeElapsedSinceLastStart () {
if (!this.startTime) {
return 0;
}
return Date.now() - this.startTime;
}
start () {
if (this.isRunning) {
return console.error('Timer is already running');
}
this.isRunning = true;
this.startTime = Date.now();
}
stop () {
if (!this.isRunning) {
return console.error('Timer is already stopped');
}
this.isRunning = false;
this.overallTime = this.overallTime + this._getTimeElapsedSinceLastStart();
}
reset () {
this.overallTime = 0;
if (this.isRunning) {
this.startTime = Date.now();
return;
}
this.startTime = 0;
}
getTime () {
if (!this.startTime) {
return 0;
}
if (this.isRunning) {
return this.overallTime + this._getTimeElapsedSinceLastStart();
}
return this.overallTime;
}
}
let the_interval;
function round_nearest_hundred(num){
return Math.floor(num / 100)*100;
}
function onUpdateTimer(start, duration){
const startTime = timer.getTime() + start;
const timeInSeconds = Math.floor(timer.getTime() / 1000);
document.getElementById('time').innerText = timeInSeconds;
document.getElementById('accTime').innerText = round_nearest_hundred(startTime);
console.log(round_nearest_hundred(startTime));
if(round_nearest_hundred(timer.getTime()) >= (duration - start)){
document.getElementById('status').innerText = 'complete';
timer.stop();
timer_manager(false);
}
}
function timer_manager(flag, updateFunction, time, start, duration){
if(flag){
the_interval = setInterval(function(){updateFunction(start, duration);}, time);
} else {
clearInterval(the_interval);
}
}
const timer = new Timer();
//timer.start();
timer_manager(true, onUpdateTimer, 50, 1000, 10000);
document.getElementById('start').addEventListener('click', function(){
timer.start();
});
document.getElementById('stop').addEventListener('click', function(){
timer.stop();
});
document.getElementById('restart').addEventListener('click', function(){
timer_manager(false);
timer_manager(true, onUpdateTimer, 100, 0, 10000);
timer.reset();
timer.start();
});
<p>Elapsed time: <span id="time">0</span>s</p>
<p id="accTime"></p>
<p id="status"></p>
<button id="start">start</button>
<button id="stop">pause</button>
<button id="restart">restart</button>
Math.round() is a little confusing in this context because it means 500ms rounds up to 1s, making you think you've reached that time before you really have. It's better to use Math.floor() (rounds down) so that you only see the number of seconds that have really elapsed. I think this should solve the skipping issue.
In the Reset function, it's good practice to clear the last interval before setting a new one. It seems that otherwise you would be running two setInterval functions, with only the latest one being referred to by variable the_interval.
To start from a specific number, I've added an argument (start) to the timer_manager function. This gets passed to the onUpdateTimer function, because that is where your logic decides if the timer has finished or not (clearly, that would depend on which value it started from). Finally, also in that function, it's up to you whether you want to display to the user the actual number of seconds elapsed (e.g. start: 1s, end: 10s, elapsed: 9s), or that plus the starting point (e.g. start: 1s, end: 10s, elapsed: 10s).
In order to provide a start time value, you simply have to modify the constructor so that it accepts the start time as a parameter:
class Timer {
constructor (startTime = 0) {
this.isRunning = false;
this.startTime = startTime;
this.overallTime = startTime;
}
// ...
}
const timer1 = new Timer(); // timer1 will start from 0
const timer2 = new Timer(500); // timer2 will start from 500
For what concerns the interval, if you want to display hundredths of seconds rounded to hundreds (e.g. 100, 200, 300, ...), you have to set the interval time to 10ms and use the function "round_nearest_hundred()" you already have:
// ...
function onUpdateTimer(duration) {
//const timeInSeconds = Math.round(timer.getTime() / 1000);
//document.getElementById('time').innerText = timeInSeconds;
const timeInHundredthsOfSeconds = round_nearest_hundred(timer.getTime());
document.getElementById('time').innerText = HundredthsOf;
document.getElementById('accTime').innerText = round_nearest_hundred(timer.getTime());
console.log(round_nearest_hundred(timer.getTime()));
if (round_nearest_hundred(timer.getTime()) >= duration) {
document.getElementById('status').innerText = 'complete';
timer.stop();
timer_manager(false);
}
}
// ...
timer_manager(true, onUpdateTimer, 10, 10000);
// ...

Issues with setInterval

I'm creating a simple slideshow using jQuery and some javascript, but I'm running into issues using the setInterval functions.
JSFiddle of the Project
$(document).ready(function () {
slidePos = 1;
autoScrollInterval = setInterval(function () {
slidePos = SlideRight(slidePos)
}, 7000);
$(".ss-indicator-arrow").css("width", $(".ss-slideshow").width() / $(".ss-slide").length);
$(".ss-right-arrow").click(function () {
window.clearInterval(autoScrollInterval);
slidePos = SlideRight(slidePos);
setTimeout(function () {
autoScrollInterval = setInterval(function () {
slidePos = SlideRight(slidePos)
}, 7000);
}, 10000);
});
$(".ss-left-arrow").click(function () {
window.clearInterval($.autoScrollInterval);
slidePos = SlideLeft(slidePos);
setTimeout(function () {
autoScrollInterval = setInterval(function () {
slidePos = SlideRight(slidePos)
}, 7000);
}, 10000);
})
});
$(window).resize(function () {
$(".ss-indicator-arrow").css("width", $(".ss-slideshow").width() / $(".ss-slide").length);
Reset();
});
function SlideRight(slidePos) {
slidePos++;
if (slidePos <= $(".ss-slide").length) {
$(".ss-container").css("margin-left", -((slidePos - 1) * $(".ss-slideshow").width()) + "px");
$(".ss-indicator-arrow").css("left", ($(".ss-indicator-arrow").width() * (slidePos - 1) + "px"));
}
else
Reset();
return slidePos
}
function SlideLeft(slidePos) {
slidePos--;
if (slidePos > 0) {
$(".ss-container").css("margin-left", -((slidePos - 1) * $(".ss-slideshow").width()) + "px");
$(".ss-indicator-arrow").css("left", ($(".ss-indicator-arrow").width() * (slidePos - 1) + "px"));
}
else {
slidePos = $(".ss-slide").length;
$(".ss-container").css("margin-left", -((slidePos - 1) * $(".ss-slideshow").width()) + "px");
$(".ss-indicator-arrow").css("left", ($(".ss-indicator-arrow").width() * (slidePos - 1) + "px"));
}
return slidePos;
}
function Reset() {
slidePos = 1;
$(".ss-container").css("margin-left", "0px");
$(".ss-indicator-arrow").css("left", "0px");
}
So far I've tried many different methods, and have somewhat ruined the basic functionality I had before. But for now, the primary issue is that if an arrow is pressed multiple times, after the wait setTimeout period, it will then progress through the same number of slides (ie if the button is pressed 3 times, when the setInterval starts over it will move 3 slides again)
What is the most effective way I can have an interval that pauses after user input, then resumes again?
What is the most effective way I can have an interval that pauses
after user input, then resumes again?
Look at this example
DEMO: http://jsfiddle.net/n8c3pycw/1/
var Timer = {
totalSeconds: 300,
start: function () {
var self = this;
this.interval = setInterval(function () {
self.totalSeconds -= 1;
if (self.totalSeconds == 0) {
Timer.pause();
}
$("#timer").text(parseInt(self.totalSeconds, 10));
}, 1000);
},
pause: function () {
clearInterval(this.interval);
delete this.interval;
},
resume: function () {
if (!this.interval) this.start();
}
}
Timer.start();
$("#start").click(function(){
Timer.resume();
});
$("#stop").click(function(){
Timer.pause();
});
Try using either setTimeout or setInterval.
example: var autoScrollInterval = runInterval();
function tochangeyourimage (delta) {
autoRunInterval = runInterval();
};
function runInterval() {
return setInterval(tochangeyourimage, 7000, 1);

clearTimeout not working in recursion function - javascript

Here is the code I am using. When ticks becomes equal to 5 the recursion function should stop clearing the mainThread timeout. Anybody please help.
var mainThread;
var ticks = 0;
function tickTimer() {
clearTimeout(mainThread);
if (ticks >= 5) {
endGame();
}
else {
mainThread = setTimeout(function () {
ticks++;
tickTimer();
}, 1000);
}
}
Let me know if any concerns.
Thank you in advance.
Try this instead:
function tickTimer() {
if (++ticks >= 5) {
clearInterval (mainThread);
endGame();
}
}
var mainThread = setInterval(tickTimer, 1000);
var ticks = 0;
you can try this. all you need to do is clear interval every time tickTimer function is called.
var mainThread = setInterval(tickTimer, 1000);
var ticks = 0;
function tickTimer() {
if (++ticks >= 5) {
clearInterval (mainThread);
endGame();
}
}
Did you declare mainThread ? Like this
var mainThread = null;
function tickTimer() {
clearTimeout(mainThread);
mainThread = null;
if (ticks >= 5) {
endGame();
}
else {
mainThread = setTimeout(function () {
ticks++;
tickTimer();
}, 1000);
}
}
And ticks++ not ticks--
Please try to replace ticks-- to ticks++
I've think just send your timer as argument
function tickTimer(timer) {
timer && clearTimeout(timer);
if (ticks >= 5) {
endGame();
}
else {
var timer = setTimeout(function () {
ticks--;
tickTimer(timer);
}, 1000);
}
}
Don't use global scope )))
I thing you should Initialize variable ticks as the function is triggered.

How to activate mouseleave, if it has been x amount of time?

So, I've got this type of situation, but I only want to "Do something" if the user "mouseleave(s)" for more than x amount of time, say one second. How should I implement that?
$("#someElement, #someOtherElement").mouseleave(function() {
// Do something.
});
Later I added:
$('.popover3-test').popover({
placement:'bottom',
template: $('.popover2'),
trigger: 'manual',
}).mouseenter(function(e) {
$(this).popover('show');
$(".popover3-test, .popover2").each(function() {
var t = null;
$(this)
.mouseleave(function() {
t = setTimeout(function() {
$('.popover2').hide();
}, 1000); // Or however many milliseconds
})
.mouseenter(function() {
if(t !== null)
clearTimeout(t);
})
;
});
});
setTimeout should do the trick:
$("#someElement, #someOtherElement").each(function() {
var t = null;
$(this)
.mouseleave(function() {
t = setTimeout(function() {
// Do something.
}, 1000); // Or however many milliseconds
})
.mouseenter(function() {
if(t !== null) {
clearTimeout(t);
t = null;
}
})
;
});
EDIT: If you want it to work on either, just remove the .each:
var t = null;
$("#someElement, #someOtherElement")
.mouseleave(function() {
t = setTimeout(function() {
// Do something.
}, 1000); // Or however many milliseconds
})
.mouseenter(function() {
if(t !== null) {
clearTimeout(t);
t = null;
}
})
;
$("#someElement, #someOtherElement").bind('mouseenter mouseleave', (function() {
var timer;
return function (e) {
if(e.type === 'mouseleave') {
timer = setTimeout(function () {
//do something
}, 1000);
} else {
clearTimeout(timer);
}
};
}()));
EDIT - usable on multiple elements
$("#someElement, #someOtherElement").bind('mouseenter mouseleave', function (e) {
var timer = $(this).data('timer');
if(e.type === 'mouseleave') {
timer = setTimeout(function () {
//do something
}, 1000);
} else {
clearTimeout(timer);
}
$(this).data('timer', timer);
};
});
this might not work as is, but gives you some ideas...
var elapsed = 0;
var timer = setInterval(function(){
elapsed += 20;
if( elapsed >= 1000 ) {
doSomething();
clearInterval(timer);
}
}, 20 );
$('#some').mouseleave(timer);
$('#some').mouseenter(function(){clearInterval(timer);elapsed=0;});

Categories