--- /dev/null
+# Simple JavaScript Slideshow
+
+This is a very basic slideshow made in JavaScript - no jQuery or other libraries.
+
+See slideshow.html for an example. To use, insert the HTML structure and link slideshow.css and slideshow.js.
+
+## Features
+
+- Auto advance (default 3 seconds, but you can change `INTERVAL` in slideshow.js or in the HTML)
+- Pause on hover and manual pause
+- Scroll through slides with buttons or dot indicator at bottom
+- Captions
+- Semantic HTML (each slide is a `<figure>` consisting of an `<img>` and `<figcaption>`)
+- Sensible behaviour when JS is disabled (static first slide)
+- Works with different sizes/aspect ratios and different length captions (set width or max-width of outer div, then slide heights are driven by the the height of the first slide at full width)
+- Works well at all screen sizes and can be styled with basic CSS
+
+## Todo
+
+- Initialise slideshows with JS object
+- Support for multiple slideshows per page
figure.slide {
/* Position slides absolutely to allow overlapping */
+ text-align: center;
position: absolute;
top: 0;
left: 0;
+ width: 100%;
margin: 0;
/* Slides start at 0 opacity */
opacity: 0;
-moz-transition: opacity 1s ease;
}
-figure.slide *,
-div.slideshow div#controls {
- width: 100%;
-}
-
-figure.slide figcaption {
- height: var(--sl-cap);
- text-align: center;
+figure.slide img {
+ max-width: 100%;
}
top: calc(50% - calc(var(--sl-cap) + var(--sl-dots) + 50px) / 2);
width: auto;
padding: 16px;
- border-radius: 0 3px 3px 0;
}
#state {
border-radius: 3px;
}
+#prev {
+ left: 0;
+ border-radius: 0 3px 3px 0;
+}
+
#next {
/* Position next button on right */
right: 0;
div.slideshow div#controls {
text-align: center;
+ width: 100%;
}
div.slideshow div#controls span {
<body>
- <div class="slideshow" onmouseenter="mouseEnter()" onmouseleave="mouseLeave()">
+ <div class="slideshow">
+ <div class="slides">
- <figure class="slide">
- <img src="test-img/1.jpg">
- <figcaption><span>This is a long caption yeah yeah yeah</figcaption>
- </figure>
+ <figure class="slide">
+ <img src="test-img/1.jpg">
+ <figcaption>This is a caption</figcaption>
+ </figure>
- <figure class="slide">
- <img src="test-img/2.jpg">
- <figcaption><span>Shorter caption</figcaption>
- </figure>
+ <figure class="slide">
+ <img src="test-img/2.jpg">
+ <figcaption><span>This is a long caption which will probably span over multiple lines (depending on the width of the slideshow). You will see that that the height of the image adjusts to accommodate the taller caption.</figcaption>
+ </figure>
- <figure class="slide">
- <img src="test-img/3.jpg">
- <figcaption><span>Caption 3</figcaption>
- </figure>
+ <figure class="slide">
+ <img src="test-img/3.jpg">
+ <figcaption>Caption 3</figcaption>
+ </figure>
- <a id="prev" onclick="prevSlide()">❮</a>
- <a id="next" onclick="nextSlide()">❯</a>
- <a id="state" onclick="changeState()">⏸︎</a>
+ </div>
+
+ <a id="prev">❮</a>
+ <a id="next">❯</a>
+ <a id="state">⏸︎</a>
<div id="controls">
- <span class="dot" onclick="setSlide(0)"></span>
- <span class="dot" onclick="setSlide(1)"></span>
- <span class="dot" onclick="setSlide(2)"></span>
+ <span class="dot"></span>
+ <span class="dot"></span>
+ <span class="dot"></span>
</div>
</div>
let currentSlide = -1;
// Elements
+
+let slideshow = document.getElementsByClassName("slideshow")[0];
+let container = document.getElementsByClassName("slides")[0];
let slides = document.getElementsByClassName("slide");
let dots = document.getElementsByClassName("dot");
let stateBtn = document.getElementById("state");
var timeout;
var paused = false;
+// Set up event listeners
+window.addEventListener("resize", setHeights, true);
+slideshow.addEventListener("mouseenter", mouseEnter, true);
+slideshow.addEventListener("mouseleave", mouseLeave, true);
+document.getElementById("prev").addEventListener("click", prevSlide);
+document.getElementById("next").addEventListener("click", nextSlide);
+document.getElementById("state").addEventListener("click", changeState);
+if (dots.length - 1 != maxIndex) {
+ console.log("Number of control dots does not match number of slides");
+}
+for (i = 0; i <= dots.length - 1; i++) {
+ dots[i].addEventListener("click", goToSlide);
+ dots[i].slide = i;
+}
+
+
// Start the slideshow
playSlideshow();
// Recursive function that advances the slide and then calls itself with a
// delay
function playSlideshow() {
+ setHeights();
nextSlide();
timeout = setTimeout(playSlideshow, INTERVAL);
}
// Change the slide to a given index
function setSlide(slide) {
-
if (slide < 0 || slide > maxIndex) {
- console.log("Attempted to change to slide outside range");
+ console.log("Attempted to change to slide outside range (" + slide.toString() + ")");
return;
}
currentSlide = slide;
}
+function setHeights() {
+ var firstSlideHeight = slides[0].offsetHeight;
+ // Set heights (based on height of first slide with 100% width)
+ for (i = 1; i <= maxIndex; i++) {
+ var captionHeight = slides[i].getElementsByTagName("figcaption")[0].offsetHeight;
+ // Set figure height
+ slides[i].style.height = slides[0].offsetHeight.toString() + "px";
+ // Set image height
+ slides[i].getElementsByTagName("img")[0].style.height = (firstSlideHeight - captionHeight).toString() + "px";
+ }
+}
+
function nextSlide() {
// Go to the next slide
if (currentSlide == maxIndex) {
}
}
+function goToSlide(evt) {
+ // Go to a slide specified by the event (called when the dots are clicked)
+ setSlide(evt.currentTarget.slide);
+}
+
function mouseEnter() {
// Pause the slideshow
clearTimeout(timeout);