Slideshow not working :/ - javascript

<html>
<head>
<style>
.mySlides {
display:none;
height:200px;
width:800px;
margin-left:auto;
margin-right:auto;
}
</style>
<head>
<body>
<script>
var myIndex = 0;
carousel();
function carousel() {
var i;
var x = document.getElementsByClassName("mySlides");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
myIndex++;
if (myIndex > x.length) { myIndex = 1 }
x[myIndex - 1].style.display = "block";
setTimeout(carousel, 2000); // Change image every 2 seconds
}
</script>
<section id="images">
<img id="yeah" class="mySlides" src="image1.jpg" />
<img class="mySlides" src="image2.jpg" />
<img class="mySlides" src="image3.jpg" />
</section>
</body>
</html>
So i'm not sure why this automatic slideshow isn't working when it was copied almost verbatim from w3schools, the result doesn't display anything. Ive been trying to find out whats wrong with it for about a day and a half now and still no luck, Please Help!

I believe that this was not working because before the edit, your script tag was before your html tags..hence the script executed the function and raised a couple of errors since your html was not fully loaded...
Place your script tag below your html codes (in this scenario)
see snippet
<html>
<style>
.mySlides {
display: none;
height: 200px;
width: 800px;
margin-left: auto;
margin-right: auto;
}
</style>
<body>
<section id="images">
<img id="yeah" class="mySlides" src="https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRxjU7k88PhMjr8f7tCmwOhiaik22dtZYY773ZtWG4TSOLgspnOeIhpOHHa" />
<img class="mySlides" src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQiUk8V76AvsGFAkDEHVjnZID8iFgB8LF7mQMbVVDB8mLnxb81v1g" />
</section>
</body>
</html>
<script>
var myIndex = 0;
carousel();
function carousel() {
var i;
var x = document.getElementsByClassName("mySlides");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
myIndex++;
console.log(x, myIndex);
if (myIndex > x.length) {
myIndex = 1
}
x[myIndex - 1].style.display = "block";
setTimeout(carousel, 2000); // Change image every 2 seconds
}
</script>

Here is a slightly different implementation of the slideshow that allows auto rotation of the images.
var image_number = 0;
function slideshow(num) {
var images = new Array("image1.jpg", "image2.jpg", "image3.png");
var description = new Array("Title1", "Title2", "Title3");
var image_length = images.length - 1;
image_number = image_number + num;
if (image_number > image_length) {
image_number = 0;
}
if (image_number < 0) {
image_number = image_length;
}
// Change <img> src and image description in DOM
document.getElementById("slideshow").src=images[image_number];
document.getElementById("description").innerHTML = description[image_number];
return false;
}
function auto_slideshow() {
setInterval(function(){
slideshow(1);
}, 3000);
}

Related

Error x[index] is undefined" in slides HTML/CSS/JS

