Pause autonomous function if user interacts? - javascript

I'm trying to make a carousel that runs automatically, but if a user interacts with the controls I want the carousel to reset its timer.
What ive built works to an extent, but if you interact with the control-dot the timer isnt reset so it throws some funny results...
Here's my JS
/* Js for carousel */
$('.steps__step-1').addClass('active');
$(function() {
var lis = $('.step'),
currentHighlight = 0;
N = 5; // Duration in seconds
setInterval(function() {
currentHighlight = (currentHighlight + 1) % lis.length;
lis.removeClass('active').eq(currentHighlight).addClass('active');
}, N * 1000);
});
$('.control-dot').on('click', function(e) {
e.preventDefault();
$('.active').removeClass('active');
var itemNo = $(this).index() - 1;
$('.step').eq(itemNo).addClass('active');
});
http://jsfiddle.net/tnzLha3o/1/

You should store interval id in a variable (let intervalId = setInterval(...)) and then use it to restart it.
Here is your updated fiddle: http://jsfiddle.net/gudzdanil/uzoydp6a/2/
So that your code will look like:
var duration = 5;
var lis = $('.step'),
currentHighlight = 0;
var intervalId = null;
$(function() {
$('.steps__step-1').addClass('active');
runCarousel();
});
$('.control-dot').on('click', function(e) {
e.preventDefault();
$('.active').removeClass('active');
var itemNo = $(this).index() - 1;
$('.step').eq(itemNo).addClass('active');
rerunCarousel();
});
function rerunCarousel() {
if(intervalId) clearInterval(intervalId);
intervalId = null;
runCarousel();
}
function runCarousel() {
intervalId = setInterval(function() {
currentHighlight = (currentHighlight + 1) % lis.length;
lis.removeClass('active').eq(currentHighlight).addClass('active');
}, N * 1000)
}

Add a variable to stop it.
var stop = false
$('.steps__step-1').addClass('active');
$(function() {
var lis = $('.step'),
currentHighlight = 0;
N = 5; // Duration in seconds
setInterval(function() {
if (!stop) {
currentHighlight = (currentHighlight + 1) % lis.length;
lis.removeClass('active').eq(currentHighlight).addClass('active');
}
}, N * 1000);
});
$('.control-dot').on('click', function(e){
e.preventDefault();
$('.active').removeClass('active');
var itemNo = $(this).index() - 1;
$('.step').eq(itemNo).addClass('active');
stop = !stop
});
http://jsfiddle.net/quvgxz63/

Related

How to make a setInterval wait until another one finishes?

How, when I click "one" link, make the second counter wait until the first one finishes and then count up to 14 (as instructed on line 155)?
https://jsfiddle.net/c4khk69f/27/
The function responsible for "one" link is function progressSim() on line 43.
$('a').on('click', function(e) {
e.preventDefault();
jQuery('.canvasmotherwrap').hide();
jQuery('.canvasmotherwrap').fadeIn();
al = 0;
al2 = 0;
window.clearInterval(sim1_1);
window.clearInterval(sim1_2);
window.clearInterval(sim2);
var storedata = $(this).attr('data');
console.log(storedata)
window[storedata]();
});
var sim1_1;
var sim1_2;
var sim2;
window.one = function() {
sim1_1 = setInterval(progressSim, 10);
sim1_2 = setInterval(progressSim, 1000);
}
window.two = function() {
sim2 = setInterval(progressSim2, 10);
}
I'm not entirely sure I understand what you are after, but I think you want two counters and when the "first" one has finished then the second should start and count to "14".
I hope this helps:
function doWork(targetDiv, startTime, countTo, onDone) {
var ticker = setInterval(function(){
diff = (((Date.now() - startTime) / 500) | 0);
targetDiv.innerText = diff;
if(diff < countTo){ return; }
clearInterval(ticker);
if(typeof(onDone) === 'function') { onDone(); }
}, 100);
}
var divFoo = document.getElementById("foo");
var divBar = document.getElementById("bar");
// your on "click"
doWork(divFoo, Date.now(), 5, function(){
doWork(divBar, Date.now(), 14);
});
<table><tr>
<td><div id="foo">0</div></td>
<td><div id="bar">0</div></td>
</table>

How to use setTimeout with a "do while" loop in Javascript?

I'm trying to make a 30 second countdown on a span element (#thirty) that will be started on click of another element (#start). It doesn't seem to work. I would appreciate your help.
var countdown = function() {
setTimeout(function() {
var i = 30;
do {
$("#thirty").text(i);
i--;
} while (i > 0);
}, 1000);
}
$("#start-timer").click(countdown());
use this :
var i = 30;
var countdown = function() {
var timeout_ = setInterval(function() {
$("#thirty").text(i);
i--;
if(i==0){
i = 30;
clearInterval(timeout_);
}
}, 1000);
}
$("#start-timer").click(countdown);

Mouseover and mouseout not working on firefox?

I want to try image slide show on mouseover and stop on mouse out
Following is my code: but with mouse over mouse out is also calling..its working fine on chrome...
default_image = '';
timer = 0;
jQuery('.sales-product-images').on('mouseover',function(){
var counter = 0;
var selector = jQuery(this);
var pd_id = jQuery(this).attr('id');
var imageArray = jQuery.parseJSON(images);
var product_images= imageArray[pd_id];
default_image = jQuery(this).attr('data-image');
console.log('default-image= ' + default_image);
timer = setInterval(function(){selector.fadeOut("fast", function () {
console.log(counter);
if (counter === product_images.length) {
console.log('==');
counter = 0;
}
console.log('localhost/product/' + product_images[counter]);
selector.attr('src', 'localhost/product/' + product_images[counter]);
selector.fadeIn(2500);
counter = counter+ 1;
});
}, 2000)});
jQuery('.sales-product-images').on('mouseleave', function() {
console.log('now end');
// var counter = 0;
clearInterval(timer);
)};
problem is: "now end" is also printed on mouseover in firefox.Which should not be.
Try this :
jQuery('.sales-product-images').on('mouseout', function() {
console.log('now end');
// var counter = 0;
clearInterval(timer);
)};
The problem is likely caused by using mouseover with mouseleave, when it's paired event should be mouseout. The pairings can be seen below.
mouseover / mouseout
$( ".sales-product-images" )
.mouseover(function() {
console.log("mouse over");
})
.mouseout(function() {
console.log("mouse out");
});
mouseenter / mouseleave
$( ".sales-product-images" )
.mouseenter(function() {
console.log("mouse enter");
})
.mouseleave(function() {
console.log("mouse leave");
});
The above methods are shortcuts for the .on("", function(){}) method.
You could rewrite your javascript as follows:
default_image = '';
timer = 0;
jQuery('.sales-product-images').mouseover(function(){
var counter = 0;
var selector = jQuery(this);
var pd_id = jQuery(this).attr('id');
var imageArray = jQuery.parseJSON(images);
var product_images= imageArray[pd_id];
default_image = jQuery(this).attr('data-image');
console.log('default-image= ' + default_image);
timer = setInterval(function(){
selector.fadeOut("fast", function () {
console.log(counter);
if (counter === product_images.length) {
console.log('==');
counter = 0;
}
console.log('localhost/product/' + product_images[counter]);
selector.attr('src', 'localhost/product/' + product_images[counter]);
selector.fadeIn(2500);
counter = counter+ 1;
});
}, 2000);
}).mouseout(function() {
console.log('now end');
// var counter = 0;
clearInterval(timer);
});

Execute function IF another function is complete NOT when

