Debounce return timer - javascript

I don't understand the principle of operation. I have a code in which I have to create a delay of 2 seconds during the twist but during the delay script should not work using the debounce script but for some reason it always returns some timer and not an answer from function that the debounce script accepts
function debounce(f, ms) {
let timer = null;
return function(...args) {
const onComplete = () => {
f.apply(this, args);
timer = null;
}
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(onComplete, ms);
};
}
var delay = false;
$('.window').on('mousewheel', function(event) {
var pozition = $(document).scrollTop();
var block2 = $(".main_step").offset().top
var elemId = $(this).attr('id'),
scrollDir = event.deltaY;
var indicatorL = $(".indicator_main").data("counter");
if (elemId == 'steps' && scrollDir < 0 && delay === false) {
if (indicatorL != "4") {
$("#sli-" + indicatorL).css("display", "none");
indicatorL = indicatorL + 1;
$("#sli-" + indicatorL).css("display", "block");
$(".indicator_main").data("counter", indicatorL);
$(".indicator_main").animate({
"left": "+=25%"
}, "slow");
$(".indicator_num").text("0" + indicatorL);
$(".step_nr").text("0" + indicatorL);
}
}
delay = true;
var f = function() {
var delay = false;
return delay;
};
delay = debounce(f, 2000);
console.log(delay);
});

Related

JavaScript clearTimeout not firing correctly

