How to remove an attribute after animation in jquery - javascript

I'd like to remove an id from an image after its animation is completed. I have this in my code:
if(index == 1 && direction =='down'){
$('#slidetext1 #rock').animate({right:"0"});
$('#slidetext1 #deer').animate({left: "0"}).addClass('open').removeAttr('id');
}
It's not working because it removes the id before even starting the animation, but what I want to do is to remove the id #deer from the image and add ('open') after the .animate() has been executed.
so here i made a jsfiddle: http://jsfiddle.net/67oe1jvn/45/ . pay attection to the left image as you scroll down under the HELLO h1. the thing i want to achive is: when i get to the second section, i'd like to see both of the images slide in the view with the directive "transition:all 1.2s ease-out;" AND whenever the section gets changed make them slide out of the view with a faster transiction, so it won't been noticed that much.

You need to supply the complete callback function which is fired once the animation is complete. You can achieve this by updating the code to following
if(index == 1 && direction =='down'){
$('#slidetext1 #rock').animate({right:"0"});
$('#slidetext1 #deer').animate({left: "0"}, function(){
$(this).addClass('open').removeAttr('id')
});
}
For reference - http://api.jquery.com/animate/

Please try this
$.when($('#slidetext1 #deer').animate({left: "0"})).then(function(){
$('#slidetext1 #deer').addClass('open').removeAttr('id')
});
If a single Deferred is passed to jQuery.when(), its Promise object (a subset of the Deferred methods) is returned by the method. Additional methods of the Promise object can be called to attach callbacks, such as deferred.then. When the Deferred is resolved or rejected, usually by the code that created the Deferred originally, the appropriate callbacks will be called.
OR
$('#slidetext1 #deer').animate({left: "0"}).promise().done(function(){
$('#slidetext1 #deer').addClass('open').removeAttr('id')
});
The .promise() method returns a dynamically generated Promise that is resolved once all actions of a certain type bound to the collection, queued or not, have ended.
DEMO with .promise()
DEMO with .when()

Related

Does dojo/_base/fx support promises?

I am need to execute a method after an animation on a dom element ends.
At the moment I am using the following code with no success.
I would like to know if dojo, support promise for animation, if no, I would like to know in which way I could work it out.
fx.fadeOut({ node: 'target'}).play().then(function () {
// do smt here
}.bind(this));
Yes can you use the registered Callback of the FadeOut function.
the fadeOut (dojo/_base/fx function which returns an annimation instance)
provides 5 registred callback functions :
beforeBegin
onBegin
onEnd
onPlay
onAnimate (with argument)
In your case you need to make some actions when the animation is done so passe the onEnd function in the FadOut arguments, it should look like :
fx.fadeOut({
node:"target",
onEnd: function(){
// Some stuff at the end of the animation.
}
}).play();
you can also use the above callback as args .
I was able to solve this issue using 'dojo/on' and subscribing to the End event on fx.fadeOut(). Still I am very interesting to understand if there are better way for the same result.
var anim = fx.fadeOut({ node: 'target'}).play();
on(anim, "End", function () {
// dom smt here
}.bind(this));

understanding how $.promise works similar to transitionEnd

I was just messing around on the documentation page of jQuery.promise() and came across the following peice of code :
$("button").on("click", function () {
$("p").append("Started...");
$("div").each(function (i) {
$(this).fadeIn().fadeOut(1000 * (i + 1));
});
$("div").promise().done(function () {
$("p").append(" Finished! ");
});
});
FIDDLE HERE
Now I do understand that $.defer in jQuery assists in Asynchronous programming, also I understand that $.done and $.fail are part of the $promise object .
I have read an interesting article HERE. There are a few good examples of how $.defer can be used to monitor css-3 transitions.
However in the fiddle example I provide, I fail to understand how $.promise picks up the fact that the transition is complete. How does promise pick up that that fadeout() is complete?
How does the below piece of code really work?
$("div").promise().done(function () {
$("p").append(" Finished! ");
});
How is promise really working here? Can anyone explain?
To put it simply, jQuery creates a queue of Deferred objects on each object returned by the $("div") selector (these are visible using the .data() function).
When you add some CSS animations to the divs with jQuery functions such as fadeIn() or fadeOut(), it creates Deferred objects that are appended to each individual div queues.
Using$("div").promise().done() on the parent collection allows to check if all of the children Deferred object queues are empty (jQuery will iterate on the children elements).
I haven't delved into the jQuery source, but here's my understanding.
$.promise returns a Promise which completes once all actions of a certain type have ended. By default, the 'type' is fx (source).
When the fx queue is empty, the promise will resolve.
In your fiddle, you call fadeIn(), which adds the animation to the fx queue. ($.fadeIn() has queue: true by default.) $.fadeOut does the same.
When the queue is empty, the promise will resolve. This fiddle would support that. (Queue is 'inprogress' whilst the animations are running, but empty 100ms later.)
A slightly more convoluted fiddle - notice how the promise completes when we clear the fx queue using $(el).queue('fx',[]);?

clearInterval() and setInterval() when all animations are complete