I'm new in front end development and I want some help with this error
can you please help me fix the problem im facing
var index = 1; show(index);
function move(n) { show(index = index + n); }
function show(n) { var i; var x =
document.getElementsByClassName("slides"); for (i = 0; i < x.length;
i++) { x[i].style.display = "none"; } x[index].style.display =
"block"; }
.w3-content{max-width:980px;margin:auto}
.w3-center{text-align:center!important}
.w3-btn-floating:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
.w3-button{color:#000;background-color:#f1f1f1;padding:8px 16px}.w3-button:hover{color:#000!important;background-color:#ccc!important}
.w3-btn,.w3-btn-floating{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.w3-btn-floating{display:inline-block;text-align:center;color:#fff;background-color:#000;position:relative;overflow:hidden;z-index:1;padding:0;border-radius:50%;cursor:pointer;font-size:24px}
.w3-btn-floating{width:40px;height:40px;line-height:40px}
.w3-btn-floating:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
.w3-btn-floating{-webkit-transition:background-color .25s,color .15s,box-shadow .25s,opacity 0.25s,filter 0.25s,border 0.15s;transition:background-color .25s,color .15s,box-shadow .15s,opacity .25s,filter .25s,border .15s}
<!DOCTYPE html>
<html>
<body>
<div class="w3-content" style="max-width:400px;position:relative">
<img class="slides" src="https://i.stack.imgur.com/Qypol.jpg" style="width:100%">
<img class="slides" src="https://i.stack.imgur.com/yU7fs.jpg" style="width:100%">
<img class="slides" src="https://i.stack.imgur.com/xxLmR.jpg" style="width:100%">
<img class="slides" src="https://i.stack.imgur.com/YiIiQ.jpg" style="width:100%">
<a class="w3-btn-floating" style="position:absolute;top:45%;left:0" onclick="move(-1)">❮</a>
<a class="w3-btn-floating" style="position:absolute;top:45%;right:0" onclick="move(1)">❯</a>
</div>
</body>
</html>
So the problem with your JS code is that you don't consider changing index based on length of the slides which are your clicks to the right and left buttons.
What I mean to say you should think what will happen when you keep clicking the right button so every time the index will increase so you need to set it back to the first image or slide in this case with this condition if (n > x.length) {index = 1}
and vice versa if (n < 1) {index = x.length} for the case when you decrease the images or slides (left button).
Here is the JS code you need to solve this problem:
var index = 1;
show(index);
function move(n) {
show(index = index + n);
}
function show(n) {
var i;
var x = document.getElementsByClassName("slides");
if (n > x.length) {index = 1}
if (n < 1) {index = x.length}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[index-1].style.display = "block";
}
Fiddle(View):
var index = 1;
show(index);
function move(n) {
show(index = index + n);
}
function show(n) {
var i;
var x = document.getElementsByClassName("slides");
if (n > x.length) {index = 1}
if (n < 1) {index = x.length}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[index-1].style.display = "block";
}
.w3-content{max-width:980px;margin:auto}
.w3-center{text-align:center!important}
.w3-btn-floating:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
.w3-button{color:#000;background-color:#f1f1f1;padding:8px 16px}.w3-button:hover{color:#000!important;background-color:#ccc!important}
.w3-btn,.w3-btn-floating{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.w3-btn-floating{display:inline-block;text-align:center;color:#fff;background-color:#000;position:relative;overflow:hidden;z-index:1;padding:0;border-radius:50%;cursor:pointer;font-size:24px}
.w3-btn-floating{width:40px;height:40px;line-height:40px}
.w3-btn-floating:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
.w3-btn-floating{-webkit-transition:background-color .25s,color .15s,box-shadow .25s,opacity 0.25s,filter 0.25s,border 0.15s;transition:background-color .25s,color .15s,box-shadow .15s,opacity .25s,filter .25s,border .15s}
<!DOCTYPE html>
<html>
<body>
<div class="w3-content" style="max-width:400px;position:relative">
<img class="slides" src="https://i.stack.imgur.com/Qypol.jpg" style="width:100%">
<img class="slides" src="https://i.stack.imgur.com/yU7fs.jpg" style="width:100%">
<img class="slides" src="https://i.stack.imgur.com/xxLmR.jpg" style="width:100%">
<img class="slides" src="https://i.stack.imgur.com/YiIiQ.jpg" style="width:100%">
<a class="w3-btn-floating" style="position:absolute;top:45%;left:0" onclick="move(-1)">❮</a>
<a class="w3-btn-floating" style="position:absolute;top:45%;right:0" onclick="move(1)">❯</a>
</div>
</body>
</html>

Autoplay on slider doesn't play after showing next div

I want to have an autoplay in my slider but I encounter a problem. After showing next div it doesn't continue to show another div.
How can I fix this?
Here is my code:
<div class="container">
<div class="mySlides active" style="background-image: url('images/1.jpg')">
</div>
<div class="mySlides" style="background-image: url('images/2.jpg');">
</div>
<div class="mySlides" style="background-image: url('images/3.jpg');">
</div>
</div>
<script>
var currentSlide = 1;
var isPlaying = true;
function nextSlide() {
showSlide(currentSlide += 1)
}
function showSlide() {
var slides = document.getElementsByClassName("mySlides");
if (currentSlide > slides.length) {
currentSlide = 1;
}
for (i = 1; i < slides.length; i++) {
slides[i].style.opacity = "0";
}
slides[currentSlide-1].style.opacity = "1";
slides[currentSlide-1].style.transition = "all .5s";
// slides[slideIndex-1].setAttribute("style", "opacity: 1; transition: ease .5s;");
}
if (isPlaying) {
setTimeout(nextSlide, 1000);
}
</script>
I have modified your provided code a bit. Here is working example:
HTML
<div class="container">
<div class="mySlides" style="background-image: url('images/1.jpg')">1
</div>
<div class="mySlides" style="background-image: url('images/2.jpg');">2
</div>
<div class="mySlides" style="background-image: url('images/3.jpg');">3
</div>
Javascript:
var currentSlide = 1;
var isPlaying = true;
function nextSlide() {
showSlide(currentSlide += 1)
}
function showSlide() {
var slides = document.getElementsByClassName("mySlides");
if (currentSlide >= slides.length) {
currentSlide = 0;
}
for (i = 0; i < slides.length; i++) {
slides[i].style.opacity = "0";
slides[i].style.display = "none";
}
slides[currentSlide].style.display = "block";
slides[currentSlide].style.opacity = "1";
slides[currentSlide].style.transition = "all .5s";
// slides[slideIndex-1].setAttribute("style", "opacity: 1; transition: ease .5s;");
}
if (isPlaying) {
setInterval(nextSlide, 500);
}

JavaScript - periodically change "active" image

I have 4 pictures and want them to periodically change class (I have .active class, which is similar to hover).
.active,
.pic:hover{
position: absolute;
border: 1px solid black;
transform: scale(1.1);
transition: transform .2s;
}
Basically I need the first picture to have the class active and after some time change it so the next picture has the class and the first one lose it.
Is something like that even possible?
Picture in HTML:
<div class="products">
<a href="http://example.com/produkt1">
<img class="pic" src="image.jpg" alt="image" width="75" height="75">
</a>
</div>
and JS:
productIndex = 0;
slideshow();
function slideshow(){
var i;
var pic = document.getElementsByClassName("pic");
for(i = 0; i < pic.length; i++){
pic[i].className = pic[i].className.replace("active", "");
}
productIndex++;
if(productIndex > pic.length){
productIndex = 1;
}
pic[productIndex-1].className += active;
setInterval(slideshow, 2000);
}
You can use setInterval to run a function periodically that will change the active class. Something like this (psuedo-code):
var imageArray = [];
var activeIndex = 0;
setInterval(function(){
imageArray[activeIndex].removeClass('active');
activeIndex++;
activeIndex %= 4;
imageArray[activeIndex].addClass('active');
}, 5000);
The number value passed in as a parameter is how many milliseconds to wait before running the function again. In this example, 5 seconds will pass between the classes are changed.
setInterval Reference
This is ugly but it could work for super basic ... You just need to update the div blocks with images if necessary. Uses jquery...
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<style>
div {
width:50px;
height:50px;
background-color: black;
margin-bottom:10px;
}
.active {
background-color: red;
}
</style>
</head>
<body>
<div id="pic1"></div>
<div id="pic2"></div>
<div id="pic3"></div>
<div id="pic4"></div>
<script>
let lastActive = 0;
setInterval(()=>{
$('div').removeClass('active');
if(lastActive === 0){
$('#pic1').addClass('active');
lastActive = 1;
}
else if(lastActive === 1){
$('#pic2').addClass('active');
lastActive = 2;
}
else if(lastActive === 2){
$('#pic3').addClass('active');
lastActive = 3;
}
else if(lastActive === 3){
$('#pic3').addClass('active');
lastActive = 4;
}
else if(lastActive === 4){
$('#pic1').addClass('active');
lastActive = 1;
}
}, 500)
</script>
</body>
</html>
Matt L. has a good point here. Your code has the setInterval inside your slideshow function, otherwise it's fine.
productIndex = 0;
slideshow();
function slideshow(){
var i;
var pic = document.getElementsByClassName("pic");
for(i = 0; i < pic.length; i++){
pic[i].className = pic[i].className.replace("active", "");
}
productIndex++;
if(productIndex > pic.length){
productIndex = 1;
}
pic[productIndex-1].className += active;
}
setInterval(slideshow, 2000);
could probably work. Matt's answer is a lot better, and I came up with something similar, which is testable on jsfiddle.
You could do it like this for example:
$(document).ready(function() {
setInterval(function() {
var active = $('.active');
active.nextOrFirst().addClass('active');
active.removeClass('active');
}, 3000);
});
$.fn.nextOrFirst = function(selector)
{
var next = this.next(selector);
return (next.length) ? next : this.prevAll(selector).last();
};
.active,
.pic:hover{
border: 1px solid black;
}
.pic {
width: 150px;
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="image-container">
<img class="pic active" src="https://via.placeholder.com/350x150">
<img class="pic" src="https://via.placeholder.com/350x150">
<img class="pic" src="https://via.placeholder.com/350x150">
<img class="pic" src="https://via.placeholder.com/350x150">
</div>
Edit:
This, instead of most other solutions, will work with any amount of items. To use it only on pictures just specify via selector in the function.
Checkout this working example. I've made use of a combination of setInterval and setTimeout.
$(window).ready(()=>{
// get all the images inside the image-container div
let $images = $('.image-container').find('.image');
let currImage = 0;
// execute this code every 2 seconds
window.setInterval(()=>{
// add the active class to the current image
$($images[currImage]).addClass('active');
setTimeout(()=>{
// execute the code here after 1.5 seconds
// remove the active class from the previous image
$($images[currImage-1]).removeClass('active');
}, 1500);
// make sure we don't go over the number of elements in the collection
currImage = currImage >= $images.length ? 0 : currImage + 1;
}, 2000);
});
.image.active {
border: thin solid blue;
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<div class="image-container" class="">
<img src="https://via.placeholder.com/200x200" class="image active">
<img src="https://via.placeholder.com/200x200" class="image">
<img src="https://via.placeholder.com/200x200" class="image">
<img src="https://via.placeholder.com/200x200" class="image">
</div>
Do make sure that the code in setTimeout will execute before the next interval. Meaning, the time set for setTimeout is always less than setInterval's :)
Yes it is possible:
function carousel() {
var images = document.querySelectorAll(".container img");
for(var i = 0; i < images.length; i++) {
if(images[i].classList.contains("active")) {
images[i].classList.remove("active");
if(i == images.length - 1) {
images[0].classList.add("active");
} else {
images[i + 1].classList.add("active");
}
break;
}
}
}
setInterval(carousel,1000);
img {
width: 100px;
margin-left: 10px;
transition: .2s;
}
.active {
transform: scale(1.1);
}
<div class="container">
<img src="https://i.stack.imgur.com/cb20A.png" class="active"/>
<img src="https://i.stack.imgur.com/cb20A.png"/>
<img src="https://i.stack.imgur.com/cb20A.png"/>
<img src="https://i.stack.imgur.com/cb20A.png"/>
</div>
You can then replace the .active class by whatever you want.

Stop image slider forward button on last image in jquery

I put an image slider on my website to show the image one by one on click event, but on the last image I want to stop image slider. I don't want to repeat image again and I don't want forward slide but we can go back.
<script>
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";
}
</script>
HTML:
<div class="w3-content w3-display-container">
<div style="margin-left:150px">
<img class="mySlides" src="../../../../../imageslider2/slide1.jpg" style="width:auto; height:auto"/>
<img class="mySlides" src="../../../../../imageslider2/slide2.jpg" style="width:auto; height:auto"/>
<pre> <a class="w3-btn-floating w3-display-left" onclick="plusDivs(-1)">❮</a>
<a class="w3-btn-floating w3-display-right" onclick="plusDivs(1)">❯</a>
</div>
First you need to get a count of the total number of slides and set it as a variable, which you can do with .length and then you need to add a conditional statement to your plusDivs function to do something(alert in the below example) if the slideIndex value is equal to that of the total number of slides:
var slideIndex = 1,
totalSlides = document.querySelectorAll('.mySlides').length;
showDivs(slideIndex);
function plusDivs(n) {
if (slideIndex === totalSlides) {
alert('End of slideshow');
} else {
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";
}
<div class="w3-content w3-display-container">
<div style="margin-left:150px">
<img class="mySlides" src="http://placehold.it/250x250" style="width:auto; height:auto"/>
<img class="mySlides" src="http://placehold.it/250x250/000/fff" style="width:auto; height:auto"/>
<pre>❮
❯ </pre>
</div>
</div>
Alternatively, you could use the same approach to simply hide the previous or next buttons if they are at the start or the end of the slideshow.

Javascript slideshow not working - Appearance is incorrect

I'm having some issues with a slideshow banner for the top of my webpage. I tried following the W3 tutorial on it but not having much luck. So, below is my code:
HTML:
<div class="slide-content" style="max-width:1000px"> <img class="slidepic" src="testheadphoto.jpg" style="width:100%" border="0" /> <img class="slidepic" src="testphototwo.jpg" style="width:100%" border="0" />
<div class="slide-center slide-section slide-large slide-text-white slide-display-bottommiddle" style="width:100%">
<div class="slide-left slide-padding-left slide-hover-text-khaki" onclick="plusDivs(-1)">❮</div>
<div class="slide-right slide-padding-right slide-hover-text-khaki" onclick="plusDivs(-1)">❯</div>
<span class="slide-stamp demo slide-border slide-transparent slide-hover-white" _="_" span="span"> <span class="slide-stamp demo slide-border slide-transparent slide-hover-white" onclick="currentDiv(1)"></span> <span class="slide-stamp demo slide-border slide-transparent slide-hover-white" onclick="currentDiv(2)"></span> </span> </div>
CSS:
.slide {
display:none;
}
.slide-left, .slide-right, .slide-stamp {
cursor: pointer;
}
.slide-stamp {
height: 13px;
width: 13px;
padding: 0;
}
Javascript:
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("slidepic");
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(" slide-white", "");
}
x[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " slide-white";
}
At the moment, the two images are both appearing on the page at the same time and the arrows for right and left are below them. When you click an arrow, one of the pictures disappears and the slide effectively does work. It doesn't look how it's supposed to though. I've attached two images (One of how the slide should look and the other, how mine looks. As always, any help is much appreciated!
Thanks
Your images are line breaking because the container is not setup right.
In your CSS, try:
.slide-content {
white-space: nowrap;
}
I also recommend putting your controls into this same container and positioning them absolutely to their respective corners, with a z-index set to ensure they'll be on top of the images that are sliding in.

Categories