I am having trouble creating a slider that pauses on hover, because I execute the animation function again on mouse off, if I flick the mouse over it rapidly (thereby calling the function multiple times) it starts to play up, I would like it so that the function is only called if the other function is complete, otherwise it does not call at all (to avoid queue build up and messy animations)
What's the easiest/best way to do this?
$(document).ready(function() {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
$('.slider_container').hover(function() {
//Mouse on
n = 0;
$('.slider').stop(true, false);
}, function() {
//Mouse off
n = 1;
if (fnct == 0) sliderLoop();
});
//Called in Slide Loop
function animateSlider() {
$('.slider').delay(3000).animate({ marginLeft: -(slide_width * i) }, function() {
i++;
sliderLoop();
});
}
var i = 0;
var fnct = 0
//Called in Doc Load
function sliderLoop() {
fnct = 1
if(n == 1) {
if (i < number_of_slides) {
animateSlider();
}
else
{
i = 0;
sliderLoop();
}
}
fnct = 0
}
sliderLoop();
});
The slider works fine normally, but if I quickly move my mouse on and off it, then the slider starts jolting back and forth rapidly...been trying to come up with a solution for this for hours now..
Here's what fixed it, works a charm!
$(document).ready(function() {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
var t = 0;
$('.slider_container').hover(function() {
clearInterval(t);
}, function() {
t = setInterval(sliderLoop,3000);
});
var marginSize = i = 1;
var fnctcmp = 0;
//Called in Doc Load
function sliderLoop() {
if (i < number_of_slides) {
marginSize = -(slide_width * i++);
}
else
{
marginSize = i = 1;
}
$('.slider').animate({ marginLeft: marginSize });
}
t = setInterval(sliderLoop,3000);
});

get interval ID from else statement when set in IF

I am attempting to create a responsive slider, that will change to a simple set of dot points when in mobile mode (< 940).
The issue I am facing is in my else statement I am unable to clearintervals that were made in the if statement, because t comes up as undefined. I have resorted to using
for (var i = 1; i < 99999; i++) window.clearInterval(i); to clear the interval which works, but I don't like it because it's ugly and cumbersome, is there another way of accomplishing this?
$(document).ready(function() {
function rePosition() {
//get responsive width
var container_width = $('.container').width();
//Slider for desktops only
if(container_width >= 940) {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
var t = 0;
$('.slider_container').hover(function() {
clearInterval(t);
}, function() {
t = setInterval(sliderLoop,6000);
});
var marginSize = i = 1;
//Called in Doc Load
function sliderLoop(trans_speed) {
if (trans_speed) {
var trans_speed = trans_speed;
}
else
{
var trans_speed = 3000;
}
if (i < number_of_slides) {
marginSize = -(slide_width * i++);
}
else
{
marginSize = i = 1;
}
$('.slider').animate({ marginLeft: marginSize }, trans_speed);
}
t = setInterval(sliderLoop,6000);
$('.items li').hover(function() {
$('.slider').stop();
clearInterval(t);
var item_numb = $(this).index();
i = item_numb;
sliderLoop(500);
}, function() {
t = setInterval(sliderLoop,6000);
});
}
else
{
for (var i = 1; i < 99999; i++)
window.clearInterval(i);
$('.slider').stop(true, true);
$('.slider').css('margin-left', '0px');
//rearrange content
if($('.slider .slide .slide_title').length < 1) {
$('.items ul li').each(function() {
var item_numb = $(this).index();
var content = $(this).text();
$('.slider .slide:eq(' + item_numb + ')').prepend('<div class="title slide_title">' + content + '</div>')
});
}
}
}
rePosition();
$(window).resize(function() {
rePosition();
});
});
Teemu's comment is correct. I'll expand on it. Make an array available to all of the relevant code (just remember that globals are bad).
$(document).ready(function() {
var myIntervalArray = [];
Now, whenever you create an interval you will need to reference later, do this:
var t = setInterval();//etc
myIntervalArray.push(t); //or just put the interval directly in.
Then to clear them, just loop the array and clear each interval.
for (var i=0; i<myIntervalArray.length; i++)
clearInterval(myIntervalArray[i]);
}
Umm, wouldn't t only be defined when the if part ran... as far as I can tell, this is going to run and be done... the scope will be destroyed. If you need to maintain the scope across calls, you'll need to move your var statements outside of reposition(), like so:
$(document).ready(function() {
var t = 0;
...
function rePosition() { ... }
});

Categories

Resources