I am trying to create a slideshow completely from scratch using html, css and plain javascript but I can't figure out what to do so that when I click one of the slideshow indicators the setInterval() resets its timer (in order to be able to change slide without it directly switching to the next one because there is, for example, only 1 sec left)
I have tried to reset the timer with clearInterval() and then reactivating the setInterval() but when I then click on one of the slideshow indicators the slides start changing at random moments (they don't follow the 6000ms timer of the SetInterval() for some reason).
var slides = document.querySelectorAll(".slide");
var dots = document.querySelectorAll(".dot");
function removeClass() {
for (var i = 0; i < slides.length; i++) {
slides[i].classList.remove('active');
}
}
function removeNext() {
for (var i = 0; i < slides.length; i++) {
slides[i].classList.remove('next');
}
}
function slideshow() {
currentSlide = document.querySelector(".active");
nextSlide = currentSlide.nextElementSibling;
if (nextSlide != null) {
removeClass();
nextSlide.classList.add('next');
nextSlide.classList.add('active');
} else {
removeClass();
slides[0].classList.add('next');
slides[0].classList.add('active');
}
removeNext();
}
var slideDelay = setInterval(slideshow, 6000);
document.addEventListener("click", function(event){
if (event.target.className == "dot") {
removeClass();
var dotAttrValue = event.target.getAttribute('data-slide-to');
slides[dotAttrValue-1].classList.add('active');
clearInterval(slideDelay);
var slideDelay = setInterval(slideshow, 6000);
}
});
Having two var declarations creates two separate intervals. Just get rid of the second one and you should be good to go.
var slides = document.querySelectorAll(".slide");
var dots = document.querySelectorAll(".dot");
function removeClass() {
for (var i = 0; i < slides.length; i++) {
slides[i].classList.remove('active');
}
}
function removeNext() {
for (var i = 0; i < slides.length; i++) {
slides[i].classList.remove('next');
}
}
function slideshow() {
currentSlide = document.querySelector(".active");
nextSlide = currentSlide.nextElementSibling;
if (nextSlide != null) {
removeClass();
nextSlide.classList.add('next');
nextSlide.classList.add('active');
} else {
removeClass();
slides[0].classList.add('next');
slides[0].classList.add('active');
}
removeNext();
}
var slideDelay = setInterval(slideshow, 6000);
document.addEventListener("click", function (event) {
if (event.target.className == "dot") {
removeClass();
var dotAttrValue = event.target.getAttribute('data-slide-to');
slides[dotAttrValue - 1].classList.add('active');
clearInterval(slideDelay);
slideDelay = setInterval(slideshow, 6000);//Var removed from here.
}
});
Related
I want to build something like this: https://jenniferlynnwagner.com/spanish360/story_html5.html (just for reference). I have images with content, now I want to display them on the screen and when the user clicks on next or previous button, able to do so. So, how can I achieve this thing in my project using JavaScript and Spring boot (backend)?
Below is the script to handle current, next and previous slide.
window.addEventListener('DOMContentLoaded', event => {
// Toggle the side navigation
const sidebarToggle = document.body.querySelector('#sidebarToggle');
if (sidebarToggle) {
// Uncomment Below to persist sidebar toggle between refreshes
// if (localStorage.getItem('sb|sidebar-toggle') === 'true') {
// document.body.classList.toggle('sb-sidenav-toggled');
// }
sidebarToggle.addEventListener('click', event => {
event.preventDefault();
document.body.classList.toggle('sb-sidenav-toggled');
localStorage.setItem('sb|sidebar-toggle', document.body.classList.contains('sb-sidenav-toggled'));
});
}
});
var slide_index = 1;
displaySlides(slide_index);
//chapter1-image 1-182
//chapter 2-image-1-127
//chapter 3-image 1-56
//chapter 4-image 1-42
//chapter 5-image 1-67
function nextSlide(n) {
document.getElementById("slide-img").src="img/slider-2.jpg"
playAudio(slide_index);
}
function playAudio(number) {
var audioElement = document.getElementById("my_audio");
audioElement.pause();
audioElement.currentTime = 0;
audioElement.src = "audio/" + number + ".mp3";
audioElement.load();
audioElement.play();
}
function currentSlide(n) {
displaySlides(slide_index = n);
}
function displaySlides(n) {
var i;
var slides = document.getElementsByClassName("showSlide");
if (n > slides.length) { slide_index = 1 }
if (n < 1) { slide_index = slides.length }
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slides[slide_index - 1].style.display = "block";
}
I have a slideshow of images,that it changes automatically( autoslide() ) every 4 sec, so when i press one of the next/back buttons, the countdown continues.
How I want to behaves : When one of the next/back buttons is pressed, the autoslide function countdown starts over from 0 seconds, without continuing the previous countdown.
var index = 1;
function plusindex(n) {
showimage(index += n);
}
showimage(index);
function showimage(n) {
var slide = document.getElementsByClassName('sliders');
if (n > slide.length) {
index = 1
};
if (n < 1) {
index = slide.length
};
for (i = 0; i < slide.length; i++) {
slide[i].style.display = "none";
}
slide[index - 1].style.display = "block";
}
var time = 4000;
autoslide()
function autoslide() {
var slide = document.getElementsByClassName('sliders');
for (i = 0; i < slide.length; i++) {
slide[i].style.display = "none";
}
if (index > slide.length) {
index = 1
};
slide[index - 1].style.display = "block";
index++;
setTimeout(autoslide, time);
}
<button class="btn" id="btn1" onclick="plusindex(-1)">❮</button>
<button class="btn" id="btn2" onclick="plusindex(1)">❯</button>
You could do this using clearTimeout. You function autoslide is to be modified as follows:
var timer;
function autoslide() {
var slide = document.getElementsByClassName('sliders');
for (i = 0; i < slide.length; i++) {
slide[i].style.display = "none";
}
if (index > slide.length) {
index = 1
};
slide[index - 1].style.display = "block";
index++;
timer = setTimeout(autoslide, time);
}
Here the timer keeps track of your next scheduled sliding. So, here's how you could use that to reset the timer:
function plusindex(n){
showimage(index +=n);
clearTimeout(timer);
timer = setTimeout(autoslide,time);
}
I wrote this line of code to animate the pictures on my webpage:
var SlideShow = function (container) {
this.images = [];
this.curImage = 0;
for (i = 0; i < container.childElementCount; i++) {
this.images.push(container.children[i]);
this.images[i].style.display = "none";
}
var nextSlide = function(){
for (var i = 0; i < this.images.length; i++) {
this.images[i].style.display = "none";
}
this.images[this.curImage].style.display = "block";
this.curImage++;
if (this.curImage >= this.images.length) {
this.curImage = 0;
}
window.setTimeout(nextSlide.bind(this), 3000);
};
nextSlide.call(this);
};
SlideShow(document.getElementById("testslide"));
The slide show works, pictures change but the style is boring. I want it to either slide in from the right to the left or fade in or something similar, any style at all other than just changing. How do I achieve this?
I'm working on some web pages that use a button to scroll to the next div. I can get it to work on every page, except in this particular instance (see jsfiddle).
My problem is that the buttons don't work on loading the page, the user first has to start scrolling manually, before the buttons work. I'm assuming that's because of some fault in my jQuery coding, which I've looked over and over, but I can't seem to find the problem. Is there anyone who is a bit more familiar with jQuery than I am who can offer me a solution?
http://jsfiddle.net/y5wx7nst/3/
$(document).ready(function () {
var currentElement = $("#bodytext > div:nth-child(1)");
var onScroll = function () {
var container = $("#bodytext");
var children = $(".section");
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
var childLeft = container.offset().left < child.offset().left;
if (childLeft) {
currentElement = child;
console.log(currentElement);
return;
}
}
};
var scrollToElement = function ($element) {
var container = $("#bodytext");
var children = $(".section");
var width = 0;
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
if (child.get(0) == $element.get(0)) {
if (i === 0) {
width = 0;
}
container.animate({
scrollLeft: width
}, 500);
onScroll();
}
if (child.next().length > 0) {
width += child.next().offset().left - child.offset().left;
} else {
width += child.width();
}
}
};
var buttonright = function (e) {
scrollToElement(currentElement.next());
};
var buttonleft = function (e) {
var container = $("#bodytext");
if (currentElement.prev().length > 0) {
if (container.offset().left == currentElement.prev().offset().left) {
currentElement = currentElement.prev().prev().length > 0 ? currentElement.prev().prev() : currentElement.prev();
} else {
currentElement = currentElement.prev();
}
}
scrollToElement(currentElement);
};
$("#bodytext").scroll(onScroll);
$("#buttonright").click(buttonright);
$("#buttonleft").click(buttonleft);
});
You are only calling the onScroll() function after you initially scroll:
$("#bodytext").scroll(onScroll);
I added this before that declaration and it all worked:
onScroll();
jsfiddle: http://jsfiddle.net/y5wx7nst/5/
When code run value of currentElement is not correct. So you should calculate it calling a function onScroll();
...
$("#bodytext").scroll(onScroll);
$("#buttonright").click(buttonright);
$("#buttonleft").click(buttonleft);
onScroll();
});
This is my first project in Javascript. It's an image slider with a next and previous arrow. One thing really bothering me is that there can some very noticeable lag between clicking an arrow and the image actually changing.
I'd really appreciate if someone review my code and let me know what I could do better.
http://jsfiddle.net/afptfbs8/40/
var myImage = document.getElementById("mainImage");
var imageArray = ["http://lorempixel.com/400/200/sports/1/", "http://lorempixel.com/400/200/sports/2/", "http://lorempixel.com/400/200/sports/3/", "http://lorempixel.com/400/200/sports/4/"];
var imageIndex = 0;
var prevImage = document.getElementById("prev");
var nextImage = document.getElementById("next");
var myTime = 3000;
var myInterval = setInterval(changeImage, myTime);
function changeImage() {
imageIndex++;
if (imageIndex >= imageArray.length) {
imageIndex = 0;
}
myImage.setAttribute("src", imageArray[imageIndex]);
}
prevImage.onclick = function() {
clearInterval(myInterval);
myInterval = setInterval(changeImage, myTime);
if (imageIndex === 0) {
imageIndex = imageArray.length -1;
} else {
imageIndex = imageIndex - 1;
}
myImage.setAttribute("src", imageArray[imageIndex]);
};
nextImage.onclick = function() {
clearInterval(myInterval);
myInterval = setInterval(changeImage, myTime);
if (imageIndex === imageArray.length -1) {
imageIndex = 0;
} else {
imageIndex = imageIndex + 1;
}
myImage.setAttribute("src", imageArray[imageIndex]);
};
imageArray.forEach(function (value, index) {
var node = document.createElement("li");
var textNode = document.createTextNode(index);
node.appendChild(textNode);
document.getElementById("myList").appendChild(node);
});
myInterval
The problem is that each time you change the picture, you are refetching it from the server. Take a look at the network panel to see. I suggest preloading all of the images so that they do not need to be refetched every time.
var images = new Array();
for (var i = 0; i < imageArray.length; i++) {
images[i] = new Image();
images[i].src = imageArray[i];
}