Blog of Appliness
Zepto and Touch Gestures

This tutorial is featured in the free July issue of Appliness.
Download it on your tablet (iPad or Android).
Every month, you’ll find free technical tutorials in Appliness about web application developement. If you have to suggest ideas, if you want to contribute writing articles, feel free to contact us using the feedback form !
Zepto and Touch Gestures
Recently, I wanted to reproduce the behavior of the iOS pictures gallery in a PhoneGap application. I took this opportunity to start playing with Zepto and its touch gestures plugin. In the end, I developed an application that is very responsive and performs like a native app.
What is Zepto?
Zepto is a JavaScript micro-framework that targets modern browsers. A lot of JavaScript libraries, such as JQuery, were created before the rise of smartphones. Because WebKit is a standard in the mobile space, Zepto focuses primarily on this engine. Thomas Fuchs, the author of Zepto.js, explained at the JSConf 2011 event in Portland why he believes in JavaScript frameworks and why proprietary features, such as CSS selectors, are awesome:
//select all li elements with both “just” and “testing”classnames
document.querySelectorAll(li.just.testing)
// how many paragraphs?
document.querySelectorAll(p).length
// select even paragraphs
document.querySelectorAll(p:nth-child(2n+1))CSS selectors are very useful, but so is JSON manipulation:
JSON.stringify({ s: a string, n: 123, d: new Date})
JSON.parse({“some”:”json”,”test”:123})And Array iteration:
[1,2,3].forEach(alert);
[].slice.apply(nodelist).forEach( function(element){
alert(element.innerHTML); } );No more loops required. So that’s great, but why use Zepto and not Prototype, jQuery, or other frameworks? First, Fuchs notes that some functionalities are not supported or not meaningful on mobile devices. In addition, more code results in longer download and initialization times. Most of the downloaded code isn’t even used (for example, the code that is included to support IE6 will never be used on a mobile device). Zepto reduces code size as much as possible to minimize download and initialization time. It provides an easy-to-use API that mimics jQuery, and many developers already know jQuery. Zepto can also be extended with the jQuery plug-in mechanism. It doesn’t cover the entire jQuery API, but most of it. The minified version of Zepto.JS is super small; it is just 8K, compared to jQuery at 100K.
So Zepto is awesome for hybrid apps (combined with PhoneGap for instance). Another advantage for mobile app developers is that the source code is clear and concise because it just targets WebKit. As a result the community can easily extend the framework, and that’s just what Tom Longo did in creating Flickable.JS, a Zepto plugin to enable touch gestures on any HTML element of your app.
What is Flickable?
Flickable extends Zepto to handle complex touch interactions. Each element of your DOM becomes touchable thanks to this plugin, and you can easily slide elements around the page thanks to hardware accelerated CSS transitions. The integration is very lightweight. You just need to define a <DIV> wrapper element that will contain a Flickable wrapper DIV element.
The only constraint is that you need to indicate the number of segments by calling the flickable() method; for example:
$(‘#flickable_wrapper’).flickable({segments:3}The plugin simply calculates the width of each segment by dividing the flickable_wrapper width by the number of segments specified (which means that you need to use segments that have the same width). And that’s it, you can move your flickable_wrapper around with your finger and the plugin will automatically snap the nearest segment once you lift your finger. It will imitate the classic behavior of a smartphone picture gallery.
You can play with the complete list of complex touch events: onStart, onMove, onScroll, onScrollPrev (when an element snaps to the previous segment), onScrollNext, onFlick (a quick swipe with your finger), onFlickLeft, onFlickRight, onFlickUp, onFlickDown, and onEnd.
Most events include the event data object which is structured like so:
eventData = {
// Starting touchpoint [x pos, y pos, timestamp]
start: {x:0, y:0, time: 0},
delta: {
// Previous touchpoint
prevPos: {x:0, y:0},
// Distance relative to original touchpoint
dist: {x:0, y:0},
// Direction of touch
// [-1 left/up, +1 right/down, 0 no movement]
dir: {x:0, y:0}
},
end: {
// Duration of touch
duration: 0,
// Speed of movement along x and y axis
speed: {x:0, y:0},
// +1/-1 if the touch was deemed to
// be a flick left/right up/down
flick: {x:0, y:0}
}
}Building the iOS menu
Just for fun, I wanted to try to reproduce the iOS menu, specifically the one that displays icons at the bottom of the screen when you double tap the hardware button. To navigate through the menu, you have to swipe left and swipe right. It’s a perfect example to show the performance of Flickable. Here is my interactive sample:
You can test this sample with a touch device here: http://riagora.com/mobile/zepto/basic.html
The sample is showcased at the 47th second.
As you can see, it’s super responsive and the framework distinguishes between a tap and a swipe event without any problem.
The structure of the HTML page is very straightforward. As I mentioned above, you have to declare a wrapper (the visible area), which is #menuWrapper in this case, and the Flickable DIV, which is #menu. I’ve implemented just two segments, and each segment displays three icons.
<body class=”bodyMain”>
<div id=”menuWrapper”>
<div id=”menu”>
<div class=”icons” id=”icons1”>
<img src=”menuiOS/icon1.png” name=”dictionnary” class=”imgIcon”/>
<img src=”menuiOS/icon2.png” name=”facebook” class=”imgIcon”/>
<img src=”menuiOS/icon3.png” name=”maps” class=”imgIcon”/>
</div>
<div class=”icons” id=”icons2”>
<img src=”menuiOS/icon4.png” name=”photoshop” class=”imgIcon”/>
<img src=”menuiOS/icon5.png” name=”mouse” class=”imgIcon”/>
<img src=”menuiOS/icon6.png” name=”settings” class=”imgIcon”/>
</div>
</div>
</div>
<div id=”help”>
Swipe left and swipe right to test this iOS-like menu.
<br/>Tap an icon to get the name of the app.
</div>
<div id=”app-name”>
</div>
</body>Once the structure is declared, you can import both Zepto and Flickable JavaScript libraries and use Zepto to initialize the Flickable element. As you can see, Zepto uses the jQuery syntax. The tap method must be used on touch screens to catch the tap events on your elements. This code will only work on touch screens! That said, you can use Modernizr to create a fallback mechanism and catch classic click events. But again, I am using Zepto to target smartphones, so in this case I don’t care about mouse events.
<script src=”zepto.min.js”></script>
<script src=”zepto.flickable.min.js”></script>
<script type=”text/javascript”>
$(document).ready(function()
{
$(‘#menu’).flickable({segments:2});
$(‘#menu img’).tap(function(){
//alert(‘You just tapped “’+$(this).attr(‘name’)+’”’);
$(‘#app-name’).text(‘You just tapped “’+$(this).attr(‘name’)+’”’);
});
});
</script>One call of the flickable() method and it works!!! Magic? Well you also need to declare some properties in the CSS. The wrapper must have a hidden overflow:
#menuWrapper {
width: 464px;
height: 130px;
overflow: hidden;
background: #DDDDDD;
background-image:url(menuiOS/iosBackground.png);
padding:0;
}And the width of the Flickable element (#menu) must be the sum of all the segments:
#menu {
width: 938px;
height: 150px;
}Flickable uses CSS 3D transformations that are hardware accelerated; that’s why the experience is so smooth. It also uses pure touch events to overcome the 300ms limitation of classic click events and improve responsiveness.
Playing cards
To take things one step further, I’ve extended an official Flickable sample to create a cool navigation. It could be used to navigate an employee directory. You can swipe to navigate through employees but also tap on a card to flip it and read more information about the employee. Christophe Coenraets (who is the master of the Employee Directory application) should appreciate this sample. Here is the sample. Swipe left, swipe right, and tap on a card to flip it over.
You can test the sample in your mobile browser here:
http://riagora.com/mobile/zepto/indexMustache.html
The sample is showcased at the 58th second.
ADDING (SLOWER) navigation buttons
As you can see, I have navigation buttons in the interface. My PREV and NEXT buttons are just images. When the document is “ready”, you can listen for click events and call the flickable() method with ‘scrollNext’ or ‘scrollPrev’ as parameters.
$(document).ready(function()
{
$(‘.next’).click(function() { $(‘#demo1’).flickable(‘scrollNext’);});
$(‘.prev’).click(function() { $(‘#demo1’).flickable(‘scrollPrev’);});
});
…
<div class=”navigationBar”>
<img src=”pics/prev.png” width=”85” height=”44” class=”prev”/>
<img src=”pics/next.png” width=”85” height=”44” class=”next”/>
</div>}I’ve left click events on intentionally so that you can feel the difference between a tap and a click event. The click event is not as responsive because the browser will wait for 300ms before firing the transition to the next card. This is because the browser wants to make sure that you don’t want to “double click” an element. If you never use double tap events in your interface, you can bypass this limitation. There are numerous articles on the web, including some on the Google developers website, that explain how to enable “fast clicks”.
FLIPPING the cards
To enable the card flip, you must use CSS 3D transition and manage two states: .front and .back. Both sides, front and back, are overlaid. To hide the back side, rotate it 180 degrees on the Y axis:
.back {
color: #fff;
-webkit-transform: rotateY(180deg) translate3d(0,0,0);
background: url(pics/background3.png);
background-size:232px 232px;
}Also, specify that if an element is rotated 180°, then it should become invisible. This can be done with the webkit-backface-visibility property:
background: #fff;
position: absolute;
top: 0;
left: 0;
margin: 0;
-webkit-backface-visibility: hidden;
}Then you can declare a CSS transition:
@-webkit-keyframes cardflipped {
from { -webkit-transform: rotateY(0deg) translate3d(0,0,0); }
to { -webkit-transform: rotateY(180deg) translate3d(0,0,0); }
}And assign this transition to a CSS style such as “flipped”:
.card.flipped {
-webkit-animation-name: cardflipped;
}Now you can use Zepto to call the Flickable library (as in the previous sample) and indicate that when the user taps a card, it should assign (or unassign) the flipped style to the front and the back of a card. This can be achieved with the classic toggleClass method introduced with jQuery, and made available in Zepto.
$(document).ready(function()
{
$(‘#demo1’).flickable({segments:3});
$(‘.front, .back’).tap(function() {
var el = $(this).parent();
el.toggleClass(‘flipped’)
});
}Cleaning UP your HTML code with templates AND Mustache
As you can imagine, the HTML code to define a segment (a card) is not as simple as in my previous sample where I just had to display images. In this case, I need to get information about employees, using JSON for instance, and I have to dynamically create the cards. HTML templates are justified in this case, and I’ve chosen to use Mustache.js, another micro-framework. If you want to know more about Mustache, read Christophe’s tutorial on it in this issue.
So if you check the final source code of this project, you’ll find three parts:
- the data, which is a JSON object.
- the definition of the template, which is a string that combines HTML code and Mustache elements. In the JSON structure, I have authors objects. To loop on authors, I use {{#authors}} … {{/authors}}. Then I can use authors properties such as the firstName: <div class=”nameDisplay”>{{firstName}}</div>.
- the Mustache call and initialization. Once the document is ready, you can call Mustache to parse your data, replace all the {{elements}} with text extracted from the data and then use Zepto to inject the string in your DOM:
$(document).ready(function()
{
var html = Mustache.to_html(tpl, json);
$(‘#demo1’).html(html);
}Here is the complete JavaScript code for this example:
$(document).ready(function()
{
var html = Mustache.to_html(tpl, json);
$(‘#demo1’).html(html);
$(‘#demo1’).flickable({segments:3});
$(‘.front, .back’).tap(function() {
var el = $(this).parent();
el.toggleClass(‘flipped’)
});
$(‘.next’).click(function() { $(‘#demo1’).flickable(‘scrollNext’);});
$(‘.prev’).click(function() { $(‘#demo1’).flickable(‘scrollPrev’);});
});Ten lines of code!!! Ho my, I love micro-frameworks. If you want to discover more micro-frameworks, visit this website: http://microjs.com/
get the source code
Review and download the source code of this article on github:
https://github.com/michaelchaize/appliness/tree/master/zepto-flickable-sample
Discuss and exchange about this article with the Appliness community experts:
http://www.appliness.com/forums/topic/zepto-and-touch-gestures/
Comments
Powered by Facebook Comments






