Defining single function to handle functionality of other functions - javascript

I need to define a single function that handles the functionality provided by setSlide, setMobile, and hide and just pass in the function to be called by SetTimeout when the delay has occurred. I'm not sure how to do this. Can someone please explain how to accomplish this? Thank you.
(function($) {
var currentTime = new Date().getTime() / 1000;
var setSlide = function (timeout) {
setTimeout(showSlide, timeout * 1000);
},
showSlide = function () {
$('.newsletter-popup').addClass('slide-left');
},
setMobile = function (timeout) {
setTimeout(showMobile, timeout * 1000);
},
hide = function (timeout) {
setTimeout(hideMobile, timeout * 1000);
},
showMobile = function () {
$('.newsletter-popup').removeClass('hidden');
},
hideMobile = function () {
$('.newsletter-popup').addClass('hidden');
};
$(document).ready(function() {
if (readCookie('nl_suppress')) {
$('.newsletter-popup').removeClass('slide-left');
} else if (!readCookie('nl_display')) {
setSlide(10);
} else if (currentTime - readCookie('nl_display') > 86400) {
showSlide();
} else {
setSlide(currentTime - (readCookie('nl_display') + 86400));
}
$('.nlForm').submit(function() {
createCookie('nl_suppress', new Date(), 30);
});
function checkCookie() {
var date = new Date();
date.setTime(date.getTime() + (86400000));
$('.newsletter-popup').removeClass('slide-left');
hide(1);
if(readCookie('nl_display')) {
// already been clicked once, hide it
createCookie('nl_suppress', new Date(), 180);
return;
}
// first time this is clicked, mark it
createCookie('nl_display', new Date().getTime() / 1000, 180);
setMobile(14);
setSlide(15);
};
$('.newsletter-close').on('click', checkCookie);
});
})(jQuery);

It sounds like you want to create a function that does the same thing as setTimeout, but the delay multiplied by 1000 so that it is in seconds.
It would look like this:
function setTimeoutSeconds(func, delay) {
setTimeout(func, delay * 1000);
}
Then instead of calling setSlide, setMobile, or hide, you call setTimeoutSeconds with the desired callback.
setTimeoutSeconds(hideMobile, 1);
setTimeoutSeconds(showMobile, 14);
setTimeoutSeconds(showSlide, 15);
If you still wanted to have the setSlide... etc functions, you could use a partially applied function:
function applyTimeout(func) {
return function(delay) {
setTimeout(func, delay * 1000);
}
}
And then create them like this:
var setSlide = applyTimeout(showSlide);
And then call them the same way:
setSlide(15);

It's really simple:
const callFunctionWithTimeout = (fn, timeout) => setTimeout(fn, timeout * 1000)
Then, for example instead of setSlide(10), you do:
callFunctionWithTimeout(showSlide, 10)

Related

How to use setTimeout without using setTimeout function

Is there a way to use setTimeout without using setTimeout inbuilt function?
I don't want to use setInterval or clearInterval either or window.use. I have gone through multiple blogs, but all those use window, setInterval or clearInterval.
For example, the below code works, but I dont want to have window.
const setTimeouts = [];
function customSetTimeout(cb, interval) {
const now = window.performance.now();
const index = setTimeouts.length;
setTimeouts[index] = () => {
cb();
};
setTimeouts[index].active = true;
const handleMessage = (evt) => {
if (evt.data === index) {
if (window.performance.now() - now >= interval) {
window.removeEventListener('message', handleMessage);
if (setTimeouts[index].active) {
setTimeouts[index]();
}
} else {
window.postMessage(index, '*');
}
}
};
window.addEventListener('message', handleMessage);
window.postMessage(index, '*');
return index;
}
const setIntervals = [];
function customSetInterval(cb, interval) {
const intervalId = setIntervals.length;
setIntervals[intervalId] = function () {
if (setIntervals[intervalId].active) {
cb();
customSetTimeout(setIntervals[intervalId], interval);
}
};
setIntervals[intervalId].active = true;
customSetTimeout(setIntervals[intervalId], interval);
return intervalId;
}
function customClearInterval(intervalId) {
if (setIntervals[intervalId]) {
setIntervals[intervalId].active = false;
}
}
console.log("1");
customSetTimeout(function() {
console.log('3s');
}, 3000);
console.log("2");
=======================================
Alternate solution:
But here, again i dont want to use clearInterval and setInterval
var setMyTimeOut = function(foo,timeOut){
console.log('inside time out');
var timer;
var currentTime = new Date().getTime();
var blah=()=>{
if (new Date().getTime() >= currentTime + timeOut) {
console.log('clear interval if');
clearInterval(timer);
foo()
}
console.log('clear interval else');
}
timer= setInterval(blah, 100);
}
console.log("1");
setMyTimeOut(function() {
console.log('3s');
}, 3000);
console.log("2");
Is there way to achieve the same but without the use setInterval and clearInterval?
I use here the requestAnimationFrame with performance.now().
Its not super exact (well setTimeout neither), but it do the work.
function sleep(delay, cb) {
function check(time, delay) {
if(time >= delay) {
cb("done");
return;
}
time = performance.now();
requestAnimationFrame(check.bind(null, time,delay))
}
check(performance.now(), delay + performance.now());
}
sleep(4000, ()=> {
console.log("sleep done");
})
console.log("i do not block the main thread");
You can use a while loop which checks a set time against the current time:
const startTime = new Date().getTime() + 3000;
let currentTime = new Date().getTime();
function customTimeout() {
while (startTime > currentTime) {
currentTime = new Date().getTime();
}
return console.log('3 Seconds')
};
customTimeout();

