I found a w3 schools slideshow that seems to work half the time perfectly the other half it will give me an error that says Uncaught TypeError: Cannot read property 'style' of undefined at showDivs (slideshow.js:33) which is the x[slideIndex-1] part. I can't quite seem to figure out whats wrong.
HTML
<h2 class="w3-center"></h2>
<div class="w3-content w3-display-container">
<img class="mybottom mySlides" src="pics/pic3.3.jpg" style="width:100%">
<img class="mybottom mySlides" src="pics/pic3.jpg" style="width:100%">
<img class="mybottom mySlides" src="pics/pic2.jpg" style="width:100%">
<img class="mybottom mySlides" src="pics/pic4.jpg" style="width:100%">
<button id="back" class="w3-button w3-black w3-display-left">❮</button>
<button id="forward" class="w3-button w3-black w3-display-right">❯</button>
</div>
JS
var slideIndex = 1;
showDivs(slideIndex);
function plusDivs(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";
}
document.getElementById("back").addEventListener("click", function(){
plusDivs(-1);
});
document.getElementById("forward").addEventListener("click", function(){
plusDivs(1);
});
Related
I am trying to find a solution to having a slideshow in my chrome extension. I have buttons for > and < within the slideshow and they are not working with the inline JS issue. I have overcome this by putting it all in a JS file but its still not working.
HTML:
<div class="contents">
<div class="description">
<div id="options-greet" style="font-size: 1.75em; font-weight: bold;"></div>
<div class="overview_description">
<div class="slideshow-container">
<div class="mySlides">
<q>I love you the more in that I believe you had liked me for my own sake and for nothing else</q>
<p class="author">- John Keats</p>
</div>
<div class="mySlides">
<q>But man is not made for defeat. A man can be destroyed but not defeated.</q>
<p class="author">- Ernest Hemingway</p>
</div>
<div class="mySlides">
<q>I have not failed. I've just found 10,000 ways that won't work.</q>
<p class="author">- Thomas A. Edison</p>
</div>
<a class="prev" id="button1" >❮</a>
<a class="next" id = "button2">❯</a>
</div>
JS file:
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";
}
document.getElementById("button2").addEventListener("onclick", plusSlides(1));
When you write 'onclick', plusSlides(1) you're immediately calling plusSlides and assigning the return value to the listener. But you're not returning anything - you're just calling a new function which also doesn't return anything. So, instead, pass a function reference that does call plusSlides when you have a click event.
.addEventListener('onclick', () => plusSlides(1));
I am trying to get my slider interactive on a test i'm working on and I just can't figure it out. I have some code I have utilised from W3 but I'm trying to add a couple of events for the buttons so it is all on it's own javascript file instead of embedded in the HTML.
Here is the HTML:
<!DOCTYPE html>
<html>
<title>W3.CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<script src="main.js" defer></script>
<body>
<h2 class="w3-center">Manual Slideshow</h2>
<div class="w3-content w3-display-container">
<img class="mySlides" src="./image_1.jpg" style="width:100%">
<img class="mySlides" src="./image_2.jpg" style="width:100%">
<img class="mySlides" src="./image_3.jpg" style="width:100%">
<button id="clicker" class="w3-button w3-black w3-display-left">❮</button>
<button id="clicker" class="w3-button w3-black w3-display-right">❯</button>
</div>
</body>
</html>
Here is the Javascript:
let leftSlideButton = document.getElementById("clicker");
let rightSlideButton = document.getElementById("clicker");
var slideIndex = 1;
showDivs(slideIndex);
function plusDivs(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";
}
let slideForward = plusDivs(1);
let slideBack = plusDivs(-1);
leftSlideButton.onclick = slideBack;
rightSlideButton.onclick = slideForward;
The slider worked when the script was embedded in the hmtl but when I tried to write in some functionality for the buttons in their own javascript file it just stops working and I'm pretty stumped now. Iv'e added them to their own variable and grabbed it's html selector so I can in turn add an event handler and link it to the function but it just doesn't work. Any help would be appreciated.
Also, this is my first post so apologies if I haven't formatted it correctly.
TIA, Neil.
Most likely the problem caused by 2 x id="clicker".
Using unique ids for the buttons should solve to problem.
Next, since slideIndex declared globally it doesn't require plusDivs middle-ware.
I would also suggest to use clearer functions and variables names for the sake of better readability. Check these: slideDivs vs showDivs, step vs n, slides vs x, etc. It maybe doesn't sound like a big deal on the given example, but it is a good habit and will save you a lot of time when working on bigger projects.
There are also some minor optimizations possible, such as changing visibility in one loop and caching slides outside of sliding function to avoid selecting it again on every click. Check the snipped for suggested rewritten code.
var visibleSlideIndex = 0;
var slides = document.getElementsByClassName("mySlides");
function slideDivs(step) {
visibleSlideIndex = (visibleSlideIndex + step + slides.length) % slides.length;
for (let index = 0; index < slides.length; index++) {
slides[index].style.display = visibleSlideIndex === index ? "block" : "none";
}
}
document.getElementById("slideLeftBtn").onclick = () => slideDivs(1);
document.getElementById("slideRightBtn").onclick = () => slideDivs(-1);
slideDivs(0);
<!DOCTYPE html>
<html>
<title>W3.CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<script src="main.js" defer></script>
<body>
<h2 class="w3-center">Manual Slideshow</h2>
<div class="w3-content w3-display-container">
<img class="mySlides" src="./image_1.jpg" style="background-color: red;">
<img class="mySlides" src="./image_2.jpg" style="background-color: green;">
<img class="mySlides" src="./image_3.jpg" style="background-color: blue;">
<button id="slideLeftBtn" class="w3-button w3-black w3-display-left">❮</button>
<button id="slideRightBtn" class="w3-button w3-black w3-display-right">❯</button>
</div>
</body>
</html>
You have multiple issues :
First, the button selection. You are trying to get the 2 buttons with the same id, you have to change that.
Then, those 2 lines :
let slideForward = plusDivs(1);
let slideBack = plusDivs(-1);
plusDivs(1) and plusDivs(-1) are calling the function and returning the value. To fix it, you can create an anonymous function (or an arrow function) to call plusDivs
Here is a fixed version (I changed the width of the images to 25% so it would be easier to see in the snippet):
let leftSlideButton = document.getElementById("clickerLeft");
let rightSlideButton = document.getElementById("clickerRight");
var slideIndex = 1;
showDivs(slideIndex);
function plusDivs(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";
}
leftSlideButton.onclick = () => plusDivs(1);
rightSlideButton.onclick = () => plusDivs(-1);
<h2 class="w3-center">Manual Slideshow</h2>
<div class="w3-content w3-display-container">
<img class="mySlides" src="https://via.placeholder.com/150" style="width:25%">
<img class="mySlides" src="https://via.placeholder.com/200" style="width:25%">
<img class="mySlides" src="https://via.placeholder.com/250" style="width:25%">
<button id="clickerLeft" class="w3-button w3-black w3-display-left">❮</button>
<button id="clickerRight" class="w3-button w3-black w3-display-right">❯</button>
</div>
You can't have two identical ids, so I gave the buttons separate ids, then I attached an event listener to each one with addEventListener. Inside each listener I added the plusDivs() function directly in.
let leftSlideButton = document.getElementById("clicker-left");
let rightSlideButton = document.getElementById("clicker-right");
var slideIndex = 1;
showDivs(slideIndex);
function plusDivs(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";
}
leftSlideButton.addEventListener("click", () => {plusDivs(1)});
rightSlideButton.addEventListener("click", () => {plusDivs(-1)});
.w3-content > img{
max-height: 200px;
object-fit: contain;
background-color: lightblue;
}
<h2 class="w3-center">Manual Slideshow</h2>
<div class="w3-content w3-display-container">
<img class="mySlides" src="http://placekitten.com/100/200" style="width:100%">
<img class="mySlides" src="http://placekitten.com/200/200" style="width:100%">
<img class="mySlides" src="http://placekitten.com/150/200" style="width:100%">
<button id="clicker-left" class="w3-button w3-black w3-display-left">❮</button>
<button id="clicker-right" class="w3-button w3-black w3-display-right">❯</button>
</div>
I have used a slider. But it slides manually when I click the arrow.
Here is my HTML code:
<div class="w3-content w3-display-container" style="box-shadow: 0px 0px 5px 0px rgba(0,0,0,.3);">
<img class="mySlides" src="img1.png" />
<img class="mySlides" src="img2.png" />
<button class="w3-button w3-black w3-display-left" onclick="plusDivs(-1)">❮</button>
<button class="w3-button w3-black w3-display-right" onclick="plusDivs(1)">❯</button>
</div>
Here is my JS code:
var slideIndex = 1;
showDivs(slideIndex);
plusDivs(slideIndex);
function plusDivs(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";
}
Now I want to add autoplay to slide images.
I have added below code in your javascript and html files -
In script create autoplay variable like this:
function showDivs(n) {
var i;
var x = document.getElementsByClassName("mySlides");
var autoplay = setInterval("plusDivs(-1)", 3000);
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";
autoplay;
}
I have coded this JavaScript slideshow to display a number of images however they are not displayed anywhere, the only thing showing are the two buttons I have included for choosing slides.
var slideIndex = 1;
showDivs(slideIndex);
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";
}
<img class="slides" href="Bgimage.jpg">
<img class="slides" href="roses.jpg">
<img class="slides" href="sunflowers.jpg">
<img class="slides" href="Vessel1.jpg">
<button class="go-left" onclick="plusDivs(-1)">❮</button>
<button class="go-right" onclick="plusDivs(+1)">❯</button>
Any help is much appreciated. Thanks!
Img tag has src not href. Your code works perfectly.
var slideIndex = 1;
showDivs(slideIndex);
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";
}
<img class="slides" src="http://fakeimg.pl/250x100/">
<img class="slides" src="http://fakeimg.pl/250x100/ff0000/">
<img class="slides" src="http://fakeimg.pl/350x200/ff0000/000">
<img class="slides" src="http://fakeimg.pl/250x100/ff0000/">
<button class="go-left" onclick="plusDivs(-1)">❮</button>
<button class="go-right" onclick="plusDivs(+1)">❯</button>
The img tag uses src to determine the source of the image. If you change href to src, you should be able to see the images again.
<img class="slides" src="Bgimage.jpg">
<img class="slides" src="roses.jpg">
<img class="slides" src="sunflowers.jpg">
<img class="slides" src="Vessel1.jpg">
var slideIndex = 0;
showDivs(slideIndex);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function showDivs(n) {
var i;
var x= document.getElementsByClassName("slides");
if (n >= x.length) { slideIndex = 0; }
if (n < 0) { slideIndex = x.length-1; }
for (i = 0; i < x.length; i++) {
if(i!==slideIndex) {
x[i].style.display = "none";
} else {
x[i].style.display = "block";
}
}
}
<img class="slides" src="Bgimage.jpg">
<img class="slides" src="roses.jpg">
<img class="slides" src="sunflowers.jpg">
<img class="slides" src="Vessel1.jpg">
<button class="go-left" onclick="plusDivs(-1)">❮</button>
<button class="go-right" onclick="plusDivs(+1)">❯</button>
I try to use " setTimeout(function,time) " but it doesn't work.
I copy some of code in w3schools.com.(https://www.w3schools.com/w3css/w3css_slideshow.asp)
This is codes of W3.CSS slideshow.
<div class="w3-content w3-display-container" style="max-width:800px;">
<img class="mySlides" src="img/food/pad.jpg"
style="width:100%;cursor:pointer;" onclick="plusDivs(1)">
<img class="mySlides" src="img/food/green_curry.jpeg"
style="width:100%;cursor: pointer;" onclick="plusDivs(1)">
<img class="mySlides" src="img/food/kai.jpg"
style="width:100%;cursor:pointer;" onclick="plusDivs(1)">
<div class="w3-center w3-container w3-section w3-large w3-text-white w3-
display-bottommiddle" style="width:100%">
<div class="w3-left w3-hover-text-khaki" onclick="plusDivs(-1)" >❮
</div>
<div class="w3-right w3-hover-text-khaki" onclick="plusDivs(1)">❯</div>
<span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(1)"></span>
<span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(2)"></span>
<span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(3)"></span>
This is JavaScript code.
<script>
var slideIndex = 1;
showDivs(slideIndex);
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";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" w3-white", "");
}
x[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " w3-white";
}
here is the working code for your problem -
<!DOCTYPE html>
<html>
<title>W3.CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<style>
.mySlides {
display: none
}
</style>
<body>
<div class="w3-container">
<h2>Slideshow Indicators</h2>
<p>An example of using buttons to indicate how many slides there are in the slideshow, and which slide the user is currently viewing.</p>
</div>
<div class="w3-content" style="max-width:800px">
<img class="mySlides" src="https://www.w3schools.com/w3css/img_nature_wide.jpg" style="width:100%">
<img class="mySlides" src="https://www.w3schools.com/w3css/img_fjords_wide.jpg" style="width:100%">
<img class="mySlides" src="https://www.w3schools.com/w3css/img_mountains_wide.jpg" style="width:100%">
</div>
<div class="w3-center">
<div class="w3-section">
<button class="w3-button w3-light-grey" onclick="plusDivs(-1)">❮ Prev</button>
<button class="w3-button w3-light-grey" onclick="plusDivs(1)">Next ❯</button>
</div>
<button class="w3-button demo" onclick="currentDiv(1)">1</button>
<button class="w3-button demo" onclick="currentDiv(2)">2</button>
<button class="w3-button demo" onclick="currentDiv(3)">3</button>
</div>
<script>
var slideIndex = 0;
carousel();
function carousel() {
var i;
var x = document.getElementsByClassName("mySlides");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
slideIndex++;
if (slideIndex > x.length) {
slideIndex = 1
}
x[slideIndex - 1].style.display = "block";
setTimeout(carousel, 5000); // Change image every 5 seconds
}
</script>
<script>
var slideIndex = 1;
showDivs(slideIndex);
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";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" w3-red", "");
}
x[slideIndex - 1].style.display = "block";
dots[slideIndex - 1].className += " w3-red";
}
</script>
</body>
</html>
Here, setTimeout(function,time) is working fine