I have a function that is repeatedly being called with setInterval creating animations. If there are still animations running I need it to stop calling the function until all the animations are complete. The code I am using is as follows:
EDIT: Added coded where I am removing the animated elements from the DOM, is that the problem?
var serviceLoop = setInterval(serviceQueue, LOOP_POLL_MS); //10 ms
function serviceQueue()
{
//do some animations..
function moveMan(from, to, plane)
{
(function() {
var tmp_from = from;
var tmp_to = to;
var tmp_plane = plane;
var pos = tmp_from.offset();
var temp = tmp_from.clone(true);
temp.css({ "visibility":"visible",
"position":"absolute",
"top":pos.top + "px",
"left":pos.left + "px"});
temp.appendTo("body");
tmp_from.css("visibility", "hidden");
//if (!tmp_plane) tmp_to.css("visibility", "hidden");
temp.animate(to.offset(), moveMan.ANIMATION_TIME, function() {
tmp_to.css("visibility", "visible");
temp.remove();
});
})();
}
if ($(":animated").length > 0)
{
clearInterval(serviceLoop);
$(":animated").promise().done(function() {
serviceLoop = setInterval(serviceQueue, LOOP_POLL_MS);
});
}
}
The problem I am having is after a couple of animations the function passed to done() is never called, and the script stops.
It seems likely that you end up waiting on a promise() that is waiting on some animations, but then you remove some of those objects from the DOM and then their animation never finishes so the promise never resolves.
See this quote from the jQuery doc for .promise():
Note: The returned Promise is linked to a Deferred object stored on
the .data() for an element. Since the.remove() method removes the
element's data as well as the element itself, it will prevent any of
the element's unresolved Promises from resolving. If it is necessary
to remove an element from the DOM before its Promise is resolved, use
.detach() instead and follow with .removeData() after resolution.
One quick hack might be top call .stop(true) on any item that you are removing from the DOM.
In general, this code needs to be rewritten to be safe from that possibility and hopefully to rethink how you approach whatever it is you're trying to do every 10ms because that's generally a bad design. You should use events to trigger changes, not a 10ms polling operation. You have not explained the purpose of this code so it's not clear to me what alternative to suggest.

How to change css property (like cursor:wait, or background) before AND after ajax calls?

I'm having problems with this code, I'm trying to show a red background while a function is working, and then (only then) I'm changing the background to green.
When the following alert is not commented, I can see the red background for a while and then the green (that's what I want).
But when I comment that alert, seems like the red background is never set and once processData has finished, the background is set to green, correctly.
Can somebody solve this mystery for me? thanks!
function beforeProcess(params){
$('#result').css('background','red');
alert('now i start waiting, while background is red');
$.when(processData(params)).done(
$('#result').css('background','green')
);
}
function process(params){
//This function takes some time, and it makes (indirectly) some synchronous ajax calls (async:false)
}
The view is only updated after the function finishes execution. This can be accomplished using a setTimeout
http://jsfiddle.net/YEVHv/4/
$('#result').css('background', 'red');
//alert('now i start waiting, while background is red');
setTimeout(function () {
$.when(process("")).done(
$('#result').css('background', 'green'));
}, 0);
function process(params) {
for (var i = 0; i < 10000; i++) {
console.log("hello");
}
}
Hope that helps
My guessing is that your function "process" returns quickly... remember that every function call in JS is performed async. If you want to show progress or display some state (red color) while processing, you must be sure that the function process returns after all sub-functions finish. Right now, I can only think about using standard callbacks.
$.when is useful when it used with deferred objects. If the function you use is not a deferred object, the "done" is executed immediately. Please, take a look at the following extract from "http://api.jquery.com/jQuery.when/" : "If a single argument is passed to jQuery.when and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately."
Hope this helps

Fire a callback only once on animating two objects

I was starting to make a quite complex animation with jQuery and I was looking for a certain way to animate elements together. I wrote the code somewhat as follows, which I could use to animate multiple elements together:
Here's the fiddle: http://jsfiddle.net/wkhrU/
$(document).ready(function(){
$('#firstElement, #secondElement').animate(
{left : '+=400px'},
500,
"linear",
function(){
alert("completed");
});
});
However, the callback function fires twice i.e. each time for the element inside. What I was looking for is to be something like animating multiple elements simaltaneously for the same time duration and after the completion, fire a call inside which I wanted to swap the id attrib of the elements. I can't do the same here because on completion callback, it swaps the ids once and on the next function callback, swaps them back again. What's the appropriate way to achieve this?
SOLUTION
You could maybe use a promise() to call the function to be executed instead of the inbuilt callback of animate. This ensures that the function in done is called only after animating both the elements. It's basically like you're asking #firstElement & #secondElement to promise JS that it'll inform when both of 'em are done so that you could attach a done handler to it.
$(document).ready(function () {
$('#firstElement, #secondElement').animate({
left: '+=400px'
},
500, "linear").promise().done(function () {
alert("completed");
});
});
DEMO
http://jsfiddle.net/hungerpain/wkhrU/1/
MORE INFO ON USED METHODS :
promise
Docs : http://api.jquery.com/promise/
What it does : Makes sure that all actions of a certain type bound to the collection, queued or not, have finished.
done
Docs : http://api.jquery.com/deferred.done/
What it does : Add handlers to be called when the promise is resolved.

Categories