revolunet blog

web technologies for desktop and mobile

Learn AngularJS in 5 Steps

| Comments

I’ve seen some developers quite shy about AngularJS when confronted to all the magical powers; don’t be afraid, AngularJS indeed introduces several new concepts but you can get them in just a few weeks of practice… The Google team is working hard to lower the Angular entry barrier and to make everything as simple as possible for developers.

AngularJS is a new disruptive innovation in the Javascript frameworks world and it prefigures the future of web browsers : templates, data-binding, web components…

In this post i’ll give some advices for the AngularJS newbies and share with you the best pointers to learn and understand the core concepts quickly.

First, to understand AngularJS you of course need to know a bit of Javascript. If you’re not comfortable enough yet, pick a free book on JSbooks and practice.

If you have a jQuery background, you absolutely need to read this in-depth Stack Overflow answer : How to think in AngularJS if i have a jQuery background. Just imagine the productivity boost you’ll get when you won’t need to maintain the DOM anymore :)

To sum up key features of AngularJS :

  • Templates : Your templates lives right in the DOM. Forget mustache, handlebars, hogan…
  • Two-way data-binding : Your javascript data automagically updates your DOM and vice-versa.
  • Routing : Define routes, associate templates and controller in just a few lines.
  • Forms : Many helpers to help dealing with forms, one of the worst webdevs nightmare.
  • Directives : Encapsulates templates and code in reusable components easily.
  • Testability : AngularJS was designed in a way your web app can be fully testable.
  • Animation : Easily animate elements and views.

Here are 5 steps to boost your AngularJS skills right now :

  1. follow the official tutorial and the dev guide.
  2. watch the awesome egghead.io video series. they’re 3mins each only :)
  3. watch the 60mins AngularJS fundamentals video
  4. read the code of some great AngularJS app examples.
  5. read as many times as needed the nuances of scope prototypal inheritance

Of course, dont just watch/read, you need to experiment every step :)

After that, you should have a pretty good understanding of the framework and be able to angularize all the things :)

Need help ? Ask your questions in the comments below, or on IRC #angularjs channel, or on the dedicated google group.

BTW, if you read French, great ressources here : frangular.com and Thierry Lau’s introduction slides.

Need more ressources ?

GoogleIO 2013 Keynote Recap

| Comments

So today was the opening of the 2013 GoogleIO developer conference in San Francisco and the Googlers announced a insanely crazy amount of new projects/services/features in just the first few hours, which is very exciting for every web/android developer. The next three days will be very busy, with a lot of focus on Chrome, Android and Google+.

Though, we don’t have new Nexus devices, no Android 4.3, and no Javascript AppEngine runtime. So huge fail on my previous predictions.

The keynote started with a big fail demo effect happened in the very first demo about Android multiplayer gaming when demoing a new Google Cloud Messaging feature, quite embarassing, but then everything ran smoothly.

Here’s a little recap of the most important things announced just during the 3 hours keynote :

Android

  • Google cloud messaging : can now be used in a bidirectionnal way, and apps can now also store data in the cloud and sync it across devices (scores, leaderboards…).
  • Google Game Services platform to help game developers with new APIs
  • Samsung Galaxy S4 will be available in June on Google Play with standard Android build and unlocked bootloader ! 649$ though but without that ugly, messy, shitty Samsung overlay.
  • Android studio to replace Eclipse nightmare, finally ! good move !
  • Unified and synced notifications between devices.
  • Translation service for apps, better analytics…
  • Enhanced maps API

Google Music

  • Access to all the music for 9.99$/month
  • Discover to new recommended songs with google suggestions
  • Google powered radio feature based on what you like

Chrome / Web

  • 750 millions active chrome users globally
  • WebP and VP9 royalty-free compression standards for images and videos to increase speed specially on mobile devices.
  • Google provides a free (deactivable) proxy for Android to improve speed based on this codecs.
  • New payment autocomplete API will help process payments quickly on websites, specially useful on mobile (2 clicks payments)
  • Google will finally release a rock solid UI framework based on web components standards : polymer-project.org . I wonder how it will fit with AngularJS.
  • V8 will integrate asm.js to improve Javascript performance.

