Created
April 4, 2013 19:18
-
-
Save Lagnarok/5313298 to your computer and use it in GitHub Desktop.
This is an older copy of Swipe v2, but I've modified it to work with MSPointer events. It looks like the modifications around instances of e.pageX and e.pageY won't be necessary anymore, but the other changes should still be applicable once altered to fit your new format.
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
/* | |
* Swipe 2.0 | |
* | |
* Brad Birdsall | |
* Copyright 2012, Licensed GPL & MIT | |
* | |
*/ | |
window.Swipe = function(element, options) { | |
var _this = this; | |
// return immediately if element doesn't exist | |
if (!element) return; | |
// reference dom elements | |
this.container = element; | |
this.element = this.container.children[0]; | |
// simple feature detection | |
this.browser = { | |
touch: (function() { | |
return ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch; | |
})(), | |
point: (function() { | |
return window.navigator.msPointerEnabled; | |
})(), | |
transitions: (function() { | |
var temp = document.createElement('swipe'), | |
props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']; | |
for ( var i in props ) { | |
if (temp.style[ props[i] ] !== undefined) return true; | |
} | |
return false; | |
})() | |
}; | |
// retreive options | |
options = options || {}; | |
this.index = options.startSlide || 0; | |
this.speed = options.speed || 300; | |
this.callback = options.callback || function() {}; | |
this.transitionEnd = options.transitionEnd || function() {}; | |
this.delay = options.auto || 0; | |
this.cont = (options.continuous != undefined) ? !!options.continuous : true; | |
this.disableScroll = !!options.disableScroll; | |
// verify index is a number not string | |
this.index = parseInt(this.index,10); | |
// trigger slider initialization | |
this.setup(); | |
// begin auto slideshow | |
this.begin(); | |
// add event listeners | |
if (this.element.addEventListener) { | |
if (!!this.browser.touch) { | |
this.element.addEventListener('touchstart', this, false); | |
this.element.addEventListener('touchmove', this, false); | |
this.element.addEventListener('touchend', this, false); | |
} | |
if (!!this.browser.point) { | |
this.element.addEventListener('MSPointerDown', this, false); | |
this.element.addEventListener('MSPointerMove', this, false); | |
this.element.addEventListener('MSPointerUp', this, false); | |
} | |
if (!!this.browser.transitions) { | |
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); | |
} | |
// to play nice with old IE | |
else { | |
window.onresize = function () { | |
_this.setup(); | |
}; | |
} | |
}; | |
Swipe.prototype = { | |
setup: function() { | |
// get and measure amt of slides | |
this.slides = this.element.children; | |
this.length = this.slides.length; | |
this.cache = new Array(this.length); | |
// return immediately if their are less than two slides | |
if (this.length < 2) return; | |
// determine width of each slide | |
this.width = this.container.getBoundingClientRect().width || this.container.offsetWidth; | |
// return immediately if measurement fails | |
if (!this.width) return; | |
// store array of slides before, current, and after | |
var refArray = [[],[],[]]; | |
this.element.style.width = (this.slides.length * this.width) + 'px'; | |
// stack elements | |
for (var index = this.length - 1; index > -1; index--) { | |
var elem = this.slides[index]; | |
elem.style.width = this.width + 'px'; | |
elem.setAttribute('data-index', index); | |
if (this.browser.transitions) { | |
elem.style.left = (index * -this.width) + 'px'; | |
} | |
// add this index to the reference array 0:before 1:equal 2:after | |
refArray[this.index > index ? 0 : (this.index < index ? 2 : 1)].push(index); | |
} | |
if (this.browser.transitions) { | |
// stack left, current, and right slides | |
this._stack(refArray[0],-1); | |
this._stack(refArray[1],0); | |
this._stack(refArray[2],1); | |
} else { | |
// move "viewport" to put current slide into view | |
this.element.style.left = (this.index * -this.width)+"px"; | |
} | |
this.container.style.visibility = 'visible'; | |
}, | |
kill: function() { | |
// cancel slideshow | |
this.delay = 0; | |
clearTimeout(this.interval); | |
// clear all translations | |
var slideArray = []; | |
for (var i = this.slides.length - 1; i >= 0; i--) { | |
this.slides[i].style.width = ''; | |
slideArray.push(i); | |
} | |
this._stack(slideArray,0); | |
var elem = this.element; | |
elem.className = elem.className.replace('swipe-active',''); | |
// remove event listeners | |
if (this.element.removeEventListener) { | |
if (!!this.browser.touch) { | |
this.element.removeEventListener('touchstart', this, false); | |
this.element.removeEventListener('touchmove', this, false); | |
this.element.removeEventListener('touchend', this, false); | |
} | |
if (!!this.browser.point) { | |
this.element.removeEventListener('MSPointerDown', this, false); | |
this.element.removeEventListener('MSPointerMove', this, false); | |
this.element.removeEventListener('MSPointerUp', this, false); | |
} | |
if (!!this.browser.transitions) { | |
this.element.removeEventListener('webkitTransitionEnd', this, false); | |
this.element.removeEventListener('msTransitionEnd', this, false); | |
this.element.removeEventListener('oTransitionEnd', this, false); | |
this.element.removeEventListener('transitionend', this, false); | |
} | |
window.removeEventListener('resize', this, false); | |
} | |
// kill old IE! you can quote me on that ;) | |
else { | |
window.onresize = null; | |
} | |
}, | |
getPos: function() { | |
// return current index position | |
return this.index; | |
}, | |
prev: function(delay) { | |
// cancel slideshow | |
this.delay = delay || 0; | |
clearTimeout(this.interval); | |
// if not at first slide | |
if (this.index) this.slide(this.index-1, this.speed); | |
else if (this.cont) this.slide(this.length-1, this.speed); | |
}, | |
next: function(delay) { | |
// cancel slideshow | |
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 if (this.cont) 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; | |
}, | |
handleEvent: function(e) { | |
switch (e.type) { | |
case 'touchstart': case 'MSPointerDown': this.onTouchStart(e); break; | |
case 'touchmove': case 'MSPointerMove': this.onTouchMove(e); break; | |
case 'touchend': case 'MSPointerUp': this.onTouchEnd(e); break; | |
case 'webkitTransitionEnd': | |
case 'msTransitionEnd': | |
case 'oTransitionEnd': // opera 11 and below | |
case 'otransitionend': // opera 12 (and above?) | |
case 'transitionend': this.onTransitionEnd(e); break; | |
case 'resize': this.setup(); break; | |
} | |
e.stopPropagation(); | |
}, | |
onTouchStart: function(e) { | |
var _this = this; | |
_this.start = { | |
// get touch coordinates for delta calculations in onTouchMove | |
pageX: (e.pageX || e.touches[0].pageX), | |
pageY: (e.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; | |
}, | |
onTouchMove: function(e) { | |
var _this = this; | |
// ensure swiping with one touch and not pinching | |
if(this.browser.point && !e.isPrimary) return; | |
if(!this.browser.point && (e.touches.length > 1 || e.scale && e.scale !== 1)) return; | |
_this.deltaX = (e.pageX || 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.pageY || 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 | |
_this.delay = 0; | |
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:1 | |
_this._move([_this.index-1,_this.index,_this.index+1],_this.deltaX); | |
} else if (_this.disableScroll) { | |
// prevent native scrolling | |
e.preventDefault(); | |
} | |
}, | |
onTouchEnd: function(e) { | |
var _this = this; | |
if (window.navigator.msPointerEnabled && !e.isPrimary) return; | |
// 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 | |
direction = _this.deltaX < 0; // true:right false:left | |
// if not scrolling vertically | |
if (!_this.isScrolling) { | |
if (isValidSlide && !isPastBounds) { | |
if (direction) { | |
_this._stack([_this.index-1],-1); | |
_this._slide([_this.index,_this.index+1],-_this.width,_this.speed); | |
_this.index += 1; | |
} else { | |
_this._stack([_this.index+1],1); | |
_this._slide([_this.index-1,_this.index],_this.width,_this.speed); | |
_this.index += -1; | |
} | |
_this.callback(_this.index, _this.slides[_this.index]); | |
} else { | |
_this._slide([_this.index-1,_this.index,_this.index+1],0,_this.speed); | |
} | |
} | |
}, | |
onTransitionEnd: function(e) { | |
if (this._getElemIndex(e.target) == this.index) { // only call transition end on the main slide item | |
if (this.delay) this.begin(); | |
this.transitionEnd(this.index, this.slides[this.index]); | |
} | |
}, | |
slide: function(to, speed) { | |
var from = this.index; | |
if (from == to) return; // do nothing if already on requested slide | |
var speed = (typeof speed === "undefined") ? this.speed : speed; | |
if (this.browser.transitions) { | |
var toStack = Math.abs(from-to) - 1, | |
direction = Math.abs(from-to) / (from-to), // 1:right -1:left | |
inBetween = []; | |
while (toStack--) inBetween.push( (to > from ? to : from) - toStack - 1 ); | |
// stack em | |
this._stack(inBetween,direction); | |
// now slide from and to in the proper direction | |
this._slide([from,to],this.width * direction,speed); | |
} | |
else { | |
this._animate(from*-this.width, to * -this.width, speed) | |
} | |
this.index = to; | |
this.callback(this.index, this.slides[this.index]); | |
}, | |
_slide: function(nums, dist, speed) { | |
var _slides = this.slides, | |
l = nums.length; | |
while(l--) { | |
this._translate(_slides[nums[l]], dist + this.cache[nums[l]], speed ? speed : 0); | |
this.cache[nums[l]] += dist; | |
} | |
}, | |
_stack: function(nums, pos) { // pos: -1:left 0:center 1:right | |
var _slides = this.slides, | |
l = nums.length, | |
dist = this.width * pos; | |
while(l--) { | |
this._translate(_slides[nums[l]], dist, 0); | |
this.cache[nums[l]] = dist; | |
} | |
}, | |
_move: function(nums, dist) { // 1:1 scrolling | |
var _slides = this.slides, | |
l = nums.length; | |
while(l--) this._translate(_slides[nums[l]], dist + this.cache[nums[l]], 0); | |
}, | |
_translate: function(elem, xval, speed) { | |
if (!elem) return; | |
var style = elem.style; | |
// set duration speed to 0 | |
style.webkitTransitionDuration = | |
style.MozTransitionDuration = | |
style.msTransitionDuration = | |
style.OTransitionDuration = | |
style.transitionDuration = speed + 'ms'; | |
// translate to given position | |
style.webkitTransform = 'translate(' + xval + 'px,0)' + 'translateZ(0)'; | |
style.msTransform = | |
style.MozTransform = | |
style.OTransform = 'translateX(' + xval + 'px)'; | |
}, | |
_animate: function(from, to, speed) { | |
var elem = this.element; | |
if (!speed) { // if not an animation, just reposition | |
elem.style.left = to + 'px'; | |
return; | |
} | |
var _this = this, | |
start = new Date(), | |
timer = setInterval(function() { | |
var timeElap = new Date() - start; | |
if (timeElap > speed) { | |
elem.style.left = to + 'px'; // callback after this line | |
if (_this.delay) _this.begin(); | |
_this.transitionEnd(_this.index, _this.slides[_this.index]); | |
clearInterval(timer); | |
return; | |
} | |
elem.style.left = (( (to - from) * (Math.floor((timeElap / speed) * 100) / 100) ) + from) + 'px'; | |
}, 4); | |
}, | |
_getElemIndex: function(elem) { | |
return parseInt(elem.getAttribute('data-index'),10); | |
} | |
}; | |
if ( window.jQuery || window.Zepto ) { | |
(function($) { | |
$.fn.Swipe = function(params) { | |
return this.each(function() { | |
var _this = $(this); | |
_this.data('Swipe', new Swipe(_this[0], params)); | |
}); | |
} | |
})( window.jQuery || window.Zepto ) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Getting the following error on line 52 when I vanilla replace the original swipe.js with this one,
Uncaught TypeError: Object [object global] has no method 'setup'