How to use callback to chain animations with JavaScript - javascript

I would like to chain three animations with JavaScript and Transit.js. The second one must be launched after the first is complete. For this I'm trying to use callbacks.
It's important for me to separate these three functions. I don't want to nest them.
// fn 1
function one(callback) {
$(body).transition({
'opacity': '1'
}, 500, function(){
callback;
console.log('callback one');
});
}
// fn 2
function two(callback) {
$('section').transition({
'opacity':'1',
}, 500, function(){
console.log('callback two');
callback;
});
}
// fn 3
function three(callback) {
$('aside').transition({
'opacity':'1',
}, 500, function(){
console.log('callback three');
callback;
});
}
I start functions like this:
one(two(tree()));
The problem is, the second function starts before the first is completed. What is wrong with this script?

Wrap your callback function in setTimeout function
function one(callback) {
$(body).transition({
'opacity': '1'
}, 500, function(){
setTimeout(function(){
callback();
console.log('callback one');
},0);
});
}
// fn 2
function two(callback) {
$('section').transition({
'opacity':'1',
}, 500, function(){
setTimeout(function(){
callback();
console.log('callback two');
},0);
});
}
// fn 3
function three(callback) {
$('aside').transition({
'opacity':'1',
}, 500, function(){
setTimeout(function(){
callback();
console.log('callback three');
},0);
});
}

try this, it should work as you expected.
// fn 3
function three() {
$('aside').transition({
'opacity':'1',
}, 500, function(){
console.log('callback three');
});
}
// fn 2
function two() {
$('section').transition({
'opacity':'1',
}, 500, three);
}
// fn 1
function one() {
$(body).transition({
'opacity': '1'
}, 500, two);
}
one();//invoke fn1

You need to pass the reference of the function as the argument instead of passing the executed result.
// this would execute the function `three` and pass the
// returned value as the argumnet to function `two`
// after executing `two` the returned value would pass to
// function function `one` . Since any none of the function is
// returning anything the argument value would be `undefined`
one(two(tree()));
The better way to make it cyclic is adding the callback as the function reference.
function one() {
$(body).transition({
'opacity': '1'
}, 500, two);
}
// fn 2
function two() {
$('section').transition({
'opacity':'1',
}, 500, three);
}
// fn 3
function three() {
$('aside').transition({
'opacity':'1',
// if you don't want to make it cyclic then remove the
// callback argument `one`
}, 500, one);
}
UPDATE : If you wanna pass it as an argument then pass the reference as a callback function and within the callback call the function you want.
function one(callback) {
$(body).transition({
'opacity': '1'
}, 500, function(){ calback() });
// or simply
// }, 500, calback);
}
// fn 2
function two(callback) {
$('section').transition({
'opacity':'1',
}, 500, , function(){ calback() });
}
// fn 3
function three(callback) {
$('aside').transition({
'opacity':'1',
}, 500, , function(){ calback() });
}
// use nested callbacks as you want
one(function(){ two(function(){ three(function(){}); }); })

Related

How to stop a timeout if it is running in javascript

