Detect touch gestures with Hammer – Improvement for scrolling


In a previous post I introduced the Hammer library as a tool to detect touch gestures in your Mobile XPage Application (MXA?).

Add touch gestures to your page.


In the sample I demonstrated the Pan gesture. But beside Pan you have other recognizers:

The downsize with the Pan recognizer is that there is no velocity detection like in the swipe recognizer. This makes the pan recognizer less “natural”.

Angle detection and scrolling

When users scroll on their mobile devices the angle in which they scroll is never 100% vertical or horizontal. Your thumb tends to go from left bottom to right top.

So in order to avoid the swipe recognizer kicks in unnecessary you can detect the angle the gesture makes. Here are the values for angles:

  • Values are between -180 and 180:
    • 0 means RIGHT
    • -90 means UP
    • 90 means DOWN
    • 180 means LEFT

If you decide to only perform an action on vertical gestures with a deviation of an angle of 15 degrees your altered code could like as followed:

var mc = new Hammer(main);
mc.get(“swipe“).set({ direction: Hammer.DIRECTION_ALL });
mc.on(“swipe”, function(eventObject) {
if(eventObject.angle > -15 && eventObject.angle < 15){
left: width-20, opacity:1}, options);
left: “0”}, options);
if(eventObject.angle > 165 || eventObject.angle < -165){
left: “0”, opacity:1}, options);
left: -(width-20)}, options);

In this approach the user can scroll without the opening/closing of the left side menu to kick in unnecessary.

Use Hammer JS to add touch gestures to your XPage


In a previous post I demonstrated how you can apply a side panel to your interface to provide additional navigation for your application using the Bootstrap UI.

Toggle versus Swipe

The solution was basically a form of toggle, initiated from an element in your UI. For demonstration purpose we choose to include a image (hamburger menu) in the navbar logo section. The downsize of that is that you get 2 similar icons if you include Utiliy links and a click does feel less intuitive than a swipe gesture on a mobile device. 701-one_finger_swipe So what are your options?


If you search after javascript libraries fo touch or swipe gestures you will find a dozen. One famous is jQuery Mobile. But on top in my result list appears Hammer JS. While testing library examples I had one condition: it should work well with the Application Layout control from the Extension Library with the responsive layout behaviour. As it turned out, Hammer is pretty easy to integrate with this control.

Step 1 – Download the library

AMD and Dojo

In my first setup I noticed that the Hammer object was not available in the DOM. Thanks to Per Hendrik Lausten I got a quick reply on StackOverflow with a suggested solution. It turns out that AMD loading in the Hammer library conflicts with Dojo in XPages. From other posts on StackOverflow this seems to be a known problem. If you compare the number of questions regarding jQuery compared with Dojo perhaps IBM should consider to ditch this library but hurrah for backward compatibility. So in our local Hammer library we disable the AMD loading as suggested:

//if (typeof define == TYPE_FUNCTION && define.amd) { // define(function() { // return Hammer; // }); //} else if (typeof module != ‘undefined’ && module.exports) { if (typeof module != ‘undefined’ && module.exports) { module.exports = Hammer; } else { window[exportName] = Hammer; }

Step 2 – Set up your HTML structure

In my example we have 1 side panel and 1 main content section. My structure looks as followed:


The panel simply contains a number of list items:

and with a bit of CSS results as followed: panel The CSS:

.navigation { list-style: none; background: #eee; width: 200px; height: 100%; position: fixed; top: 50px; right: 0; bottom: 0; left: -200px; z-index: 0; }

So our panel is 200 pixels wide but is set at left-position -200px so we do not see it on the screen. The top-position is set to 50px which ensures it does not appear under the sticky navbar.

Main section

The main content section contains my Application Layout control from the Extension Library. You can set it up as you like. I chose a sticky navbar on the top. I filled the main column with some text and Boostrap panels. main The CSS is as followed:

.site-wrap { min-width: 100%; min-height: 100%; background-color: #fff; position: relative; top: -50px; bottom: 100%; left: 0; z-index: 1; padding: 4em; }

Step 3 – Create a Hammer instance and apply event listeners

In a scriptblock control we setup a new instance of a Hammer object, bind it to our main element (containing the Application layout control) and set event listeners for pan, tap and press gestures.

var main = document.getElementById(‘content’); var nav = document.getElementById(‘navigator’); //new instance var mc = new Hammer(main); // listen to events… mc.on(“panright”, function(ev) { = “200px”; = “0px”; }); mc.on(“panleft tap press”, function(ev) { = “0px”; = “-200px”; });

All set… go!

This is basically all you need. Include the Hammer JS and stylesheet in your resources and preview the xsp file in a browser. This is how the screen would look like when initially opened: normal   And this is how it looks like when you made a gesture to the right: open

Device emulator

While testing multiple libraries I experienced unexpected behavior in different browsers. I suggest you use a device emulator to minimize disillusion when viewing (worse: presenting) the end-result.

Animation effect

The appearance of the side panel is now pretty direct. You can easily apply some animation via jQuery.

var options = { duration: 150, easing: ‘swing’ }; mc.on(“panright”, function(ev) { $(main).animate({ left: “200”, opacity:0.4}, options); $(nav).animate({ left: “0”}, options); }); mc.on(“panleft tap press”, function(ev) { $(main).animate({ left: “0”, opacity:1}, options); $(nav).animate({ left: “-200”}, options); });


You can find a download under the following link. The NSF contains the adapted Hammer library a CSS stylesheet, an XPage and a custom control. Feel free to try and modify it and send me the results 😉