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();
});
});
Related
I work with big quantity of data, and all data are not fering in screen, was decided to change data depends of time interval. When my page is load in array i received 18 items, which i put in to div's.
So i need show in page first 8 items, after 10 second, another 8 items, and in the end show 2 items (because i have only 18 items.).
So i create script which show one by one div's, but i need show 8 in 10 second
var current = 0;
setInterval(function () {
var divs = $(".cards").hide();
divs.eq(current).fadeIn("normal");
console.log(divs.eq(current))
if (current < divs.length - 1)
current++;
else
current = 0;
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cards">1</div>
<div class="cards">2</div>
<div class="cards">3</div>
<div class="cards">4</div>
<div class="cards">5</div>
<div class="cards">6</div>
<div class="cards">7</div>
<div class="cards">8</div>
<div class="cards">9</div>
<div class="cards">10</div>
<div class="cards">11</div>
<div class="cards">12</div>
<div class="cards">13</div>
<div class="cards">14</div>
<div class="cards">15</div>
<div class="cards">16</div>
<div class="cards">17</div>
<div class="cards">18</div>
So how it's must works:
First 10 sec show div's from 1-8
After 10 sec show items from 9-16
And in the end show rest 2 div's
But for this exmple i have 18, but this data will be dynamicaly, and i dont know how many div's i will have
A solution:
var current = 0;
$(".cards").hide();
setInterval(function () {
var divs = $(".cards").hide();
var i = 0;
while (i < 8) {
divs.eq(current).fadeIn("normal");
console.log(divs.eq(current))
if (current < divs.length) {
i++;
current = current + 1;
} else {
i = 0;
current = 0;
}
}
}, 10000);
Solution was found:
script:
$(document).ready(function () {
var elements = $(".cards");
var index = 0;
var showNext = function (index) {
if (index >= elements.length) {
index = 0;
}
console.log(index);
elements.hide().slice(index, index + 8).show();
setTimeout(function () {
showNext(index + 8)
}, 10000);
}
showNext(0);
});
I am trying to create a simple slider using javascript.
So far, here is my code :
html:
<div class="carousel-container">
<div class="slides-container">
<div class="slide">
<img src="assets/images/image-1.jpg" alt="">
</div>
<div class="slide">
<img src="assets/images/image-3.jpg" alt="">
</div>
<div class="slide">
<img src="assets/images/image-2.jpg" alt="">
</div>
<div class="slide">
<img src="assets/images/image-3.jpg" alt="">
</div>
</div>
</div>
<div class="carousel-nav">
<button class="button-previous">Previous</button>
<button class="button-next">Next</button>
</div>
Js :
const slides = document.querySelectorAll('.slide')
const slidesContainer = document.querySelector('.slides-container')
const slidesCount = slides.length
const slideWidth = slides[0].clientWidth
const prevButton = document.querySelector('.button-previous')
const nextButton = document.querySelector('.button-next')
function nextSlide(slide) {
for (slide = 0; slide < slidesCount; slide++) {
slidesContainer.style.transform = 'translateX(-' + (slide * slideWidth) + 'px)'
}
}
nextButton.addEventListener('click', function() {
nextSlide()
})
The issue I have is that when I click on the next button, the slider goes all the way at the end of my array, thus skipping all the images in between.
What would be the best way to have my for loop stop at each image and go again when the button is clicked?
The reason it is skipping to the end with each click is: the for() loop. You are cycling through all of the slides — generating a new translateX coordinate with each pass – on every click. Leaving you with the last value every time.
The answer CheapGamer gave defines a pattern to avoid the for() loop trap by keeping track of the current “slide” index outside of the nextSlide() handler.
let current = 0; // <- independent index reference
function nextSlide(slide) {
if (current < slidesCount) {
slidesContainer.style.transform = 'translateX(-' + (current * slideWidth) + 'px)';
current++; // <- increment the index
}
}
// I changed the `slide` reference in `(slide * slideWidth)` to `current` to reflect the intent of the code
This takes care of incrementing you through the carousel until current equals 3. (The slide argument in nextSlide(slide) isn’t necessary.)
let current = 0;
function nextSlide(slide) {
if (current < slidesCount) {
slidesContainer.style.transform = 'translateX(-' + (slide * slideWidth) + 'px)';
current++;
}
}
I might not exactly understand what you try to do or why you intend to use a for loop but if it's just about selecting the next slide you may go with this:
var currentSlide = 0;
function nextSlide() {
//make sure currentSlide is in range
currentSlide = (currentSlide >= slidesCount) ? 0 : ++currentSlide;
slidesContainer.style.transform = 'translateX(-' + (currentSlide * slideWidth) + 'px)';
}
nextButton.addEventListener('click', nextSlide);
or a little bit more flexible:
var currentSlide = 0;
function nextSlide(direction /* Number */) {
if(!direction) direction = 1; //default
setSlide(currentSlide + direction % slidesCount);
}
function setSlide(index) {
if(index === currentSlide) return;
//make sure index is in range
while(index >= slidesCount) index -= slidesCount;
while(index < 0) index += slidesCount;
slidesContainer.style.transform = 'translateX(-' + (index * slideWidth) + 'px)';
currentSlide = index;
}
nextButton.addEventListener('click', function() {
nextSlide(this.dataset["direction"]); //by using data you don't need two different button classes
});
But if you insist on using a loop I'm afraid to tell that it's inappropriate in this case since the calculation of translateX is based on a given value.
I have created a website for a friend which includes a slideshow with his most recent Instagram posts. The slideshow has a right and left arrow cursor.
The right cursor is working how I want it to; it shows each image from the array upon each click, and keeps going regardless of how many times the user clicks the right cursor. When it reaches the last image in the array, it starts at the first image again due to an if statement put in place.
However, I am having trouble with the left cursor and I suspect it is the counter variable? With the current code, what happens is when I click the left cursor (with the page refreshed and without even clicking on the right cursor), it goes to the second image in the array index1, rather than the last. Then I click the left cursor again without any change happening, then when I click it the third time it goes to the last image in the array and works as it should until it reaches the second image in the array again - because after that it does not go to the first image, it skips the first image after another click of nothing happening and then goes to the last image in the array. Repeats itself in that manner (sorry for going so in-detail, but I want people to get an idea of whats happening here if the code doesn't help).
var sliderImages = [];
var counter = 1;
sliderImages[0] = "images/i1.png";
sliderImages[1] = "images/i2.png";
sliderImages[2] = "images/i3.png";
sliderImages[3] = "images/i4.png";
sliderImages[4] = "images/i5.png";
$("#right-arrow").click(function() {
$(".active").attr("src", sliderImages[counter]);
counter++;
$('#count').text(counter);
if (counter >= sliderImages.length) {
counter = 0;
}
});
$("#left-arrow").click(function() {
$(".active").attr("src", sliderImages[counter]);
counter--;
if (counter <= 0) {
counter = sliderImages.length
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section id="instagram-feed">
<div class="container">
<h2>INSTAGRAM GALLERY</h2>
<div class="insta-gallery">
<img src="images/left-arrow.png" class="arrow" id="left-arrow">
<img src="images/i1.png" class="active">
<img src="images/right-arrow.png" class="arrow" id="right-arrow">
</div>
</div>
<div class="clear"></div>
</section>
When your page loads, you set counter to 1. When you click the left-arrow button, the first thing you do is set the image to the counter value, and so you set the image to 1. (Remember, arrays are 0-indexed, meaning 1 refers to the second item).
You'd be better off if counter was referring to the current image, not trying to assume the upcoming one. See my comments in the modified code below for more information.
var sliderImages = [];
var counter = 0; //Start with first image instead of second
sliderImages[0] = "images/i1.png";
sliderImages[1] = "images/i2.png";
sliderImages[2] = "images/i3.png";
sliderImages[3] = "images/i4.png";
sliderImages[4] = "images/i5.png";
$("#right-arrow").click(function() {
counter++; //Moving forward by one
if (counter > sliderImages.length-1) counter = 0; //Wrap-around if we exceed length-1
$(".active").attr("src", sliderImages[counter]); //Update img src
});
$("#left-arrow").click(function() {
counter--; //Moving backward by one
if (counter < 0) counter = sliderImages.length-1; //Wrap-around if negative
$(".active").attr("src", sliderImages[counter]); //Update img src
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section id="instagram-feed">
<div class="container">
<h2>INSTAGRAM GALLERY</h2>
<div class="insta-gallery">
<img src="images/left-arrow.png" class="arrow" id="left-arrow">
<img src="http://via.placeholder.com/350x150" class="active">
<img src="images/right-arrow.png" class="arrow" id="right-arrow">
</div>
</div>
<div class="clear"></div>
</section>
Use a counter as if you're handling indexes, so set it initially at 0.
Here's the basic logic:
var sliderImages = [
"//placehold.it/100x100/0bf?text=O",
"//placehold.it/100x100/f0b?text=1",
"//placehold.it/100x100/0fb?text=2",
"//placehold.it/100x100/fb0?text=3",
"//placehold.it/100x100/b0f?text=4"
];
var n = sliderImages.length; // Total slides
var c = 0; // Counter
function anim () {
$("#mainImage").attr("src", sliderImages[c]);
}
$("#prev").on("click", function() {
--c; // Pre-decrement
if ( c < 0 ) { c = n-1; } // If lower than 0 - go to last slide
anim(); // animate
});
$("#next").on("click", function() {
++c; // Pre-increment
if ( c > n-1 ) { c = 0; } // If greater than num of slides - go to first slide
anim(); // animate
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img id="mainImage" src="//placehold.it/100x100/0bf?text=O">
<br>
<button id="prev">←</button>
<button id="next">→</button>
<span id="count"></span>
Or here's a neater extracted formula of the above:
var sliderImages = [
"//placehold.it/100x100/0bf?text=O",
"//placehold.it/100x100/f0b?text=1",
"//placehold.it/100x100/0fb?text=2",
"//placehold.it/100x100/fb0?text=3",
"//placehold.it/100x100/b0f?text=4"
];
var n = sliderImages.length; // Total slides
var c = 0; // Counter
function anim () {
c = c<0 ? n-1 : c%n; // Fix counter
$("#mainImage").attr("src", sliderImages[c]); // Animate (or whatever)
}
$("#prev, #next").on("click", function() {
c = this.id==="next" ? ++c : --c; // Increement or decrement
anim(); // Animate
});
// If you have bullets than you can simply do like:
$(".bullet").on("click", function() {
c = $(this).index();
anim();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img id="mainImage" src="//placehold.it/100x100/0bf?text=O">
<br>
<button id="prev">←</button>
<button id="next">→</button>
<span id="count"></span>
Updated your code a bit :
var sliderImages = [];
var counter = 0;
sliderImages[0] = "images/i1.png";
sliderImages[1] = "images/i2.png";
sliderImages[2] = "images/i3.png";
sliderImages[3] = "images/i4.png";
sliderImages[4] = "images/i5.png";
$("#right-arrow").click(function() {
counter++;
$(".active").attr("src", sliderImages[counter]);
$('#count').text(counter);
if (counter >= sliderImages.length) {
counter = 0;
}
});
$("#left-arrow").click(function() {
counter--;
$(".active").attr("src", sliderImages[counter]);
if (counter <= 0) {
counter = sliderImages.length - 1;
}
});
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/
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);