swipe.js
Swipe = function(element, options) {
if (!element) {
return null;
}
var _this = this;
this.options = options || {};
this.index = this.options.startSlide || 0;
this.speed = this.options.speed || 300;
this.callback = this.options.callback ||
function() {
};
this.delay = this.options.auto || 0;
this.container = element;
this.element = this.container.children[0];
this.container.style.overflow = 'hidden';
this.element.style.listStyle = 'none';
this.element.style.margin = 0;
this.setup();
this.begin();
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('touchcancel', 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() {
this.slides = this.element.children;
this.length = this.slides.length;
if (this.length < 2) {
return null;
}
var containerRect = "getBoundingClientRect" in this.container;
this.width = Math.ceil(("getBoundingClientRect" in this.container) ? this.container.getBoundingClientRect().width : this.container.offsetWidth);
if (this.width === 0 && typeof window.getComputedStyle === 'function') {
this.width = window.getComputedStyle(this.container, null).width.replace('px', '');
}
if (!this.width) {
return null;
}
var origVisibility = this.container.style.visibility;
this.container.style.visibility = 'hidden';
this.element.style.width = Math.ceil(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';
}
this.slide(this.index, 0);
this.container.style.visibility = origVisibility;
},
slide : function(index, duration) {
var style = this.element.style;
if (duration === undefined) {
duration = this.speed;
}
style.webkitTransitionDuration = style.MozTransitionDuration = style.msTransitionDuration = style.OTransitionDuration = style.transitionDuration = duration + 'ms';
style.MozTransform = style.webkitTransform = 'translate3d(' + -(index * this.width) + 'px,0,0)';
style.msTransform = style.OTransform = 'translateX(' + -(index * this.width) + 'px)';
this.index = index;
},
getPos : function() {
return this.index;
},
prev : function(delay) {
this.delay = delay || 0;
clearTimeout(this.interval);
if (this.index) {
this.slide(this.index - 1, this.speed);
} else {
this.slide(this.length - 1, this.speed);
}
},
next : function(delay) {
this.delay = delay || 0;
clearTimeout(this.interval);
if (this.index < this.length - 1) {
this.slide(this.index + 1, this.speed);
} else {
this.slide(0, this.speed);
}
},
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 'touchcancel' :
case 'touchend':
this.onTouchEnd(e);
break;
case 'webkitTransitionEnd':
case 'msTransitionEnd':
case 'oTransitionEnd':
case 'transitionend':
this.transitionEnd(e);
break;
case 'resize':
this.setup();
break;
}
},
transitionEnd : function(e) {
if (this.delay) {
this.begin();
}
this.callback(e, this.index, this.slides[this.index]);
},
onTouchStart : function(e) {
this.start = {
pageX : e.touches[0].pageX,
pageY : e.touches[0].pageY,
time : Number(new Date())
};
this.isScrolling = undefined;
this.deltaX = 0;
this.element.style.MozTransitionDuration = this.element.style.webkitTransitionDuration = 0;
e.stopPropagation();
},
onTouchMove : function(e) {
if (e.touches.length > 1 || e.scale && e.scale !== 1) {
return;
}
this.deltaX = e.touches[0].pageX - this.start.pageX;
if ( typeof this.isScrolling === 'undefined') {
this.isScrolling = !!(this.isScrolling || Math.abs(this.deltaX) < Math.abs(e.touches[0].pageY - this.start.pageY) );
}
if (!this.isScrolling) {
e.preventDefault();
clearTimeout(this.interval);
this.deltaX = this.deltaX / ((!this.index && this.deltaX > 0
|| this.index === this.length - 1
&& this.deltaX < 0
) ? (Math.abs(this.deltaX) / this.width + 1 )
: 1 );
this.element.style.MozTransform = this.element.style.webkitTransform = 'translate3d(' + (this.deltaX - this.index * this.width) + 'px,0,0)';
e.stopPropagation();
}
},
onTouchEnd : function(e) {
var isValidSlide = Number(new Date()) - this.start.time < 250
&& Math.abs(this.deltaX) > 20
|| Math.abs(this.deltaX) > this.width / 2,
isPastBounds = !this.index && this.deltaX > 0
|| this.index === this.length - 1 && this.deltaX < 0;
if (!this.isScrolling) {
this.slide(this.index + (isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0 ), this.speed);
}
e.stopPropagation();
}
};