Google +

  • New interface :)
  • Better Hangouts
  • Unified notifications across devices
  • Better pictures management, event an ‘auto awesome’ mode :)

Maps

  • iPad version this summer
  • Brand new Google maps, with new design, more space for content, and builtin 3D thanks to WebGL

Gmail

In other news

Anything missed ?

You can still watch the full keynote on Youtube of course.

Making of the Angular-carousel

| Comments

Our first real life experiment with AngularJS is a mobile and touch-friendly carousel directive.

As this project shed some lights on various AngularJS aspects, we’d like to share it with you; The full demo+code is available here : http://blog.revolunet.com/angular-carousel

The goal is to transform any ng-repeat directive into a carousel, just by adding the rn-carousel attribute to its ul container. The directive take care of the dirty work for you, without any jQuery.

Here’s a very basic example of a Youtube API call, with the data displayed in a regular Angular template; We just add a rn-carousel attribute to the ul element to ask a carousel :)



This rn-carousel directive is responsible of :

1) wrapping the real ul/li in a carousel container and add CSS classes

We first wrap the original ul block in an outer div using JQlite wraps method during the directive link phase. This cannot be doneduring the compile phase as it would lead to an infinite recursion loop. (AngularJS will wrap again an again as the original directive stays untouched).

Then we add some CSS classes and an unique carousel identifier class so we can target that instance easily later.

The CSS makes the ul/li block appears as a single horizontal line composed of many li blocks, so its very easy to slide the blocks horizontally.

2) watching the ng-repeat expression

Because we want to monitor precisely the items in our carousel, and we want to be able to dynamically add/remove items, we need to extract and watch the original ng-repeat expression. We can then watch that expression and then be notified when its updated. This is useful to know how many slides we have and update our indicators accordingly for example.

This extraction is done by literally parsing the ng-repeat expression in a generic way, using the generated normalized comment node. Credits goes to @bennadel for this awesome trick.

Update : I ended up with just extracting the li ng-repeat attribute during the compile phase which is much less overhead.

3) binding touch and click events

Like most directives, we bind events in the linking phase. We just take care of binding both touch and mouse events.

1
2
3
4
// bind events
container.bind('mousedown touchstart', swipeStart);
container.bind('mousemove touchmove', swipe);
container.bind('mouseup touchend', swipeEnd);

4) animating the slides smoothly

When we detect a touchstart we just store the initial event position. On touchemove we update the horizontal offset and move the whole ul accordingly using CSS. Then on touchend, we detect the desired position (prev or next) and dynamically add CSS styles and classes to move the slides accordingly, or restore the current position in some cases.

The slide movement is made thanks to the CSS transition and translate3d properties to force CSS 3D transforms and thus animate the slides using the GPU which make the movement much more smooth especially on mobile devices.

1
2
3
4
5
6
7
8
// the offset value is simply : desiredSlideIndex * slideWidth
carousel.css({
    '-webkit-transform': 'translate3d(' + offset + 'px,0,0)',
    '-moz-transform': 'translate3d(' + offset + 'px,0,0)',
    '-ms-transform': 'translate3d(' + offset + 'px,0,0)',
    '-o-transform': 'translate3d(' + offset + 'px,0,0)',
    'transform': 'translate3d(' + offset + 'px,0,0)'
});

5) adding an indicator to our carousel

As we already watch the ng-repeat expression, we track the number of slides in the carousel and so its quite easy to add data-bound indicators to our carousel. You can enable these by adding a rn-carousel-indicator="true" attribute on your ul.

The indicators are produced by the rn-carousel-indicators directive, completely decoupled, during the linking phase. For the directive to be executed, we compile it through the $compile service before appending it to our container.

It just takes items and index attributes that will be injected in an isolated scope to produce the indicators and set the CSS classes.

