I have a series of animation to do, among other stuff between events..., I would like to know if it if possible to use a custom queue for that. I know I could use other stuff like setTimeout or using callback...but a queue would be handy so I could use it through out functions and not mess the animations (for curiosity to..)
I was thinking something like:
$("#content")
.queue("cont_queue", function() {
$("#backgroung").animate({
width : "85.6%"
},900);
}).queue("cont_queue", function() {
$("#elem1").fadeIn(900);
}).queue("cont_queue", function() {
do order stuf
}).queue("cont_queue", function() {
$("#elem2").fadeIn(900);
})
.dequeue("cont_queue").delay(1000, "cont_queue")
.dequeue("cont_queue").delay(1000, "cont_queue")
.dequeue("cont_queue").delay(100, "cont_queue")
.dequeue("cont_queue").delay(1200, "cont_queue");
Thanks =)
//you can use the animation complete parameter in jquery animate.
$("something").animate( properties [, duration ] [, easing ], function() {
//first animation is done
$("somethingElse").animate( properties [, duration ] [, easing ], function() {
//second animation is done and so on
});
} )
//another option
var cont = $(".container");
animation1 = function(next) {
setTimeout(function() {
cont.css("background-color","black");
if (next) {next();}
}, 2000);
}
animation2 = function(next) {
setTimeout(function() {
cont.css("background-color","white");
if (next) {next();}
}, 2000);
}
jQuery.queue(cont,"animations",animation1);
jQuery.queue(cont,"animations",animation2);
jQuery.queue(cont,"animations",animation1);
jQuery.queue(cont,"animations",animation2);
jQuery.dequeue(cont, "animations");
jsFiddle
$("#conteudo")
.queue("cont_queue", function() {
$("#backgroung").animate({
width : "85.6%"
},900);
}).queue("cont_queue", function() {
setTimeout(function(){$("#painel_subsistemas").fadeIn(900);}, 950);
}).queue("cont_queue", function() {
carregaTopicos(sistema);
}).queue("cont_queue", function() {
setTimeout(function(){$("#topicos_lista").fadeIn(900);}, 950);
});
$("#conteudo").dequeue("cont_queue");
$("#conteudo").dequeue("cont_queue");
$("#conteudo").dequeue("cont_queue");
$("#conteudo").dequeue("cont_queue");
Related
I've got a following code for fadeOut, load another content and fadeIn, but I've got a problem, that sometimes, when the load function is very fast, it switches the loaded content even before the timeline completely fadeOut, so the effect is a bit weird at this case. How can I prevent this?
Note
I want to load content immediately after click, so putting the load function into the first fadeTo callback function is not the solution. Thanks!
$(".switches li").click(function(evn) {
$(".switches li").removeClass("active");
$(evn.target).addClass("active");
$(".timeline").fadeTo(400, 0, function(){
$(this).css("visibility", "hidden");
});
$(".timeline").load("inc-timeline/"+evn.target.id+".html", function() {
$(this).fadeTo(400, 100, function() {
$(this).css("visibility", "visible");
if(evn.target.id === "data-girls") {
$(".data-girls-powered").fadeIn(400);
} else {
$(".data-girls-powered").fadeOut(400);
}
});
});
});
Use start option of .animate(), .finish()
// call `.load()` when `.fadeTo(400, 0)` starts
$(".timeline").finish().animate({opacity:0},{
start: function() {
// do asynchronous stuff; e.g., `.load()`
$(this).load("inc-timeline/"+evn.target.id+".html", function() {
// stop `.fadeTo(400, 0)` animation,
// start animating to `opacity:1`
$(this).finish().fadeTo(400, 1, function() {
// do stuff
});
});
},
duration: 400
});
$("button").click(function() {
// call `.load()` when `.fadeTo(400, 0)` starts
$(".timeline").finish().animate({opacity:0},{
start: function() {
var el = $(this);
// do asynchronous stuff; e.g., `.load()`
$.Deferred(function(dfd) {
setTimeout(function() {
dfd.resolveWith(el)
}, Math.floor(Math.random() * 3500))
}).promise().then(function() {
// stop `.fadeTo(400, 0)` animation,
// start animating to `opacity:1`
$(this).finish().fadeTo(400, 1, function() {
});
});
},
duration: 400
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>click</button>
<div class="timeline">abc</div>
What about changing the duration of the load..to be longer than 400 milliseconds, would that help?
I got an element that is slided down by JQuery using .slideDown() method
$('#dropdown_shopping_cart').slideDown(800);
Now i want it to slide up after 6 seconds, but only if there is no hover on the element, if there is an hover, it should not .slideUp().
So far i worked with a timeout that added display:none to the element while i was giving the element´s hover display:block!important; in CSS so it would not get display: none until the hover is over.
JS
setTimeout(function () {
$('#dropdown_shopping_cart').css('display', 'none');
}, 6000);
_______________________________________________________
CSS
#dropdown_shopping_cart:hover {
display: block!important;
}
Now i want to add the .slideUp() to this.
Check this:
var myVar;
myVar = setTimeout(function() {
$('#dropdown_shopping_cart').slideUp(800)
}, 6000);
$("#dropdown_shopping_cart").hover(
function() {
clearTimeout(myVar);
},
function() {
myVar = setTimeout(function() {
$('#dropdown_shopping_cart').slideUp(800)
}, 6000);
}
);
By default shopping cart will slideUp() after 6 seconds, if mouse hover action occured, setTimeOut will be cleared, after mouse leave the shopping cart, setTimeOut will setted automatically
You can clear the timeout on mouseenter and reset it on mouseleave like this:
var hide_div_to;
function hideDiv(){
hide_div_to = setTimeout(function () {
$('#dropdown_shopping_cart').slideUp(800);
}, 6000);
}
$('#dropdown_shopping_cart').slideDown(800,hideDiv());
$('#dropdown_shopping_cart').mouseenter(function(){
clearTimeout(hide_div_to);
});
$('#dropdown_shopping_cart').mouseleave(function(){
hideDiv();
});
Here is a working JSFiddle
UPDATE
If you don't wan't to wait the timeout again when you leave, after the timeout is reached, you can do this:
$('#dropdown_shopping_cart').slideDown(800);
setTimeout(function () {
if(!$('#dropdown_shopping_cart').is(':hover')){
$('#dropdown_shopping_cart').slideUp(800);
}
else{
$('#dropdown_shopping_cart').mouseleave(function(){
$('#dropdown_shopping_cart').slideUp(800);
});
}
}, 3000);
And here is a JSFiddle and here is another one that shows how this can be triggered multiple times.
Id suggest you work with mouseover and a class:
$('#dropdown_shopping_cart').hover(function(){
if(!$('#dropdown_shopping_cart').hasClass('active'))
{
$(this).addClass('active');
}
else
{
$(this).removeClass('active');
}
},
function() {
var myVar = setTimeout(function() {
if(!$('#dropdown_shopping_cart').hasClass('active'))
{
$('#dropdown_shopping_cart').slideUp()
}
}, 6000);
})
And than in your setTimeout Function you add:
demo: http://jsfiddle.net/yo5gnvy3/7/
$('#dropdown_shopping_cart').hide().slideDown(800, function () {
var events = $._data($(this)[0], "events") || {};
if (events.mouseover === undefined) {
$(this).delay(1000).slideUp()
}
});
Here I tried to run some code after height animation
<button id="btn1">Animate height</button>
<div id="box"style="background:#98bf21;height:100px;width:100px;margin:6px;"></div>
$(document).ready(function () {
$("#btn1").click(function () {
$("#box").animate({height:"300px"});
});
var x = $('#box').height();
if(x == 300){alert('animation is finished');}
});
I can't place the code which I want to run after height animation into animate method callback cause the animating box script is placed in one document and code which I want to run in other.
use jquery .promise().done
$(document).ready(function () {
$("#btn1").click(function () {
$("#box").animate({
height: "300px"
}).promise().done(function () {
alert('animation is finished');
});;
})
});
or separately like this:
$(document).ready(function () {
$("#btn1").click(function () {
$("#box").animate({
height: "300px"
});
$("#box").promise().done(function () {
alert('animation is finished');
});
})
});
Fixed Fiddle
Event-driven JavaScript a la jQuery:
//file 1
$("#box").animate({height:"300px"},function() {
$(this).trigger('myBoxFinishedAnimatingHeight');
});
//file 2
$('#box').on('myBoxFinishedAnimatingHeight',function() {
//your code
});
You can simply use the complete property as a callback function:
.animate( properties [, duration ] [, easing ] [, complete ] )
From http://api.jquery.com/animate
Here's a demo
$("#adjest").animate({"height":"300px"},1000);
$("#adjest").promise().done(
function() {
alert("done");
}
);
i would use promise and done, if you can't run it inside animate().
see here
http://jsfiddle.net/5p8Ww/
You could name space your file and call the fucntion...
var NameSpace = Namespace || {};
NameSpace.yourFunction() {
//Do stuff...
}
Then in your html/other_file
.animate( properties , 1000, ease, NameSpace.yourFunction())
I'm trying to create an animation sequence with jQuery where one animation starts after the previous one is done. But I just can't wrap my head around it. I've tried to make use of the jQuery.queue, but I don't think I can use that because it seems to have one individual queue for each element in the jQuery array.
I need something like:
$('li.some').each(function(){
// Add to queue
$(this).animate({ width: '+=100' }, 'fast', function(){
// Remove from queue
// Start next animation
});
});
Is there a jQuery way to do this or do I have to write and handle my own queue manually?
You can make a custom .queue() to avoid the limitless nesting..
var q = $({});
function animToQueue(theQueue, selector, animationprops) {
theQueue.queue(function(next) {
$(selector).animate(animationprops, next);
});
}
// usage
animToQueue(q, '#first', {width: '+=100'});
animToQueue(q, '#second', {height: '+=100'});
animToQueue(q, '#second', {width: '-=50'});
animToQueue(q, '#first', {height: '-=50'});
Demo at http://jsfiddle.net/gaby/qDbRm/2/
If, on the other hand, you want to perform the same animation for a multitude of elements one after the other then you can use their index to .delay() each element's animation for the duration of all the previous ones..
$('li.some').each(function(idx){
var duration = 500;
$(this).delay(duration*idx).animate({ width: '+=100' }, duration);
});
Demo at http://jsfiddle.net/gaby/qDbRm/3/
The callback of .animate() actually accepts another .animate(), so all you would have to do would be
$(this).animate({ width: '+=100' }, 'fast', function(){
$(selector).animate({attr: val}, 'speed', function(){
});
});
and so on.
You could call the next one recursively.
function animate(item) {
var elem = $('li.some').eq(item);
if(elem.length) {
elem.animate({ width: '+=100' }, 'fast', function() {
animate(item + 1);
});
}
}
animate(0);
why not build up a queue?
var interval = 0; //time for each animation
var speed = 200;
$('li.some').each(function(){
interval++;
$(this).delay(interval * speed).animate({ width: '+=100' }, speed);
});
EDIT: added speed param
Thanks to everybody replying!
I thought I should share the outcome of my question. Here is a simple jQuery slideDownAll plugin that slides down one item at a time rather than all at once.
(function ($) {
'use strict';
$.fn.slideDownAll = function (duration, callback) {
var that = this, size = this.length, animationQueue = $({});
var addToAnimationQueue = function (element, duration, easing, callback) {
animationQueue.queue(function (next) {
$(element).slideDown(duration, easing, function () {
if (typeof callback === 'function') {
callback.call(this);
}
next();
});
});
};
return this.each(function (index) {
var complete = null,
easing = 'linear';
if (index + 1 === size) {
complete = callback;
easing = 'swing';
}
addToAnimationQueue(this, duration / size, easing, complete);
});
};
} (jQuery));
Not very well test, but anyways.
Enjoy!!
I have this function and I am wondering why the setTimeout is not working:
$(document).ready(function() {
$('.sliding .text').css("top","130px")
$('.sliding').mouseenter(function() {
mouseOverTimer = setTimeout(function() {
$(this).find('.text').animate({"top": "0"}, 200);
}, 500);
})
.mouseleave(function() {
$(this).find('.text').delay(500).animate({"top": "130px"}, 400);
});
});
I tried wrapping the mouseenter event in the timeout, but that didn't seem like a great idea. I just want the animation on mouseenter to only work after the mouse has been over it for at least half a second.
Alternatively, is there a better way of doing it in jQuery?
The this value inside your timeout handler will not be what you think it'll be. Add an explicit variable:
$('.sliding').mouseenter(function() {
var self = this;
mouseOverTimer = setTimeout(function() {
$(self).find('.text').animate({"top": "0"}, 200);
}, 500);
})
Also you should declare "mouseOverTimer" as a local variable outside the handler setup code (that is, as a local variable of the "ready" handler) and then cancel the timeout in the "mouseleave" handler:
var mouseOverTimer = null;
$('.sliding').mouseenter(function() {
var self = this;
mouseOverTimer = setTimeout(function() {
$(self).find('.text').animate({"top": "0"}, 200);
}, 500);
})
.mouseleave(function() {
$(this).find('.text').delay(500).animate({"top": "130px"}, 400);
cancelTimeout(mouseOverTimer);
});
As I look at this, I'm pretty sure that the "mouseleave" code isn't really what you want; specifically I think the delay is probably unnecessary. I'm not 100% sure about what you want things to look like, however.
I would perhaps simplify the problem this way: On mouseover I would instantiate a new Date(), getTime() on it and stash it into a var. Then on mouseleave you take another date, grabbing the timestamp again. In that same mouseleave, do an evaluation: if the difference between date 1 and date 2 is greater than 1/2 second, you fire your action. Else, you reset date 1.
you could try this instead of using setTimeout:
$(document).ready(function() {
$('.sliding .text').css("top","130px")
$('.sliding').mouseenter(function() {
$(this).find('.text').stop().delay(500).animate({"top": "0"}, 200);
})
.mouseleave(function() {
$(this).find('.text').stop().animate({"top": "130px"}, 400);
});
});
This will delay the mouseover animation by 500ms. If you mouse out, it calls stop(), which would kill the pending animation and then animate back to the starting position. If it never moved, the mouseout animation will also not happen (correctly - it has nowhere to go).
Another way to do this
mouseIn = false;
$(document).ready(function() {
$('.sliding .text').css("top","130px")
$('.sliding').mouseenter(function() {
mouseIn = true;
mouseOverTimer = setTimeout(function() {
if(mouseIn==true)
$(this).find('.text').animate({"top": "0"}, 200);
}, 500);
})
.mouseleave(function() {
mouseIn=false;
$(this).find('.text').delay(500).animate({"top": "130px"}, 400);
});
});