Last active
September 24, 2016 20:05
-
-
Save tlaak/3b1ec4cbc55212e2683b5466f0201f4d to your computer and use it in GitHub Desktop.
jQuery plugin for a custom responsive image carousel. Found from the depths of my Dropbox
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @version 0.1 Alpha | |
* @author Timo Laak 6/6/2013 | |
* | |
*/ | |
(function($) { | |
/** | |
* Constants for recurring use | |
*/ | |
var constants = { | |
/** @const */ | |
PLUGIN_NAME: 'bmmCarousel', | |
PLUGIN_CSS_CLASS: 'bmm-carousel' | |
}; | |
/** | |
* Templates for repeating elements | |
*/ | |
var templates = { | |
overlayLeft: '<div class="carousel-overlay" id="left-overlay"></div>', | |
overlayRight: '<div class="carousel-overlay" id="right-overlay"></div>', | |
carouselNav: '<div class="carousel-nav"></div>', | |
btnNext: '<i class="btn-next"></i>', | |
btnPrev: '<i class="btn-prev"></i>' | |
}; | |
/** | |
* Plugin methods | |
*/ | |
var methods = { | |
/** | |
* Init the plugin | |
*/ | |
init: function(options) { | |
// Add identifying class for css styles | |
this.addClass(constants.PLUGIN_CSS_CLASS); | |
this.data('length', $('.carousel-item', this).length); | |
// Build the carousel, add overlay, buttons and add bindings | |
methods.buildCarousel.apply(this); | |
methods.addOverlay.apply(this); | |
methods.addButtons.apply(this); | |
methods.addBindings.apply(this); | |
}, | |
/** | |
* Build the carousel | |
*/ | |
buildCarousel: function() { | |
var _head, _tail, _tailClone, _this = this, _data = this.data(), carousel = this.children('.carousel'); | |
_head = $('.carousel-item', this).first(); | |
_tail = $('.carousel-item', this).last(); | |
// Do not show items outside the page wrapper if there are less than 3 of them | |
if (_data.length < 3) { | |
this.addClass('overlay-opaque'); | |
} | |
if (_data.length < 2) { | |
this.addClass('no-navigation'); | |
} | |
// If there are only 3 items, clone the last item to the front to prevent | |
// showing empty slot | |
if (_data.length == 2 || _data.length == 3) { | |
_tail.clone().prependTo(carousel); | |
_head = $('.carousel-item').first(); | |
_data.length++; | |
} | |
// Single item width as percentages | |
_data.itemWidth = 100 / _data.length; | |
$('.carousel-item', this).each(function() { | |
$(this).width(_data.itemWidth + '%'); | |
}); | |
$(carousel).width(this.width() * _data.length); | |
if (_data.length > 1) { | |
// Active item is the second item | |
$(carousel).css('left', '-100%'); | |
} | |
}, | |
/** | |
* Add the transparent overlay to cover overflow items | |
*/ | |
addOverlay: function() { | |
this.append($(templates.overlayLeft)); | |
this.append($(templates.overlayRight)); | |
}, | |
/** | |
* Add control buttons | |
*/ | |
addButtons: function() { | |
var carouselNav = $(templates.carouselNav), | |
_btnNext = $(templates.btnNext), | |
_btnPrev = $(templates.btnPrev), | |
_this = this; | |
_btnNext.on('click', function(e) { | |
methods.next.apply(_this); | |
}); | |
_btnPrev.on('click', function(e) { | |
methods.prev.apply(_this); | |
}); | |
carouselNav.append(_btnNext); | |
carouselNav.prepend(_btnPrev); | |
this.append(carouselNav); | |
}, | |
/** | |
* Add bindings for events | |
*/ | |
addBindings: function() { | |
var _this = this; | |
$(window).on('resize', function() { | |
methods.resize.apply(_this); | |
}); | |
}, | |
/** | |
* Rotate carousel forward | |
*/ | |
next: function() { | |
var _this = this, _data = this.data(), carousel = this.children('.carousel'); | |
// Return if already rotating to prevent multiple button clicks | |
if (_data.rotating === true) { | |
return; | |
} | |
// Start rotating | |
_data.rotating = true; | |
// Offset is one item to the left of the carousel | |
// Animate to two items on the left | |
$(carousel).animate({ | |
left: '-200%' | |
}, 'slow', 'swing', function() { | |
// Remove the first item and clone the second one (the new first) to the end of the carousel | |
$('.carousel-item', _this).first().remove(); | |
$('.carousel-item', _this).first().clone().appendTo(carousel); | |
// Update position back to one item on the left and stop rotating | |
$(carousel).css('left', '-100%'); | |
_data.rotating = false; | |
}); | |
}, | |
/** | |
* Rotate carousel backwards | |
*/ | |
prev: function() { | |
var _this = this, _data = this.data(), carousel = this.children('.carousel'); | |
// Return if already rotating to prevent multiple button clicks | |
if (_this.data('rotating') === true) { | |
return; | |
} | |
// Start rotating | |
_data.rotating = true; | |
// Clone last item to front and remove the last item to keep length the same | |
$('.carousel-item', _this).last().prev().clone().prependTo(carousel); | |
$('.carousel-item', _this).last().remove(); | |
// Offset is 2 items to the left in the beginning and there are 2 items on the left of the active one | |
$(carousel).css('left', '-200%'); | |
// Animate 1 item to the right. There will be 1 item on the left of the active one in the end | |
$(carousel).animate({ | |
left: '-100%' | |
}, 'slow', 'swing', function() { | |
_data.rotating = false; | |
}); | |
}, | |
/** | |
* Handle resize events | |
*/ | |
resize: function() { | |
$('.carousel', this).width(this.width() * this.data('length')); | |
} | |
}; | |
/** | |
* The actual plugin | |
*/ | |
$.fn[constants.PLUGIN_NAME] = function(method) { | |
this.each(function() { | |
_this = $(this); | |
if ( methods[method] ) { | |
return methods[method].apply( _this, Array.prototype.slice.call( arguments, 1 )); | |
} else if ( typeof method === 'object' || ! method ) { | |
return methods.init.apply( _this, arguments ); | |
} else { | |
$.error( 'Method ' + method + ' does not exist on bmmCarousel' ); | |
} | |
}); | |
}; | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment