Javascript: Putting a looping jQuery animation inside a js function - javascript

I want to nest a looping jQuery animation function inside a js function, and I can't figure out how to do it.
I have an audio file that plays when a div is clicked (and pauses if the div is clicked again), and at the same time the div text changes from a play symbol to a pause symbol. I want to animate another div while the music is playing, and stop the animation when the music is paused.
Here is my audio function code:
function play() {
var audio = document.getElementById('whatchaDoin');
if (audio.paused) {
audio.play();
document.getElementById('playButton').innerHTML = '\u2016';
} else {
audio.pause();
document.getElementById('playButton').innerHTML = '\u25BA';
}
}
And here's my animation:
$(document).ready(function() {
function animateBox() {
$('#greenBox').animate({
'margin-top': '20px',
'height': '150px',
'width': '150px'
}, 195).animate({
'margin-top': '30px',
'height': '140px',
'width': '140px'
}, 390, animateBox);
}
animateBox();
});
I can't seem to find a way to put them together without breaking the play function.
Thanks for any help you can give me!

This should work. I haven't tried it with an audio object, but the animation loop should be correct. Here is a jsFiddle without audio object:
https://jsfiddle.net/5fwdcq37/1/
The code below should be it with audio, important to know that when you stop an animation in jquery and you set the "jumpToEnd" flag to true it will fire the complete function. In your example before that would then again start the animation loop, so you would never be able to stop it. Therefore you need to add an additional variable loop to check if it is supposed to loop:
function play() {
var audio = document.getElementById('whatchaDoin');
if (audio.paused) {
audio.play();
document.getElementById('playButton').innerHTML = '\u2016';
startAnimation();
} else {
audio.pause();
document.getElementById('playButton').innerHTML = '\u25BA';
stopAnimation();
}
}
var loop = false;
function startAnimation(){
loop = true;
$('#greenBox').animate({
'margin-top': '20px',
'height': '150px',
'width': '150px'
}, 195).animate({
'margin-top': '30px',
'height': '140px',
'width': '140px'
}, 390, function(){ if(loop){ startAnimation(); } });
}
function stopAnimation(){
loop = false;
$('#greenBox').stop( true, true );
}
$( "#playButton" ).click( play );

Related

jQuery: stop animation that is delayed, before it is triggered

I'm foolin around with the jquery hover functionality. the current code snippet looks like this:
$leftColumn.children().first().hover(
function(event) {
var $this = jQuery(this);
$this.css({
'background-color': '#505050'
}).parent().stop()
.animate(
{
'z-index': '999',
width: '220px'
},
{
duration: '1000'
}
);
},
function(event) {
var $this = jQuery(this);
$this.parent().stop()
.animate(
{
width: '38px',
'z-index': '1'
},
{
duration: '1500',
complete: function() {
$this.css({
'background-color': 'transparent'
});
}
}
);
}
);
What this basically does is increasing the width of a div (which is position absolute) to overlay another div.
I choosed to use jQuerys animate() functionality instead of CSS3s transition because I want to trigger a callback whenever the closing (decreasing the width again) animation is done.
My problem now is, that I want to delay the closing animation for 2 seconds (and yes I know about the delay() vs setTimeout() discussion) which worked fine with setTimeout(). However as the animation is timed out for the given duration it will run, even if I enter the hoverable area again. This of course makes sense as the stop() only triggeres while an animation is on the go, which is not the case if it is timed out.
How can I make this thing work (stop the closing animation when reentering the hoverable area) and still keep a timeout / delay before decreasing the width on "hover leave"?

Only allow one jQuery function to execute at a time

I have a grid layout and I am using jQuery to change what is displayed in each grid depending on which grid was clicked. At the moment I can click a grid and it changes and then if I click the same grid it goes back to the default but after their initial click If they happen to click in another grid it will trigger another function. I cannot hide the div's because I am using them to display content. I would like to only let one function be triggered at a time. Below is my code.
(function() {
var count = 0;
jQuery('#home-grid-one-two').click(function () {
count += 1;
jQuery('#home-grid-two-one').css({
'visibility': 'hidden'
});
jQuery('#home-grid-two-two').css({
'visibility': 'hidden'
});
jQuery('#home-grid-two-three').hide();
jQuery('#home-grid-three-two').css('background-image', 'url("A PICTURE")');
jQuery('#home-grid-three-two').css({
'background-size': 'cover'
});
jQuery('#home-grid-three-three').hide();
jQuery('#home-grid-two-two').css({
'margin-top': '-450px'
});
jQuery('#home-grid-three-two').css({
'margin-top': '-420px'
});
jQuery(".leftpara").show();
jQuery(".rightpara").show();
jQuery(".ptagexp").hide();
if (count == 2) {
jQuery('#home-grid-two-one').css({
'visibility': 'visible'
});
jQuery('#home-grid-two-two').css({
'visibility': 'visible'
});
jQuery('#home-grid-three-two').show();
jQuery('#home-grid-three-two').css('background-image', 'none');
jQuery('#home-grid-two-two').css({
'margin-top': '0px'
});
jQuery('#home-grid-three-two').css({
'margin-top': '0px'
});
jQuery('#home-grid-two-one').show();
jQuery('#home-grid-three-one').show();
jQuery('#home-grid-two-three').show();
jQuery('#home-grid-three-three').show();
jQuery(".leftpara").hide();
jQuery(".rightpara").hide();
jQuery(".ptagexp").show();
count = 0;
}
});
})();
(function() {
var count = 0;
jQuery('#home-grid-three-two').click(function () {
count += 1;
jQuery('#home-grid-one-one').css('background-image', 'url("A PICTURE")');
jQuery('#home-grid-one-one').css({
'background-size': 'contain',
'background-repeat': 'no-repeat',
'background-position': '50%'
});
jQuery('#home-grid-one-two').css('background-image', 'url("A PICTURE")');
jQuery('#home-grid-one-two').css({
'background-color': 'transparent',
'background-size': 'contain',
'background-repeat': 'no-repeat',
'background-position': '50%'
});
if (count == 2) {
jQuery('.home-grid').css('background-image', 'none');
jQuery('#home-grid-one-two').css('background-color', '#cccccc');
jQuery('#home-grid-two-one').css('background-color', '#cccccc');
jQuery('#home-grid-two-three').css('background-color', '#cccccc');
jQuery('#home-grid-three-two').css('background-color', '#cccccc');
jQuery('#home-grid-one-two').find('p').show();
jQuery('#home-grid-two-one').find('p').show();
jQuery('#home-grid-two-two').find('p').show();
jQuery('#home-grid-two-three').find('p').show();
jQuery('#home-grid-three-two').find('p').show();
count = 0;
}
});
})();
A simple solution would perhaps be to declare a global variable that keep tabs on when a function is running, and checking it before running other functions.
Just make them unclickable (should work in most browsers but I have not tested all) by adding and removing a couple of classes. (saves binding/unbinding which could get messy)
sample fiddle to play with: http://jsfiddle.net/MarkSchultheiss/3mLzx3o7/
Example html:
<div class="mygrids active">one</div>
<div class="mygrids">two</div>
<div class="mygrids">three</div>
<div class="mygrids">four</div>
<div class="mygrids">five</div>
<div id='showactive'>active:<span>none</span></div>
Sample CSS
.mygrids.inactive { pointer-events: none; }
.mygrids.active { pointer-events: auto;
border: solid lime 1px;}
sample code
$('.mygrids').on('click',function(){
$('#showactive>span').text($(this).text());
if ($(this).hasClass('active')){
$(this).removeClass('active');
$(this).siblings().removeClass('inactive');
}
else{
$(this).addClass('active');
$(this).siblings().addClass('inactive');
}
});
$('.mygrids').not('.active').addClass('inactive');

Callback complete function not working properly using transit js and jQuery.

So
I am trying to build some navigation using jquery transit
The opens/slide down navigation is working fine. It sets the child ul to display block and then runs the animation/transition.
The issue is occurring when closing the navigation item. The ul gets hidden immediately diespite being written inside the callback. I've also added a console log of 'animation ended' once the transition has finished and this is firing at the right time, so not sure why the ul is being hidden immediately.
The jquery/js looks like this:
var dropDown = (function(){
var mainNav = $('#mainNav');
var navA = mainNav.find('li a');
var navUL = mainNav.find('ul');
var iconAll = mainNav.find('i');
navUL.transition({
'max-height': '0px',
'height': '0px',
'overflow': 'hidden',
'display': 'none'
});
navA.on('click',function(){
var nextUL = $(this).next();
var icon = $(this).find('i');
var nextULHidden = nextUL.css('display') === 'none';
if(nextULHidden) {
nextUL.css('display','block').transition({
duration: 1000,
'height': 'auto',
'max-height': '1000px',
easing: 'ease-in'
});
$(this).addClass('active');
icon.removeClass('fa-chevron-down').addClass('fa-chevron-up');
console.log('hidden');
}else if(!nextULHidden){
nextUL.transition({
duration: 1000,
'height': '0px',
'max-height': '0px',
easing: 'ease-in',
complete: function(){
nextUL.css('display','none');
console.log('animation ended');
}
});
$(this).removeClass('active');
icon.removeClass('fa-chevron-up').addClass('fa-chevron-down');
console.log('visible');
}else{
console.log('some error');
}
return false;
});
}());
And I have a fiddle here that can be tinkered with: http://jsfiddle.net/lharby/o5w8ebu8/2/
I've tried various combinations of using css visibility, jquery show() and hide() functions, but each time the ul vanishes as the transition starts (on click effectively). And I've tested Chrome, Firefox and Safari just in case there were any anomalies.
I believe the callback is firing at the correct time (after 1000 milliseconds) the problem is that the transition animation isn't working.
Changing to 'height': 'auto' on the shrinking transition seems to achieve the effect you are after. Though I can't say I really know why.

Setinterval for different events with jQuery

I have created my own slider. Each slide has different animations over different elements, so I have something like this for the buttons to change from one slide to another.
$('.content1').click(function(e){
$('#image1').animate({'margin-left': '0px', 'margin-top': '0px'});
$('#box1').animate({'margin-top': '0px'});
hide2(); //hiddeing slide2
hide3(); //hidding slide3
e.preventDefault();
});
$('.content2').click(function(e){
hide1(); //hidding slide1
hide3(); //hidding slide2
$('#box2').animate({'margin-top': '0px'});
$('#image2').animate({'margin-top': '0px'});
e.preventDefault();
});
$('.content3').click(function(e){
hide1();
hide2();
$('#box3').animate({'margin-left': '0px'});
$('#image3').stop().delay(1000).show().animate({'opacity': '1'});
e.preventDefault();
});
I would like now to add an interval for the slider to move alone every X seconds.
I wonder if it is possible to make 3 different calls instead of just one function I am used to:
setInterval(function(){
nameOfFunction();
}, 6*1000);
Thanks.
Finally I solved it using setTimeout as #BradM recommended.
Im sure there's a more simple way, but here is how I did it.
Here's the code:
Menu click events:
$('.content1').click(function(e){
slide1();
e.preventDefault();
});
$('.content2').click(function(e){
slide2();
e.preventDefault();
});
$('.content3').click(function(e){
slide3();
e.preventDefault();
});
Slide effects
function slide1(){
next = 2; //setting which is gonna be the next slide
$('#image1').animate({'margin-left': '0px', 'margin-top': '0px'});
$('#box1').animate({'margin-top': '0px'});
hide2();
hide3();
}
function slide2(){
next = 3; //setting which is gonna be the next slide
hide1();
hide3();
$('#box2').animate({'margin-top': '0px'});
$('#image2').animate({'margin-top': '0px'});
}
function slide3(){
next = 1; //setting which is gonna be the next slide
hide1();
hide2();
$('#box3').animate({'margin-left': '0px'});
$('#image3').stop().delay(1000).show().animate({'opacity': '1'});
}
Hidding functions
function hide1(){
$('#image1').animate({'margin-left': '2000px'});
$('#box1').animate({'margin-top': '-2000px'});
}
function hide2(){
$('#box2').animate({'margin-top': '600px'});
$('#image2').animate({'margin-top': '-2000px'});
}
function hide3(){
$('#box3').animate({'margin-left': '-2000px'});
$('#image3').animate({'opacity' : '0', 'display' : 'none'}, function(){
$(this).hide();
});
}
Onmouse over/out actions
//when its over, we stop the movement
var delay = 6000; //6 seconds
$('#slider').hover(function(){
clearTimeout(timer);
}, function(){
//starting again the animation (since the last slide)
timer = window.setTimeout(playSlide, delay);
});
Main playslide function
var next = 2; //next slide will be the 2nd one at the start
function playSlide(){
var name = "slide" + next;
var method = eval(name);
method();
//calling recursively the function
timer = window.setTimeout(playSlide, delay);
}
First call
//only if there's an slider, we initate it
if($('#slider').length){
//first call the the slider
timer = window.setTimeout(playSlide, delay);
}

Jquery animation looping

I am trying to make this animation loop
$(".jquery_bounce").ready(function(){
$("img", this).animate({ marginLeft : '20px' } , {
duration: 200,
complete:function() {
$(this).animate({ marginLeft : '0px' } , {
duration: 200,
easing: 'easeInCubic',
});
}
});
})
});
<div class="example">
<h4>Bounce</h4>
<div class="jquery_bounce bounce">
<img src="images/bounceimg.png" class="bounceimg" />
</div>
</div>
Please help.
try this~
$(function(){
$.extend({
show:function(){
$(".jquery_bounce").ready(function(){
$("img", this).animate({ marginLeft : '20px' } , {
duration: 200,
complete:function() {
$(this).animate({ marginLeft : '0px' } , {
specialEasing: {
left: 'swing',
top: 'easeOutBounce'
}
});
}
});
})
}
});
setInterval("$.show()",1000);
});
Demo:
http://jsfiddle.net/VpKw2/
Why don't you use setInterval()?
Edit:
Your animation bounces once, then stops, because...
You trigger the margin=20 part.
Upon completeness, another animation is scheduled: margin=0.
That's it. It doesn't loop because nothing is rescheduled to happen after the first pass.
Read the documentation on setInterval(): it's a function that let's you call another function at fixed (in milliseconds) intervals.
If you still want to do it as above, you must fix the problem I pointed out. Try thinking your way around it, and I'll help if you can't figure it out :).
Cheers.
Setup a bounce function that will continue the animation, either moving the element left or right:
function bounce(elm, leftZero) {
var px = leftZero ? '0px' : '20px';
elm.animate({ marginLeft : px}, {
duration: 200,
complete:function(){
//Continue bouncing
setTimeout(function(){
bounce(elm, !left);
},1);
}
});
}
$(".jquery_bounce").ready(function(){
$("img", this).each(function(){
//Start bouncing
bounce($(this), false);
});
})
});

Categories