Javascript - setInterval to advance slideshow - javascript

I have created a basic image gallery following w3 schools tutorial for a manual slideshow. I'm trying to add some functionality by using setInterval() to advance the images even when the user doesn't click the button. Nothing seems to be occurring on the interval however. Any guidance in getting a timer to advance the slides would be greatly appreciated!
<div align="center">
<div class="slideViewer">
<img class="slides" src="images/dragonborn.jpg" style="width:50%">
<img class="slides" src="images/mountain.jpg" style="width:50%">
<img class="slides" src="images/nords.jpg" style="width:50%">
<img class="slides" src="images/dragon.jpg" style="width:50%">
<button class="display-left" onclick="plusDivs(-1)">❮</button>
<button class="display-right" onclick="plusDivs(1)">❯</button>
</div>
</div>
<script>
var slideIndex = 1;
showDivs(slideIndex);
var timer = setInterval(plusDivs(1), 1000);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function showDivs(n) {
var i;
var x = document.getElementsByClassName("slides");
if (n > x.length) {slideIndex = 1}
if (n < 1) {slideIndex = x.length}
for (i = 0; i < x.length; i++) {
x[i].style.display ="none";
}
x[slideIndex-1].style.display = "block";
}
</script>

You need to pass setInterval a function-- by calling the function in your code, you aren't passing the function, but instead the result of a single call. Instead, pass an anonymous function that then executes what you want to occur:
<div align="center">
<div class="slideViewer">
<img class="slides" src="images/dragonborn.jpg" style="width:50%">
<img class="slides" src="images/mountain.jpg" style="width:50%">
<img class="slides" src="images/nords.jpg" style="width:50%">
<img class="slides" src="images/dragon.jpg" style="width:50%">
<button class="display-left" onclick="plusDivs(-1)">❮</button>
<button class="display-right" onclick="plusDivs(1)">❯</button>
</div>
</div>
<script>
var slideIndex = 1;
showDivs(slideIndex);
var timer = setInterval(function () {
plusDivs(1);
}, 1000);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function showDivs(n) {
var i;
var x = document.getElementsByClassName("slides");
if (n > x.length) {slideIndex = 1}
if (n < 1) {slideIndex = x.length}
for (i = 0; i < x.length; i++) {
x[i].style.display ="none";
}
x[slideIndex-1].style.display = "block";
}
</script>

setInterval takes as its first parameter a function. By using the double-parenthesis you actually executed the plusDivs function and passed its return value (undefined) to setInterval
Instead, try the following:
setInterval(function() { plusDivs(1); }, 1000);
Or, alternatively, modify plusDivs so that it doesn't need a parameter and then just pass plusDivs directly like so:
setInterval(plusDivs, 1000):
function plusDivs(n) {
n = n || 1; // Default value
// ...
}
While we're at it, it's generally not considered a good practice to use a function before it's been declared. So you should move the plusDivs function above the call to setInterval

You need to pass a function as argument to setInterval. Currently, you just pass the result of calling plusDivs once.
Try this:
var timer = setInterval(() => plusDivs(1), 1000);
Note the parentheses and arrow - that defines an anonymous function that is executed with every interval.

this is the way to pass a parameter to a function and return a function
var plusDivs = function(n) {
return function() {
showDivs(slideIndex += n);
}
}
setInterval(plusDivs(1), 1000);

Related

Why won't the first image at first when loading the page? What is wrong with my javaScript?

I am working with wordpress theme twenty twenty-one for the first time and trying to create a slide show of images.. The problem that I am having is that when the page first appears no image is shown. When you click on the button then the first images shows up. Also when you get to the last image I want the first image in the array to show up, but instead no image shows up and you would have to click on the "previous arrow button" that I have created to see the last image again. First time working with the wordpress theme so I am thinking that something is overriding my script or that my script is wrong.
<div>
<img class="exe1-img"
src="https://www.ttttea.co.uk/wp-content/uploads/2021/05/fullsizeoutput_8ca.jpeg" alt="">
<img class="exe1-img" src="https://www.ttttea.co.uk/wp-content/uploads/2021/05/fullsizeoutput_945.jpeg" alt="">
<button class="previous-img" onclick="plusDivs(-1)">❮ </button
button class="next-img" onclick="plusDivs(1)"> ❯</button>
</div>
<script>
let slideIndex = 1;
showDivs(slideIndex);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function showDivs(n) {
let i;
let x = document.getElementsByClassName("exe1-img");
if (n > x.length) {
slideIndex = 1
}
if (n < 1) {
slideIndex = x.length
}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex-1].style.display = "block";
}
</script>
Had also had an issue with getting the automatic p tags out of the code in wordpress so had to write the script in single line. Apologies for the readability.
After replacing the images (yours were not resolving) and fixing the broken tags (which I think was an artifact of the way it was pasted into your question without using the {} button), it seems to work. Look at the snippet below and see if it's not doing what you want it to.
let slideIndex = 1;
showDivs(slideIndex);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function showDivs(n) {
let i;
let x = document.getElementsByClassName("exe1-img");
if (n > x.length) {
slideIndex = 1
}
if (n < 1) {
slideIndex = x.length
}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex - 1].style.display = "block";
}
<div>
<img class="exe1-img" src="https://images.unsplash.com/photo-1621343498292-eb469c743b25" height='100' alt="">
<img class="exe1-img" height='100' src="https://images.unsplash.com/photo-1621347797284-abb4b9d4ad40" alt="">
<button class="previous-img" onclick="plusDivs(-1)">❮ </button>
<button class="next-img" onclick="plusDivs(1)"> ❯</button>
</div>

Global variable is interfering with other code I would like to put it into these functions as a local variable of make it all into 1 big function

I have A global scope variable that is interfering with the rest of my code I want to be able to implement it within these 3 functions or to turn it all into 1 function that doesn't use global variables but I'm not sure how to achieve this can someone help me. Any help would be appreciated thank you.
var slideIndex = 1;
showSlides(slideIndex);
function plusSlides(n) {
showSlides((slideIndex += n));
}
function currentSlide(n) {
showSlides((slideIndex = n));
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("dot");
if (n > slides.length) {
slideIndex = 1;
}
if (n < 1) {
slideIndex = slides.length;
}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex - 1].style.display = "block";
dots[slideIndex - 1].className += " active";
}
<div>
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
</div>
<!-- slideshow-container -->
<div class="dot-container-for-slide-banner">
<span class="dot" onclick="currentSlide(1)"></span>
<span class="dot" onclick="currentSlide(2)"></span>
<span class="dot" onclick="currentSlide(3)"></span>
<span class="dot" onclick="currentSlide(4)"></span>
</div>
If you just put the whole code here inside an Immediately Invoked Function Expression (short IIFE), that should prevent any unnecessary global variables:
(() => {
var slideIndex = 1;
showSlides(slideIndex);
// ...
})();
You should also absolutely avoid inline attribute handlers like
onclick="plusSlides(-1)"
and
onclick="currentSlide(1)"
because they require global pollution and have a demented scope chain. Attach the listeners properly using addEventListener instead:
document.querySelector('.prev').addEventListener('click', () => {
plusSlides(-1);
});
document.querySelector('.next').addEventListener('click', () => {
plusSlides(1);
});
document.querySelectorAll('.dot').forEach((span, i) => {
span.addEventListener('click', () => {
currentSlide(i + 1);
});
});

Function not changing value of variable

I am working on an HTML page where I want function typewriter to be executed first and then for a loop to start that prints '.', to make it look like a loading screen.
This is the code I am using:
var y = 0
var i = 0;
var txt = '//Welcome To My Playground!';
var speed = 100;
function typeWriter() {
if (i < txt.length) {
document.getElementById("typing").innerHTML += txt.charAt(i);
i++;
setTimeout(typeWriter, speed);
}
y = 1;
}
while (y == 1) {
var span = document.getElementById('myspan');
var int = setInterval(function() {
if ((span.innerHTML += '.').length == 11)
span.innerHTML = '';
}, 200);
}
window.onload = typeWriter;
<div class="main d-none d-lg-block">
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-1">Hi,<br>I'm Shalaj<span id="myspan"></span>
</h1>
<h1 id="typing" class="display-5" style="margin-top:30px;"></h1>
<h1 class="display-5" style="margin-top:100px;">
Prototyping = ["Arduino", "Raspberry Pi"]
<br> Languages = ["HTML", "CSS", "PYTHON", "C++"]
</h1>
</div>
</div>
</div>
The function typewriter() is getting executed but the code following it doesn't start, I assume this is because the value of y is not being set as 1. Could someone help me out here?
Thanks
Perhaps you could create another function that is called where y is being set:
var i = 0;
var txt = '//Welcome To My Playground!';
var speed = 100;
function typeWriter() {
if (i < txt.length) {
document.getElementById("typing").innerHTML += txt.charAt(i);
i++;
setTimeout(typeWriter, speed);
} else {
typeEllipses();
}
}
function typeEllipses() {
var span = document.getElementById('myspan');
var int = setInterval(function() {
if ((span.innerHTML += '.').length == 11)
span.innerHTML = '';
}, 200);
}
window.onload = typeWriter;
<div class="main d-none d-lg-block">
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-1">Hi,<br>I'm Shalaj<span id="myspan"></span>
</h1>
<h1 id="typing" class="display-5" style="margin-top:30px;"></h1>
<h1 class="display-5" style="margin-top:100px;">
Prototyping = ["Arduino", "Raspberry Pi"]
<br> Languages = ["HTML", "CSS", "PYTHON", "C++"]
</h1>
</div>
</div>
</div>
You can see what is happening if you change
while(statement) {
//code
}
to
do{
//code
}while(statement)
The do...while loop only executes once. That's because it's being run one time on execution, at the time that y == 0. The while loop the way you have it never fires at all because the one time its statement is interpreted, y == 0.
If you want to call it every time typeWriter() is called, you already have a recursive loop for that function, so just put the while code in its own function and call it from inside there.
var y = 0
var i = 0;
var txt = '//Welcome To My Playground!';
var speed = 100;
function typeWriter() {
if (i < txt.length) {
document.getElementById("typing").innerHTML += txt.charAt(i);
i++;
setTimeout(typeWriter, speed);
}
console.log(y)
y = 1;
}
do{
console.log("test")
/*var span = document.getElementById('myspan');
var int = setInterval(function() {
if ((span.innerHTML += '.').length == 11)
span.innerHTML = '';
}, 200);*/
}while (y == 1)
window.onload = typeWriter;
<div id="typing"></div>
Hey try this No Need For Loop
If you use while loop of infinite it will crash.
so just use setInterval and clear the interval once theed for the loading is done clear the interval using clearInterval()
var y = 0
var i = 0;
var txt = '//Welcome To My Playground!';
var speed = 100;
function typeWriter() {
if (i < txt.length) {
document.getElementById("typing").innerHTML += txt.charAt(i);
i++;
setTimeout(typeWriter, speed);
}
y = 1;
}
var span = document.getElementById('myspan');
var interval = setInterval(function () {
if ((span.innerHTML += '.').length == 11)
span.innerHTML = '';
}, 200);
window.onload = typeWriter;
<div class="main d-none d-lg-block">
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-1">Hi,<br>I'm Shalaj<span id="myspan"></span>
</h1>
<h1 id="typing" class="display-5" style="margin-top:30px;"></h1>
<h1 class="display-5" style="margin-top:100px;">
Prototyping = ["Arduino", "Raspberry Pi"]
<br>
Languages = ["HTML", "CSS", "PYTHON", "C++"]
</h1>
</div>
</div>
</div>
Try this instead,
var i = 0;
var txt = "//Welcome To My Playground!";
var speed = 100;
var loading;
function typeWriter() {
if (i < txt.length) {
document.getElementById("typing").innerHTML += txt.charAt(i);
i++;
setTimeout(typeWriter, speed);
} else {
var span = document.getElementById("myspan");
var loading = setInterval(function () {
span.innerHTML = span.innerHTML.length == 11 ? "" : span.innerHTML;
span.innerHTML += ".";
}, speed);
// clearInterval(loading); // to stop loading dots
}
}

Can I use for loop with onclick to write out multiple results?

Sorry for my English.
A want to write out numbers (0, 3, 6, 9... 27) with the help of a for loop, but it seems it is harder than I thought. Thank You for your help.
I found a similar problem: For loop onclick button
function count() {
var i = 0;
if (i < 10) {
document.getElementById("demo").innerHTML = (i * 3);
} else {
document.getElementById("demo").innerHTML = "nothing";
}
i++;
}
<div>
<h1>This is a Heading</h1>
<h1 onclick="count()"><span>Click on me</span></h1>
<br/>
<p id="demo"></p>
</div>
View on JSFiddle
If I understand correctly, I don't think you need a for loop.
Your current code defines i=0 each time the function is called.
You'll just need to define the i variable outside of your function so it can be properly incremented.
var i = 0;
function count() {
if (i < 10) {
document.getElementById("demo").innerHTML = (i * 3);
} else {
document.getElementById("demo").innerHTML = "nothing";
}
i++;
}
<div>
<h1>This is a Heading</h1>
<h1 onclick="count()"><span>Click on me</span></h1>
<br/>
<p id="demo"></p>
</div>
Alternatively, increment the counter by three upon each click. Below, I'm using the ternary operator. It's saying, "if i is less than 27, add three. otherwise, set it to 'nothing'."
var i = 0,
output = document.getElementById('output');
function increment() {
i = i < 27 ? i + 3 : 'nothing';
output.innerHTML = i;
}
document.getElementById('trigger').addEventListener('click', increment);
<h1 id="trigger">Click on me</h1>
<p id="output">0</p>
How about something like that:
function count() {
for (i=0; i<10; i++) {
document.getElementById("demo").innerHTML += (i * 3)
}
}

JS onclick not executing for slideshow

I am trying to use W3.CSS Slideshow, the section "Slideshow Indicators".
However I need to create the previous and next buttons dynamically using JS.
But for some reason the prev and next buttons are not working..! (nothing happen onclick)
Here is my code:
HTML Code:
<title>Pre:D</title>
<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">
<script src="script.js"></script>
</head>
<body>
<div class="w3-row-padding" style = "width: 800px" id="form">
<div class="mySlides">First Slide</div>
<div class="mySlides">Second Slide</div>
<div class="mySlides">Third Slide</div>
</div>
<div id="toggle" class="w3-center" style = "width: 800px">
</div>
</body>
Js Code:
var slideIndex = 1;
function plusDivs(n) {
showDivs(slideIndex += n);
}
function currentDiv(n) {
showDivs(slideIndex = n);
}
function showDivs(n) {
var i;
var x = document.getElementsByClassName("mySlides");
//var dots = document.getElementsByClassName("demo");
if (n > x.length) {slideIndex = 1}
if (n < 1) {slideIndex = x.length}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex-1].style.display = "block";
}
window.onload=function(){
var dump = document.getElementById("toggle");
var sec = document.createElement("div");
sec.className = "w3-section";
var prev = document.createElement("button");
prev.className = "w3-btn";
prev.addEventListener("click", plusDivs(-1));
prev.innerHTML = "Previous";
var next = document.createElement("button");
next.className = "w3-btn";
next.addEventListener("click", plusDivs(1));
next.innerHTML = "Next";
sec.appendChild(prev);
sec.appendChild(next);
dump.appendChild(sec);
showDivs(slideIndex);
};
The buttons were working when created in the html file, but once I created them using js they got created but the onclick function doesn't work..
In case of passing parameters, bind it like prev.addEventListener("click", function() { plusDivs(-1) });
Here is an Example:
var slideIndex = 1;
function plusDivs(n) {
showDivs(slideIndex += n);
}
function currentDiv(n) {
showDivs(slideIndex = n);
}
function showDivs(n) {
var i;
var x = document.getElementsByClassName("mySlides");
if (n > x.length) {
slideIndex = 1
}
if (n < 1) {
slideIndex = x.length
}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex - 1].style.display = "block";
}
window.onload = function() {
var dump = document.getElementById("toggle");
var sec = document.createElement("div");
sec.className = "w3-section";
var prev = document.createElement("button");
prev.className = "w3-btn";
prev.addEventListener("click", function() {
plusDivs(-1)
});
prev.innerHTML = "Previous";
var next = document.createElement("button");
next.className = "w3-btn";
next.addEventListener("click", function() {
plusDivs(1)
});
next.innerHTML = "Next";
sec.appendChild(prev);
sec.appendChild(next);
dump.appendChild(sec);
showDivs(slideIndex);
};
<link href="http://www.w3schools.com/lib/w3.css" rel="stylesheet" />
<div class="w3-row-padding" style="width: 800px" id="form">
<div class="mySlides">First Slide</div>
<div class="mySlides">Second Slide</div>
<div class="mySlides">Third Slide</div>
</div>
<div id="toggle" class="w3-center" style="width: 800px">
</div>

Categories

Resources