setInterval increment index mystery - javascript

I am bangging my head against a wall, I cant figure out what is happening when I try increment my index value from outside my function.
So I starts off as 0, great! Each loop through i gets i +1 (this all seems great) ... but when I click #sliderNext you will see I dont add to the i value, yet it still increments the i value (why???) That means when I click prev I have to decrease the value by 2 instead of i-- (again, why?) ... am I being thick and not seeing something obvious?
Perhaps a better way to add prev + next (one that does not stop the setinterval completely)
$.when( loadImages() ).done(function(a1){
var i = 0;
var numberOfImgs = imgArr.length;
function sliderRotate(passi){
$('#autoSlider').html(imgArr[i]); //show with current i index
i++; //it should increment AFTER image has shown
if (i >= numberOfImgs || i < 0){ i = 0; }
}
sliderRotate();
intervalID = setInterval(sliderRotate, 3000);
//prev + next clicks
$('#sliderNext').on( 'click' , function(){
clearTimeout(intervalID);
//x = i + 1;
sliderRotate();
});
$('#sliderPrev').on( 'click' , function(){
clearTimeout(intervalID);
if ( i === 0 ){ i = imgArr.length -2; } //this only kind of works if I click twice on the first image
else{i = i - 2; }
sliderRotate();
});
});// end of when
Here is a snippet example:
$(document).ready(function(){
var imgArr = [
'<img src="http://www.freedigitalphotos.net/images/img/homepage/87357.jpg">',
'<img src="http://assets.barcroftmedia.com.s3-website-eu-west-1.amazonaws.com/assets/images/recent-images-11.jpg">',
'<img src="https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/pia20645_main.jpg?itok=dLn7SngD">',
'<img src="https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/pia18368-1041.jpg?itok=Fkc2j_kw">',
'<img src="http://www.irishtimes.com/polopoly_fs/1.2527148.1454955520!/image/image.jpg_gen/derivatives/landscape_685/image.jpg">',
'<img src="http://www.gettyimages.in/gi-resources/images/Homepage/Hero/US/Feb2016/video-481880130.jpg">'
];
var i = 0;
var numberOfImgs = imgArr.length;
function sliderRotate(passi){
$('#autoSlider').html(imgArr[i]);
i++; //should increment here, not before???
if (i >= numberOfImgs || i < 0){ i = 0; }
}
sliderRotate();
intervalID = setInterval(sliderRotate, 3000);
//prev + next clicks
$('#sliderNext').on( 'click' , function(){
clearTimeout(intervalID);
//x = i + 1;
sliderRotate();
});
$('#sliderPrev').on( 'click' , function(){
clearTimeout(intervalID);
if ( i === 0 ){ i = imgArr.length -2; } //kindah works, but still buggy
else{i = i - 2; }
sliderRotate();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sliderContainer">
<div id="sliderNext">Next</div><br><br><br>
<div id="sliderPrev">Prev</div>
<div id="autoSlider"></div>
</div>

Initial value of i is 0. sliderRotate function renders the first image (at index 0) and increments i by 1. In the next execution of this function the second image (at index 1) will be shown and i will have a value 2.
Now, you want to get back to the previous image (at index 0). But value of i is 2. You have to show image at index i - 2.

You are calling sliderRotate():
$('#sliderNext').on( 'click' , function(){
clearTimeout(intervalID);
//x = i + 1;
**sliderRotate();**
});
And that will increment it by 1:
function sliderRotate(passi){
$('#autoSlider').html(imgArr[i]);
i++; //should increment here, not before???
if (i >= numberOfImgs || i < 0){ i = 0; }
}
Same for "prev", you are adding 1 when you call sliderRotate(), that is why you need to subtract 2.
Here is a working example with your code: https://jsfiddle.net/owbL084z/2/

Related

Javascript: slideshow not slide when click

I have simple code where is slideshow which automatic slides every 5000ms.
Now I tried to make button which when I click on this button next image will not slide every 5000ms but when I click.
When I make code like this browser giving me errors.
Is there any solutions or I need make ned slideshow?
This is original code:
function cycleBackgrounds() {
var index = 0;
$imageEls = $('.container .slide');
setInterval(function () {
index = index + 1 < $imageEls.length ? index + 1 : 0;
$imageEls.eq(index).addClass('show');
$imageEls.eq(index - 1).removeClass('show');
}, 5000);
};
$(function () {
cycleBackgrounds();
});
This is added code:
function rightSlide() {
index = index + 1 < $imageEls.length ? index + 1 : 0;
$imageEls.eq(index).addClass('show');
$imageEls.eq(index - 1).removeClass('show');
}
EDIT added HTML
<section class="slide show" style="background-image: url('https://s7img.ftdi.com/is/image/ProvideCommerce/FTD_19_EDAY_19M3_HP_HEROBANNER?$ftd-product-banner-lv$');">
<div class="slide-content-wrapper">
<div class="slide-content">
<h2>02</h2>
</div>
</div>
</section>
<section class="slide" style="background-image: url('https://s7img.ftdi.com/is/image/ProvideCommerce/FTD_19_EDAY_19M3_HP_HEROBANNER?$ftd-product-banner-lv$');">
<div class="slide-content-wrapper right">
<div class="slide-content">
<h2>01</h2>
</div>
</div>
</section>
The problem is that you are creating an interval and then never clearing it. This means that once the interval is created it will keep going on forever (currently). You can read more about intervals here.
To briefly explain how to solve it:
You need to assign the interval to a variable
When you want to manually change images then clear the interval
Code snippet from the site:
var myVar = setInterval(myTimer, 1000);
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
function myStopFunction() {
clearInterval(myVar);
}
Inside of your code, when creating the interval you need to assign it into a variable and inside of the function rightSlide() you would need to clear it clearInterval(<yourIntervalHere>);
var intervalVariable = setInterval(function () {
index = index + 1 < $imageEls.length ? index + 1 : 0;
$imageEls.eq(index).addClass('show');
$imageEls.eq(index - 1).removeClass('show');
}, 5000);
function rightSlide() {
clearInterval(intervalVariable);
index = index + 1 < $imageEls.length ? index + 1 : 0;
$imageEls.eq(index).addClass('show');
$imageEls.eq(index - 1).removeClass('show');
}
You need to clear the interval but that's not the only problem:
Probably, the $imageEls and index variables are not in the scope of your custom click handler. It is definitely not the cleanest solution, but for now we will add them to the global window object
This is how I would write it (untested):
function cycleBackgrounds() {
window.index = (window.index + 1 < window.$imageEls.length) ? window.index + 1 : 0;
window.$imageEls.eq(index).addClass('show');
window.$imageEls.eq(index - 1).removeClass('show');
}
$(function () {
// add the new variables to window so they are globally accessible
window.index = 0;
window.$imageEls = $('.container .slide');
// start sliding images
window.slideshow_interval = setInterval(cycleBackgrounds, 5000);
// register onClick handler for the button with id "myButton"
$('#myButton').on('click', function(){
if (window.slideshow_interval != -1){
clearInterval(window.slideshow_interval);
window.slideshow_interval = -1;
}
cycleBackgrounds();
});
});

setInterval doesnt tigger inner script on first time run

Maybe I'm not properly understanding setInterval but I have made a kind of slideshow script, as below:
var i = 0;
setInterval(function() {
$('.slide').fadeOut('slow').delay(200);
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i++;
if(i == 5){
i = 0;
}
}, 4000);
This works, except for the first run - no slides will display for the first 4 seconds.
See Fiddle here: http://jsfiddle.net/vpa89snf/6/
Is there anyway I can trigger whats inside the setInterval function when it runs the first time round?
Use setTimeOut instead of setInterval for better performance, inspect the sample below:
Here is working jsFiddle.
var i = -1;
var totalSlide = $('.slide').length-1;
var slideTimer = 0;
function nextFrame() {
i == totalSlide ? i = -1 : i;
i++;
$('.slide').fadeOut(200);
$('.slide').eq(i).fadeIn(200);
slideTimer = setTimeout(nextFrame,4000);
}
$('#holder').addClass('isAni');
nextFrame();
// play / pause animation
$('#holder').click(function() {
if ( $(this).hasClass('isAni') ) {
$(this).removeClass('isAni');
clearTimeout(slideTimer);
}else{
$(this).addClass('isAni');
nextFrame();
}
});
You need to run the function and not wait for the 4 first seconds:
var i = 0;
function doSomething() {
$('.slide').fadeOut('slow').delay(200);
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i = (i + 1) % 5;
}
$document.ready(function () {
setInterval(doSomething, 4000);
doSomething(); // run it!
});
JSFIDDLE.
This is how setInterval is executed. It runs your function after x milliseconds set as 2nd parameter.
What you have to do in order to show the first slide is to have the 1rst slide fadein like below:
var i = 0;
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i++;
setInterval(function() {
...
}, 4000);

For loop using jQuery and JavaScript

I'm trying to do a simple for loop in JavaScript/jQuery
every time I click NEXT, I want the I to increment once.
But it is not working. When I press next, nothing happens.
<script>
//function to show form
function show_form_field(product_field){
$(product_field).show("slow");
}
$(document).ready(function(){
//start increment with 0, until it is reach 5, and increment by 1
for (var i=0; i < 5 ;i++)
{
//when I click next field, run this function
$("#next_field").click(function(){
// fields are equial to field with id that are incrementing
var fields_box = '#field_'+[i];
show_form_field(fields_box)
})
}
});
</script>
You do not need the for loop. Just declare var i outside click function and increment it inside the function.
//function to show form
function show_form_field(product_field) {
$(product_field).show("slow");
}
$(document).ready(function () {
var i = 0; // declaring i
$("#next_field").click(function () {
if (i <= 5) { // Checking whether i has reached value 5
var fields_box = '#field_' + i;
show_form_field(fields_box);
i++; // incrementing value of i
}else{
return false; // do what you want if i has reached 5
}
});
});
You should declare variable i document wide, not inside the click handler.
//function to show form
function show_form_field(product_field){
$(product_field).show("slow");
}
$(document).ready(function(){
var i=0;
$("#next_field").click(function(){
var fields_box = '#field_'+ i++ ;
show_form_field(fields_box)
})
});
Call $("#next_field").click just one time, and in the click function, increase i every time.
$(document).ready(function() {
var i = 0;
$("#next_field").click(function() {
if (i >= 5) {
//the last one, no more next
return;
}
show_form_field('#field_' + (i++));
});
});
try this
$(document).ready(function(){
//start increment with 0, untill it is reach 5, and increment by 1
var i = 0;
$("#next_field").click(function(){
// fields are equial to field with id that are incrementing
if(i<5)
{
var fields_box = '#field_'+i;
show_form_field(fields_box);
i+=1;
}
else
{
return;
}
});
});

my jquery slider is running well but there is bug that it sometimes does'nt shows images on next or prev click

Found solution for the playing and stopping the slider.But problem is now with my next and prev links .these links some times does not shows any image.
my code is on the
http://jsfiddle.net/yogesh84/ftkLd/12/
var slides;
var cnt;
var amount;
var i;
var x;
var timer;
slides = jQuery('#my_slider').children();
cnt = jQuery('#counter');
amount = slides.length;
i=amount;
cnt.text(i+' / '+amount);
function run_prev() {
jQuery(slides[i]).fadeOut(1000);
i--;
if (i <= 0) i = amount;
jQuery(slides[i]).fadeIn(1000);
// updating counter
cnt.text(i+' / '+amount);
}
x=0;
function run_next() {
// hiding previous image and showing next
jQuery(slides[x]).fadeOut(1000);
x++;
if (x >= amount) x = 0;
jQuery(slides[x]).fadeIn(1000);
cnt.text(x+1+' / '+amount);
}
/***********start and stop functions***************/
function run() {
// hiding previous image and showing next
jQuery(slides[x]).fadeOut(1000);
x++;
if (x >= amount) x = 0;
jQuery(slides[x]).fadeIn(1000);
timer = setTimeout(run,2000);
}
function MySlider() {
timer = setTimeout(run,2000);
}
function stoper() {
clearTimeout(timer);
}
/***********end start and stop functions***************/
function slide_show(){
var timer;
if(jQuery('#slide_show').html()=='Play Slideshow')
{
jQuery('#slide_show').html('Stop Slideshow');
MySlider();
}
else
{
jQuery('#slide_show').html('Play Slideshow');
stoper()
}
}
// custom initialization
jQuery('#prev2').on("click",run_prev);
jQuery('#next2').on("click",run_next);
jQuery('#slide_show').on("click",slide_show);
I think you forgot to set timer
You declare at the top: timer but it is never filled.
So i think you should do:
timer = setTimeout( run, inetrval );
Also take the function outside of Run()
function run() {
}
if ( inetrval > 0 ) {
alert( inetrval );
run();
timer = SetTimeOut( run, inetrval )
}

Can't change css in Jquery when using a variable to reference an index of an array

var bubble = [$('#bubble1'), $('#bubble2'), $('#bubble3'), $('#bubble4'), $('#bubble5'), $('#bubble6')];
var bubbleFirst = 0;
var visibleBubbles = 3;
var bubbleHeight = 200;
var bubbleTimeDelay = 5000;
var bubbleTimer = setTimeout(function(){animateBubbles();}, bubbleTimeDelay/2);
function animateBubbles(){
clearTimeout(bubbleTimer);//stop from looping before this is finished
for(var i = 0; i < visibleBubbles + 1; i++){
count = i + bubbleFirst;
if ( count >= bubble.length ) count = count - bubble.length;//keep index inside array
bubble[count].animate({top:'-=' + bubbleHeight}, 2000);
}
bubble[bubbleFirst].css('top', '600px');//put elements moving off top to bottom
//resetBubbles();
bubbleFirst++;
if(bubbleFirst >= bubble.length) bubbleFirst = 0;//bubbles have looped
bubbleTimer = setTimeout(function(){animateBubbles();}, bubbleTimeDelay);//start looping again
}
bubble1 starts with top: 0px;
bubble2 starts with top: 200px;
bubble3 starts with top: 400px;
bubble4-6 start with top: 600px;
all are position: absolute in a wrapper div
Apologies for the code dump. My problems are all centered around line 16:
bubble[bubbleFirst].css('top', '600px');
This code is seemingly never executed, there is no error in my console and I have verified that bubble[bubbleFirst] is returning the correct element using console.log. (It's a div)
I'm currently using a workaround, but it is not dynamic:
function resetBubbles(){
/*bubble[bubbleFirst].css('top', '600px');//put elements moving off top to bottom*/
if(bubble[0].css('top') == '-200px') bubble[0].css('top', '600px');
if(bubble[1].css('top') == '-200px') bubble[1].css('top', '600px');
if(bubble[2].css('top') == '-200px') bubble[2].css('top', '600px');
if(bubble[3].css('top') == '-200px') bubble[3].css('top', '600px');
if(bubble[4].css('top') == '-200px') bubble[4].css('top', '600px');
if(bubble[5].css('top') == '-200px') bubble[5].css('top', '600px');
}
I have no idea why this isn't working, it's probably a logical error on my part. But I can't for the life of me find it. Any help would be appreciated. Thanks for your time.
Is it possible that the call to animate conflicts with you custom settings the top property? ie. you set it, but top is immediately altered again by animate. You can pass a callback to animate that will run when the animation has finished. That's when you should reset your bubble position.
function animate_bubble(index) {
bubble[index].animate({ top: "0px" }, 2000 /* 2 seconds */, function () {
bubble[index].css({ top: "600px" });
animate_bubble(index);
}
}
animate_bubble(0);
animate_bubble(1);
// etc .. probably do this in a for-loop
You'll need to find some way to cancel the animation though, shouldn't be too hard.
The problem was that bubbleFirst was incremented before the animation was finished. I changed my function to the following:
function animateBubbles(){
clearTimeout(bubbleTimer);//stop from looping before this is finished
for(var i = 0; i < visibleBubbles + 1; i++){
count = i + bubbleFirst;
if ( count >= bubble.length ) count = count - bubble.length;//keep index inside array
if (count == bubbleFirst)
{
bubble[count].animate({top:'-=' + bubbleHeight, opacity: 0}, bubbleAnimationSpeed, function(){
bubble[bubbleFirst].css('top', displayHeight+'px');
bubble[bubbleFirst].css('opacity', '1');
});
}
else if(i == visibleBubbles)
{
bubble[count].animate({top:'-=' + bubbleHeight}, bubbleAnimationSpeed, function(){
bubbleFirst++;
if(bubbleFirst >= bubble.length) bubbleFirst = 0;//bubbles have looped
bubbleTimer = setTimeout(function(){animateBubbles();}, bubbleTimeDelay);/*start looping again*/
});
}
else bubble[count].animate({top:'-=' + bubbleHeight}, bubbleAnimationSpeed);
}
}
Thanks for your input guys!

Categories