I made a very simple plugin for my personal use that allows animated rotations in jQuery.
And I added callback functions.
If the rewind parameter is true, the rotation is undone and then, a callback.
If it's false, the callback is immediate after the rotation.
I had to do this because, for some reason, the .promise().done(function(){ ... }) is called before complete: of animate()
So I had to skirt this.
Now the problem is that if I target multiple elements, the callback is called for each element. 'cause I use an each function I presume. But I want only one callback for the whole animation.
Here is the fiddle
How to do this please? Thx !
PS: I saw a similar question here : jQuery $.animate() multiple elements but only fire callback once but not applying because of the .promise().done() issue. And I don't want to add a variable, I want to understand ^^
You could try using the index of each and only call the callback if it is the first element
Something like:
return this.each(function(i) {
....
....
complete: function() {
i==0 && a.callback && a.callback()
}
Related
I have this function but I know the error is I put two commands, first to fadein an element and hide other. How can I made this in correct mode?
$(maisJuridico).on("mousedown", function(){
$(Juridico).fadeIn();
$(menosJuridico).hide();
}, false);
First of all, as long as you're using jQuery, you don't need .addEventListener. You can bind your events with on.
So, if you want the second method to be invoked after the fadeIn animation is finished, you can pass a complete callback function and call the second method from there.
Something like this:
(maisJuridico).on("mousedown", function(){
$(Juridico).fadeIn({
complete: function() {
$(menosJuridico).hide();
}
});
}, false);
From the docs:
.fadeIn( options )
complete
Type: Function()
A function that is called once the animation
on an element is complete.
Another syntax is pass the complete callback as a second parameter. In this case, the first argument is duration. Like this:
$(Juridico).fadeIn(400, function() {
$(menosJuridico).hide();
});
See JSfiddle!
I am wanting to animate a set of elements and execute a callback when finished like so:
s.selectAll('.active').animate( {
transform: matrix
},
300,
mina.linear,
function() {
//callback doesnt fire
alert('callback')
}
)
The elements are animated correctly but the callback isnt executed.
However, when I apply the animation to a group of elements, the callback is fired:
group.animate( {
transform: matrix
},
300,
mina.linear,
function() {
alert('callback')
}
)
.. But I don't want to put my selected elements in a group as this would cause more complications in other places.
Is it possible to animate a set of elements that I got via a .select() or .selectAll() while being able to fire the callback?
Thanks a lot in advance!
Edit: For future readers, you can animate a set of elements by using forEach and counting if all elements are done animating:
function hideToPoint(elements, x, y, callback) {
var finished = 0;
elements.forEach(function(e) {
e.animate( {
//do stuff
},
300,
mina.linear,
function () {
finished++;
if (finished == elements.length) {
callback();
}
}
)
})
}
I'm going to have a stab at answering a couple of problems, even though I'm not sure if related to the callback. Its hard to tell if its just the example code or not without a proper test like a jsfiddle.
However, there are at least 2 problems in the code above.
Creating a matrix is with
new Snap.Matrix(); // as opposed to Snap.matrix()
Also
elements.animate()
The problem here is that animate acts on one element (edit: looks like it can work on elements within a set, but not the callback as example here, edit2: callbacks on sets may now be supported), not multiple elements as such (you can sometimes apply somethings to a set which deals with them individually, but as far as I'm aware, thats not the case with animate).
So you either want to do a
elements.forEach( function(el) { el.animate({blah: value}, 2000, mina.linear.callback )
});
or if its an svg group (as opposed to a set), the original code would possibly work (but I would call it 'myGroup' or something instead of 'elements' for code readability and guessing what it contains)
fiddle (have included a different animation using snap animation string)
I just want to animate element during a game of cards, but the problem is that when I use the animate function the code is continue to run.
I tried with the promise() and done() function, but for some reason it doesn't help.
Here is what I did:
$(document).ready( function() {
$(".demoCard").animate({
"margin-top": '-150'
}, 1000, "easeInSine", function() {
$(".demoCard").remove();
});
});
According to the api documentation. Your callback is correct. Try updating your jQuery api. Maybe you are using an outdated version. If that doesn't work, try removing your easing argument. JQuery might be trying to use the easing argument as a callback function. If you need your easing, make sure you have jQuery UI installed and loaded. Otherwise, jQuery won't recognize the easing, and try to use easeInOutSine as the callback function.
I have some code, with the order of the functions in the order I want them executed. However, they seem to at the same time (they begin sequentially within microseconds of eachother presumably).
The problem is that some of the functions include animations. How do I make it so the next function doesn't execute until the previous functions are completely finished???
Following is some of my code. I created a callback chain thinking that it would be the solution, but indeed it is not. The functions themselves call jQuery animations. I'm guessing i need to use some type of notofication from jQuery to tell me when animations are done. Anyhow, any advice is greatly appreciated!
show_loader(0, function() {
close_box($target_close, '/', '#' + $target_close.attr('id') + ' .post_wrap', function() {
open_box($target_open, event.value, '.wide-col', function() {
hide_loader(function() {
scroll_to_content($target_open, function() {
});
});
});
});
});
To be precise, I want the scroll_to_content() function to be executed after all the previous actions have been completed in their entirety. Currently, it executes at the same time as everything else, and therefore my page scroll is completely off because the size of my content continues changing after scroll_to_content() is finished.
Callback chains are basically the solution but I suspect you're not threading your callbacks correctly in your calls to jQuery. $.animate(...) has an optional complete callback-- that's where you want to pass the function that should execute after your initial animation finishes. All of the Effects in jQuery UI should have a similar optional argument.
You can use a similar pattern yourself in order to chain event handlers, for instance:
function handler(event, callback) {
// do some work
// ...
callback();
}
This strategy for chaining function evaluations is called continuation-passing style and is handy in a lot of situations. Be careful using it, however, as many people find it more confusing to read than a traditional, sequential implementation.
http://api.jquery.com/queue/
Sorry, I don't have enough time to go into detail, but as the previous commenter said, queues are what you want to be focusing on to solve this problem.
you have 3 options:
1- Split your animations into multiple chained animate() calls.
This is an example to clarify it for you.
2- Follow the answer posted by #dml.
3- Try to use this plugin to add delays between your calls (don't know if it can fix this scenario or not, give it a try)
http://www.evanbyrne.com/article/jquery-delay-plugin
I'm trying to figure out how to chain custom functions:
I have something like this:
show_loader(0, function() {
open_box($target_open, event.value, '.wide-col', function() {
hide_loader(function() {
scroll_to_content($target_open, function() {
});
$(this).dequeue();
});
$(this).dequeue();
});
$(this).dequeue();
});
Those functions have a callback implemented that looks something like this:
function show_loader(position, callback) {
$ajaxSpinner.fadeIn();
status = "loading"; //some non-jQuery stuff
if (callback) $ajaxSpinner.queue( function() {callback()} );
}
You can see the basic idea of what i'm trying to do: execute my functions after the animations inside the functions are complete.
I don't think my code is quite right. The order should be: show loader, open box, hide loader, then finally scroll to content. Instead, it seems like this is what's actually happening when i test it: show loader, hide loader, scroll to content, then open box.
How do I get that order of function calls properly queued? And am I using the keyowrd "this" in the proper context?
You can see the basic idea of what i'm trying to do: execute my functions after the animations inside the functions are complete.
If you use standard animation functions from jQuery, you should be able to directly pass a callback to them. E.g.:
function show_loader(position, callback) {
$ajaxSpinner.fadeIn(callback);
status = "loading"; //some non-jQuery stuff
}
Have a look at http://api.jquery.com and see how they work.
Update:
Here is an example that produces the desired result using queue. I'm using a newer form, where the next function to execute is passed as argument to the callback. Maybe you are doing something wrong with dequeue. Edit: I tried your code and it works fine. I guess your are not using queue properly in the other functions.