jQuery - setInterval/clearInterval delay - javascript

I'm new to jQuery and am trying to fill a div over a certain amount of time. When that time is up I want to clear the div - pretty simple, right?
Summary: I click a button and the div starts filling(using animate({ height: "100%"}, workPeriod * 1000) over workPeriod which is 20 seconds. Once it's filled I want the div to be emptied. The div fills without issue and then once it's complete it takes about 5-10 seconds before it clears using animate({ height: "0%"}, workPeriod * 5000)
$('#begin').click(function () {
var workPeriod = 20
var start = new Date($.now());
var end = new Date(start.getTime() + 1000 * workPeriod);
var workInterval = setInterval(function () {
var currentDif = Math.floor((new Date($.now()) - end) / 1000) * -1;
if (currentDif < 0) {
$('#session-time').animate({
height: '0%'
}, 0);
clearInterval(workInterval);
//I want the animation above to occur instantly but it's happening several seconds after
//the clearInterval call
} else {
$('#session-time').animate({
height: '100%'
}, workPeriod * 1000);
}
}, 1000);
Question: How can I make the div empty immediately once it's full instead of waiting the 5-10 seconds?
btw, I'm very new to jQuery and still very much a beginner when it comes to programming so any advice will be well received

So, if you want to call another function/animation once your animation is complete, that functionality is already built into jQuery's animate function.
From the jQuery documentation:
$( "#clickme" ).click(function() {
$( "#book" ).animate({
opacity: 0.25,
left: "+=50",
height: "toggle"
}, 5000, function() {
// Animation complete.
});
});
I tried to get it to work with your code posted above, but I couldn't get your timer stuff to work. Nevertheless, I made this codepen, to show that the animation complete function does work when your complete function is another animation.

Related

Stuck with Jquery animate infinite loop

I am trying create bubbles, after few repetitions my browser getting stuck. here is my code. someone please help.... How do I get it done with out making many requests .
It looks like my post is mostly code , but I added enough details for this Stackoverflow :)
Thanks!
Jquery:
$(document).ready(function() {
function bubbles()
{
var i = 0;
$(".circle").remove();
for(i = 0; i < 3; i ++ )
{
var CreateDiv = document.createElement('div');
var AppendElem = document.body.appendChild(CreateDiv);
AppendElem.setAttribute('class','circle');
CreateDiv.style.position = "absolute";
var randomPosTop = Math.floor((Math.random() * 800) + 1);
CreateDiv.style.top = randomPosTop +"px";
var randomPosLeft = Math.floor((Math.random() * 1200) + 1);
CreateDiv.style.left = randomPosLeft +"px";
}
$( ".circle" ).animate({ opacity :0.0,height:100, width:100 }, 5000,bubbles);
}
bubbles();
});
CSS
.circle{ width: 20px;
height: 20px;
background-color: #000;
border-radius: 100px; position:absolute;}
jsfiddle
https://jsfiddle.net/krishnakamal549/u4krxq8o/
The issue is that the callback in the animation gets called for each element it finds. So.. the first time it gets called 3 times, the second time 9, the third time 18, it gets tripled each time, eventually you're running hundreds of instances of "bubbles".
You want to use a promise to do the callback like so.
$(".circle").animate({
opacity: 0.0,
height: 100,
width: 100
}, 5000).promise().done(bubbles);
This way, the callback only fires once for the entire animation, not per element.
FIDDLE
$(".circle").animate({
opacity: 0.0,
height: 100,
width: 100
}, 5000);
$("body").animate({ opacity: 1 }, 5000, bubbles);
Try this, this also works. But i suggest to use approach specified by Smeegs.
This method adds an extra process to the body for an animation while approach by Smeegs directly deals where the animation is applied and no need for an extra animation process on body

setInterval running really slow

I made a website where I need to animate strings that are longer than the containing parent.
This is the website: Here
If you click on next, you can see multiple pages of breeders with long names, that need to animate from left to right, but this only happens after 10 or 15 seconds and it takes a long time for it to start.
Now I have checked my code and this is where I create my functions:
function newsTicker() {
console.log('newsTicker')
verifyLength();
$('.breeder').not('.short-breed-name').each(function() {
var breederNameWidth = $(this).find('.breeder_name').width();
var divBreederNameWidth = $(this).find('.breeder_name_div').width();
var diff = Math.max(parseInt(breederNameWidth - divBreederNameWidth),0);
// console.log('diff:',diff)
$(this).find('.breeder_name').animate({
marginLeft: -diff
}, 3000,
function(){
$(this).animate({
marginLeft : 0
},3000)
})
})
}
function verifyLength() {
// console.log('verifyLength')
$('.breeder.visible').each(function() {
// debugger
var breederNameWidth = $(this).find('.breeder_name').width() + 10;
var divBreederNameWidth = $(this).find('.breeder_name_div').innerWidth();
if(breederNameWidth < divBreederNameWidth) {
$(this).addClass('short-breed-name');
$(this).find('.breeder_name').css({'width':'100%','text-align':'center'})
}
})
}
And this is where I call newsTicker:
function breederAnimate(){
verifyLength();
newsTicker();
setInterval(newsTicker, 1000);
}
Why is it so slow when my times are between 1 and 3 seconds?
You should be calling setTimeout not setInterval because you only want your animation to run once. You're restarting your animations every second
Also, you should be cancelling existing setIntervals when you click next or previous

jquery multiple function timing and repeat

I've created somewhat of a movie using jquery; it's composed of multiple functions representing each scene of the movie. Some scenes have to run longer than others. I'm having trouble creating a loop of the total movie. I've tried setting up setInterval several ways but they all seem to fail. To complicate things (for me at least) this is inside of a slide show that would ideally trigger the "next" button when it's complete.
feel free to knock the strategy I've used as the setTimeout for each scene was the only way I could figure out how to get each function to run after the next has ran for long enough. I couldn't figure out how to call each function with the amount of time that scene should run for vs. my current strategy of calling the next function after the previous one is complete.
Thanks for the direction
I think I need javascript to calculate the total time and call the atrAnime() in a setTimeout with the value but I can't seem to get it to calculate and pass back.
here's what I have:
$(document).ready(function(){
atrAnime(2000);
});
function atrAnime(dur){
first();
setTimeout(second, dur);
setTimeout(third, dur += 2000);
setTimeout(forth, dur += 2000);
setTimeout(fifth, dur += 2000);
setTimeout(sixth, dur += 6000);
setTimeout(seventh, dur += 2000);
setTimeout(eighth, dur += 2000);
setTimeout(ninth, dur += 2000);
setTimeout(tenth, dur += 2000);
setTimeout(end, dur += 3000);
};
Some scene examples:
function first(dur){
$('.pcba')
.css({
left: '150px'
})
.show();
$('.pcb_cad')
.css({
left: '275px',
top: '50px'
})
.show();
}
function second(dur){
$('.pcba').fadeOut();
$('.arrows')
.css({
left: '275px',
top: '50px'
})
.fadeIn();
$('.heatGenComps')
.css({
left: '325px',
top: '20px'
})
.fadeIn();
}
EDIT
My new ghetto solution has the last function in atrAnime() call as:
setTimeout(caller, dur += 2000);
};
and then another function
function caller(){
atrAnime(2000);
}
You are using some functions in your animations that actually provide a callback method once their action is completed. For example, the fadeIn/fadeOut functions have an "onComplete" callback for when the element has totally been shown/hidden -
$("#elem").fadeOut(function(){
alert('element has faded out!');
});
You could possible utilize these callback function, having them all call one central function that manages the sequence of execution. Each callback would trigger the next sequence. Both the show() and fadeIn() functions provide this callback as detailed in the documentation.
show()
fadeIn()
Wouldn't it better to nest all animations in callbacks? It just doesn't feel right relying on setTimeout :). What I mean is using the callbacks of the relevant animations so the next stage of animation will only fire once the previous one is finished. Something along the lines of:
$("firstElement").slideDown(500, function () {
$("secondElement").slideDown(500, function () {
$("thirdElement").slideDown(500, function () {
//etc
});
});
});

