Skip to content

Instantly share code, notes, and snippets.

@jshakes
Created April 30, 2016 02:16
Show Gist options
  • Save jshakes/68345bee3365a18cd165ae5dcfe83e6f to your computer and use it in GitHub Desktop.
Save jshakes/68345bee3365a18cd165ae5dcfe83e6f to your computer and use it in GitHub Desktop.
Slideshow
/*
Slideshow Component
-----------------
An extensible class for adding slideshow functionality to a group of elements. Supports next/prev buttons,
autoplay and counter elements for showing the current and total number of slides.
@ $slides (jQuery el) - The element containing the slides (jQuery object)
@ $nextButton (jQuery el) - The forward button
@ $prevButton (jQuery el) - The previous button
@ $counterCurrent (jQuery el) - The element to display the current slide
@ $counterTotal (jQuery el) - The element to display the total number of slides
@ autoPlay (int|bool) - Speed to autoplay the slides in ms, or false turns off autoplay
@ firstSlide (int) - Which slide to start on (defaults to 0)
@ loopForwards (bool) - Whether we should restart the slideshow when we go past the last slide
@ loopBackwards (bool) - Whether we should go the end of the slideshow when we go past the first slide
*/
function Slideshow(data) {
/*
Set properties from the data object
*/
this.$slides = data.$slides
this.$nextButton = typeof(data.$nextButton) != "undefined" ? data.$nextButton : [];
this.$prevButton = typeof(data.$prevButton) != "undefined" ? data.$prevButton : [];
this.$counterCurrent = typeof(data.$counterCurrent) != "undefined" ? data.$counterCurrent : false;
this.$counterTotal = typeof(data.$counterTotal) != "undefined" ? data.$counterTotal : false;
this.autoPlay = data.autoPlay ? data.autoPlay : false;
this.firstSlide = typeof(data.firstSlide) === "number" ? data.firstSlide : 0;
this.loopForwards = data.loopForwards ? true : false;
this.loopBackwards = data.loopBackwards ? true : false;
this.$items = this.$slides.find("> *");
this.currIndex = this.firstSlide;
this.maxIndex = this.$items.length;
/*
Set up bindings
*/
_this = this;
if(this.$nextButton.length){
this.$nextButton.on("click.advance", $.proxy(this.advance, this));
}
if(this.$prevButton.length){
this.$prevButton.on("click.recede", $.proxy(this.recede, this));
}
if(this.$counterCurrent.length){
// Update the counter when the slideshow is updated
this.$slides.on("recalc:slideshow", $.proxy(this.setCounterCurrent, this));
}
if(this.$counterTotal.length){
this.setCounterTotal();
}
_.defer(function(){
// Start the gallery
_this.$slides.trigger("initialize:slideshow");
_this.recalculateGallery(true);
});
return this;
};
/*
Autoplay slideshow
*/
Slideshow.prototype.initAutoPlay = function(ms) {
var _this = this;
if (this.timerID) {
clearTimeout(this.timerID);
}
return this.timerID = setTimeout((function() {
return _this.advance();
}), ms);
};
/*
Movement Functions
*/
/*
Set current index field to the next slide position
*/
Slideshow.prototype.advance = function() {
this.currIndex++;
if (this.currIndex + 1 > this.maxIndex) {
this.handleMaxLimit();
}
else {
this.recalculateGallery();
}
};
/*
Set current index field to the previous slide position
*/
Slideshow.prototype.recede = function() {
this.currIndex--;
if (this.currIndex < 0) {
this.handleMinLimit();
}
else {
this.recalculateGallery();
}
};
/*
Set current index field to the arguments position
*/
Slideshow.prototype.gotoIndex = function(index) {
this.currIndex = index;
return this.recalculateGallery();
};
Slideshow.prototype.goToStart = function() {
return this.gotoIndex(0);
};
Slideshow.prototype.goToEnd = function() {
return this.gotoIndex(this.maxIndex);
};
/*
When the final slide is reached, trigger the maxLimit event and go back to the beginning if this.loopForwards == true
*/
Slideshow.prototype.handleMaxLimit = function() {
this.$slides.trigger("maxLimit:slideshow");
if(this.loopForwards){
return this.goToStart();
}
else{
this.currIndex = this.maxLimit - 1;
}
};
/*
When the first slide is reached, trigger the minLimit event and go to the end if this.loopBackwards == true
*/
Slideshow.prototype.handleMinLimit = function() {
this.$slides.trigger("minLimit:slideshow");
if(this.loopBackwards){
return this.goToEnd();
}
else{
this.currIndex = 0;
}
};
/*
Apply classes based upon current position field
Note: Doesn't cause a reflow - all the slides are out of the document flow.
*/
Slideshow.prototype.recalculateGallery = function(init) {
var _this = this;
$.each(this.$items, function(i, el){
if (i < _this.currIndex) {
$(el).addClass('passed').removeClass("current upcoming");
}
if (i === _this.currIndex) {
$(el).addClass('current').removeClass("passed upcoming").trigger('isCurrent');
}
if (i > _this.currIndex) {
$(el).addClass('upcoming').removeClass("passed current");
}
});
/*
Reset the autoplay
*/
if(typeof(this.autoPlay) === "number"){
this.initAutoPlay(this.autoPlay);
}
/*
Fire events
*/
this.$slides.trigger("recalc:slideshow", this);
};
Slideshow.prototype.getCurrentItem = function() {
return this.$items[this.currIndex];
};
Slideshow.prototype.getCurrentIndex = function() {
return this.currIndex;
};
Slideshow.prototype.setCounterTotal = function() {
return this.$counterTotal.text(this.maxIndex);
};
Slideshow.prototype.setCounterCurrent = function() {
return this.$counterCurrent.text(this.currIndex + 1);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment