Skip to content

Instantly share code, notes, and snippets.

@mathiasbynens
Created April 22, 2011 08:06
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save mathiasbynens/936253 to your computer and use it in GitHub Desktop.
Save mathiasbynens/936253 to your computer and use it in GitHub Desktop.
Improved swipe gestures plugin for jQuery

Improved swipe gestures plugin for jQuery

What was changed (compared to the original v0.1.2):

  • Don’t modify the default settings internally.
  • Merge the options recursively (deep copy) so that the custom threshold values actually get used.
  • Allow overriding the options globally through $.fn.swipe.options.
  • Use namespaced jQuery events (using the swipe namespace) instead of DOM2 addEventListener to prevent errors in old IEs.
  • Simplified and optimized code.
  • Changed swipeLeft and swipeRight functions to be called within the context of the bound element. Thanks, @kswedberg!

Mathias

/*
* jSwipe - jQuery Plugin
* http://plugins.jquery.com/project/swipe
* http://ryanscherf.com/demos/swipe/
*
* Copyright (c) 2009 Ryan Scherf <http://ryanscherf.com/>
* Modified by Mathias Bynens <http://mathiasbynens.be/>
* Modified by Karl Swedberg <http://learningjquery.com/>
* Licensed under the MIT license
*
* $Date: 2011-05-25 (Wed, 25 May 2011) $
* $version: 0.2.2
*
* This jQuery plugin will work on any device that supports touch events,
* while degrading gracefully (without throwing errors) on others.
*/
(function($) {
$.fn.swipe = function(options) {
// Default thresholds & swipe functions
options = $.extend(true, {}, $.fn.swipe.options, options);
return this.each(function() {
var self = this,
originalCoord = { 'x': 0, 'y': 0 },
finalCoord = { 'x': 0, 'y': 0 };
// Screen touched, store the initial coordinates
function touchStart(event) {
var touch = event.originalEvent.targetTouches[0];
originalCoord.x = touch.pageX;
originalCoord.y = touch.pageY;
}
// Store coordinates as finger is swiping
function touchMove(event) {
var touch = event.originalEvent.targetTouches[0];
finalCoord.x = touch.pageX; // Updated X,Y coordinates
finalCoord.y = touch.pageY;
event.preventDefault();
}
// Done swiping
// Swipe should only be on X axis, ignore if swipe on Y axis
// Calculate if the swipe was left or right
function touchEnd() {
var changeY = originalCoord.y - finalCoord.y,
changeX,
threshold = options.threshold,
y = threshold.y,
x = threshold.x;
if (changeY < y && changeY > (- y)) {
changeX = originalCoord.x - finalCoord.x;
if (changeX > x) {
options.swipeLeft.call(self);
} else if (changeX < (- x)) {
options.swipeRight.call(self);
}
}
}
// Swipe was canceled
function touchCancel() {
//console.log('Canceling swipe gesture…')
}
// Add gestures to all swipable areas
$(self).bind({
'touchstart.swipe': touchStart,
'touchmove.swipe': touchMove,
'touchend.swipe': touchEnd,
'touchcancel.swipe': touchCancel
});
});
};
$.fn.swipe.options = {
'threshold': {
'x': 30,
'y': 10
},
'swipeLeft': function() {
alert('swiped left');
},
'swipeRight': function() {
alert('swiped right');
}
};
}(jQuery));
/*
* jSwipe - jQuery Plugin
* http://plugins.jquery.com/project/swipe
* http://www.ryanscherf.com/demos/swipe/
*
* Copyright (c) 2009 Ryan Scherf (www.ryanscherf.com)
* Licensed under the MIT license
*
* $Date: 2009-07-14 (Tue, 14 Jul 2009) $
* $version: 0.1.2
*
* This jQuery plugin will only run on devices running Mobile Safari
* on iPhone or iPod Touch devices running iPhone OS 2.0 or later.
* http://developer.apple.com/iphone/library/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html#//apple_ref/doc/uid/TP40006511-SW5
*/
(function($) {
$.fn.swipe = function(options) {
// Default thresholds & swipe functions
var defaults = {
threshold: {
x: 30,
y: 10
},
swipeLeft: function() { alert('swiped left') },
swipeRight: function() { alert('swiped right') }
};
var options = $.extend(defaults, options);
if (!this) return false;
return this.each(function() {
var me = $(this)
// Private variables for each element
var originalCoord = { x: 0, y: 0 }
var finalCoord = { x: 0, y: 0 }
// Screen touched, store the original coordinate
function touchStart(event) {
//console.log('Starting swipe gesture...')
originalCoord.x = event.targetTouches[0].pageX
originalCoord.y = event.targetTouches[0].pageY
}
// Store coordinates as finger is swiping
function touchMove(event) {
event.preventDefault();
finalCoord.x = event.targetTouches[0].pageX // Updated X,Y coordinates
finalCoord.y = event.targetTouches[0].pageY
}
// Done Swiping
// Swipe should only be on X axis, ignore if swipe on Y axis
// Calculate if the swipe was left or right
function touchEnd(event) {
//console.log('Ending swipe gesture...')
var changeY = originalCoord.y - finalCoord.y
if(changeY < defaults.threshold.y && changeY > (defaults.threshold.y*-1)) {
changeX = originalCoord.x - finalCoord.x
if(changeX > defaults.threshold.x) {
defaults.swipeLeft()
}
if(changeX < (defaults.threshold.x*-1)) {
defaults.swipeRight()
}
}
}
// Swipe was started
function touchStart(event) {
//console.log('Starting swipe gesture...')
originalCoord.x = event.targetTouches[0].pageX
originalCoord.y = event.targetTouches[0].pageY
finalCoord.x = originalCoord.x
finalCoord.y = originalCoord.y
}
// Swipe was canceled
function touchCancel(event) {
//console.log('Canceling swipe gesture...')
}
// Add gestures to all swipable areas
this.addEventListener("touchstart", touchStart, false);
this.addEventListener("touchmove", touchMove, false);
this.addEventListener("touchend", touchEnd, false);
this.addEventListener("touchcancel", touchCancel, false);
});
};
})(jQuery);
@mathiasbynens
Copy link
Author

If backwards compatibility with pre-1.4 jQueries is a concern, just replace the following lines:

$(this).bind({
    'touchstart.swipe': touchStart,
    'touchmove.swipe': touchMove,
    'touchend.swipe': touchEnd,
    'touchcancel.swipe': touchCancel
});

With:

$(this)
    .bind('touchstart.swipe', touchStart)
    .bind('touchmove.swipe', touchMove)
    .bind('touchend.swipe', touchEnd)
    .bind('touchcancel.swipe', touchCancel);

Copy link

ghost commented Apr 25, 2011

I think you accidentally omitted the event argument in the touchStart and touchMove functions.

@mathiasbynens
Copy link
Author

@kitcambridge Actually, that was intentional. This way it’s just using the global event object. Is it better to keep it as an argument?

Copy link

ghost commented Apr 25, 2011

@mathiasbynens As far as I know, the global event object is only available in Internet Explorer and recent versions of WebKit...

@mathiasbynens
Copy link
Author

@kitcambridge Yeah, but the same goes for touch events, no?

Update: Thanks for pointing this out! I hadn’t considered other mobile browsers with touch events support. (Opera Mobile doesn’t support them, but I don’t know about other non-IE or WebKit browsers, for example.) Probably best to just add the argument, just to be safe. Thanks!

Note to self: the jQuery-normalized event object lacks the targetTouches object, so it’s necessary to use event.originalEvent.targetTouches. Extending jQuery.event.props by using jQuery.event.props.push('targetTouches') is another option, but I’d rather not have jQuery copy the targetTouches object for every single element out there for performance reasons.

Copy link

ghost commented Apr 25, 2011

@mathiasbynens Interesting, I didn't know about the global touch event objects. Apparently, more browsers implement event than I thought… Thanks for fixing that, though!

@vitalyrotari
Copy link

Just leave this here: https://gist.github.com/4044976 ;)

@elevateweb
Copy link

Thanks for the script

I found the left and right were firing for me on slight touch. So I added a distance option in so the user has to do more of a definitive swipe.

https://gist.github.com/4555026

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