jQuery - use .hover instead of .click

I have the following code on my page.
http://jsfiddle.net/SO_AMK/r7ZDm/
As you see it's a list of links, and every time a link is clicked, the popup box opens up right underneath the link in question.
Now, what I need to do is basically the same, except I need to use the .hover event and delay the execution by 2 seconds. So instead of clicking, the user should keep the cursor over a link for 2 seconds.
Sounds simple enough but I can't get the positioning to work properly. here's what I tried:
$('a.showreranks').hover(function()
{
$(this).data('timeout', window.setTimeout(function()
{
position = $(this).position();
$('#rerank_details').css('top', position.top + 17);
$('#rerank_details').slideToggle(300);
}, 2000));
},
function()
{
clearTimeout($(this).data('timeout'));
});
Can someone modify this to make it work?
Try like this:
$('a.showreranks').hover(function()
{
var self = this;
$(this).data('timeout', window.setTimeout(function() {
var position = $(self).offset();
$('#rerank_details').css('top', position.top + 17);
$('#rerank_details').slideToggle(300);
}, 2000));
},
function()
{
clearTimeout($(this).data('timeout'));
});
DEMO
jsFiddle demo
$('ul').on('mousemove','li',function(e){
var m = {x: e.pageX, y: e.pageY};
$('#rerank_details').css({left: m.x+20, top: m.y-10});
}).on('mouseenter','li',function(){
var t = setTimeout(function() {
$('#rerank_details').stop().slideDown(300);
},2000);
$(this).data('timeout', t);
}).on('mouseleave','li',function(){
$('#rerank_details').stop().slideUp(300);
clearTimeout($(this).data('timeout'));
});
The setTimeout will act like a hover intent that actually delays the execution for 2 seconds and counts the time hovered inside a data attribute of the hovered element - that gets 'nulled' on mouseleave.
I added also a few lines of code that will make your tooltip follow the mousemove.