I have a timeout setup like this below:
var someObj = {
init: function() {
someObj.timeout();
someObj.someWork();
},
timeout : setTimeout(function() {
someObj.myFunc();
}, 15000),
myFunc: function() {
console.log('myFunction called');
},
someWork: function(){
console.log('some work');
if(this.timeout !== null){
console.log('clearing timeout...');
clearTimeout(this.timeout);
}
}
}
$(function() {
someObj.init();
});
I want to stop the timeout if it is assigned to timeout variable and not null.
Jsfiddle link: https://jsfiddle.net/jy2p7jtd/17/
Is it possible?
Update:
Is this valid way to assign a timeout and clear it?
var someObj = {
timeout :null,
init: function() {
someObj.make();
someObj.someWork();
},
make: function(){
this.timeout = setTimeout(function() {
console.log('myFunction called');
}, 15000)
},
someWork: function(){
console.log('timeout is ', this.timeout);
if(this.timeout !== null){
console.log('clearing timeout...');
clearTimeout(this.timeout);
}
}
}
$(function() {
someObj.init();
});
updated link: https://jsfiddle.net/jy2p7jtd/41/
declare another property timeoutId:null and check if it is present then clear it.
var someObj = {
timeoutId: null,
init: function() {
this.timeoutId = this.timeout();
someObj.someWork();
},
timeout: function() {
return setTimeout(function() {
someObj.myFunc();
}, 15000)
},
myFunc: function() {
console.log('myFunction called');
},
someWork: function() {
console.log('some work');
if (this.timeoutId) {
console.log('clearing timeout...');
clearTimeout(this.timeoutId);
}
}
}
$(function() {
someObj.init();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
clearTimeout() prevents the function set with the setTimeout() to execute.

How to looping this function after the last value

var board = new DepartureBoard(document.getElementById('test'), {
rowCount: 1,
letterCount: 13
});
window.setTimeout(function() {
board.setValue(['VISA SERVICES', ]);
}, 0)
window.setTimeout(function() {
board.setValue(['POE CLEARENCE', ]);
}, 8000);
window.setTimeout(function() {
board.setValue(['STAMPING', ]);
}, 16000);
window.setTimeout(function() {
board.setValue(['ATTESTATION', ]);
}, 24000);
window.setTimeout(function() {
board.setValue(['INSURANCE', ]);
}, 32000);
window.setTimeout(function() {
board.setValue(['FOREX', ]);
}, 40000);
https://codepen.io/Mtn_Wolf/pen/LKsvz
I am trying like the Airport departure but i can't able to looping the value after the last value displayed in my website to show services how i can loop the value after the last content displayed
Using direct timeouts in modern ECMAScript is not good pattern, not just because "modern approach", but because better chaining and error handling
function delay(time) { return new Promise(resolve => setTimeout(resolve, time) }
function worker() {
return Promise.resolve()
.then(() => board.setValue(['VISA SERVICES']))
.then(() => delay(1000))
// and so on
.then(worker);
}
worker().catch((error) => {
// Error handling here
})
Basically you could use an outer interval, which length is the complete period and inside call the smaller timeout for the next actions.
function startInterval() {
window.setTimeout(function() { board.setValue(['VISA SERVICES']); }, 0)
window.setTimeout(function() { board.setValue(['POE CLEARENCE' ]); }, 8000);
window.setTimeout(function() { board.setValue(['STAMPING']); }, 16000);
window.setTimeout(function() { board.setValue(['ATTESTATION']); }, 24000);
window.setTimeout(function() { board.setValue(['INSURANCE']); }, 32000);
window.setTimeout(function() { board.setValue(['FOREX']); }, 40000);
}
startInterval();
setInterval(startInterval, 48000); // use the length of the period
There are many ways you could accomplish this, here's my suggestion, which basically keeps your current code intact -
Put all of your calls to window.setTimeout() in a function - at the end, add one more call to window.setTimeout() that just calls the function, which will start it again. Something like...
var board = new DepartureBoard(document.getElementById('test'), { rowCount: 1, letterCount: 13 });
var myFunction = function(){
window.setTimeout(function() {
board.setValue(['VISA SERVICES', ]);
}, 0)
window.setTimeout(function() {
board.setValue(['POE CLEARENCE', ]);
}, 8000);
window.setTimeout(function() {
board.setValue(['STAMPING', ]);
}, 16000);
window.setTimeout(function() {
board.setValue(['ATTESTATION', ]);
}, 24000);
window.setTimeout(function() {
board.setValue(['INSURANCE', ]);
}, 32000);
window.setTimeout(function() {
board.setValue(['FOREX', ]);
}, 40000);
window.setTimeout(function() {
myFunction(); // call it again here, and the process will start over
}, 50000);
}
myFunction(); // don't forget - now that all of the window.setTimeout calls are wrapped in a function, the process won't start unless you call the function here, setting off the loop

how to get callback when scrollTo mCustomScrollbar or run function

how to get alert when scrollTo mCustomScrollbar or run function
$('.section-wrap').mCustomScrollbar("scrollTo", 0, {
scrollInertia: 1500,
scrollEasing: "easeOut",
callback:{
alert() or somefunc ();
}
});
function somefunc(){
alert();
}
Use onScroll or some other callback:
jQuery('.section-wrap').mCustomScrollbar("scrollTo", 0, {
scrollInertia: 1500,
scrollEasing: "easeOut",
callbacks: {
onScroll: function() {
// your code
alert('content scrolled...');
}
}
});

jQuery deferred - when multiple timeout tasks have completed

Having a few teething problems with $.deferred, $.when and $.done.
I'm calling a method which has a couple of tasks inside on a timer. I'm looking at getting a callback when everything inside this method has completed, including the stuff in timers, so started looking at $.when() and $.done() to achieve this.
The problem I am getting is the function is firing before the tasks have completed, immediately as the method is called. So, I started playing with $.deferred and resolve(), but haven't managed to get anything working. Without the timers, I can do it.
This is where I call the method:
$.when(cover.start()).done(function() {
console.log("Cover has started.");
});
This is the entire method:
return {
other: function() {},
start: function() {
var dfd = $.Deferred();
el.filter.animate({
"opacity": "0.6", "filter": "alpha(opacity=60)"
}, 2000, "easeInOutCirc", function() {
el.share.removeClass('fa-spin');
setTimeout(function() {
el.share.removeClass('fa-cog').addClass('fa-bars');
},1000);
setTimeout(function() {
el.scroll.animate({
"opacity": "1",
"bottom": "40px"
}, 1200, "easeOutBounce", function() {
var pulseOptions = { opacity: "0" };
setTimeout(function() {
el.scroll.pulse(pulseOptions, {
duration : 400,
pulses: 3,
interval: 500,
returnDelay: 800
});
}, 2000);
dfd.resolve();
});
}, 2000);
return dfd.promise();
});
}
} // end return
As you can see, after my original attempt failed, I added dfd.resolve() to where I want the callback and tried to return the promise. However, the function still fires too early. Where am I going wrong?
The problem is, you need to return promise from the start method
return {
other: function () {},
start: function () {
var dfd = $.Deferred();
el.filter.animate({
"opacity": "0.6",
"filter": "alpha(opacity=60)"
}, 2000, "easeInOutCirc", function () {
el.share.removeClass('fa-spin');
setTimeout(function () {
el.share.removeClass('fa-cog').addClass('fa-bars');
}, 1000);
setTimeout(function () {
el.scroll.animate({
"opacity": "1",
"bottom": "40px"
}, 1200, "easeOutBounce", function () {
var pulseOptions = {
opacity: "0"
};
setTimeout(function () {
el.scroll.pulse(pulseOptions, {
duration: 400,
pulses: 3,
interval: 500,
returnDelay: 800
});
}, 2000);
dfd.resolve();
});
}, 2000);
});
//need to return from start
return dfd.promise();
}
} // end return
Not fishing to steal APJ's rep' but out of interest, you could avoid callback hell by exploiting .delay() and .promise(), both of which relate to the default "fx" animation queue.
Something along the following lines would fix the problem, and would be more readable :
//animation maps
var maps = [];
maps[0] = { 'opacity':0.6, 'filter':'alpha(opacity=60)' };
maps[1] = { 'opacity':1, 'bottom':'40px' };
maps[2] = { 'opacity':0 };
maps[3] = { 'duration':400, 'pulses':3, 'interval':500, 'returnDelay':800 };
//animation functions
var f = [];
f[0] = function () {
return el.filter.animate(maps[0], 2000, "easeInOutCirc").promise();
};
f[1] = function () {
return el.share.removeClass('fa-spin').delay(1000).promise();
};
f[2] = function () {
return el.share.removeClass('fa-cog').addClass('fa-bars').delay(1000).promise();
};
f[3] = function () {
el.scroll.animate(maps[1], 1200, "easeOutBounce").promise();
}
f[4] = function () {
return el.scroll.delay(2000).promise();//delay() could be called on any element. `el.scroll` is arbitrary.
};
f[5] = function () {
el.scroll.pulse(maps[2], maps[3]);
};
return {
other: function () {},
start: function () {
//animation sequence
var p = f[0]().then(f[1]).then(f[2]).then(f[3]);
p.then(f[4]).then(f[5]);
return p;//<<<< and here's the all important return
}
}
Not sure this is 100% correct - might need some work.
It's worth noting that there are performance pros and cons with this approach :
Pros: Reusable animation maps; Reusable functions;
Cons: More liberal use of promises will cause a larger memory spike.

how to wait the execution of line in Javascript?

$("#div_id").click(function() {
$(this).effect("shake", { times:3 }, 300);
// Here I want wait that the div_id can complete its shake
alert('hello');
}
.delay I tried but it is not working.
$(this).effect("shake", { times:3 }, 300, function() {
// this will alert once the animation has completed
alert('hello');
});
If you're using jQuery UI, you should just be able to add a callback as the 4th parameter.
See: http://jqueryui.com/demos/effect/
$("#div_id").click(function() {
$(this).effect("shake", { times:3 }, 300, function(){
alert('hello');
});
}
$(this).effect("shake", { times:3 }, 300, function() {
alert('hello');
});

Categories

Resources