Skip to content
Open
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a7c1bde
Add instructions for running example locally
tyler-vs Dec 1, 2021
c9cd10b
Update HTML content
tyler-vs Dec 1, 2021
4690159
Update script
tyler-vs Dec 1, 2021
b2abea3
Update script comments
tyler-vs Dec 1, 2021
9e4973f
Move carousel initialization to index.html
tyler-vs Dec 1, 2021
ad3d35e
Add jsdocs to methods
tyler-vs Dec 1, 2021
2c492b6
Return if no value was passed for parameter
tyler-vs Dec 1, 2021
31c58c3
Update carousel empty element with more data- attributes for features
tyler-vs Dec 1, 2021
69da7ee
Add auto controls feature check
tyler-vs Dec 1, 2021
50facdf
Add renderAutoControls method
tyler-vs Dec 1, 2021
b9319d9
Remove commented out code
tyler-vs Dec 1, 2021
d0a0d41
Replace renderButtons with renderAutoControls
tyler-vs Dec 1, 2021
fff50f4
Uncomment fade related code in the JSON slider's constructor
tyler-vs Dec 1, 2021
052ed0c
Update styles with button and fade support
tyler-vs Dec 1, 2021
56d2377
Remove unnecessary code
tyler-vs Dec 1, 2021
fb61589
Update placeholder div element with data- attributes
tyler-vs Dec 1, 2021
d7e5203
Add support for captions
tyler-vs Dec 1, 2021
59fbb4f
Add support for pager
tyler-vs Dec 1, 2021
2f4c0d1
Add event listeners for "slide to" buttons
tyler-vs Dec 1, 2021
2efecd7
Fix left/prev button styles
tyler-vs Dec 1, 2021
d4b3ad1
Add inspiration section
tyler-vs Dec 10, 2021
c01cf75
Move slides variables
tyler-vs Dec 10, 2021
8440912
Add errors.js
tyler-vs Dec 10, 2021
e3852c3
Include errors.js to example
tyler-vs Dec 10, 2021
f5881f0
Throw custom error if no selector
tyler-vs Dec 10, 2021
5c7c356
Replace x with this.slides
tyler-vs Dec 10, 2021
007834c
Remove x variable
tyler-vs Dec 10, 2021
84837ea
Change new of showDivs method to showSlide
tyler-vs Dec 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update script
  • Loading branch information
tyler-vs committed Dec 1, 2021
commit 46901595c3c80aea978f5a553b9f3f13c00a8817
258 changes: 183 additions & 75 deletions index.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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"
Expand All @@ -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");
Expand All @@ -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 [
"<div class='carousel-items'>",
headings
.map((heading, i) => {
return this.renderSlide(heading, i);
})
.join(""),
this.renderSlide(),
"</div>",
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 [
"<div class='carousel-item carousel-item--" + index + "'>",
"<div class='carousel-item__inner'>",
"<div class='carousel-item__box-ratio'>",
"<img src='" + slide.image + "' class='carousel-item__img'>",
"</div>",
"<div class='carousel-item__caption'>",
"<h3>" + slide.heading + "</h3>",
"<p>" + slide.subheading + "</p>",
"</div>",
"</div>",
"</div>"
].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 [
"<button ",
// @todo add checks
// "<button " +
// (css !== undefined ? this.renderClassAttribute(css) : "") +
this.renderClassAttribute(css),
this.renderDataAttribute("slide", data),
this.renderTitleAttribute(title),
">",
content,
"</button>"
].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 [
// "<button class='button button--prev' data-slide='prev' title='Prev'>&#10094;</button>",
// "<button class='button button--play'>Play</button>",
// "<button class='button button--pause'>Pause</button>",
// "<button class='button button--next' data-slide='next' title='Next'>&#10095;</button>"
this.renderButton("&#10094;", "button button--prev", "Prev", "prev"),
this.renderButton("Play", "button button--play"),
this.renderButton("Pause", "button button--pause"),
this.renderButton("&#10095;", "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