Skip to content

Instantly share code, notes, and snippets.

@mindplay-dk
Last active December 25, 2015 05:09
Show Gist options
  • Save mindplay-dk/6922957 to your computer and use it in GitHub Desktop.
Save mindplay-dk/6922957 to your computer and use it in GitHub Desktop.
jQuery slideshow plugin (responsive version with CSS3 optimized animation)
/* main container: */
#test {
clear: both;
width: 100%;
min-width: 240px;
max-width: 790px;
height: 320px;
overflow: hidden;
font-family: Verdana, Arial;
position: relative;
}
#test .slide {
display: none;
overflow: hidden;
height: inherit;
width: 100%;
position: absolute;
left: 0%;
}
#test .slide img {
width: 640px;
position: absolute;
left: 50%;
margin-left: -320px;
}
@media (max-width:320px) {
#test { height: 150px; }
#test .slide img {
width: 320px;
margin-left: -160px;
}
}
@media (min-width:640px) {
#test { height: 450px; }
#test .slide img {
width: 800px;
margin-left: -400px;
}
}
/* toggle button: */
#test .toggle {
position: absolute;
top: 8px;
right: 8px;
width: 30px;
height: 30px;
font-size: 15px;
font-weight: bold;
color: white;
text-align: center;
line-height: 28px;
background: black;
opacity: 0.5;
cursor: pointer;
border-radius: 5px;
}
/* index buttons (1, 2, 3...) */
#test .buttons {
position: absolute;
height: 32px;
bottom: 0px;
left: 55px;
}
#test .buttons a {
display: block;
width: 24px;
height: 22px;
text-align: center;
line-height: 20px;
color: white;
font-size: 12px;
font-weight: bold;
text-decoration: none;
background: black;
margin-left: 2px;
border-radius: 5px;
opacity: 0.5;
float: left;
}
#test .buttons a:hover {
opacity: 1.0;
color: yellow;
}
#test .buttons a.active {
background: white;
color: black;
opacity: 1.0;
}
/* left/right arrow buttons: */
#test .nav {
position: absolute;
width: 100%;
height: 50px;
bottom: 0px;
}
#test .nav a {
font-size: 36px;
text-decoration: none;
color: white;
display: block;
width: 50px;
text-align: center;
height: 50px;
position: absolute;
overflow: hidden;
}
#test .nav a:hover {
color: yellow;
}
#test .nav a.prev {
left: 1%;
}
#test .nav a.next {
right: 1%;
}
jQuery(document).ready(function() {
var slideshow = $('#test').Slideshow({
slides: '#test div.slide',
buttons: '#test div.buttons',
prev: '#test a.prev',
next: '#test a.next'
});
// example demonstrating a custom play/pause control:
var pauseButton = $('#test div.toggle');
pauseButton.click(function() {
slideshow.toggle();
pauseButton.text(slideshow.playing() ? '>' : '||');
return false;
});
});
/**
* jQuery Slideshow plugin
* (responsive version with CSS3 optimized animation)
*
* author: Rasmus Schultz <rasmus@mindplay.dk>
* license: LGPL <http://www.gnu.org/licenses/lgpl-3.0.txt>
*
* This plugin creates a panning slideshow, optionally with left/right controls
* and direct access to the individual slides via (numbered) index-buttons.
*
* No CSS is required, and there is no dependencies on any particular class-names,
* element-types or element hierarchy - you can use whatever you want for slides,
* containers, buttons, etc.
*
*
* USAGE
* =====
*
* Width and height options are not required - by default, the plugin picks up
* the inner width/height of the slideshow container, so you can define that
* using CSS, if you like.
*
* The slides must reside in a container, but it doesn't have to be the element
* you applied the slideshow to - for example, if that element is a wrapper with
* a background, you can use the "container" option to specify the actual container.
*
* You can specify the delay for individual slides, by adding a data-delay attribute
* to the individual slide elements, specifying the time in seconds (decimals allowed.)
*
* If a container for index-buttons is specified (using the "buttons" option),
* the plugin will generate an index-button for each slide; you can override the
* default button-creation method using the "createButton" callback-option.
*
* The plugin does not generate the next/previous buttons - you can use the "next"
* and "prev" options to apply event-handlers to your existing buttons/elements.
*
* Basic options: (all optional, except for "slides")
*
* slides selector or set of individual slides (required)
* container overrides the slide container element (defaults to this)
* width width in pixels (defaults to container's inner width)
* height height in pixels (defaults to container's inner height)
*
* Animation options: (all optional)
*
* easing jQuery animation easing algorithm (defaults to "swing")
* speed animation speed (in seconds - decimal allowed, default = 1.0)
* delay delay between slides (in seconds - decimal allowed, default = 3.0)
* (override using data-delay attribute on individual slides.)
*
* Navigation options: (all optional)
*
* next element for "next" button (by default, no next-button)
* prev element for "previous" button (by deafult, no previous-button)
* buttons container element for index-buttons (by default, no buttons)
* active class-name for active index-button (defaults to "active")
* createButton callback: function($slide,index)
* creates an index button for a slide
* (by default, an <a>-tag with a number is created)
*
* Public API:
*
* You can control the plugin from your code - for example, to stop a slideshow:
*
* $('#my-slideshow').Slideshow().stop();
*
* The following public methods are available:
*
* stop() pause the animation
* start() resume the animation
* toggle() toggle the animation (start or stop)
* playing() returns true if animation is running (otherwise false)
* next() advance to next slide
* prev() rewind to previous slide
* goto(index) go to a specific slide (uses a 0-based index)
*
*/
(function($) {
/* https://gist.github.com/jonraasch/373874 */
function supports_transitions() {
var thisBody = document.body || document.documentElement,
thisStyle = thisBody.style;
return thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined;
}
function Slideshow(el, options) {
var
$el = $(options.container || el), // slideshow container element
$slides = $(options.slides), // list of slides
$buttons = null, // index buttons
_delay = [], // delay in milliseconds (for each slide)
_easing = options.easing || 'swing', // easing mode (for animation)
_speed = parseFloat(options.speed || 1)*1000, // speed (animation time)
_timer = null, // timer handle (for delay between slides)
_blocked = false, // user interface blocking (during animation)
_resume = null, // callback-function (when unblocking interface)
_active = options.active || 'active', // active class-name (for index buttons)
_count = $slides.length, // number of slides
_index = 0; // current slide index
var LEFT = '-100%', // left position (CSS/animation)
RIGHT = '100%', // right position (CSS/animation)
CENTER = '0%'; // center position (CSS/animation)
var _slide = function (el, from, to, then) {
$(el).css('left', from).animate(
{ left: to },
_speed,
_easing,
then
);
};
if (supports_transitions()) {
// optimized slide function using CSS3 transitions:
_slide = function (el, from, to, then) {
$(el).css('transition', '0s').css('left', from);
window.setTimeout(function() {
$(el).css('transition', 'left ' + _speed + 'ms ease').css('left', to);
window.setTimeout(function () {
then.apply(el);
}, _speed + 100);
}, 20);
};
}
$el.css('position', 'relative');
$slides.each(function(i) {
$(this).css({
position: 'absolute',
left: CENTER
}).toggle(i==0);
_delay[i] = parseFloat($(this).attr('data-delay') || options.delay || 3) * 1000;
});
if (options.buttons) {
var create = options.createButton || _createButton;
var $ct = $(options.buttons);
$slides.each(function(i) {
$ct.append(
$(create(this, i+1))
.click(function() { _goto(i); return false; })
);
});
$buttons = $ct.children();
$buttons.eq(_index).addClass(_active);
}
function _createButton(el, i) {
return $(document.createElement('a'))
.attr('href', '#')
.text(i);
}
function _start() {
_stop(); // clear any previous timeout
_timer = window.setTimeout(_next, _delay[_index]);
}
function _stop() {
window.clearTimeout(_timer);
_timer = null;
}
function _playing() {
return !(_timer == null);
}
function _toggle() {
_playing() ? _stop() : _start();
return _playing();
}
function _goto(index, direction) {
if (_blocked) {
// postpone this method-call until user interface is unblocked:
_resume = function() {
_goto(index, direction);
};
return;
}
if (index == _index) return;
window.clearTimeout(_timer); // clear timer
_blocked = true;
if (direction === undefined) {
direction = index > _index;
}
// remove previous slide:
_slide($slides.eq(_index).show(), CENTER, direction ? LEFT : RIGHT, function() {
$(this).hide(); // hide the slide
if (_timer) { _start(); } // resume playback
});
// display next slide:
_slide($slides.eq(index).show(), direction ? RIGHT : LEFT, CENTER, function() {
_blocked = false; // unblock user inteface
if (_resume) {
_resume();
_resume = null;
}
});
// update buttons:
if ($buttons) {
$buttons.eq(_index).removeClass(_active);
$buttons.eq(index).addClass(_active);
}
// switch index:
_index = index;
}
function _prev() {
if (_blocked) {
_resume = _prev;
return;
}
_goto(_index == 0 ? _count-1 : _index-1, false);
}
function _next() {
if (_blocked) {
_resume = _next;
return;
}
_goto((_index+1) % _count, true);
}
_start();
if (options.prev) {
$(options.prev).click(function(){ _prev(); return false; });
}
if (options.next) {
$(options.next).click(function(){ _next(); return false; });
}
$.extend(this, {
start: _start,
stop: _stop,
toggle: _toggle,
playing: _playing,
next: _next,
prev: _prev,
goto: _goto
});
}
$.fn.Slideshow = function(options) {
if (options === undefined) {
return $(this).data('Slideshow');
} else {
var inst = new Slideshow(this, options);
$(this).data('Slideshow', inst);
return inst;
}
};
})(jQuery);
@mindplay-dk
Copy link
Author

Previous version (not responsive, not CSS3 optimized)

Example (jsFiddle)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment