I've setup a way for my family to upload and display photos but I've run into an issue. I've tried to make it into a slideshow. I've tried different methods but haven't found any solution. This is my html:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/index2.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="js/display.js"></script>
<script src="js/slideshow.js"></script>
<title>Test Images</title>
</head>
<body>
<div id="slideshow">
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
</div>
<br>
<div style="text-align:center">
<span class="dot" onclick="currentSlide(1)"></span>
<span class="dot" onclick="currentSlide(2)"></span>
<span class="dot" onclick="currentSlide(3)"></span>
</div>
</body>
</html>
This is my method to put the images into the html:
var folder = "uploads/";
var img = "<img src='";
var imgStyle = "style='width:100%'";
var imgClass = "class='mySlides fade'";
$.ajax({
url : folder,
success : function (data) {
$(data).find("a").attr("href", function (i, val){
if( val.match(/\.(jpe?g|png|gif)$/) ) {
$( "#slideshow" ).append( img + folder + val + "'" + imgStyle + ">");
}
});
}
});
And this is my current slideshow method:
var slideIndex = 1;
showSlides(slideIndex);
// Next/previous controls
function plusSlides(n) {
showSlides(slideIndex += n);
}
// Thumbnail image controls
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";
}
I'm getting this error:
Uncaught ReferenceError: plusSlides is not defined
at HTMLAnchorElement.onclick
I don't have any idea on how to fix this issue.
I came across this problem as well recently! It was answered below in another post here.
The general gist is to use a window load event instead, as HTML can't find the function because it is hidden inside another function. Just change
function plusSlides(n) {
showSlides(slideIndex += n);
}
to
window.plusSlides = function (n) {
showSlides(slideIndex += n);
};`
Related
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>
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);
});
});
How could I make the slides clickable to navigate forward in the slider? That is how could I make the plusSlides function work for each individual slideshow on one page?
This is the main structure of any slideshow which I could repeat in the same page.
HTLM
<div class="slideshow-container" data-cycle="2000">
<div class="slider fade"><img onclick="plusSlides()" src="assets/img/1.jpg"></div>
<div class="slider fade"><img onclick="plusSlides()" src="assets/img/2.jpg"></div>
<div class="slider fade"><img onclick="plusSlides()" src="assets/img/3.jpg"></div>
<div class="slider fade"><img onclick="plusSlides()" src="assets/img/4.jpg"></div>
<div>
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</div>
And this code which works for any slider with the same structure and contained in a div with the class slideshow-container. The slideshows are automatic and have dots.
JS
var slideshowContainers = document.getElementsByClassName("slideshow-container");
for(let s = 0; s < slideshowContainers.length; s++) {
var cont = slideshowContainers[s];
var cycle = slideshowContainers[s].dataset.cycle;
var slides = slideshowContainers[s].querySelectorAll('.slider');
var dots = slideshowContainers[s].querySelectorAll('.dot');
var slideIndex = 0;
showSlides(cont, slides, slideIndex, cycle, dots);
};
var timer = null;
function showSlides(cont, slides, slideIndex, cycle, dots) {
var cont;
slideIndex++;
if (slideIndex > slides.length) {
slideIndex = 1
}
if (slideIndex < 1) {
slideIndex = slides.length
}
for (cont = 0; cont < slides.length; cont++) {
slides[cont].style.display = "none";
}
for (cont = 0; cont < dots.length; cont++) {
dots[cont].className = dots[cont].className.replace(" active", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " active";
setTimeout(function() {
showSlides(cont, slides, slideIndex, cycle, dots)
}, cycle);
};
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);
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>