1
2
3
4
5
6
7
8
9
10
11
// enable carousel indicator
var showIndicator = (iAttrs['rnCarouselIndicator']==='true');
if (showIndicator) {
    // as the HTML contains a directive, we need to $compile it
    // before appending it to our container
    var indicator = $compile("<div id='" + carouselId +"-indicator' " +
        " index='carouselIndex' items='carouselItems' rn-carousel-indicators " +
        " class='rn-carousel-indicator'></div>"
    )(scope);
    container.append(indicator);
}

6) offer a two-way data binding for the active slide index

The carousel current index position can be data-bound to an optional rn-carousel-index attribute if provided. This allows you to display the carousel position somewhere else, add custom controls/indicators, initialise to a different slide…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// set initial position at first slide
scope.carouselIndex = 0;

if (iAttrs.rnCarouselIndex) {
    //  if a binding attribute is present, use it.
    var activeModel = $parse(iAttrs['rnCarouselIndex']);
    scope.$watch('carouselIndex', function(newValue) {
        // when the carousel internal index changes, update the model
        activeModel.assign(scope.$parent, newValue);
    });
    scope.$parent.$watch($parse(iAttrs.rnCarouselIndex), function(newValue) {
        // when the model change, update the local position
        // this is also useful for the initial position
        scope.carouselIndex = newValue;
        updateSlidePosition();
    });
} else {
    // if no index attribute, just watch internal index and update display
    scope.$watch('carouselIndex', function(newValue) {
        updateSlidePosition();
    });
}

The updateSlidePosition() function simply moves the ul block based on the carouselIndex value and the width of the slides. We do this with CSS transition and translate3d so this is animated and hardware accelerated.

7) tests and grunt automation

These subjects will have a dedicated article soon :)

Limitations

  • Only works with ul/li structure
  • Carousel dimensions is based on the first li detected

UPDATE : the carousel can now be buffered to improve performance with large datasets !

Easy isn’t it ?

If you have questions, suggestions, issues, pulls requests… just comment below or on Github :)

AngularJS Tips’n’tricks Part 1

| Comments

In the past few months we learned a lot of new AngularJS stuff. Here is a first bunch of tricks, please comment and help us improve theses exemples if your tricks are even more awesome :)

We compiled most of our best AngularJS ressources in a gist and we maintain a list of related twitter accounts here : https://twitter.com/revolunet/angularjs.

Scopes

You definitely need to read this article : http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs

Directives

The official documentation is not crystal clear at first approach but it documents most of what you need to understand: http://docs.angularjs.org/guide/directive. So read it. And again. And again.

Watch an object or a list

If you watch a list or an object with the objectEquality parameter not set, then the $watch callback won’t be triggered if the object is only updated partially. Setting it to true will trigger it on any modification; this has performance impact so use carefully.

1
2
3
4
// the last `true` means compare by value and not by ref, useful for nested objects :)
$scope.$watch('myConfig', function(newValue, oldValue) {
    console.log('myConfig changed !', newValue);
}, true)

Two way data binding attribute without explicit scope declaration.

Sometimes you need to access a directive attribute with a two-way data binding without declaring it explicitely in the directive scope configuration. You can do this using the $parse service.

If your directive scope is isolated (scope: {}) you have to use scope.$parent instead of scope.



Use a callback function with arguments in your directive

To call a function defined in one of your attribute, declare it in the scope with &.

If you need to pass arguments, you must execute the callback using an object form for the arguments. AngularJS then call the function with your arguments in the correct order comparing your object and the callback declaration.

The following example also demonstrates how to watch multiples values at once.



Custom transclusion

This example shows how to define a custom transclusion function and modify its scope.



Announcer/Notifier pattern

If you need to listen to DOM objects creation/deletion, you can simply create a ‘notifier’ directive and an ‘announcer’ directive that you’ll add to the objects you want to monitor. That directive will announce new instances creation (link called) and destruction (scope.$destroy called).

It can be useful if you want to monitor arbitrary objects lifecycles, for example a ng-repeat. The ‘announcement’ can be made via events, or better, using a custom notifier controller. All credits goes to @garanajpr for the ideas.



Many more tricks to come, stay tuned :)

Using AngularJS Views Animations for Mobile Applications

| Comments

AngularJS team recently added the very expected animation feature to their framework. You can have a great overview with the Miško Hevery introduction video and a complete overview article at the great Year of Moo blog.

From now (AngularJS 1.1.4), you can easily animate any directive, just by adding an ng-animate attribute and defining the animation CSS class.

UPDATE : AngularJS team fixed the following problem in the last 1.1.5 release. The ng-animate will now be evaulated on each animation, Yahoo :)

As a mobile web developer, the first thing that come to mind is animating your mobile applications views. Its quite easy to add slide-in effects with the current routing system :



As you can see, the code is very simple code and the animation is always the same (appear from right). But typically, if you open a screen in your mobile application, and there is a ‘Back’ button, the user expects the slide animation to be reversed when he touches it. If you don’t do this, you expose your users to an unexpected behaviour, and an akward #WTF moment.

With the actual AngularJS implementation, there is a problem with the ng-view directive, which is heavily used for the AngularJS routing : it doesn’t handle dynamic ng-animate directive at all, despite what says the doc. You can only set the enter and leave animation once, because these are set at linking time in case of the ng-view. And thus, you can only have one pre-defined enter and leave animation for your application view and for the whole application lifecycle.

There are a few issues opened and we can hope the team must be working on it and that should be resolved some day.

But an easy workaround to achieve this is to act on the enter and leave CSS classes themselves directly. Instead of changing the CSS classes names at the DOM level, one could update the CSS classes definitions to achieve the same result without even touching the DOM. The ng-view directive still has the same enter and leave CSS classes names and instead we change theses classes definition, and thus the animation direction.

There are several ways to do this. We could dynamically add a stylesheet to the document, or change the stylesheet source using ng-src attribute but this wouldn’t be very efficient due to multiple downloads of the ressource.

But, as we are AngularJS powered, we could simply bind a style tag to a javascript variable so it can be updated dynamically like any other DOM element.

Here’s how we’ve done bi-directionnal animations for the ng-view. Note the usage of the ng-bind-html-unsafe that take cares of not escaping the CSS output and the use of transition and transform CSS properties to force the use of GPU and improve the animation smoothness, especially on mobile devices.



Another clever solution, as pointed out by Andrej in the comments below, is to simply wrap the ng-view in another div that have a dynamic class name, which could change when we need to change the animation direction, like LR then RL. This way we just need to update that classname and the CSS will pick the good one.

1
2
3
4
.LR .enter-setup {...}
.LR .leave-setup {...}
.RL .enter-setup {...}
.RL .leave-setup {...}

Octopress Cheat Sheet

| Comments

When you switch to Octopress for blogging there are a very few things to know :

Command line

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# create a new post
rake new_post['Title of the post']

# create a new page 
rake new_page['Title of the page']

# preview your work
rake preview

# publish it
rake generate && rake deploy

# commit and backup(automatic message)
git commit -am "`date`" && git push origin source

Creating a post

You can create a post just by adding a .markdown file in the source/_posts folder and preview it with rake preview. The name of the file will be your post url so use an appropriate slugified name.

You must add some metas at the top of the file :

1
2
3
4
5
6
7
8
9
---
layout: post
title: My Awesome article.
date: 2013-05-1 00:00
categories: news technology web
author: Super Man
comments: true
published: false
---

If you set published: false, your posts will only be visible in preview mode.

Publish

When ready, just use rake generate && rake deploy to publish it :)

Here’s a micro script to simplify the publish process, jsut put it in the blog root folder :

1
2
3
4
5
#!/bin/sh
# push.sh : publish & commit with a single command
git add source
git commit -am "`date`" && git push origin source
rake generate && rake deploy

A Fresh Start

| Comments

Our good old WordPress blog has been shutdown since a few months and now its time for us to start a brand new blogging adventure with OctoPress. As expected, we’ll talk about Web technologies, Rich web applications, Javascript, Python and Phonegap among others.

We’ve got so many stories to tell, so many tips to share and so much code to dissect, so stay tuned.

140 chars isn’t long enough.

1
console.log('Welcome :)');