From a0b380c3049345ba70e7ae31917a210783ae814f Mon Sep 17 00:00:00 2001 From: Andrew Lorimer Date: Thu, 23 Jun 2022 20:25:33 +1000 Subject: [PATCH] initialise listeners in JS, set heights at runtime, add readme --- README.md | 21 +++++++++++++++++++++ slideshow.css | 19 ++++++++++--------- slideshow.html | 41 ++++++++++++++++++++++------------------- slideshow.js | 40 ++++++++++++++++++++++++++++++++++++++-- test-img/1.jpg | Bin 33260 -> 3217481 bytes test-img/2.jpg | Bin 51851 -> 3547180 bytes test-img/3.jpg | Bin 60405 -> 811614 bytes 7 files changed, 91 insertions(+), 30 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..383134a --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# 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 `
` consisting of an `` and `
`) +- 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 diff --git a/slideshow.css b/slideshow.css index 552d5fb..3cd4ce0 100644 --- a/slideshow.css +++ b/slideshow.css @@ -23,9 +23,11 @@ figure.slide:first-child { 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; @@ -46,14 +48,8 @@ figure.slide.active { -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%; } @@ -76,7 +72,6 @@ figure.slide figcaption { top: calc(50% - calc(var(--sl-cap) + var(--sl-dots) + 50px) / 2); width: auto; padding: 16px; - border-radius: 0 3px 3px 0; } #state { @@ -90,6 +85,11 @@ figure.slide figcaption { border-radius: 3px; } +#prev { + left: 0; + border-radius: 0 3px 3px 0; +} + #next { /* Position next button on right */ right: 0; @@ -116,6 +116,7 @@ div.slideshow:hover #state { div.slideshow div#controls { text-align: center; + width: 100%; } div.slideshow div#controls span { diff --git a/slideshow.html b/slideshow.html index a581b1f..8896456 100644 --- a/slideshow.html +++ b/slideshow.html @@ -6,31 +6,34 @@ -
+
+
-
- -
This is a long caption yeah yeah yeah
-
+
+ +
This is a caption
+
-
- -
Shorter caption
-
+
+ +
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.
+
-
- -
Caption 3
-
+
+ +
Caption 3
+
- - - ⏸︎ +
+ + + + ⏸︎
- - - + + +
diff --git a/slideshow.js b/slideshow.js index f73a888..80614c9 100644 --- a/slideshow.js +++ b/slideshow.js @@ -7,6 +7,9 @@ const STATE_PLAY = "⏵︎"; 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"); @@ -16,21 +19,37 @@ let maxIndex = slides.length - 1; 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; } @@ -47,6 +66,18 @@ function setSlide(slide) { 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) { @@ -67,6 +98,11 @@ function prevSlide() { } } +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); diff --git a/test-img/1.jpg b/test-img/1.jpg index bab22804e477b3523473355ad7ea21c66fdce5d4..ffff16dc7f575b310dcd4c19aea3948ff5602db8 100644 GIT binary patch literal 3217481 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