During development of recent project, I have had to realize a JavaScript solution that will detect when a visitor swipes the page and then perform an action based on the swipe direction and distance.

Of course this is not a new challenge and many solutions have already been found. jQuery mobile ships with a built in swipe event but I did not require such an extensive framework and decided to write the cleanest answer that solved the problem.

Below you will find the source code to a jQuery plugin I call "Swipe.JS", which provides the same swipe event to any DOM node.

Usage

First I will show how to use the plugin. Multiple swipe events can be bound to different nodes but for the sake of example, we will use the "body".

$("body").swipe(function( direction, offset ) {
  console.log( "Moving", direction.x, "and", direction.y );
  console.log( "Touch moved by", offset.x, "horizontally and", offset.y, "vertically" );    
});

Swipe.JS console output

Discussion

I have not released this code as an official plugin because I believe that although a good example, it serves my needs very precisely and would not be a great fit for other projects. For example, the direction argument in the callback gives "left", "right", "top" or "bottom" as values, this could be easily calculated from the secondary offset argument by checking if the values were negative or not instead.

I have also included mouse in the event bindings as I need this code to function on a desktop if the user drags their mouse. This is probably unnecessary for most mobile developers and is inefficient, so feel free to remove this from the code.

Source

$(function() {
  $.fn.swipe = function( callback ) {
    var touchDown = false,
      originalPosition = null,
      $el = $( this );

    function swipeInfo( event ) {
      var x = event.originalEvent.pageX,
        y = event.originalEvent.pageY,
        dx, dy;

      dx = ( x > originalPosition.x ) ? "right" : "left";
      dy = ( y > originalPosition.y ) ? "down" : "up";

      return {
        direction: {
          x: dx,
          y: dy
        },
        offset: {
          x: x - originalPosition.x,
          y: originalPosition.y - y
        }
      };
    }

    $el.on( "touchstart mousedown", function ( event ) {
      touchDown = true;
      originalPosition = {
        x: event.originalEvent.pageX,
        y: event.originalEvent.pageY
      };
    } );

    $el.on( "touchend mouseup", function () {
      touchDown = false;
      originalPosition = null;
    } );

    $el.on( "touchmove mousemove", function ( event ) {
      if ( !touchDown ) { return;}
      var info = swipeInfo( event );
      callback( info.direction, info.offset );
    } );

    return true;
  };
});