From a7c1bde3848595210a7223902c54525dddc28a63 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 14:18:56 -0500 Subject: [PATCH 01/28] Add instructions for running example locally --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 02cb833..bbbcc5d 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,5 @@ w3school carousel See how to build a [JavaScript carousel here](https://www.w3schools.com/howto/howto_js_slideshow.asp) + +Run locally with `python -m SimpleHTTPServer 4000`. From c9cd10b214adb988c73af0cdd839ee140acc8368 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 14:19:09 -0500 Subject: [PATCH 02/28] Update HTML content --- index.html | 78 ++---------------------------------------------------- 1 file changed, 2 insertions(+), 76 deletions(-) diff --git a/index.html b/index.html index 3e73b74..783799a 100644 --- a/index.html +++ b/index.html @@ -3,13 +3,11 @@ - W3Schools Carousels + W3Schools JSON Carousels
-

w3schools carousel

-

See full tutorial.

Slider #1

From 46901595c3c80aea978f5a553b9f3f13c00a8817 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 14:19:15 -0500 Subject: [PATCH 03/28] Update script --- index.js | 258 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 183 insertions(+), 75 deletions(-) diff --git a/index.js b/index.js index 2dd71a8..ff5cdb5 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,7 @@ -/** - * Carousel class - * @author Tyler Van Schaick - * @file Carousel class - */ +console.clear(); + class Carousel { constructor(selector) { - // @TODO Feature detection // Get DOM elements @@ -14,17 +10,22 @@ class Carousel { console.error("Error, no carousel element found! Bail!"); return false; } + // Bind "this" to methods + this.init = this.init.bind(this); + this.init(); + } + + init() { + console.count("Original init"); + // Set up variables + this.slideIndex = null; + this.sliderInterval = null; this.playButton = this.carousel.querySelector(".button--play"); this.nextButton = this.carousel.querySelector(".button--next"); this.prevButton = this.carousel.querySelector(".button--prev"); this.pauseButton = this.carousel.querySelector(".button--pause"); - // Set variables - this.slideIndex = null; - this.sliderInterval = null; - // Get data- attribute values - // Last image goes back to first image this.wrap = this.carousel.hasAttribute("data-wrap") ? // Convert the boolean string data- attribute to a real boolean value using this technique https://stackoverflow.com/a/264037 this.carousel.getAttribute("data-wrap") === "true" @@ -34,35 +35,31 @@ class Carousel { : defaults.interval; this.slideIndex = 1; - // Bind functions + // Bind "this" with methods this.play = this.play.bind(this); this.nextSlide = this.nextSlide.bind(this); this.prevSlide = this.prevSlide.bind(this); this.pause = this.pause.bind(this); + + // Even private methods this.showDivs = this.showDivs.bind(this); - this.addEventListenersV2(); + // Add event listeners without bind() in the call. + // this.addEventListeners = this.addEventListeners.bind(this); + this.addEventListeners(); // Init this.showDivs(this.slideIndex); - } // end constructor + } - /** - * Add carousel related event listeners. - */ - addEventListenersV2() { - // Add event listeners + // Binding in the constructor instead of here. + addEventListeners() { this.playButton.addEventListener("click", this.play); this.nextButton.addEventListener("click", this.nextSlide); this.prevButton.addEventListener("click", this.prevSlide); this.pauseButton.addEventListener("click", this.pause); } - /** - * Show a specified div element/carousel slide - * @param {number} n carousel slide index number - * @return {[type]} [description] - */ showDivs(n) { var i; var x = this.carousel.querySelectorAll(".carousel-item"); @@ -89,70 +86,181 @@ class Carousel { x[i].style.display = "none"; } x[this.slideIndex - 1].style.display = "block"; - }; - - /** - * Pause the carousel - * @return {[type]} [description] - */ + } pause() { clearInterval(this.sliderInterval); - }; - - /** - * Go to previous carousel slide - * @return {[type]} [description] - */ + } prevSlide() { this.showDivs((this.slideIndex += -1)); - }; - - /** - * Go to next carousel slide - * @return {[type]} [description] - */ + } nextSlide() { this.showDivs((this.slideIndex += 1)); - }; - - /** - * Play the carousel slides - * @return {[type]} [description] - */ + } play() { this.sliderInterval = setInterval(() => { this.nextSlide(); }, this.interval); - }; -}; + } +} -// Initiate +// Initiate fist carousel const carousel1 = new Carousel("#carousel--1"); -// Extend SuperCarousel from the Carousel class -class SuperCarousel extends Carousel { - constructor(selector) { +// Sub classing with "extends" on the Carousel class. +// This Super JSON Carousel will use JSON to generate a similar +// carousel slider like the Carousel class does. +class SuperJSONCarousel extends Carousel { + constructor(selector, slidesObject) { + // Pass selector to the parent class super(selector); - this.slideToButtons = this.carousel.querySelectorAll("[data-slide-to]"); - if (!this.slideToButtons.length > 0) { - console.error('Error, no "slide-to" buttons found.'); - return false; + + // Get slides object/array + this.slides = slidesObject; + + // Bind methods with "this" + this.renderApp = this.renderApp.bind(this); + this.renderSlide = this.renderSlide.bind(this); + this.renderButtons = this.renderButtons.bind(this); + + // Render the slides + this.carousel.innerHTML = this.renderApp(this.slides); + + // Call super/parent init method + super.init(); + } + + // Add an init() method that basically overrides the parent classes + // init() method. This is because the parent init() method assumes + // DOM elements will be available, while in this extended class + // we are building the DOM elements in the script. + // + // We need to render those script created elements before + // running the parent init() method. + init() { + console.count("SuperJSONCarousel init"); + } + + // Returns an UL with rendered headings + renderApp(headings) { + return [ + "", + this.renderButtons() + ].join(""); + } + + // Render a slide's HTML + renderSlide(slide, index) { + if (!slide) { + console.log("Error. Must provide slide parameter"); + return; } - this.slideToButtons.forEach((button) => { - button.addEventListener("click", (event) => { - this.selectSlide(Number(event.target.dataset.slideTo)); - }); + return [ + "" + ].join(""); + } + + // Helper method to create HTML button elements from scratch + renderButton(content, css, title, data) { + if (!content) { + console.log("Must provide content to the renderButton function."); + return; + } + + return [ + "" + ].join(""); + } + + // @todo handle [...class] array of classes + renderClassAttribute(name) { + if (!name) { + console.log("Error. Must provide a class name."); + return; + } + // return 'class="' + name + '" '; + return `class="${name}" `; + } + + renderTitleAttribute(title) { + if (!title) { + console.log("Error. Must provide a title for the title attribute."); + return; + } + // return 'title="' + title + '" '; + return `title="${title}" `; + } + + renderDataAttribute(name = "slide", value) { + if (!value) { + console.log( + "Error. Value must be provided for the renderDataAttribute function." + ); + } + return `data-${name}="${value}"`; + } + + // Renders slideshow buttons + renderButtons() { + return [ + // "", + // "", + // "", + // "" + this.renderButton("❮", "button button--prev", "Prev", "prev"), + this.renderButton("Play", "button button--play"), + this.renderButton("Pause", "button button--pause"), + this.renderButton("❯", "button button--next", "Next", "next") + ].join(""); + } +} + +// async function to get JSON data, run this before +// initiating a new carousel. +function getJson() { + return fetch("https://assets.codepen.io/307033/slides.json") + .then(function (response) { + // The API call was successful! + return response.json(); + }) + .then(function (data) { + // This is the JSON from our response + console.log(data); + return data.slides; + }) + .catch(function (err) { + // There was an error + console.warn("Something went wrong.", err); }); - }; // end constructor - - /** - * Select a certain carousel slide - * @param {[type]} n [description] - * @return {[type]} [description] - */ - selectSlide(n) { - this.showDivs((this.slideIndex = n)); - }; -}; - -const carousel2 = new SuperCarousel("#carousel--2"); +} +getJson().then((data) => { + console.log("data", data); + const carousel2 = new SuperJSONCarousel("#carousel--2", data); +}); + +// Static methods, logger utility, utility functions, mixins From b2abea3a8cfc3c821e5d3f039e734dbe34c7b371 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 14:35:58 -0500 Subject: [PATCH 04/28] Update script comments --- index.js | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index ff5cdb5..f8e4640 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,3 @@ -console.clear(); - class Carousel { constructor(selector) { // @TODO Feature detection @@ -15,8 +13,16 @@ class Carousel { this.init(); } + /** + * Initializes the carousel by: + * - setting up variables + * - Getting data- attribute values + * - Binding "this" to methods + * - Invoke addEventListeners() method + * - Show initial slide + * @return {[type]} [description] + */ init() { - console.count("Original init"); // Set up variables this.slideIndex = null; this.sliderInterval = null; @@ -44,8 +50,7 @@ class Carousel { // Even private methods this.showDivs = this.showDivs.bind(this); - // Add event listeners without bind() in the call. - // this.addEventListeners = this.addEventListeners.bind(this); + // Add event listeners this.addEventListeners(); // Init @@ -176,7 +181,14 @@ class SuperJSONCarousel extends Carousel { ].join(""); } - // Helper method to create HTML button elements from scratch + /** + * Helper method to create HTML button elements from scratch. + * @param {String} content HTML/string content + * @param {String} css String for CSS classes + * @param {String} title String title for title attribute + * @param {String} data String value for data- attribute + * @return {[type]} [description] + */ renderButton(content, css, title, data) { if (!content) { console.log("Must provide content to the renderButton function."); @@ -185,9 +197,6 @@ class SuperJSONCarousel extends Carousel { return [ "", From 9e4973fbc0d38793f413582ae2c997e8e0033a7d Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 14:36:10 -0500 Subject: [PATCH 05/28] Move carousel initialization to index.html --- index.html | 27 +++++++++++++++++++++++++++ index.js | 26 -------------------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/index.html b/index.html index 783799a..f080321 100644 --- a/index.html +++ b/index.html @@ -83,5 +83,32 @@

Slider #2

+ diff --git a/index.js b/index.js index f8e4640..d4bb9c3 100644 --- a/index.js +++ b/index.js @@ -108,9 +108,6 @@ class Carousel { } } -// Initiate fist carousel -const carousel1 = new Carousel("#carousel--1"); - // Sub classing with "extends" on the Carousel class. // This Super JSON Carousel will use JSON to generate a similar // carousel slider like the Carousel class does. @@ -267,27 +264,4 @@ class SuperJSONCarousel extends Carousel { } } -// async function to get JSON data, run this before -// initiating a new carousel. -function getJson() { - return fetch("https://assets.codepen.io/307033/slides.json") - .then(function (response) { - // The API call was successful! - return response.json(); - }) - .then(function (data) { - // This is the JSON from our response - console.log(data); - return data.slides; - }) - .catch(function (err) { - // There was an error - console.warn("Something went wrong.", err); - }); -} -getJson().then((data) => { - console.log("data", data); - const carousel2 = new SuperJSONCarousel("#carousel--2", data); -}); - // Static methods, logger utility, utility functions, mixins From ad3d35e0fa6c1087d393e0f1746f4fda4edd6446 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 15:35:18 -0500 Subject: [PATCH 06/28] Add jsdocs to methods --- index.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index d4bb9c3..eb25eca 100644 --- a/index.js +++ b/index.js @@ -138,15 +138,23 @@ class SuperJSONCarousel extends Carousel { // // We need to render those script created elements before // running the parent init() method. + /** + * Init to override the original classe's init method + * @return {[type]} [description] + */ init() { console.count("SuperJSONCarousel init"); } - // Returns an UL with rendered headings - renderApp(headings) { + /** + * Returns an UL with rendered slides + * @param {Array} slides Array of slide data. + * @return {[type]} [description] + */ + renderApp(slides) { return [ " From 69da7ee6422010f4078abb5affc78c8dedcf4562 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 17:38:03 -0500 Subject: [PATCH 09/28] Add auto controls feature check --- index.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/index.js b/index.js index 672238e..b5624a2 100644 --- a/index.js +++ b/index.js @@ -119,6 +119,31 @@ class SuperJSONCarousel extends Carousel { // Get slides object/array this.slides = slidesObject; + // Add auto controls (play/pause) support + this.autoControls = this.carousel.hasAttribute("data-auto-controls") + ? this.carousel.getAttribute("data-auto-controls") === "true" + : false; + console.log("this.autoControls", this.autoControls); + if (this.autoControls) { + this.renderAutoControls = this.renderAutoControls.bind(this); + } + // // Add fade support + // this.fade = this.carousel.hasAttribute("data-fade") + // ? this.carousel.getAttribute("data-fade") === "true" + // : false; + // console.log("this.fade", this.fade); + // // if (this.fade) { + // // this.fade = this.fade.bind(this); + // // } + // // Add caption support + // this.captions = this.carousel.hasAttribute("data-captions") + // ? this.carousel.getAttribute("data-captions") === "true" + // : false; + // console.log("this.captions", this.captions); + // if (this.captions) { + // this.renderCaptions = this.renderCaptions.bind(this); + // } + // Bind methods with "this" this.renderApp = this.renderApp.bind(this); this.renderSlide = this.renderSlide.bind(this); From 50facdfcd0d1ba68abaa44493e1f985082ac363b Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 17:38:13 -0500 Subject: [PATCH 10/28] Add renderAutoControls method --- index.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/index.js b/index.js index b5624a2..06fa1e9 100644 --- a/index.js +++ b/index.js @@ -285,6 +285,20 @@ class SuperJSONCarousel extends Carousel { return `data-${name}="${value}"`; } + /** + * Render auto controls (play/pause) buttons + * @return {[type]} [description] + */ + renderAutoControls() { + if (!this.autoControls) { + return ""; + } + return [ + this.renderButton("Play", "button button--play", null, null), + this.renderButton("Pause", "button button--pause", null, null) + ].join(""); + } + /** * Helper method to render slideshow buttons. * @return {[type]} [description] From b9319d972869144a22216f3b5dc7867956811350 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 17:38:22 -0500 Subject: [PATCH 11/28] Remove commented out code --- index.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/index.js b/index.js index 06fa1e9..182028e 100644 --- a/index.js +++ b/index.js @@ -305,10 +305,6 @@ class SuperJSONCarousel extends Carousel { */ renderButtons() { return [ - // "", - // "", - // "", - // "" this.renderButton("❮", "button button--prev", "Prev", "prev"), this.renderButton("Play", "button button--play"), this.renderButton("Pause", "button button--pause"), From d0a0d41868505eb9208d57e1c5db62ebefaaf439 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 17:38:36 -0500 Subject: [PATCH 12/28] Replace renderButtons with renderAutoControls --- index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 182028e..14584ad 100644 --- a/index.js +++ b/index.js @@ -306,8 +306,9 @@ class SuperJSONCarousel extends Carousel { renderButtons() { return [ this.renderButton("❮", "button button--prev", "Prev", "prev"), - this.renderButton("Play", "button button--play"), - this.renderButton("Pause", "button button--pause"), + // this.renderButton("Play", "button button--play"), + // this.renderButton("Pause", "button button--pause"), + this.renderAutoControls(), this.renderButton("❯", "button button--next", "Next", "next") ].join(""); } From fff50f4c3ebbd44c3a0d0d038b6a26822d2aae0d Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 17:43:38 -0500 Subject: [PATCH 13/28] Uncomment fade related code in the JSON slider's constructor --- index.js | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 14584ad..9b3dca1 100644 --- a/index.js +++ b/index.js @@ -127,14 +127,14 @@ class SuperJSONCarousel extends Carousel { if (this.autoControls) { this.renderAutoControls = this.renderAutoControls.bind(this); } - // // Add fade support - // this.fade = this.carousel.hasAttribute("data-fade") - // ? this.carousel.getAttribute("data-fade") === "true" - // : false; - // console.log("this.fade", this.fade); - // // if (this.fade) { - // // this.fade = this.fade.bind(this); - // // } + // Add fade support + this.fade = this.carousel.hasAttribute("data-fade") + ? this.carousel.getAttribute("data-fade") === "true" + : false; + console.log("this.fade", this.fade); + // if (this.fade) { + // this.fade = this.fade.bind(this); + // } // // Add caption support // this.captions = this.carousel.hasAttribute("data-captions") // ? this.carousel.getAttribute("data-captions") === "true" @@ -202,16 +202,35 @@ class SuperJSONCarousel extends Carousel { return; } return [ - "", "" ].join(""); } From 052ed0ce1eef7f49197a811c6f237c5fe6684199 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 17:43:49 -0500 Subject: [PATCH 14/28] Update styles with button and fade support --- styles.css | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/styles.css b/styles.css index d277ec2..d0b2241 100644 --- a/styles.css +++ b/styles.css @@ -1,8 +1,15 @@ +* { + box-sizing: border-box; +} + .wrap { display: flex; flex-direction: column; position: relative; } +.carousel { + position: relative; +} .carousel-item { display: none; } @@ -21,3 +28,65 @@ width: 100%; height: auto; } + +/* prev/next buttons */ +.button[data-slide] { + cursor: pointer; + position: absolute; + top: 50%; + width: auto; + margin-top: -22px; + padding: 16px; + color: white; + font-weight: bold; + font-size: 18px; + transition: 0.6s ease; + border-radius: 0 3px 3px 0; + user-select: none; +} +.button[data-slide]:hover { + background-color: rgba(0, 0, 0, 0.8); +} +.button[data-slide="prev"] { +} +.button[data-slide="next"] { + right: 0; + border-radius: 3px 0 0 3px; +} + +/* captions */ +.carousel-item__caption { + color: #f2f2f2; + font-size: 15px; + padding: 8px 12px; + position: absolute; + bottom: 8px; + width: 100%; + text-align: center; +} + +/* Fading animation */ +.fade { + -webkit-animation-name: fade; + -webkit-animation-duration: 1.5s; + animation-name: fade; + animation-duration: 1.5s; +} + +@-webkit-keyframes fade { + from { + opacity: 0.4; + } + to { + opacity: 1; + } +} + +@keyframes fade { + from { + opacity: 0.4; + } + to { + opacity: 1; + } +} From 56d2377441e075a8cc46839b411a796bd5c9ba4f Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 17:44:02 -0500 Subject: [PATCH 15/28] Remove unnecessary code --- index.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/index.js b/index.js index 9b3dca1..fe4f76c 100644 --- a/index.js +++ b/index.js @@ -132,9 +132,6 @@ class SuperJSONCarousel extends Carousel { ? this.carousel.getAttribute("data-fade") === "true" : false; console.log("this.fade", this.fade); - // if (this.fade) { - // this.fade = this.fade.bind(this); - // } // // Add caption support // this.captions = this.carousel.hasAttribute("data-captions") // ? this.carousel.getAttribute("data-captions") === "true" From fb615897a76ce7d0c0e1a6b29d884d4f80b5b76c Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 18:30:25 -0500 Subject: [PATCH 16/28] Update placeholder div element with data- attributes --- index.html | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index ef00b2c..a072f68 100644 --- a/index.html +++ b/index.html @@ -79,7 +79,15 @@

Slide #5: Drizzle

Slider #2

- +
From d7e520305fded306b381814c7bb98fa541708c14 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 18:30:37 -0500 Subject: [PATCH 17/28] Add support for captions --- index.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index fe4f76c..45a07b6 100644 --- a/index.js +++ b/index.js @@ -132,14 +132,14 @@ class SuperJSONCarousel extends Carousel { ? this.carousel.getAttribute("data-fade") === "true" : false; console.log("this.fade", this.fade); - // // Add caption support - // this.captions = this.carousel.hasAttribute("data-captions") - // ? this.carousel.getAttribute("data-captions") === "true" - // : false; - // console.log("this.captions", this.captions); - // if (this.captions) { - // this.renderCaptions = this.renderCaptions.bind(this); - // } + // Add caption support + this.captions = this.carousel.hasAttribute("data-captions") + ? this.carousel.getAttribute("data-captions") === "true" + : false; + console.log("this.captions", this.captions); + if (this.captions) { + this.renderCaptions = this.renderCaptions.bind(this); + } // Bind methods with "this" this.renderApp = this.renderApp.bind(this); From 59fbb4f6d082252a0c29dc5e4736aec68e283e54 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 18:30:54 -0500 Subject: [PATCH 18/28] Add support for pager --- index.js | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 45a07b6..194bde3 100644 --- a/index.js +++ b/index.js @@ -140,6 +140,14 @@ class SuperJSONCarousel extends Carousel { if (this.captions) { this.renderCaptions = this.renderCaptions.bind(this); } + // Add pager support + this.pager = this.carousel.hasAttribute("data-pager") + ? this.carousel.getAttribute("data-pager") === "true" + : false; + console.log("this.pager", this.pager); + if (this.pager) { + this.renderPager = this.renderPager.bind(this); + } // Bind methods with "this" this.renderApp = this.renderApp.bind(this); @@ -213,6 +221,56 @@ class SuperJSONCarousel extends Carousel { "" ].join(""); } + /** + * Render pager + * @return {[type]} [description] + */ + renderPager() { + if (!this.pager) { + console.log("Error. Pager is not set to true."); + return; + } + + // Old school way + // return [ + // "", + // "", + // "", + // "", + // "" + // ].join(""); + + // Check that we have slides + if (this.slidesLength > 0) { + // Get an array of DOM strings + const arr = []; + + // For each slide + this.slides.forEach((slide, i) => { + // Push render dot into the array + arr.push(this.renderDot(i + 1)); + }); + + return arr.join(""); + } else { + console.log("Error. No slides."); + return; + } + } + + renderDot(i) { + // Old school way + // const button = document.createElement("button"); + // button.classList.add("button", "button--inidicator"); + // button.setAttribute("data-slide-to", i); + // button.textContent = `Slide to #${i}`; + // New way + return [ + "" + ].join(""); + } /** * Render slide captions @@ -321,9 +379,8 @@ class SuperJSONCarousel extends Carousel { */ renderButtons() { return [ + this.renderPager(), this.renderButton("❮", "button button--prev", "Prev", "prev"), - // this.renderButton("Play", "button button--play"), - // this.renderButton("Pause", "button button--pause"), this.renderAutoControls(), this.renderButton("❯", "button button--next", "Next", "next") ].join(""); From 2f4c0d1143690968fad5305acc3468135ecc0d89 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 18:34:43 -0500 Subject: [PATCH 19/28] Add event listeners for "slide to" buttons Must come after super.init() --- index.js | 48 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index 194bde3..6b98c6d 100644 --- a/index.js +++ b/index.js @@ -159,6 +159,23 @@ class SuperJSONCarousel extends Carousel { // Call super/parent init method super.init(); + + // Must be called after super.init(); + // Get "slide to" buttons + this.slideToButtons = this.carousel.querySelectorAll("[data-slide-to]"); + // Bail if no "slide to" buttons found + if (!this.slideToButtons.length > 0) { + console.log('Error, no "slide-to" buttons found.'); + return false; + } + // Loop through each button + this.slideToButtons.forEach((button) => { + // Add click event handler + button.addEventListener("click", (event) => { + // Select slide + this.selectSlide(Number(event.target.dataset.slideTo)); + }); + }); } // Add an init() method that basically overrides the parent classes @@ -232,18 +249,19 @@ class SuperJSONCarousel extends Carousel { } // Old school way - // return [ - // "", - // "", - // "", - // "", - // "" - // ].join(""); + return [ + "", + "", + "", + "", + "" + ].join(""); + + // Get an array of DOM strings + const arr = []; // Check that we have slides if (this.slidesLength > 0) { - // Get an array of DOM strings - const arr = []; // For each slide this.slides.forEach((slide, i) => { @@ -251,11 +269,12 @@ class SuperJSONCarousel extends Carousel { arr.push(this.renderDot(i + 1)); }); - return arr.join(""); } else { console.log("Error. No slides."); return; } + + return arr.join(""); } renderDot(i) { @@ -385,6 +404,15 @@ class SuperJSONCarousel extends Carousel { this.renderButton("❯", "button button--next", "Next", "next") ].join(""); } + + /** + * Select slide by number + * @param {[type]} n [description] + * @return {[type]} [description] + */ + selectSlide(n) { + this.showDivs((this.slideIndex = n)); + } } // Static methods, logger utility, utility functions, mixins From 2efecd79f87c9465dbde88c19afa38d8954b66da Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Wed, 1 Dec 2021 18:34:52 -0500 Subject: [PATCH 20/28] Fix left/prev button styles --- styles.css | 1 + 1 file changed, 1 insertion(+) diff --git a/styles.css b/styles.css index d0b2241..57e971e 100644 --- a/styles.css +++ b/styles.css @@ -48,6 +48,7 @@ background-color: rgba(0, 0, 0, 0.8); } .button[data-slide="prev"] { + left: 0; } .button[data-slide="next"] { right: 0; From d4b3ad1cba00d3f4909ad2b7b7d06b914de91970 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Fri, 10 Dec 2021 17:20:43 -0500 Subject: [PATCH 21/28] Add inspiration section --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index bbbcc5d..1ab164b 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,11 @@ w3school carousel See how to build a [JavaScript carousel here](https://www.w3schools.com/howto/howto_js_slideshow.asp) Run locally with `python -m SimpleHTTPServer 4000`. + +Inspirations: + +- [BXSlider](https://bxslider.com/install/) +- [Flickity](https://flickity.metafizzy.co/) +- [Bootstrap Carousel](https://getbootstrap.com/docs/5.1/components/carousel/#via-javascript) + +https://codepen.io/tvs/pen/77d3abe973ed4c9f89caf373a5e38b6d?editors=1111 From c01cf75a71d511fdcf405e8f60c6a5135eb7b321 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Fri, 10 Dec 2021 17:25:04 -0500 Subject: [PATCH 22/28] Move slides variables --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 6b98c6d..15619c5 100644 --- a/index.js +++ b/index.js @@ -26,6 +26,7 @@ class Carousel { // Set up variables this.slideIndex = null; this.sliderInterval = null; + this.slides = this.carousel.querySelectorAll(".carousel-item"); this.playButton = this.carousel.querySelector(".button--play"); this.nextButton = this.carousel.querySelector(".button--next"); this.prevButton = this.carousel.querySelector(".button--prev"); @@ -67,7 +68,7 @@ class Carousel { showDivs(n) { var i; - var x = this.carousel.querySelectorAll(".carousel-item"); + var x = this.slides; // Go back to first slide if (n > x.length) { From 84409129fbcfd5a485702567a48ebddc348da991 Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Fri, 10 Dec 2021 17:59:02 -0500 Subject: [PATCH 23/28] Add errors.js --- errors.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 errors.js diff --git a/errors.js b/errors.js new file mode 100644 index 0000000..f2b1ecb --- /dev/null +++ b/errors.js @@ -0,0 +1,19 @@ +/** + * errors.js + * + */ + +// Custom error +class InvalidSelectorError extends Error { + constructor(message) { + super(message); + this.name = "InvalidSelectorError"; + } +} + +class InvalidCSSNameError extends Error { + constructor(message) { + super(message); + this.name = "InvalidCSSNameError"; + } +} From e3852c337865cb7775c52d4cd9f9dc27bf1f252f Mon Sep 17 00:00:00 2001 From: tyler-vs Date: Fri, 10 Dec 2021 17:59:16 -0500 Subject: [PATCH 24/28] Include errors.js to example --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index a072f68..bb87943 100644 --- a/index.html +++ b/index.html @@ -90,6 +90,7 @@

Slider #2

data-pager="true"> +