How can I set the duration of this jQuery animation proportionally?

I've created a quick test to show what I'm trying to do:
http://jsfiddle.net/zY3HH/
If you click the "Toggle Width" button once, a square will take one second to grow to full width. Click it again, and it will take one second to shrink down to zero width.
However, click the "Toggle Width" button twice in rapid succession - the second time when the square has grown to only a small fraction of its total width (like 10%) - you'll notice that the animation still takes a full second to return the square to zero width, which looks awkward, IMO.
While that behavior is expected, I'd like the latter animation to happen in an amount of time that's proportional to the width that it's covering. In other words, if you click "Toggle Width" a second time when the square is at 10% of its total width, I'd like it to take about 1/10th of a second to shrink back to zero width.
It should be relatively easy (I think) to make the value of the duration property dynamic, calculated when the jQuery click handler is run, to measure the current width of the square and determine the duration accordingly.
However, am I missing a better way to do this? Does jQuery provide an easy way, or expose some sort of method or property to make this easier?
I don't think jQuery has any built-in utility for doing this. The math required to do what you want is fairly straightforward, however, so I'd suggest just going that route. Something like:
var expanded = false;
$('input').click(function() {
$('div').stop();
var duration;
if (expanded) {
duration = ($('div').width() / 100) * 1000;
$('div').animate({ width: '0' }, { queue: false, duration: duration });
expanded = false;
} else {
duration = ((100 - $('div').width()) / 100) * 1000;
$('div').animate({ width: '100px' }, { queue: false, duration: duration });
expanded = true;
}
});
Here's a working example: http://jsfiddle.net/zY3HH/2/
If you've got some free time on your hands, maybe you could make the duration interpolation logic a bit more generic and package it up as a jQuery extension/plugin.
This is what you want - http://jsfiddle.net/FloydPink/qe3Yz/
var expanded = false;
$('input').click(function() {
var width = $('div').width(); //gives the current width of the div as a number (without 'px' etc.)
if (expanded) {
$('div').animate({
width: '0'
}, {
queue: false,
duration: (width/100 * 1000)// (current width/total width * 1 sec in ms) });
expanded = false;
} else {
$('div').animate({
width: '100px'
}, {
queue: false,
duration: 1000
});
expanded = true;
}
});

Categories

Resources