I have a submit function on a textbox with JavaScript. When the script fires, it checks a Kendo grid for a certain article and adds +1 to its quantity as well as opening the corresponding cell in editing mode. What I want to achieve is that on every submit the timer that starts grid.editCell() will reset its timer.
Currently, the event fires properly. However, the timer doesn't get reset, although the clearTimeout() does work if I just simply start the timer and then clear it right afterwards.
JavaScript:
$('#txtBarcode').submit(function (e) {
var grid = $("#PickListDetailGrid").data("kendoGrid");
var dataSource = $("#PickListDetailGrid").data("kendoGrid").dataSource;
var allData = grid.dataSource.data();
var code = this.value;
var notification = $("#notification").data("kendoNotification");
var timer = null;
clearTimeout(timer);
$.each(allData, function (index, item) {
if (item.ArticleID == code) {
clearTimeout(timer);
timer = null;
if (item.Quantity > item.PickedQuantity && item.PickedQuantity.toString().length < 4) {
var edit = function () {
if (item.PickedQuantity != item.Quantity && timer != null) {
grid.select("tr:eq(" + (index) + ")");
grid.editCell("tr:eq(" + (index + 1) + ") td:eq(" + (5) + ")");
} else {
//do nothing
}
}
item.PickedQuantity++;
item.dirty = true;
dataSource.sync();
if (item.PickedQuantity != item.Quantity) {
console.log("tik tok");
if (timer) {
clearTimeout(timer); //cancel the previous timer.
timer = null;
}
timer = setTimeout(edit, 3000);
} else {
clearTimeout(timer);
timer = null;
}
document.getElementById("txtBarcode").value = "";
} else {
if (item.PickedQuantity.toString().length > 4) {
notification.hide();
notification.show({
message: "Added item"
}, "upload-success");
} else {
notification.hide();
notification.show({
title: "Quantity Error",
message: "You already picked this item to the maximum"
}, "error");
document.getElementById("txtBarcode").value = "";
grid.select("tr:eq(" + (index) + ")");
grid.editCell("tr:eq(" + (index + 1) + ") td:eq(" + (5) + ")");
$('.focus :input').focus();
}
}
}
})
})
You can try delay function like this. The delay function should be outside of the each function.
var delay = (function() {
var timer = 0;
return function(callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})();
delay(function() {
//do something
}, 3000);
The problem was that var timer = null; had to be outside of the submit function to be properly cleared and set to null before assigning a new setTimeout() to it.

Change images with different timeinterval using Js or jquery

How to change images with different time interval in a single div using CSS3, JavaScript or jQuery. At the last time interval should be cleared.
You can try this http://codepen.io/jammer99/pen/PNErKp
var timing = [1000, 2000, 500, 300, 800],
timeouts
function runinterval() {
timeouts = setTimeout(function() {
clearTimeout(timeouts);
timing.shift();
$(".imgholder").css("background-image", "url(https://unsplash.it/100/100/?random&i=" + new Date().getTime() + ")")
if (timing.length != 0)
runinterval();
}, timing[0])
}
runinterval();
Maybe something like this can help you.
var setTimer = (function(){
function setTimer( options ){
this.timings = options.timings;
this.element = options.element;
this.images = options.images;
this.index = -1;
this.interval = false;
this.init();
}
setTimer.prototype.init = function(){
this.image_ = document.createElement('img');
this.image_.setAttribute('class','slider-image');
this.element.appendChild( this.image_ );
this.set();
};
setTimer.prototype.set = function(){
if( this.interval && false !== this.interval ){
clearTimeout( this.interval );
}
if( this.index >= this.images.length-1 ){ this.index = 0; }
else{ this.index++; }
var timing = this.timings[this.index];
console.log(this.index);
console.log(timing);
this.interval = (function(_this){
return setTimeout(function(){
_this.switch_image();
},timing);
})(this);
};
setTimer.prototype.switch_image = function(){
var index = this.index;
console.log('switching image to '+this.images[index]);
this.image_.setAttribute('src',this.images[index]);
this.set();
}
return setTimer;
})();
setTimeout(function(){
var options = {
timings: [10,1000,2000],
images : [ 'url1','url2','url3'],
element: document.getElementById('your-image-container-id')
};
new setTimer(options);
},1000);

Starting Javascript intervals nonsynchronously and stop each after three runs

I have a function for letting blink a OpenLayer marker three times. The simplified version which only shows console messages:
function blink_three_times(layername){
var x = 0;
setTimeout(function() {
blink_in = setInterval(function() {
x = x+1;
if ( x === 3) {clearInterval(blink_in)};
console.log(layername + ' is visible');
}, 500);
}, 250);
blink_out = setInterval(function() {
if (x === 2) {clearInterval(blink_out)};
console.log(layername + ' is invisible');
}, 500);
};
It works fine, but if it is started multiple times before one has finished, the counter (x) exceeds 3 and the interval does not stop. How can I avoid that?
That is because you have funcions blink_in & blink_out in global scope. When you are calling it second time it overwrites the definitions of functions.
Define them using var to make them local.
var blink_in = setInterval(function() {..})
and
var blink_out = setInterval(function() {..})
DEMO
Your variables blink_in and blink_out are global ones so if you call the function multiple times they will override it and therefore cannot stop the interval properly.
Use them in your function scope by definining them with "var" in order to avoid the problem (see http://jsfiddle.net/cb0h8tst/)
function blink_three_times(layername){
var x = 0;
var blink_in, blink_out;
setTimeout(function() {
blink_in = setInterval(function() {
x = x+1;
if ( x === 3) {clearInterval(blink_in)};
console.log(layername + ' is visible');
}, 500);
}, 250);
blink_out = setInterval(function() {
if (x === 2) {clearInterval(blink_out)};
console.log(layername + ' is invisible');
}, 500);
};
Based on your last update question,
you could also make a more dynamic to keep track of the layers that are actually being blinked, a possible example
function Blinker(opt) {
var ts = {};
this.elementId = opt ? opt.elementId : undefined;
this.runs = (opt ? opt.runs : 3) || 3;
this.completed = (opt ? opt.completed : function() { }) || function() { };
this.start = function(arg) {
var timestamp = arg || this.elementId, that = this;
if (typeof ts[timestamp] !== 'undefined') {
console.log('Cannot run multiple times on same layer');
return;
}
ts[timestamp] = {
timestamp: timestamp,
count: 0,
element: document.getElementById(arg || this.elementId),
controller: this
};
setTimeout(function() {
ts[timestamp].showInterval = setInterval(that.setVisibility.bind(ts[timestamp], true), 500);
}, 250);
ts[timestamp].hideInterval = setInterval(this.setVisibility.bind(ts[timestamp], false), 500);
};
this.setVisibility = function(visible) {
this.element.style.visibility = visible ? 'visible' : 'hidden';
this.element.style.display = visible ? 'inherit' : 'none';
if (visible) {
this.count++;
}
if (!visible && this.count === 2)
{
clearInterval(this.hideInterval);
}
if (visible && this.count === 3)
{
clearInterval(this.showInterval);
this.controller.completed.apply(this.controller, [this.element.id]);
delete ts[this.timestamp];
}
};
}
var blinker = new Blinker({
elementId: 'blinker',
runs: 3,
completed: function(elementId) {
var log = document.getElementById('log');
log.innerHTML += '<p><strong>' + elementId + '</strong> has finished blinking</p>';
}
});
you could find the fiddle here: http://jsfiddle.net/q70w0kpx/

Game Timer (Start, Pause, Stop)

I have a timer that starts when the game starts.
I need to figure out how to stop the timer when the game is over and then return the value (time that has elapsed)
Here is the timer I have:
function gameTimer(status) {
$(".notes").text(status);
if (gameStart == true) {
gameStart = false; // so game will not repeat when image is clicked again to start game
var timer = setInterval(calltimer, 1000);
function calltimer() {
$(".timerInner").text(time);
if (status == true) {
time++;
}
}
}
}
Here is how I vision the functions working:
gameTimer(start); // start timer
gameTimer(pause); // pause timer in case user needs to step away
gameTimer(stop); // stop timer and return value
Any ideas on how I would get something like this implemented?
Thanks,
Maybe u want something like this:
var gameStart = false;
function gameTimer (status) {
switch (status) {
case "start":
if (gameStart === false) {
var timer = setInterval(callTimer, 1000);
gameStart = true;
}
break;
case "pause":
if (gameStart === true && timer !== null) {
clearInterval(timer);
gameStart = false;
}
break;
case "continue":
if (gameStart === false && timer !== undefined && timer !== null) {
timer = setInterval(callTimer, 1000);
gameStart = true;
}
break;
case "stop":
if (timer !== null) {
timer = null;
gameStart = false;
}
break;
}
$(".notes").text(status);
}
As u can see from the code u can use the method "clearInterval(nameOfTheTimer)" to pause the interval, if u want to reset it u have to reset the timer variable.
Hope it will help! :D
Use that:
Function.prototype.scope = function(context) {
var f = this;
return function() {
return f.apply(context, arguments);
};
};
Timer = function() {
this.tick = 0;
this.intervalId = null;
this.period = 1000; // in ms
this.isPaused = false;
};
jQuery.extend(Timer.prototype, {
onTick: function() {
if (!this.isPaused) {
this.tick++;
}
},
start: function() {
this.intervalId = setInterval(function() {this.onTick()}.scope(this), this.period);
},
pause: function() {
this.isPaused = !this.isPaused;
},
stop: function() {
clearInterval(this.intervalId);
var result = this.tick;
this.tick = 0;
this.isPaused = false;
return result;
}
});
t = new Timer();
t.start();
t.pause();
t.stop();
Stop the Timer the way you started it. What is the trigger? On what event the timer started?

Add duration to JS setTimeout after the timer is running

I'm trying to figure out a way to emulate AS3's Timer class.
If you're not familiar, one of the cool things you can do is add duration to the timer even if it's already running. This functionality has a lot of very nice uses.
Anyone have any thoughts on doing this in js?
I'm not familiar with this class, but you can easily create something similar in JavaScript:
function Timer(callback, time) {
this.setTimeout(callback, time);
}
Timer.prototype.setTimeout = function(callback, time) {
var self = this;
if(this.timer) {
clearTimeout(this.timer);
}
this.finished = false;
this.callback = callback;
this.time = time;
this.timer = setTimeout(function() {
self.finished = true;
callback();
}, time);
this.start = Date.now();
}
Timer.prototype.add = function(time) {
if(!this.finished) {
// add time to time left
time = this.time - (Date.now() - this.start) + time;
this.setTimeout(this.callback, time);
}
}
Usage:
var timer = new Timer(function() { // init timer with 5 seconds
alert('foo');
}, 5000);
timer.add(2000); // add two seconds
Clear the timeout, then set a new timeout to the new desired end time.
Wrap the function with another one, and when the timer runs out, test to see if an extra time variable has been set. If it has, start again with the new time, otherwise execute the function.
A quickly hacked together script might look like:
function test() {
tim = new timer(function () { alert('hello'); }, 5000);
}
function extend() {
if (tim) { tim.addTime(5000); }
}
function timer(func, time) {
var self = this,
execute = function () {
self.execute()
};
this.func = func;
this.extraTime = 0;
setTimeout(execute, time);
};
timer.prototype.execute = function () {
var self = this,
execute = function () {
self.execute()
};
if (this.extraTime) {
setTimeout(execute, this.extraTime);
this.extraTime = 0;
} else {
this.func();
}
};
timer.prototype.addTime = function (time) {
this.extraTime += time;
}
<input type="button" value="Start" onclick="test()">
<input type="button" value="Extend" onclick="extend()">
There you go hope it helps :) just call setInterval with the time you want to have.
Edit: added stop and start in case you want to stop your loop :p
function Timer(defaultInterval, callback){
var interval = defaultInterval;
var running = true;
function loop(){
callback();
if(running){
setTimeout(function(){
loop();
}, interval);
}
}
loop();
return {
setInterval: function(newInterval){
interval = newInterval;
},
stop: function(){
running = false;
},
start: function(){
if(running===false){
running = true;
loop();
}
},
add: function(milliToAdd){
interval += milliToAdd*1;
}
}
}
var myTimer = Timer(250, function() { process code here });
myTimer.setInterval(1000); // sets interval to 1 second
myTimer.stop(); // stops the function
myTimer.start(); // re-starts the loop;
function Timer(func, delay) {
var done = false;
var callback = function() {
done = true;
return func();
};
var startTime = Date.now();
var timeout = setTimeout(callback, delay);
this.add = function(ms) {
if (!done) {
this.cancel();
delay = delay - (Date.now() - startTime) + ms;
timeout = setTimeout(callback, delay);
}
};
this.cancel = function() {
clearTimeout(timeout);
};
this.immediately = function() {
if (!done) {
this.cancel();
callback();
}
};
};
quick test in the console
start = Date.now();
t = new Timer(function() { console.log(Date.now() - start); }, 1000);
t.add(200);
start = Date.now();
t = new Timer(function() { console.log(Date.now() - start); }, 1000000);
t.immediately();
t.immediately();
you can add negative times too.
start = Date.now();
t = new Timer(function() { console.log(Date.now() - start); }, 1000);
t.add(-200);
Here's my shot. It keeps track of when the timer was set, and adds the difference to the specified time when you add time.
var Timer = {
set: function(p_function, p_time)
{
var d = new Date();
this.timeStarted = d.getTime();
this.func = p_function;
this.timeout = setTimeout(p_function, p_time);
console.log('timer started at ' + (this.timeStarted / 1000) + ' seconds');
},
add: function(p_time)
{
var d = new Date(),
diff = d.getTime() - this.timeStarted,
newTime = diff + p_time;
if (this.timeout)
{
clearTimeout(this.timeout);
}
this.timeout = setTimeout(this.func, newTime);
this.timeStarted = d.getTime();
}
};
var myTimer = Object.create(Timer);
myTimer.set(function() {
var d = new Date();
console.log('Timer fired at ' + (d.getTime() / 1000) + ' seconds');
}, 10000);
setTimeout(function () {
myTimer.add(5000);
}, 5000);
Here's a jsFiddle
Please note that due to overhead of calculation and function calls, this may be a couple milliseconds off.
I decided to throw my little rubber ducky into the pool.
var setTimeout2 = function(callback, delay) {
this.complete = false;
this.callback = callback;
this.delay = delay;
this.timeout = false;
this.dotimeout = function() {
this.timeout = setTimeout(function() {
this.complete = true;
this.callback.call();
}, this.delay);
};
this.start = Date.now();
this.add = function(delay) {
if (!this.complete) {
this.delay = this.delay - (Date.now() - this.start) + delay;
clearTimeout(this.timeout);
this.dotimeout.call();
}
};
return this;
};
usage
var start = Date.now();
var to = setTimeout2(function() {
document.write(Date.now() - start);
}, 3000);
to.add(3000);
similar to this approach but a little more compact / no proto

Categories

Resources