Skip to content

Instantly share code, notes, and snippets.

@AugustMiller
Last active April 27, 2019 10:18
Show Gist options
  • Save AugustMiller/7521053 to your computer and use it in GitHub Desktop.
Save AugustMiller/7521053 to your computer and use it in GitHub Desktop.
Simple responsive slider with support for touch devices.
<!DOCTYPE html>
<html>
<head>
<title>Slides.js Demo</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://gist.github.com/AugustMiller/7521053/raw/e5900f4a6628719c730c7c3f8acfcc6b28223aa3/Slides.js"></script>
<style>
html , body {
margin: 0;
padding: 0;
}
body {
padding: 1em;
}
#slideshow {
overflow: hidden;
position: relative;
}
.slideshow-controls {
position: absolute;
right: 1em;
bottom: 1em;
}
.slides {
position: relative;
}
.slide {
float: left;
}
img {
width: 100%;
pointer-events: none;
}
</style>
</head>
<body>
<div class="slideshow">
<div class="slides">
<div class="slide">
<img src="http://placehold.it/1200x800/FFFFFF/000000" />
</div>
<div class="slide">
<img src="http://placehold.it/1200x800/EEEEEE/111111" />
</div>
<div class="slide">
<img src="http://placehold.it/1200x800/DDDDDD/222222" />
</div>
<div class="slide">
<img src="http://placehold.it/1200x800/CCCCCC/333333" />
</div>
<div class="slide">
<img src="http://placehold.it/1200x800/BBBBBB/444444" />
</div>
</div>
<div class="slideshow-controls">
<span class="prev">Previous</span> / <span class="next">Next</span>
</div>
</div>
</body>
</html>
/*
Slides.js
August W. Miller
http://www.gusmiller.com/
2013
*/
var Gallery;
$(document).ready( function ( ) {
// New instance with the scope for this slideshow.
Gallery = new Slideshow( '.slideshow' , {
// Selector to use for a next button. Optionally, any event can trigger:
// Gallery.next(); or Gallery.prev(); or Gallery.pick(index);
forward : ".next",
// Selector to use for a previous button.
back : ".prev",
// Selector for slides wrapper/
wrapper : ".slides",
// Selector for individual slide elements.
slides : ".slide",
// Maximum transition speed allowed (swipes can be faster):
speed : 350,
// Show this slide on init (0 is the first one)
show : 0,
// Use keyboard nav. Probably don't want two
// in the same page with keyboard controls, huh?
// (This may change if we can make a good guess
// which one the user is looking at...)
useKeyboard : true
});
});
function Slideshow ( el , opts ) {
var self = this;
self.el = $(el);
self.slides = [];
self.current = 0;
// Some defaults ought to be here.
self.options = {
forward : $(opts.forward),
back : $(opts.back),
wrapper : self.el.find(opts.wrapper) || self.el.find(".slides"),
slides : self.el.find(opts.slides) || self.el.find(".slide" ),
speed : opts.speed || 500,
show : opts.show,
keyboard : opts.useKeyboard || false
};
// We're going to stash some touch event stuff in here:
self.touch = {};
// Split these out because the constructor gets fat right quick:
self.listen();
self.init();
}
Slideshow.prototype = {
init : function ( ) {
var self = this,
els = self.options.slides;
els.each( function ( index ) {
self.slides.push( new Slide ( this , self , index ) );
});
// Fire this once to size all the slides and their container.
self.layout();
// Choose the current one to set our left edge properly.
self.pick( self.options.show );
},
listen : function ( ) {
var self = this;
$(window).on( "resize" , function ( e ) {
// There is a fair amount to do here, and it trickles down to each slide.
self.layout( e );
});
$(self.options.forward).on( 'click' , function ( e ) {
self.next( self.options.speed );
});
$(self.options.back).on( 'click' , function ( e ) {
self.prev( self.options.speed );
});
if ( self.options.keyboard ) {
$(window).on( "keydown" , function ( e ) {
switch ( e.keyCode ) {
case 39 :
self.next( self.options.speed );
break;
case 37 :
self.prev( self.options.speed );
break;
}
});
}
$(self.el).on( 'touchstart' , function ( e ) {
self.touchSetup( e.originalEvent );
}).on( 'touchmove' , function ( e ) {
self.touchPan( e.originalEvent );
}).on( 'touchend' , function ( e ) {
self.touchConclude( e.originalEvent );
});
},
touchSetup : function ( e ) {
var self = this;
self.touch = {
start : {
position : e.touches[0].pageX,
time : e.timeStamp
},
delta : {
distance : 0,
duration : 0
}
};
},
touchPan : function ( e ) {
var self = this;
self.touch.delta.distance = ( self.touch.start.position - e.touches[0].pageX );
self.touch.delta.duration = ( e.timeStamp - self.touch.start.time );
self.options.wrapper.css({
left : ( ( - self.touch.delta.distance ) - ( self.el.width() * self.current ) )
});
},
touchConclude : function ( e ) {
var self = this;
if ( Math.abs( self.touch.delta.distance ) > ( self.el.width() / 4 ) ) {
if ( self.touch.delta.distance > 0 ) {
self.next( Math.min( self.touch.delta.duration , self.options.speed ) );
} else {
self.prev( Math.min( self.touch.delta.duration , self.options.speed ) );
}
} else {
self.pick( self.current , 250 );
}
},
next : function ( speed ) {
var self = this;
// Sort of crazy, but it ensures we don't go out of bounds.
self.pick( ( ( self.current + 1 < self.slides.length ) ? ( self.current + 1 ) : ( self.slides.length - 1 ) ) , speed );
},
prev : function ( speed ) {
var self = this;
// Same here...
self.pick( ( ( self.current - 1 >= 0 ) ? ( self.current - 1 ) : ( 0 ) ) , speed );
},
pick : function ( index , speed ) {
var self = this,
destination = Math.max( 0 , Math.min( ( self.slides.length - 1 ) , index ) );
// We've protected against out-of-bounds slide selection
if ( speed ) {
// If there is a non-zero number supplied, we'll animate the transition.
$(self.options.wrapper).animate({
"left" : - ( destination * self.el.width() )
} , {
duration : ( speed + ( ( speed / 4 ) * Math.abs( self.current - destination ) ) ),
queue : false
});
} else {
// Otherwise, assume we want it swapped immediately.
$(self.options.wrapper).css({
"left" : - ( destination * self.el.width() )
});
}
self.current = destination;
},
layout : function ( e ) {
var self = this,
width = self.el.width();
// Critical to make sure the slides float correctly
self.options.wrapper.css({
"width" : ( self.slides.length * self.el.width() )
});
// Fire a resize on each of the slide elements.
for ( var s = 0; s < self.slides.length; s++ ) {
self.slides[s].resize( width );
}
self.pick( self.current , 0 );
}
}
function Slide ( el , parent , index ) {
var self = this;
self.Slideshow = parent;
self.el = self.Slideshow.options.wrapper.find(el);
self.index = index;
}
Slide.prototype.resize = function ( width ) {
var self = this;
// Just set the width
self.el.css({
"width" : width
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment