prevent animation double click issue - javascript

Hi I have problem with my slider please visit this site and check http://paruyr.bl.ee/
after click on my arrows it becomes work in an asynchronous way, ones it changes very fast and then slow and it repeats.
I think it is from start slider and stop slider.
var sliderPrev = 0,
sliderNext = 1;
$("#slider > img").fadeIn(1000);
startSlider();
function startSlider(){
count = $("#slider > img").size();
loop = setInterval(function(){
if (sliderNext>(count-1)) {
sliderNext = 0;
sliderPrev = 0;
};
$("#slider").animate({left:+(-sliderNext)*100+'%'},900);
sliderPrev = sliderNext;
sliderNext=sliderNext+1;
},6000)
}
function prev () {
var newSlide=sliderPrev-1;
showSlide(newSlide);
}
function next () {
var newSlide=sliderPrev+1;
showSlide(sliderNext);
}
function stopLoop () {
window.clearInterval(loop);
}
function showSlide(id) {
stopLoop();
if (id>(count-1)) {
id = 0;
} else if(id<0){
id=count-1;
}
$("#slider").animate({left:+(-id)*100+'%'},900);
sliderPrev = id;
sliderNext=id+1;
startSlider();
};
$("#slider, .arrows").hover(function() {
stopLoop()
}, function() {
startSlider()
});
function onlyNext () {
var newSlide=sliderPrev+1;
onlyShowSlide(newSlide);
}
function onlyShowSlide(id) {
if (id>(count-1)) {
id = 0;
} else if(id<0){
id=count-1;
}
$("#slider").animate({left:+(-id)*100+'%'},900);
sliderPrev = id;
sliderNext=id+1;
};

I think the best option would be to check if the animation is in progress and prevent the action if it is, something like this:
function prev () {
if(!$('#slider').is(":animated"))
{
var newSlide=sliderPrev-1;
showSlide(newSlide);
}
}
function next () {
if(!$('#slider').is(":animated"))
{
var newSlide=sliderPrev+1;
showSlide(sliderNext);
}
}
To illustrate the difference between this and just sticking a stop() in, check this JSFiddle. You will notice some choppy movements if you click multiple times in the stop() version.

What I would do is add a class to your slider when the animation starts and remove the class when it finishes:
$("#slider").animate({left:+(-id)*100+'%'}, {
duration: 900,
start: function() {
$('#slider').addClass('blocked');
},
complete: function() {
$('#slider').removeClass('blocked');
}
});
Now check on each click event if the slider is blocked or not:
function next () {
if (!$('#slider').hasClass('blocked')) {
var newSlide=sliderPrev+1;
showSlide(sliderNext);
}
}
This is a very simple solution, I'm sure there is a better one.
EDIT: As marcjae pointed out, you could stop the animations from queuing. This means when you double click, the slideshow still will move 2 slides. With my approach the second click will be ignored completely.

You can use a variable flag to control if the animation is still being done, or simply use .stop() to avoid stacking the animation.
$("#pull").click(function(){
$("#togle-menu").stop().slideToggle("slow");
});

It is occurring because your animations are being queued.
Try adding:
.stop( true, true )
Before each of your animation methods. i.e.
$("#slider").stop( true, true ).animate({left:+(-id)*100+'%'},900);

The answers about stop are good, but you have a bigger issue that is causing the described behavior. The issue is here:
$("#slider, .arrows").hover(function() {
stopLoop()
}, function() {
startSlider()
});
You have bound this to the .arrows as well as the #slider and the arrows are contained within the slider. So, when you mouse out of an arrow and then out of the entire slider, you are calling start twice in a row without calling stop between. You can see this if you hover onto the arrow and then off of the slider multiple times in a row. The slides will change many times after 6 seconds.
Similarly, consider the case of a single click:
Enter the `#slider` [stopLoop]
Enter the `.arrows` [stopLoop]
Click the arrow [stopLoop]
[startSlider]
Leave the `.arrows` [startSlider]
Leave the `#slider` [startSlider]
As you can see from this sequence of events, startSlider is called 3 times in a row without calling stopLoop inbetween. The result is 3 intervals created, 2 of which will not be stopped the next time stopLoop is called.
You should just have this hover on the #slider and more importantly, add a call to stopLoop as the first step in startSlider. That will ensure that the interval is always cleared before creating a new one.
$("#slider").hover(function() {
stopLoop()
}, function() {
startSlider()
});
function startSlider(){
stopLoop();
/* start the slider */
}

Related

Infinite loop to fade away a div to reveal div underneath

I have two div's which are absolute positioned to sit on top of each other. I'm just looking to create a simple jQuery function which fades away the div on top (.group-fcallout-b) to reveal the one underneath (.group-fcallout-a).
Here's my JS:
$(document).ready(function() {
InfiniteRotator();
});
function InfiniteRotator() {
var fadeO = setInterval(function() {
$('.group-fcallout-b').fadeOut(500);
}, 5000);
clearInterval(InfiniteRotator);
var fadeI = setInterval(function() {
$('.group-fcallout-b').fadeIn(500);
}, 5000);
}
I think the issue I'm having at the moment is that fadeIn starts immediately after fadeOut has finished - obviously I want a delay between the two functions.
JSFiddle Link: https://jsfiddle.net/02xLjh1y/11/
Many thanks!
Here is one way to achieve what I think is your goal (fiddle here):
$(document).ready(function() {
InfiniteRotator(jQuery.fn.fadeOut, jQuery.fn.fadeIn);
});
function InfiniteRotator(fadeFunc, callback) {
fadeFunc.call($('.group-fcallout-b'), 500, function() {
setTimeout(function() { InfiniteRotator(callback, fadeFunc); }, 1000);
});
}
[Edit: added a timeout before fading back the other way]
Since both fadeIn and fadeOut take an optional callback argument, you can exploit this instead of using setInterval.
N.B. I don't know whether you care or not, but the use of a capital 'I' in InfiniteRotator is a bit unusual - normally the capital letter would tend to imply that this is a constructor function, which it isn't.
It's actually a one liner:
setInterval(function(){ $('.group-fcallout-b').fadeToggle(500); }, 5000)
updated fiddle
Is this correct for you ?
See this fiddle
I changed value of timeout in the second one.
var fadeO = setInterval(function() {
$('.group-fcallout-b').fadeOut(500);
}, 5000);
clearInterval(InfiniteRotator);
var fadeI = setInterval(function() {
$('.group-fcallout-b').fadeIn(500);
}, 10000);
how about this?
$(document).ready(function() {
InfiniteRotator();
});
function InfiniteRotator() {
var flag = 1;
var fadeOut = function() {
$('.group-fcallout-b').fadeOut(500);
flag = 0;
}
var fadeIn = function() {
$('.group-fcallout-b').fadeIn(500);
flag = 1;
}
var timer = setInterval(function(){
if(flag)
fadeOut();
else
fadeIn();
}, 5000);
}

jQuery increment variable in recursive function

There are other questions with almost the same title as this but they don't seem to answer my question.
I am trying to make a simple javascript function that uses jQuery to fade div blocks in and out one after the other, and goes back to the first div once it get's to the end. This should continue while the user is on the page, much like a slideshow.
There are 5 'slides' or divs to be shown and hidden in sequence. They have the classes 'content1', 'content2', 'content3' etc.
$(document).ready(function() {
var slide = 1;
nextSlide(slide);
function nextSlide(slide) {
$('.content' + slide.toString()).fadeTo(2000, 1.0).delay(5000).fadeTo(2000, 0.0).delay(2000);
if(slide > 5) {
slide = 1;
} else {
slide++;
}
nextSlide(slide);
};
});
This does not fade each div in and out in sequence, what it actually does is fade all of the slides in and out simultaneously.
How do I get it to reference each slides class in turn and then loop back to the first slide?
Many thanks.
Your function will recurse immediately, dispatching all of the animation requests around the same time.
To stagger them, you should recurse with a timeout:
$(document).ready(function() {
var slide = 1;
nextSlide();
function nextSlide() {
$('.content' + slide.toString()).fadeTo(2000, 1.0).delay(5000).fadeTo(2000, 0.0).delay(2000);
if(slide > 5) {
slide = 1;
} else {
slide++;
}
setTimeout(nextSlide, 2000); // second param is delay in ms
};
});
This will cause the next call to occur after 2000ms. Thanks to closure, your slide variable should be captured and will persist its value between calls.
No need for a timeout. Simply call the next iteration as a callback of the last fadeTo method:
$(document).ready(function() {
var slide = 1;
nextSlide(slide);
function nextSlide(slide) {
$('.content' + slide.toString())
.fadeTo(2000, 1.0)
.delay(5000)
.fadeTo(2000, 0.0, function(){
if(slide > 5) {
slide = 1;
} else {
slide++;
}
nextSlide(slide);
});
};
});
http://jsfiddle.net/3L09b505/

jQuery Rotate prevent stacking function after a click

fiddle link
Hello,
I am using this jQueryRotate plugin to rotate my div's after a user clicks on the button.
I would like to stop stacking the rotation after the button is clicked more than once. It just keeps on speeding up.
I have researched it and using .stop() nor return false; wont help.
All I want is to know, whether there is a way to reset the rotation on the next click, or stop it after clicking on another button.
Thanks a lot!
The glitch came from having the declaration multiple times in the loop.
I pulled the variables outside the click event which stopped the glitch.
To prevent the speed increasing, i did a quick check to see if the button had already been clicked. See below
$(document).ready(function () {
var angle = 0
var angleone = 0;
var clicked = false;
$('.concept').click(function () {
if (!clicked) {
setInterval(function () {
angle += 3;
$(".gear").rotate(angle);
}, 50);
setInterval(function () {
angleone -= 3;
$(".gear-one").rotate(angle);
}, 50);
clicked = true;
}
});
$('.bar').click(function () {
if ($('#default').is(':visible')) {
$('#default').fadeOut(200);
};
});
});