How to clear interval in randomly generated function

I have several functions defined. The setInterval is picking one at random every second. How do I temporarily clear the interval to pause this behavior?
Demo:
http://jsfiddle.net/kthornbloom/NtVBZ/1/
Code:
function playZoomout() {
$('.debug').append('1');
}
function playZoomin() {
$('.debug').append('2');
}
function playPanright() {
$('.debug').append('3');
}
function playPanleft() {
$('.debug').append('4');
}
var fns = [playZoomout, playZoomin, playPanright, playPanleft]
setInterval(function () {
fns[Math.floor(Math.random() * fns.length)]();
}, 1000);
// This isn't working. Probably because the interval above isn't really named?
$('.pause').hover(function(ev){
clearInterval(fns);
}, function(ev){
timer = setInterval( fns, 1000);
});
var fns = [playZoomout, playZoomin, playPanright, playPanleft];
var fn = function () {
fns[Math.floor(Math.random() * fns.length)]();
}
var myInterval = setInterval(fn, 1000);
$('.pause').hover(function(ev){
clearInterval(myInterval);
}, function(ev){
//timer = setInterval( fns, 1000); -> this does not make sense
myInterval = setInterval(fn, 1000); // this does
});
Working demo

Repeating setTimeout

I am trying to repeat setTimeout every 10 seconds. I know that setTimeout by default only waits and then performs an action one time. How can I repeat the process?
setTimeout(function() {
setTimeout(function() {
console.log("10 seconds");
}, 10000);
}, 10000);
Maybe you should use setInterval()
setInterval() is probably what you're looking for, but if you want to do get the same effect with setTimeout():
function doSomething() {
console.log("10 seconds");
setTimeout(doSomething, 10000);
}
setTimeout(doSomething, 10000);
Or if you don't want to declare a separate function and want to stick with a function expression you need to make it a named function expression:
setTimeout(function doSomething() {
console.log("10 seconds");
setTimeout(doSomething, 10000);
}, 10000);
(Or use arguments.callee if you don't mind using deprecated language features.)
according to me setInterval() is the best way in your case.
here is some code :
setInterval(function() {
//your code
}, 10000);
// you can change your delay by changing this value "10000".
Unlike the answers provided by #nnnnnn and #uzyn I discourage you from making use of setInterval for reasons elaborated in the following answer. Instead make use of the following Delta Timing script:
function DeltaTimer(render, interval) {
var timeout;
var lastTime;
this.start = start;
this.stop = stop;
function start() {
timeout = setTimeout(loop, 0);
lastTime = + new Date;
return lastTime;
}
function stop() {
clearTimeout(timeout);
return lastTime;
}
function loop() {
var thisTime = + new Date;
var deltaTime = thisTime - lastTime;
var delay = Math.max(interval - deltaTime, 0);
timeout = setTimeout(loop, delay);
lastTime = thisTime + delay;
render(thisTime);
}
}
The above script runs the given render function as close as possible to the specified interval, and to answer your question it makes use of setTimeout to repeat a process. In your case you may do something as follows:
var timer = new DeltaTimer(function (time) {
console.log("10 seconds");
}, 10000);
var start = timer.start();
const myFunction = () => {
setTimeout(() => {
document.getElementById('demo').innerHTML = Date();
myFunction();
}, 10000);
}
Easiest, but not efficient way!
Here is a function using setTimeout that tried to call itself as close as it can to a regular interval. If you watch the output, you can see the time drifting and being reset.
<script type="text/javascript">
function Timer(fn, interval) {
this.fn = fn;
this.interval = interval;
}
Timer.prototype.run = function() {
var timer = this;
var timeDiff = this.interval;
var now = new Date(); // Date.now is not supported by IE 8
var newInterval;
// Only run if all is good
if (typeof timer.interval != 'undefined' && timer.fn) {
// Don't do this on the first run
if (timer.lastTime) {
timeDiff = now - timer.lastTime;
}
timer.lastTime = now;
// Adjust the interval
newInterval = 2 * timer.interval - timeDiff;
// Do it
timer.fn();
// Call function again, setting its this correctly
timer.timeout = setTimeout(function(){timer.run()}, newInterval);
}
}
var t = new Timer(function() {
var d = new Date();
document.getElementById('msg').innerHTML = d + ' : ' + d.getMilliseconds();
}, 1000);
window.onload = function() {
t.run();
};
</script>
<span id="msg"></span>
Using jQuery, this is what you could do:
function updatePage() {
var interval = setTimeout(updatePage, 10000); // 10' Seconds
$('a[href]').click(function() {
$(this).data('clicked', true);
clearInterval(interval); // Clears Upon Clicking any href Link
console.log('Interval Cleared!');
});
// REPLACE 'YOUR_FUNCTION_NAME' function you would like to execute
setTimeout(YOUR_FUNCTION_NAME, 500);
} // Function updatePage close syntax
updatePage(); // call the function again.

Looping functions with timeout

I want to have two functions (an animation downwards and animation upwards) executing one after the other in a loop having a timeout of a few seconds between both animations. But I don't know how to say it in JS …
Here what I have so far:
Function 1
// Play the Peek animation - downwards
function peekTile() {
var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
// Reposition tiles to their desired post-animation position
tile1.style.top = "-150px";
tile2.style.top = "-150px";
peekAnimation.execute();
}
Function 2
// Play the Peek animation - upwards
function unpeekTile() {
var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
// Reposition tiles to their desired post-animation position
tile1.style.top = "0px";
tile2.style.top = "0px";
peekAnimation.execute();
}
And here's a sketch how both functions should be executed:
var page = WinJS.UI.Pages.define("/html/updateTile.html", {
ready: function (element, options) {
peekTile();
[timeOut]
unpeekTile();
[timeOut]
peekTile();
[timeOut]
unpeekTile();
[timeOut]
and so on …
}
});
You can do this using setTimeout or setInterval, so a simple function to do what you want is:
function cycleWithDelay() {
var delay = arguments[arguments.length - 1],
functions = Array.prototype.slice.call(arguments, 0, arguments.length - 1),
pos = 0;
return setInterval(function () {
functions[pos++]();
pos = pos % functions.length;
}, delay);
}
Usage would be like this for you:
var si = cycleWithDelay(peekTile, unpeekTile, 300);
and to stop it:
clearInterval(si);
This will just cycle through the functions calling the next one in the list every delay msec, repeating back at the beginning when the last one is called. This will result in your peekTile, wait, unpeekTile, wait, peekTile, etc.
If you prefer to start/stop at will, perhaps a more generic solution would suit you:
function Cycler(f) {
if (!(this instanceof Cycler)) {
// Force new
return new Cycler(arguments);
}
// Unbox args
if (f instanceof Function) {
this.fns = Array.prototype.slice.call(arguments);
} else if (f && f.length) {
this.fns = Array.prototype.slice.call(f);
} else {
throw new Error('Invalid arguments supplied to Cycler constructor.');
}
this.pos = 0;
}
Cycler.prototype.start = function (interval) {
var that = this;
interval = interval || 1000;
this.intervalId = setInterval(function () {
that.fns[that.pos++]();
that.pos %= that.fns.length;
}, interval);
}
Cycler.prototype.stop = function () {
if (null !== this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
}
Example usage:
var c = Cycler(peekTile, unpeekTile);
c.start();
// Future
c.stop();
You use setInterval() to call unpeekTile() every 1000 milliseconds and then you call setTimeOut() to run peekTile() after 1000 milliseconds at the end of the unpeekTile() function:
function peekTile() {
var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
// Reposition tiles to their desired post-animation position
tile1.style.top = "-150px";
tile2.style.top = "-150px";
peekAnimation.execute();
}
function unpeekTile() {
/* your code here */
setTimeout(peekTile, 1000);
}
setInterval(unpeekTile, 1000);
Check out the fiddle
var animation = (function () {
var peekInterval, unpeekInterval, delay;
return {
start: function (ip) {
delay = ip;
peekInterval = setTimeout(animation.peekTile, delay);
},
peekTile: function () {
//Your Code goes here
console.log('peek');
unpeekInterval = setTimeout(animation.unpeekTile, delay);
},
unpeekTile: function () {
//Your Code goes here
console.log('unpeek');
peekInterval = setTimeout(animation.peekTile, delay);
},
stop: function () {
clearTimeout(peekInterval);
clearTimeout(unpeekInterval);
}
}
})();
animation.start(1000);
// To stop
setTimeout(animation.stop, 3000);
​
I can't use this instead of animation.peekTile as setTimeout executes in global scope

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