Skip to content

Instantly share code, notes, and snippets.

@lqez
Created April 17, 2012 09:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lqez/2404749 to your computer and use it in GitHub Desktop.
Save lqez/2404749 to your computer and use it in GitHub Desktop.
Modified swipe.js to get callback point on beginning swipe.
/*
* Swipe 1.0
*
* Brad Birdsall, Prime
* Copyright 2011, Licensed GPL & MIT
*
*/
window.Swipe = function(element, options) {
// return immediately if element doesn't exist
if (!element) return null;
var _this = this;
// retreive options
this.options = options || {};
this.index = this.options.startSlide || 0;
this.speed = this.options.speed || 300;
this.callback = this.options.callback || function() {};
this.callbackBegin = this.options.callbackBegin || function() {};
this.delay = this.options.auto || 0;
this.glance = this.options.glance || 0;
// reference dom elements
this.container = element;
this.element = this.container.children[0]; // the slide pane
// static css
this.container.style.overflow = 'hidden';
this.element.style.listStyle = 'none';
// trigger slider initialization
this.setup();
// begin auto slideshow
this.begin();
// add event listeners
if (this.element.addEventListener) {
this.element.addEventListener('touchstart', this, false);
this.element.addEventListener('touchmove', this, false);
this.element.addEventListener('touchend', this, false);
this.element.addEventListener('webkitTransitionEnd', this, false);
this.element.addEventListener('msTransitionEnd', this, false);
this.element.addEventListener('oTransitionEnd', this, false);
this.element.addEventListener('transitionend', this, false);
window.addEventListener('resize', this, false);
}
};
Swipe.prototype = {
setup: function() {
// get and measure amt of slides
this.slides = this.element.children;
this.length = this.slides.length;
// return immediately if their are less than two slides
if (this.length < 2) return null;
// determine width of each slide
this.oriwidth = this.container.getBoundingClientRect().width;
this.glance = this.oriwidth * this.glance;
this.width = this.oriwidth - this.glance;
// return immediately if measurement fails
if (!this.width) return null;
// hide slider element but keep positioning during setup
this.container.style.visibility = 'hidden';
// dynamic css
this.element.style.width = (this.slides.length * this.width) + 'px';
var index = this.slides.length;
while (index--) {
var el = this.slides[index];
el.style.width = this.width + 'px';
el.style.display = 'table-cell';
el.style.verticalAlign = 'top';
var childNodes = el.childNodes;
for( var i = 0; i < childNodes.length; i++ ) {
var child = childNodes[i];
if( child.attributes == null ) continue;
child.style.width = this.oriwidth + 'px';
child.style.marginRight = -this.glance + 'px'
}
}
// set start position and force translate to remove initial flickering
this.slide(this.index, 0);
// show slider element
this.container.style.visibility = 'visible';
},
slide: function(index, duration) {
var style = this.element.style;
// set duration speed (0 represents 1-to-1 scrolling)
style.webkitTransitionDuration = style.MozTransitionDuration = style.msTransitionDuration = style.OTransitionDuration = style.transitionDuration = duration + 'ms';
// translate to given index position
style.webkitTransform = 'translate3d(' + -(index * this.width) + 'px,0,0)';
style.msTransform = style.MozTransform = style.OTransform = 'translateX(' + -(index * this.width) + 'px)';
this.transitionBegin(index);
// set new index to allow for expression arguments
this.index = index;
},
getPos: function() {
// return current index position
return this.index;
},
prev: function(delay) {
// cancel next scheduled automatic transition, if any
this.delay = delay || 0;
clearTimeout(this.interval);
// if not at first slide
if (this.index) this.slide(this.index-1, this.speed);
},
next: function(delay) {
// cancel next scheduled automatic transition, if any
this.delay = delay || 0;
clearTimeout(this.interval);
if (this.index < this.length - 1) this.slide(this.index+1, this.speed); // if not last slide
else this.slide(0, this.speed); //if last slide return to start
},
begin: function() {
var _this = this;
this.interval = (this.delay)
? setTimeout(function() {
_this.next(_this.delay);
}, this.delay)
: 0;
},
stop: function() {
this.delay = 0;
clearTimeout(this.interval);
},
resume: function() {
this.delay = this.options.auto || 0;
this.begin();
},
handleEvent: function(e) {
switch (e.type) {
case 'touchstart': this.onTouchStart(e); break;
case 'touchmove': this.onTouchMove(e); break;
case 'touchend': this.onTouchEnd(e); break;
case 'webkitTransitionEnd':
case 'msTransitionEnd':
case 'oTransitionEnd':
case 'transitionend': this.transitionEnd(e); break;
case 'resize': this.setup(); break;
}
},
transitionBegin: function(index) {
this.callbackBegin(index);
},
transitionEnd: function(e) {
if (this.delay) this.begin();
this.callback(e, this.index, this.slides[this.index]);
},
onTouchStart: function(e) {
this.start = {
// get touch coordinates for delta calculations in onTouchMove
pageX: e.touches[0].pageX,
pageY: e.touches[0].pageY,
// set initial timestamp of touch sequence
time: Number( new Date() )
};
// used for testing first onTouchMove event
this.isScrolling = undefined;
// reset deltaX
this.deltaX = 0;
// set transition time to 0 for 1-to-1 touch movement
this.element.style.webkitTransitionDuration = 0;
},
onTouchMove: function(e) {
// ensure swiping with one touch and not pinching
if(e.touches.length > 1 || e.scale && e.scale !== 1) return;
this.deltaX = e.touches[0].pageX - this.start.pageX;
// determine if scrolling test has run - one time test
if ( typeof this.isScrolling == 'undefined') {
this.isScrolling = !!( this.isScrolling || Math.abs(this.deltaX) < Math.abs(e.touches[0].pageY - this.start.pageY) );
}
// if user is not trying to scroll vertically
if (!this.isScrolling) {
// prevent native scrolling
e.preventDefault();
// cancel slideshow
clearTimeout(this.interval);
// increase resistance if first or last slide
this.deltaX =
this.deltaX /
( (!this.index && this.deltaX > 0 // if first slide and sliding left
|| this.index == this.length - 1 // or if last slide and sliding right
&& this.deltaX < 0 // and if sliding at all
) ?
( Math.abs(this.deltaX) / this.width + 1 ) // determine resistance level
: 1 ); // no resistance if false
// translate immediately 1-to-1
this.element.style.webkitTransform = 'translate3d(' + (this.deltaX - this.index * this.width) + 'px,0,0)';
}
},
onTouchEnd: function(e) {
// determine if slide attempt triggers next/prev slide
var isValidSlide =
Number(new Date()) - this.start.time < 250 // if slide duration is less than 250ms
&& Math.abs(this.deltaX) > 20 // and if slide amt is greater than 20px
|| Math.abs(this.deltaX) > this.width/2, // or if slide amt is greater than half the width
// determine if slide attempt is past start and end
isPastBounds =
!this.index && this.deltaX > 0 // if first slide and slide amt is greater than 0
|| this.index == this.length - 1 && this.deltaX < 0; // or if last slide and slide amt is less than 0
// if not scrolling vertically
if (!this.isScrolling) {
// call slide function with slide end value based on isValidSlide and isPastBounds tests
this.slide( this.index + ( isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0 ), this.speed );
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment