How to add swipe gesture controls to the ShiftNav Responsive Mobile Menu for WordPress

One feature that off-canvas menus sometimes have that ShiftNav does not support out of the box are swipe-to-open and swipe-to-close gestures.


The reason for this is that these touch gestures can very easily cause conflicts with themes, so there isn’t a way to do this 100% reliably for every theme. Moreover, if your site already includes a touch library, it is much more efficient to use that library in conjunction with the ShiftNav Javascript API than to include a separate touch library just for this small piece of functionality.

However, for those who would like to implement swipe gestures to open and close their menu, we provide this tutorial for installing Hammer.js, a really nice touch library, and hooking it up to ShiftNav.

Step 1. Install Hammer.js

First, you need to include the Hammer.js touch library on your site.

Note: you might wonder why include an entire touch library rather than just use native touch events directly? The reason is that touch events are still non-standard across browsers, and Hammer.js helps to unify these into a single, simple-to-use library. You can certainly just use native touch events if that’s what you prefer, but we won’t cover that here.

To keep things simple, we’ll load Hammer.js from github, but you could also install the script on your site and load it there if you prefer.

This code would go in the child theme’s functions.php, or a custom plugin:

function shiftnav_touch_gestures_load_assets(){

  //Enqueue Hammer.js
  wp_enqueue_script( 'hammer-js' ,'https://hammerjs.github.io/dist/hammer.js' , array( 'shiftnav' ), false, true );

}
add_action( 'wp_enqueue_scripts' , 'shiftnav_touch_gestures_load_assets' , 20 );

Step 2. Set up the shiftnav-touch-gestures.js file

2.1 Create the custom Javascript file

In your child theme, create a file called shiftnav-touch-gestures.js

2.2 Load the custom Javascript file

Then, in the child theme’s functions.php, modify the shiftnav_touch_gestures_load_assets() function to also include our new custom file. The complete function looks like this:

function shiftnav_touch_gestures_load_assets(){

  //Enqueue Hammer.js
  wp_enqueue_script( 'hammer-js' ,'https://hammerjs.github.io/dist/hammer.js' , array( 'shiftnav' ), false, true );

  //Get the active theme directory
  $dir = trailingslashit( get_stylesheet_directory_uri() );

  //Enqueue the custom script, which is located in the active theme directory
  wp_enqueue_script( 'shiftnav-touch-gestures-js' , $dir.'shiftnav-touch-gestures.js' , array( 'shiftnav' , 'hammer-js' ) , false , true );

}
add_action( 'wp_enqueue_scripts' , 'shiftnav_touch_gestures_load_assets' , 20 );

Note: if you’re placing the file in a subdirectory of your child theme, or in a custom plugin, adjust the $dir variable assignment as necessary

2.3 Confirm file is properly loaded

To confirm that your new Javascript file is loading on your site, add the following content inside your shiftnav-touch-gestures.js:

console.log( 'Loaded shiftnav-touch-gestures.js' );

Then load your site and open the Developer Tools console and check that the message Loaded shiftnav-touch-gestures.js is printed.

If you don’t see the message in your console, view your source and see if your new Javascript file is being properly loaded. Check the URL and that it is actually pointing to the file you created.

Step 3. Add the touch gesture listeners

Please note, for simplicity we’re going to assume a single ShiftNav instance, aligned to the left of our site. To handle multiple instances or right-aligned menus, you can use this as an example to adapt from.

Now it’s time to write the actual Javascript that will add the swipe gesture detection to our site.

We’ll need to capture two swipe events:

1. A right swipe on the body will open the menu.

2. A left swipe on the menu panel will close the menu.

So let’s set up some scaffolding using Hammer.js in our shiftnav-touch-gestures.js file:

(function($){

   // Swipe Open Hammer Instance
   // -- right swipe anywhere on the site body
   var swipeOpenTarget = document.querySelector( 'body' );
   var openHammer = new Hammer( swipeOpenTarget );
   openHammer.on( 'swiperight' , function( e ){
       console.log( 'open ShiftNav on swipe right' );
   });

   // Swipe Close Hammer Instance
   // -- left swipe on the ShiftNav Panel
   var swipeCloseTarget = document.querySelector( '.shiftnav .shiftnav-inner' );
   var closeHammer = new Hammer( swipeCloseTarget );
   closeHammer.on('swipeleft', function( e ) {
       console.log( 'close ShiftNav on swipe left' );
   });

})(jQuery);

In the above code, we set up two swipe listeners, and when the swipe gesture is detected, a message is printed to the console.

At this point, you can test the code so far by opening the site in Chrome, going to the DevTools and enabling the mobile emulation (to use touch events with your mouse), and then swipe right on the body and left on the ShiftNav Panel and checking the console output.

Step 4. Connect the touch gesture listeners to the ShiftNav API

Now, let’s replace our console.logs with the ShiftNav Javascript API function calls to our code to hook up the ShiftNav open and closing commands to the swipe events.

To open the menu, we’ll use

$( '.shiftnav-shiftnav-main' ).shiftnav( 'openShiftNav' );

To close the menu, we’ll use

$( '.shiftnav-shiftnav-main' ).shiftnav( 'closeShiftNav' );

The final shiftnav-touch-gestures.js file looks like this:

(function($){

  // Swipe Open Hammer Instance
  // -- right swipe anywhere on the site body
  var swipeOpenTarget = document.querySelector( 'body' );
  var openHammer = new Hammer( swipeOpenTarget );
  openHammer.on( 'swiperight' , function( e ){
      $( '.shiftnav-shiftnav-main' ).shiftnav( 'openShiftNav' );
  });

  // Swipe Close Hammer Instance
  // -- left swipe on the ShiftNav Panel
  var swipeCloseTarget = document.querySelector( '.shiftnav-shiftnav-main .shiftnav-inner' );
  var closeHammer = new Hammer( swipeCloseTarget );
  closeHammer.on('swipeleft', function( e ) {
      $( '.shiftnav-shiftnav-main' ).shiftnav( 'closeShiftNav' );
  });

})(jQuery);

And that’s it! Here’s our result:

Caveats

Please note that there are many themes that interfere with touch events such as these, especially the event on the body. If you try this out and it doesn’t work with your theme, that’s likely the issue. This isn’t a 100% foolproof way to implement this, unfortunately, but you may be able to attach the swiperight event elsewhere on your site, or you may need to modify the theme’s Javascript if you need to make this work.

Also note that Javascript touch is still finicky on many devices. We recommend treating swipe gestures as a nice-to-have, but you should not rely on them (make sure there is another way to open and close the menu).

Do please note that this is a customization, and not a supported feature of ShiftNav. While we offer this tutorial in the hope it’ll help you out, please understand this functionality is outside the scope of support.

Some mobile browsers use swiping from the edges of the viewport for other gesture control, and those will supersede the Javascript-based controls above.