does jQuery stop() work on custom functions?

There are three images that I have made a tooltip for each.
I wanted to show tooltips within timed intervals say for 2 seconds first tooltip shows and for the second interval the 2nd tooltips fades in and so on.
for example it can be done with this function
function cycle(id) {
var nextId = (id == "block1") ? "block2": "block1";
$("#" + id)
.delay(shortIntervalTime)
.fadeIn(500)
.delay(longIntervalTime)
.fadeOut(500, function() {cycle(nextId)});
}
now what i want is to stop the cycle function when moseover action occurs on each of the images and show the corresponding tooltip. And again when the mouse went away again the cycle function fires.
If I understand everthing correctly, than try this code. Tt stops the proccess if you hover the image and continues if you leave the image. The stop() function will work on custom functions if you implement them like the fadeOut(), slideIn(), ... functions of jquery.
$('#' + id)
.fadeIn(500, function () {
var img = $(this).find('img'),
self = $(this),
fadeOut = true;
img.hover(function () {
fadeOut = false;
},
function () {
window.setTimeout(function () {
self.fadeOut(500);
}, 2000);
}
);
window.setTimeout(function () {
if (fadeOut === false) {
return;
}
self.fadeOut(500);
}, 2000);
});​

Javascript "while hovered" loop

Can anybody help me on this one...I have a button which when is hovered, triggers an action. But I'd like it to repeat it for as long as the button is hovered.
I'd appreciate any solution, be it in jquery or pure javascript - here is how my code looks at this moment (in jquery):
var scrollingposition = 0;
$('#button').hover(function(){
++scrollingposition;
$('#object').css("right", scrollingposition);
});
Now how can i put this into some kind of while loop, so that #object is moving px by px for as #button is hovered, not just when the mouse enters it?
OK... another stab at the answer:
$('myselector').each(function () {
var hovered = false;
var loop = window.setInterval(function () {
if (hovered) {
// ...
}
}, 250);
$(this).hover(
function () {
hovered = true;
},
function () {
hovered = false;
}
);
});
The 250 means the task repeats every quarter of a second. You can decrease this number to make it faster or increase it to make it slower.
Nathan's answer is a good start, but you should also use window.clearInterval when the mouse leaves the element (mouseleave event) to cancel the repeated action which was set up using setInterval(), because this way the "loop" is running only when the mouse pointer enters the element (mouseover event).
Here is a sample code:
function doSomethingRepeatedly(){
// do this repeatedly when hovering the element
}
var intervalId;
$(document).ready(function () {
$('#myelement').hover(function () {
var intervalDelay = 10;
// call doSomethingRepeatedly() function repeatedly with 10ms delay between the function calls
intervalId = setInterval(doSomethingRepeatedly, intervalDelay);
}, function () {
// cancel calling doSomethingRepeatedly() function repeatedly
clearInterval(intervalId);
});
});
I created a sample code on jsFiddle which demonstrates how to scroll the background-image of an element left-to-right and then backwards on hover with the code shown above:
http://jsfiddle.net/Sk8erPeter/HLT3J/15/
If its an animation you can "stop" an animation half way through. So it looks like you're moving something to the left so you could do:
var maxScroll = 9999;
$('#button').hover(
function(){ $('#object').animate({ "right":maxScroll+"px" }, 10000); },
function(){ $('#object').stop(); } );
var buttonHovered = false;
$('#button').hover(function () {
buttonHovered = true;
while (buttonHovered) {
...
}
},
function () {
buttonHovered = false;
});
If you want to do this for multiple objects, it might be better to make it a bit more object oriented than a global variable though.
Edit:
Think the best way of dealing with multiple objects is to put it in an .each() block:
$('myselector').each(function () {
var hovered = false;
$(this).hover(function () {
hovered = true;
while (hovered) {
...
}
},
function () {
hovered = false;
});
});
Edit2:
Or you could do it by adding a class:
$('selector').hover(function () {
$(this).addClass('hovered');
while ($(this).hasClass('hovered')) {
...
}
}, function () {
$(this).removeClass('hovered');
});
var scrollingposition = 0;
$('#button').hover(function(){
var $this = $(this);
var $obj = $("#object");
while ( $this.is(":hover") ) {
scrollingposition += 1;
$obj.css("right", scrollingposition);
}
});

Categories