revolunet blog

web technologies for desktop and mobile

Object-oriented AngularJS Services

| Comments

Javascript prototypal inheritance can be confusing at first if you come from classical OOP languages, due to Javascript versatility, and the variety of Javascript OOP patterns available. Combined with the new service and factory concepts introduced in AngularJS, implementing OOP in your applications can lead to serious headaches, so i’ll try to show you some solutions here.

If you need a step-by-step explanation of the Javascript prototypal inheritance, you can read the great Dr. Axel Rauschmayer JavaScript inheritance by example article.

Once your app grow and your services multiply, you’ll quickly feel the need to reuse your code, and to split it in small modules to be able to separate concerns and setup some serious unit testing.

In this post, i’ll show how to create a base AngularJS service, based on the Github API, that we’ll be able to extend and reuse in different scenarios. We’ll also leverage the power of promises chaining to extend the server responses and add additional data before returning the final result.

Something important to note here is that factories are useful to define our classes that you can instantiate many times using the new keyword, while services always create singletons.

Create our base service

Our first service will be responsible of fetching Github basic user data and return the result. We’ll use a factory instead of a service, which will make it easier to instantiate many versions of the service in our application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
app.factory('SimpleGithubUser', function($http) {

    var apiUrl = 'https://api.github.com/';

    // instantiate our initial object
    var SimpleGithubUser = function(username) {
        this.username = username;
        this.profile = null;
    };

    // define the getProfile method which will fetch data
    // from GH API and *returns* a promise
    SimpleGithubUser.prototype.getProfile = function() {

        // Generally, javascript callbacks, like here the $http.get callback,
        // change the value of the "this" variable inside it
        // so we need to keep a reference to the current instance "this" :
        var self = this;

        return $http.get(apiUrl + 'users/' + this.username).then(function(response) {

            // when we get the results we store the data in user.profile
            self.profile = response.data

            // promises success should always return something in order to allow chaining
            return response;

        });
    };
    return SimpleGithubUser;
})

So we can now easily inject our factory anywhere and use it like this :

1
2
3
4
5
6
7
8
9
// we first inject our factory
app.controller('MyCtrl', function(SimpleGithubUser) {
    // instantiate a new user
    var user = new SimpleGithubUser('substack');
    // fetch data and publish on scope
    user.getProfile().then(function() {
        $scope.userLogin = user.profile.login;
    })
});

Extending the base service

Now we’d like to attach some additional data to our users. Instead of modiying the original factory, or even worse, duplicate it, we can create another factory that extends the original one, just by using the regular javascript prototypal inheritance. We’ll override some methods and use promises chaining to deliver the final data only when all the subsequent requests have been completed.

This has the advantage of encapsulating the logic inside the new service, making it easily testable while keeping your controllers light.

In this example we’ll add some data from the Github events API and attach it to the user profile before returning the final result.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// we define a new factory and inject our original service so we can extend it properly
app.factory('AdvancedGithubUser', function($http, SimpleGithubUser) {

    var apiUrl = 'https://api.github.com/';

    // create our new custom object that reuse the original object constructor
    var AdvancedGithubUser = function() {
        SimpleGithubUser.apply(this, arguments);
    };

    // reuse the original object prototype
    AdvancedGithubUser.prototype = new SimpleGithubUser();

    // define a new internal private method for this object
    function getUserEvents() {
        var self = this;
        return $http.get(apiUrl + 'users/' + this.username + '/events').then(function(response) {

            // attach the events API result to our user profile
            self.profile.events = response.data;

            // promises should always return a result
            return response;
        });
    }

    // Now let's override our original getProfile method
    AdvancedGithubUser.prototype.getProfile = function() {

        var self = this;

        // we first call the original getProfile method (aka super method)
        var originalGetProfile = SimpleGithubUser.prototype.getProfile.apply(this, arguments);

        // we use promises chaining to add additional data
        return originalGetProfile.then(function() {

            // before returning the result,
            // call our new private method and bind "this" to "self"
            // we need to do this because the method is not part of the prototype
            return getUserEvents.call(self);
        });
    };
    return AdvancedGithubUser;
});

Usage is exactly the same, except the service added the events data for us :

1
2
3
4
5
6
7
8
9
// we first inject our factory
app.controller('MyCtrl', function(AdvancedGithubUser) {
    // instantiate a new user
    var user = new AdvancedGithubUser('substack');
    // fetch data and publish on scope
    user.getProfile().then(function() {
        $scope.userEvents = user.profile.events;
    })
});

Create a service instance

Now that you have some solid factories, you can also instantiate some app-wide services that expose pre-configured instances.

1
2
3
4
5
app.service('MyUserProfile', function(AdvancedGithubUser) {
    var user = new AdvancedGithubUser('revolunet');
    user.getProfile();
    return user;
});

And use it like this :

1
2
3
4
app.controller('MyCtrl', function(MyUserProfile) {
    $scope.user = MyUserProfile;
    alert(MyUserProfile.location);
})

Final result



Hope this has been useful to you, please ask below or on twitter @revolunet for any question/suggestion :)

Unit Testing an AngularJS Directive

| Comments

In this article, i’ll detail the process to unit test the stepper directive we’ve created in the last week custom component creation article. Next week, i’ll cover how to distribute your component via GitHub and Bower.

Unit testing is the art of testing individually every smallest part of your code, which are the foundations of your apps sanity. Once correctly tested, these parts assembled together will also play nicely, as their behaviour has already been validated independently.

Unit testing helps you prevent regressions, increase quality, maintenability, and trust in your codebase, thus better team collaboration, easier refactoring… and WIN :)

Another usage is, when you get a new bug report, you add the revelant test that demo the bug, fix it in your code so the test will pass, then keep it there as a proof of reliability.

Among AngularJS best friends there is the KarmaJS test runner (A nodeJS server to launch the tests in browsers and reports the results) and the Jasmine behaviour-driven testing framework (the language to define your tests and expectations). We’ll use the grunt-karma task to integrate karma in our classic yet awesome grunt workflow and launch the tests in our browsers. Note that karma can run the tests in remote cloud browsers, for example via SauceLabs or BrowserStack.

AngularJS is made from ground-up for testing, so make yourself a favor, start NOW :)

Glossary

There are some terms that may need clarification before we go further :

  • spec : the specifications of something you want to test, consisting one or many tests suites. should cover all the expected behaviour.
  • test suite : This is a group of tests; defined within a describe block in Jasmine. blocks can be nested as much as needed.
  • test : Test instructions, that ends with one or more expectations; defined within a it block in Jasmine.
  • actual : this is the value you test in your expectation.
  • expected value : this is the value you test the actual value against.
  • matcher : A function that compares the actual and the expected values and returns a boolean success result to Jasmine. eg : toEqual, toBeGreatherThan, toHaveBeenCalledWith… you can even define your owns.
  • expectation : Use the expect function to test a value, called the actual. It is chained with a matcher function, which takes the expected value.
  • mock : a stubbed service that replace a real one at runtime with fake data/methods that you can control during your tests.

Here’s an example spec file :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// a test suite (group of tests)
describe('sample component test', function() {
    // a single test
    it('ensure addition is correct', function() {
        // sample expectation
        expect(1+1).toEqual(2);
        //                  `--- the expected value (2)
        //             `--- the matcher method (equality)
        //       `-- the actual value (2)
    });
    // another test
    it('ensure substraction is correct', function() {
        expect(1-1).toEqual(0);
    });
});

Setup the test environnement

Add grunt-karma to your project dependencies

1
npm install grunt-karma --save-dev

Create karma-unit.js file

Here is our full example. This file defines :

  • the javascript files to be loaded in the browsers for the tests. Typically, this is the libraries you use, your application files, but also the files for your tests and the eventuals mocks.
  • which browsers to run the tests against.
  • how to reports the results : console, browser… ?
  • optional plugins.

Here’s our example “files” section :

1
2
3
4
5
6
files: [
  "http://code.angularjs.org/1.2.1/angular.js",       <-- angular source
  "http://code.angularjs.org/1.2.1/angular-mocks.js", <-- angular mocks & test utils
  "src/angular-stepper.js",                           <-- our component source code
  "src/angular-stepper.spec.js"                       <-- our component test suite
]

NB: One could add jquery here if it helps you write your test code (more powerful selectors, CSS tests, size computation…)

Add the karma grunt tasks to your Gruntfile.js

1
2
3
4
5
6
7
8
9
karma: {
    unit: {
        configFile: 'karma-unit.js',
        // run karma in the background
        background: true,
        // which browsers to run the tests on
        browsers: ['Chrome', 'Firefox']
    }
}

Create angular-stepper.spec.js and paste the content of the sample test above. You can now simply run grunt karma and see your tests executing in the browsers and reporting the results in the console.

1
2
3
4
....
Chrome 33.0.1712 (Mac OS X 10.9.0): Executed 2 of 2 SUCCESS (1.65 secs / 0.004 secs)
Firefox 25.0.0 (Mac OS X 10.9): Executed 2 of 2 SUCCESS (2.085 secs / 0.006 secs)
TOTAL: 4 SUCCESS

Each dot represent a successfull test and you can see our two tests runs in the two browsers we’ve configured before in our karma-unit.js file. woot !

Now let’s code the real tests :)

Code our directive unit tests

Our component unit test suite, aka the spec should cover all the expected behaviour of our component, but also test the edge cases (eg : invalid input, unexpected server behaviours…)

Below you can see an extract of our angular-stepper component test suite (angular-stepper.spec.js), and here’s the full spec. Our tests for such a component are quite simple, no need for mocks here. The only tricky thing is that we wrap our directive inside a form to be able to test that it plays well with ngModelController and updates form validity correctly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// the describe keyword is used to define a test suite (group of tests)
describe('rnStepper directive', function() {

    // we declare some global vars to be used in the tests
    var elm,        // our directive jqLite element
        scope;      // the scope where our directive is inserted

    // load the modules we want to test
    beforeEach(module('revolunet.stepper'));

    // before each test, creates a new fresh scope
    // the inject function interest is to make use of the angularJS
    // dependency injection to get some other services in our test
    // here we need $rootScope to create a new scope
    beforeEach(inject(function($rootScope, $compile) {
        scope = $rootScope.$new();
        scope.testModel = 42;
    }));

    function compileDirective(tpl) {
        // function to compile a fresh directive with the given template, or a default one
        // compile the tpl with the $rootScope created above
        // wrap our directive inside a form to be able to test
        // that our form integration works well (via ngModelController)
        // our directive instance is then put in the global 'elm' variable for further tests
        if (!tpl) tpl = '<div rn-stepper ng-model="testModel"></div></form>';
        tpl = '<form name="form">' + tpl + '</tpl>';
        // inject allows you to use AngularJS dependency injection
        // to retrieve and use other services
        inject(function($compile) {
            var form = $compile(tpl)(scope);
            elm = form.find('div');
        });
        // $digest is necessary to finalize the directive generation
        scope.$digest();
    }

    describe('initialisation', function() {
        // before each test in this block, generates a fresh directive
        beforeEach(function() {
            compileDirective();
        });
        // a single test example, check the produced DOM
        it('should produce 2 buttons and a div', function() {
            expect(elm.find('button').length).toEqual(2);
            expect(elm.find('div').length).toEqual(1);
        });
        it('should check validity on init', function() {
            expect(scope.form.$valid).toBeTruthy();
        });
    });

    it('should update form validity initialy', function() {
        // test with a min attribute that is out of bounds
        // first set the min value
        scope.testMin = 45;
        // then produce our directive using it
        compileDirective('<div rn-stepper min="testMin" ng-model="testModel"></div>');
        // this should impact the form validity
        expect(scope.form.$valid).toBeFalsy();
    });

    it('decrease button should be disabled when min reached', function() {
        // test the initial button status
        compileDirective('<div rn-stepper min="40" ng-model="testModel"></div>');
        expect(elm.find('button').attr('disabled')).not.toBeDefined();
        // update the scope model value
        scope.testModel = 40;
        // force model change propagation
        scope.$digest();
        // validate it has updated the button status
        expect(elm.find('button').attr('disabled')).toEqual('disabled');
    });
    // and many others...
});

Some notes :

  • A directive needs to be compiled in a given scope to be tested
  • A non-isolated scope can be acceded via element.scope()
  • An isolated scope can be acceded via element.isolateScope()

Why to we have to call scope.$digest() when we change a model value in the tests ?

In a real angular app, the $digest is automatically triggered by the framework in reaction to various events (clicks, inputs, requests…). There’s no such user-based events during the automated tests so we just need to force the $digest. (the $digest is what update all the bindings).

Bonus #1: real time tests

Thanks to grunt, we can make the tests run when the source changes and be alerted in real time.

If you want the tests to be run on each code change, just add a section to your watch task :

1
2
3
4
js: {
    files: ['src/*.js'],
    tasks: ['karma:unit:run', 'build']
},

You could update your default grunt task like this

1
grunt.registerTask('default', ['karma:unit', 'connect', 'watch']);

Now, just run grunt and you’ll get real-time tests and a builtin webserver :)

Bonus #2: add code coverage reporting

As developers, we love solid metrics; and we also love continous improvements. “coverage” refers to the code coverage of your test suite; It gives you metrics and detailed info to increase your code coverage without pain.

Here’s a sample coverage HTML report :

We can see, for each folder and file, how much code is covered by our test suite. And this is updated in real-time thanks to grunt+karma integration. For each file, we can see line by line which blocks stays untested, which makes writing the remaining tests more straightforward.

100% test coverage doesnt mean your code is bug-free, but it increase quality for sure !

Its really easy to integrate this in our karma+grunt setup. Karma has a “plugin” system that allows you to plug the fantastic Istanbul code coverage tool so we just need to configure the karma-unit.js file and we’re done :)

Add coverage to karma

1
2
# add the necessary node_modules
npm install karma-coverage --save-dev

now update the karma config file with these new settings :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// here we specify which of the files we want to appear in the coverage report
preprocessors: {
    'src/angular-stepper.js': ['coverage']
},
// add the coverage plugin
plugins: [ 'karma-jasmine', 'karma-firefox-launcher', 'karma-chrome-launcher', 'karma-coverage'],
// add coverage to reporters
reporters: ['dots', 'coverage'],
// tell karma how you want the coverage results
coverageReporter: {
  type : 'html',
  // where to store the report
  dir : 'coverage/'
}

More coverage config options here : https://github.com/karma-runner/karma-coverage

You now need to run your tests again to generate your first report. It should be located in the project root “coverage” folder.

Feel free to comment/ask below :)

Next week, we’ll talk about distributing our now well tested directive on Github and Bower :)

Create a Reusable AngularJS Input Form Component

| Comments

One of the beauty of the AngularJS framework is its ability to isolate complexity with services and directives; This is perfect for segmenting our code, create very testable components, and make them reusable. A directive, which is an anticipation of the future web components, is a piece of isolated javascript, HTML and CSS that encapsulate a specific behaviour and that you can easily reuse in various apps. Once created, a directive is simply invoked by adding it to the DOM via a HTML tag (<accordion></accordion>, or a custom attribute <div accordion></div>, or a CSS class <div class="accordion"></div> (and even as HTML comment).

In this tutorial we’ll go through the creation of a custom stepper directive that can be used as a reusable input component in your applications. We’ll cover the classic directive creation but also the input validation, and the use of the ngModelController, that will allow a seamless integration with any form, leveraging the existing AngularJS forms superpowers. The next part will cover the test suites with Jasmine and KarmaJS, and the publication and distribution of our widget with GitHub and bower.

For this example we’ll build a custom numeric input widget, named “rn-stepper”. We’ll use the last AngularJS 1.2 that brings some important fixes to the private scopes management (capital point for reusable components). The full widget code is available on github as a reusable component and you can see the final result here :



Markup generation

The first step is to create a naïve directive that build our markup, and renders correctly. We just declare the directive name, and template to use.

1
2
3
4
5
6
7
8
9
10
11
12
13
// we declare a module name for our projet, and its dependencies (none)
angular.module('revolunet.stepper', [])
// declare our naïve directive
.directive('rnStepper', function() {
    return {
        // can be used as attribute or element
        restrict: 'AE',
        // which markup this directive generates
        template: '<button>-</button>' +
                  '<div>0</div>' +
                  '<button>+</button>'
    };
});

Now, to use our directive, its quite straightforward :

  • declare our revolunet.stepper module as one of our app dependencies
  • use <div rn-stepper></div> (attribute form) or simply <rn-stepper></rn-stepper> (element form). to integrate the directive somewhere.

The attribute form is better if you want to support IE8 as it works out-of-the-box.

demo : http://jsfiddle.net/revolunet/n4JHg/

Add internal behaviour

Now we need to add behaviour and internal variables to our custom component. We’ll declare a “private scope” that will hold internal variables and functions, and add the link function to our directive, which is responsible of initialising the component behaviour just after the markup has been inserted in the final page.

Here’s the updated directive code :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.directive('rnStepper', function() {
    return {
        restrict: 'AE',
        // declare the directive scope as private (and empty)
        scope: {},
        // add behaviour to our buttons and use a variable value
        template: '<button ng-click="decrement()">-</button>' +
                  '<div></div>' +
                  '<button ng-click="increment()">+</button>',
        // this function is called on each rn-stepper instance initialisation
        // we just declare what we need in the above template
        link: function(scope, iElement, iAttrs) {
            scope.value = 0;
            scope.increment = function() {
                scope.value++;
            }
            scope.decrement = function() {
                scope.value--;
            }
        }
    };
});

We now have a functionnal component with an isolated code and template.

demo : http://jsfiddle.net/revolunet/A92Aw/

Communicate with the external world

Our component works great but it would be more useful if it could control a real public variable, known as a ngModel in AngularJS.

Let’s add a databinding between our component internal value and the outer world (our application).

We just need to update our scope declaration like this :

1
2
3
scope: {
    value: '=ngModel'
}

This will automagically bind our internal value variable to the external one declared in the ngModel attribute. The = means “double data-binding” which means if ngModel is updated externally then the internal value will be updated, and vice-versa.

Say my app expose a rating variable, we could now bind it to our component simply like this :

1
<div rn-stepper ng-model="rating"></div>

demo : http://jsfiddle.net/revolunet/9e7Hy/

Make our component form-friendly

We now have a dynamic input that can manipulate arbitrary ngModel data. We need to modify a bit the code to make it play nice with the AngularJS forms. For example, AngularJS forms and input generally expose a $pristine and $dirty state which can be useful in many situation. To make the forms aware of our model changes from inside our component, we need to make use of the ngModelController.$render and ngModelController.$setViewValue API methods, which are available as soon as you “require” a ngModel on your directive.

The ngModelController.$render method is a method which you should override yourself in the directive and is responsible of updating the view; it will be called by the framework when the external ngModel changes. When the model changes, the framework executes the $formatters pipeline which is responsible of eventually converting the $modelValue raw value to a usable $viewValue.

For example, if your model is a real Date object, you’d want your input to display it as dd/mm/YY. The model-to-view conversion is made by the $formatters pipeline and the view-to-model by the $parsers pipeline. Once you get a ngModelController instance, you can easily insert new items in these pipelines.

The ngModelController.$setViewValue method should always be called when you want update a model from your directive (view). It takes care of calling the eventual $parsers pipeline. Then it applies the final value to the internal $modelValue, update the input $dirty state, update the optional parent form $dirty state and call any registered $viewChangeListeners. Here’s the full code for this function.

As pointed by a comment from @ThomasBelin4 below, we don’t need anymore to have a scope value variable, as we now have a reference to the original ngModelController which holds a reference to the viewValue.

Here’s how we update the directive declaration :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
.directive('rnStepper', function() {
    return {
        // restrict and template attributes are the same as before.
        // we don't need anymore to bind the value to the external ngModel
        // as we require its controller and thus can access it directly
        scope: {},
        // the 'require' property says we need a ngModel attribute in the declaration.
        // this require makes a 4th argument available in the link function below
        require: 'ngModel',
        // the ngModelController attribute is an instance of an ngModelController
        // for our current ngModel.
        // if we had required multiple directives in the require attribute, this 4th
        // argument would give us an array of controllers.
        link: function(scope, iElement, iAttrs, ngModelController) {
            // we can now use our ngModelController builtin methods
            // that do the heavy-lifting for us

            // when model change, update our view (just update the div content)
            ngModelController.$render = function() {
                iElement.find('div').text(ngModelController.$viewValue);
            };

            // update the model then the view
            function updateModel(offset) {
                // call $parsers pipeline then update $modelValue
                ngModelController.$setViewValue(ngModelController.$viewValue + offset);
                // update the local view
                ngModelController.$render();
            }

            // update the value when user clicks the buttons
            scope.decrement = function() {
                updateModel(-1);
            };
            scope.increment = function() {
                updateModel(+1);
            };
        }
    };
});

demo : http://jsfiddle.net/revolunet/s4gm6/

Add min/max attributes

Now our component is form-friendly, so let’s as some builtin validation rules.

We could add optional min/max attributes to our component, which will handle the form validation by himself when they are present. These attributes will be data-bound so they can be updated at any time by the application (some other inputs in a form may impact the min/max here).

The ngModelController API gives us also a $setValidity method that can inform the parent forms about our component validity, and automatically add some handy CSS classes related to validity to out form and inputs.

We just need to call ngModelController.$setValidity('outOfBounds', false) to make our input, and thus parent forms invalids, and have ng-invalid and ng-invalid-out-of-bound CSS classes added to our forms and to our component.

Our stepper component is now full functionnal and integrates seamlessly in any form.

demo: http://jsfiddle.net/revolunet/HCUNC/

Prevent invalid input

Another nice-to-have feature would be to prevent the user from entering invalid data, which means disabling the buttons when the internal value reach the min/max limits. This could be achieved in two ways :

  • BAD : manually in our link function, toggling our buttons states on each click.
  • GOOD : automagically, using a builtin ng-disabled directive in our template, that will disable the buttons under some conditions.

The second option is much more Angular-ish and there are several ways to achieve this so let’s see how we can do.

We can add ng-disabled="isOverMin()" to our first button template and add a scope.isOverMin function that returns a boolean indicating if we should disable or not the given button. same with overMax that would check if the max has been reached or not.

Our template is now :

1
2
3
<button ng-disabled="isOverMin()" ng-click="decrement()">-</button>
<div>{{ value }}</div>
<button ng-disabled="isOverMax()" ng-click="increment()">+</button>

demo : http://jsfiddle.net/revolunet/26ghx/

The next part will detail the tests suite and distribution subjects over github and bower.

Stay tuned :) and feel free to comment/ask below !

Universal .htaccess CORS Support

| Comments

What is CORS

In the internet AJAX early days (~2000) browsers vendors implemented a strict cross-domain communication policy that prevented javascript on a given page to communicate with third party domains. Many workarounds have been implemented since, like JSONP, which is only a ‘hack’ allowing cross-domain communication using javascirpt callbacks; Handy, but this prevents any other method than GET and forces the use of querystring to pass parameters.

With the RISE of internet APIs and decentralised services, having a way to communicate with 3rd party domain became critical; thus, the W3C defined the CORS protocol, acronym which stands for “Cross-Origin Resource Sharing” and allows different domains to communicate together, the same way Adobe Flash did it a long time before with the crossdomain.xml policy (remember?).

Now with CORS, the server defines which domains (applications) can communicate with him (or anyone). When CORS is enabled on the server, your javascript can communicate transparently using any HTTP method; For non-GET requests, the browser transparently make an initial OPTIONS request to check if the request is allowed or not, and then makes the real request.

CORS-enable your API

You can find the whole specs and various implementations at enable-cors.org.

Pain-free CORS for Apache servers

If you don’t want to change your code, we’ve crafted a small .htaccess for you that will force CORS on your API, without even touching your code. Just drop one of the implementations in your .htaccess and your API is magically CORS-enabled :)

Note: If you use the withCredentials version, be sure to add withCredentials: true in your AJAX requests.

You can validate your API CORS support using this demo : http://embed.plnkr.co/1E8ot9e1eVs23IrjzqKr/preview

Hope this helps !

Extending the Topcoat CSS Framework

| Comments

Introduction

Topcoat.io is the new kid on the block of the CSS-only frameworks. It’s the first one that’s built for performance from the ground up, thanks to the constant performance tracking using Chrome telemetry, which makes it a tool of choice to build your mobile applications UI.It is also easy to theme and customize thanks to a smart CSS organisation and a powerful toolchain.

Topcoat has been built for the future, thanks to solid conventions and a cutting-edge javascript architecture, and more goodness :

It’s fully open source, not “fauxpen source”, and the contributors uses various online tools to run the project :

  • Github of course for code and issues
  • codepen.io to prototype and host widgets demos
  • huboard to manage milestones on top of Github issues

All of this make it a powerful framework made to be extensible and performant.

Install Topcoat

Just download the latest release from github and extract it. The release contains the final CSS with dark and light themes for desktop and mobile, so you can use then directly; just add a link to the topcoat-mobile-light.min.css file in your app for example.

If you want to customize the themes or add new components, you need to run npm install from the topcoat folder. This will download all the widgets sources and local dependencies to your node_modules folder.

Some important things to notice :

  • Each component (button, list, checkbox…) has its own folder in the node_modules subfolder (so each one has its own npm repo). Each one also has its own gruntfile in case you want to build its css separately.
  • Most of components have a topcoat-[COMPONENT]-base folder with just enough CSS to completely reset the styling of the element, so other components can override it entirely. For example the default button hasn’t any default border or background and looks like a simple text block;
  • The topcoat-theme folder defines the 4 builtin Topcoat themes which are just a combination of variables that defines some variations of the components.
  • The main Gruntfile list the available themes and associated widgets using pattern globbing and this is from where the final CSS are built, including the given widgets.

Adding a custom theme

You can easily tweak the builtin themes by modifying the variables inside the topcoat-theme folder then run grunt to rebuild the final CSS. But its much better to add your own theme and leave the others untouched.

Let’s add a simple green theme :

  • copy the topcoat-theme/src/theme-topcoat-* file from the theme that matches the most your design, eg copy theme-topcoat-mobile-light.styl to theme-green.styl.
  • create a variables-green.styl with a bunch of variables that override the default ones (see the list of variables in the other variables-* files). For example :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// base colors
var-color = #00b400
var-background-color = #e2ffe2
var-placeholder-color--input = #4eff4e
var-background-color--down = #00b400
var-background-color--hover = #02ff01
var-border--focus = 1px solid #00b400
var-box-shadow--focus = 0 0 0 2px #00b400

// cta button colors
var-background-color--cta = #00b300
var-border--cta = 1px solid #006700
var-background-color--cta--down = #00b400
var-background-color--cta--hover = #02ff01
  • add @import variables-green to your theme-green.styl. (This allows you later to combine some variables files)
  • add the theme link in the main gruntfile, ‘stylus’ section:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
stylus: {
    green: {
        options: {
            import: ['theme-green', 'utils']
        },
        files: [{
            src: [
                // here you can eventually add/remove some components from the output
                'node_modules/topcoat-*/src/**/*.styl'
                ],
            dest: 'css/topcoat-green.css'
        }]
    }
}
  • Now run grunt and you’ll see your final topcoat-green.css and topcoat-green.min.css appear magically in the CSS folder :)
  • You also have a demo/topcoat-green.html file for free that show you the final result, generated via TopDoc.

Add a custom component

Now, let’s say you want to add a custom button to the generated theme, for example button-round.

Add a node_modules/topcoat-button-round folder and create src/topcoat-button-round.styl file. Inside, add your round button definition, with the documentation to generate the demo :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// import anything you need to extend
@import topcoat-button
/* topdoc
  name: Round Button
  description: A simple, yet round button
  modifiers:
    :active: Round button active state
    :disabled: Disabled state
    :hover: Hover state
    :focus: Focused
  markup:
    <button class="topcoat-button--round">Button</button>
    <button class="topcoat-button--round" disabled>Button</button>
  tags:
    - desktop
    - light
    - mobile
    - button
    - round
*/
.topcoat-button--round {
    @extend .topcoat-button
    border-radius: 999px;
}

.topcoat-button--round:disabled {
  @extend .topcoat-button:disabled
}

.topcoat-button--round:hover {
  @extend .topcoat-button:hover
  text-shadow: var-text-shadow;
  box-shadow: var-box-shadow;
}

.topcoat-button--round:focus {
  @extend .topcoat-button:focus
}

.topcoat-button--round:active {
    color: var-color;
    text-shadow: var-text-shadow;
    background-color: var-background-color--down;
    box-shadow: var-box-shadow--down;
}

Now, when you’ll run grunt again, the final CSS will include your button definition and the demo/topcoat-green.html demo page will present your new button with related documentation.

Creating new Topcoat components

Now you know how to add custom components and integrate them in the Topcoat workflow properly.

If you’re willing to share new components with the community (and you should), here’s the workflow :

  • demo your component markup and css on codepen.io
  • create a github repo for your component, using the same structure as any of the node_modules/topcoat-* folder.
  • if accepted, your component will be added to the main Topcoat package.json then auto-installed with npm install.

Need help ?

Comment below, use Github issues or join the #topcoat irc channel to discuss :)

I hope this quick intro will help you choose Topcoat as your next CSS framework and you will contribute to the project so we can build together a better CSS framework.

Phonegap Day Amsterdam 2013

| Comments

Once again, i’ve been lucky enough to go to Amsterdam today to attend the Phonegap Europe annual conference.

The venue was great, the talks covered various subjects, and, most importantly, the atmosphere reflected a positive and healthy community : open-minded and confident in the open web as a major platform for the future of mobile applications.

Almost 2 years after Adobe took control of Nitobi (the team behind the Phonegap genesis), the Phonegap project is in a great shape, dynamic, more open than ever, and with a sane and solid codebase, powered by node.js and a modern javascript toolchain, thanks to the hard work of the core team and many contributors.

With the 3.0 version, released a few weeks ago, Phonegap is now mature and flexible enough to serve as a foundation for your various mobile projects. Every single plugin has been extracted from codebase, which is now focused on bridging performance and plugin management.

Phonegap is the perfect example of how open source can increase code quality and grow a solid community while serving a company business.

Here is a quick recap of the most notable talks.

Distimo

Distimo is an app-analytic company that analyses app downloads, conversions and profits and compute smart data for the app developers.

They shared some interesting metrics :

  • 33% of worlwide app revenues comes from Asia.
  • Globally, ~65% of revenues comes from the AppStore and ~35% from Play Store (growing fast).
  • Candy Crush saga makes as much money in Asia on both iOS or Android
  • Games of course dominates stores revenues

More data at : http://www.distimo.com/publications

Untappd

Demo of one of the most successfull Phonegap apps : Untappd, a beautiful beer-centered social network app with 700k users and 4 stars rating. Join now !

Blackberry loves the web

Too late maybe ?

Native UI in Phonegap Apps

Tanaka Masahiro demoed the Monaca hybrid framework which gives you the ability to add native UI elements to your Phonegap app. You can wrap the phonegap webview with native tabbar/navigation bar to improve your UX, specially revelant on older Android devices. The framework also allows native transitions between various webviews, but this breaks application state. The framework hasn’t yet migrated to phonegap 3.0 so not usable as is IMHO.

Interesting real hybrid approach that demonstrates again that Phonegap is not necessarly a “full web” solution, but you can use as much “native” stuff as needed.

Apple phonegap apps rejection prevention

Rob Lauer from kendoui shared his experiences about mobile web apps rejection reasons on the Apple Store.

Here’s a bunch of common best practices to prevent your Phonegap app to be rejected :

  • Make an app, not a website
  • Create unique and useful apps
  • Don’t use annoying ads
  • User registration shouldn’t be mandatory (at least a free demo access)
  • Don’t force users to validate CGU
  • Never tag your app version lower to 1.0
  • Should work offline with minimal features
  • Don’t load remote code that change your app behaviour
  • Use beautiful, homogenous icons
  • Write accurate app description
  • Don’t try to steal Apple money, use in-app payments or die instantly

Topcoat.io

Kristofer Joseph, original TopCoat author, talked about this beautiful and slick CSS framework focused on performance and themability.

TopCoat.io provides various widgets as pure HTML/CSS and, most importantly, provides the best technical stack ever to extend it cleanly :

Another great example of a successful project, open-sourced from day one and following the best practices from the ground up.

TopCoat is definitely shaped for the future and you can already use it in your Phonegap projects !

Check out @devgirlfl article & demo : http://devgirl.org/2013/08/29/totally-rad-topcoat

WizCorp HTML5 gaming

Yes you can build great games with Phonegap. You don’t necessarly draw directly inside the webview, but as phonegap is very open and extensible, you can easily plug native features as needed, like Ejecta (off browser canvas+audio for iOS), webGL views… WizCorp team shares some interesting code on their github, like a native spinner, navigation views helper…

Chrome Cordova plugins

This may be the biggest announce of this event : We can now use Chrome APIs right in our cordova applications. For the moment, we just have socket, storage, notifications, and identity (oauth), but in a near future, we’ll see support for syncFileSystem (synced data across devices) and more.

Basically, this means that you can code a Chrome Packaged App using only chrome APIs, then distribute it on desktop via the chrome store and then on mobile app stores using cordova !

This is very early stage but Google puts some efforts to stabilize and extend capabilities quickly.

All Chrome javascript APIs : http://developer.chrome.com/apps/api_index.html

Cordova implemented APIs can be found at : http://plugins.cordova.io

Testing with appium.io

Fil Maj demonstrated appium, an open source end-to-end testing platform that fully support phonegap applications. You can write automation scripts (think selenium) then run them on your own devices, or use appium infrastructure to run the tests on various devices and produces detailed reported.

In a world of such devices fragmentation, this can be very useful :)

Firefox OS

Phonegap now also support Firefox OS ;) and Firefox provides many more javascript APIs, like ‘Activites’ (think Web intents). If you support the real open web, Mozilla is definitely the way to go :)

Phonegap CLI

This awesome talk by Michael Brooks was the most interesting and technical talk of the day. Michael showed us how powerful the cordova and phonegap CLI are. Based on a cutting edge javascript architecture, the phonegap CLI is made of nodes modules that you can use directly in the CLI, or as external nodeJS modules, which allows you to integrate the whole workflow in third-party tools and vice-versa. open source power :)

He also demonstrated how easy it is to create and compile apps with or without the locally installed SDKs, using phonegap build as a fallback. Just run for example phonegap compile ios from your machine, then in seconds you get back a QRcode that you can scan to test your final app on a real device instantly; neat !

Finally, a big thanks to Colene, Peter Paul Koch and all the Phonegap team for this event, can’t wait for next year :)

Npm vs Pip

| Comments

After my morning twitter rant about npm install > pip install i need to add some clarifications and explain why i meant. Basically i meant that npm is much easier to use from a user perspective, which is an essential point to grow a community. Package management and dependencies is an important part of modern application development workflow and thus needs high consideration.

npm (node packaged modules) was released at end of 2011 and for sure it’s inspired from many other packages manager while removing their commons hassles. Also, its used both on backend and on frontend projects (eg: AngularJS+grunt).

Some of the pip hassles are :

  • you need to install virtualenv separately
  • you need to configure it and run cryptic commands to activate virtualenvs
  • you can install virtualenvwrapper to make thing easier though
  • you still need to configure it though
  • a fresh pip install in a project containing the standard requirements.txt does nothing

On the other side, npm is a no-brainer to use :

  • npm install installs/upgrades any project dependencies
  • there’s no notion of virtualenv, it just uses what you have in the current node_modules folder or in your global install.

Both are for sure very powerful tools that goes far beyond this basic usage but this is daily work for the developer and also the first contact when entering a new project so it should work seamlessly.

Please correct me if i’m wrong :)

AngularJS Tips’n’tricks Part 2

| Comments

Here’s a new batch of AngularJS tips and gotchas; If you didn’t read it yet, you can check the part 1 and feel free to comment below :)

Access an element scope from outside

This is useful for debugging: in your Chrome console, highlight a node in the Elements tab, then, in the console, to check its scope :

1
angular.element($0).scope();

or even :

1
angular.element(document.getElementById('elementId')).scope();

The Batarang Chrome Extension is much powerful and let you inspect any scope, anywhere :)

Unwatch an expression

Sometimes you want to watch an expression only a few times, and then forget it. The $watch function returns a callback just for that. You just have to execute it back to destruct the watcher.

1
2
3
4
5
6
7
var watcher = $scope.$watch('data.counter', function(newValue, oldValue) {
    iElement.css('width', 50 * newValue + 'px');
    if (newValue >= 10) {
        // autodestruction when data.counter reaches 10
        watcher();
    }
});

Group elements in a select

If you play with selects, the ng-options directive is quite powerful and has many syntaxes.

For example you can easily group a model by attribute to have a nested select menu :

1
<select ng-options="distrib.version group by distrib.name for distrib in distribs"></select>

Of course, just add an ng-model directive to your select to data-bind it to one of the values.

Filter falsy values

You can’t use the builtin filter for falsy attributes or values :/ I don’t know if this is a bug of feature, but a simple workaround is to use a custom filter function that you can expose on the scope. (you can also define your own filter).

1
2
3
4
$scope.testValues = ['a', 'b', 'c', false, true, 0, -1, 5, 42];
$scope.isFalsy = function(val) {
  return !val;
}
1
2
3
4
5
{{ testValues|filter:true }}        //  [true]
{{ testValues|filter:5 }}           //  [5]
{{ testValues|filter:0 }}           //  ['a', 'b', 'c', false, true, 0, -1, 5, 42]
{{ testValues|filter:false }}       //  ['a', 'b', 'c', false, true, 0, -1, 5, 42]
{{ testValues|filter:isFalsy }}     //  [false, 0]

Filter on objects

The builtin filter function is quite powerful and allows you to filter a list of objects on given properties only, or on everything, exactly or not, negated or not, etc…

1
2
3
4
5
{{ games|filter:'street' }}                       //  all games containing "street" in any property
{{ games|filter:'!street' }}                      //  all games NOT containing "street" in any property
{{ games|filter:{name:'street'} }}                //  all games containing "street" in their name
{{ games|filter:{name:'street'}:true }}           //  all games named exactly "street"
{{ games|filter:{name:'street', device:'PS3'} }}  //  all games containing "street" in their name and PS3 in their device

ng-repeat with duplicate items

If for some reason you need to have duplicate items in your ng-repeat you can extend your ng-repeat expression with track by $index and it works :)

Directive : parse attribute without watching it

In one of your directive, if you need to have a read-only access to an attribute model, but without the automatic watch/binding, you can simply use & instead of = when declaring the binding in the scope. You’ll then be able to access the model value . (this may break in future releases). This is a shortcut for using the $parse service on the current scope.

1
2
3
4
5
6
7
8
9
10
11
12
app.directive('rnCounter', function() {
  return {
    scope: {
      count: '&rnCounter'
    },
    link:function(scope, iElement) {
      iElement.bind('click', function() {
        console.dir(scope.count());
      })
    }
  }
})

Data-binding to a boolean

You can bind to a boolean value, but you can’t update that value from your directive.

This won’t work :

1
<div rn-zippy status="true"></div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
app.directive('rnZippy', function() {
  return {
    restrict: 'A',
    scope: {
      status: '=?'
    },
    link: function(scope, iElement) {
      function toggle () {
        scope.$apply(function() {
          scope.status = !scope.status;
        });
      }
      iElement.bind('click', toggle);
    }
  }
})

You need to use a real model, OR, initialise a new one and use it as your model instead :

1
<div rn-zippy ng-init="status=true" status="status"></div>

Includes onload

You can trigger a callback when your ng-include partial is loaded :

1
<div ng-inlude="'partials/' + page + '.html'" onload="callback()"></div>

For the ngView, you need to listen to the $viewContentLoaded event.

Express testing

You know you should write serious tests suites ? There’s everything to help you in AngularJS with Karma test runner + Jasmine.

Once you have many tests, they can take some time to execute and there’s a little trick to speed you up : you can limit the test-runner to a given test group by using ddescribe instead of describe and to a single test with iit instead of it.

That’s awesome to focus on specific tests for a while.

Service decorators

You can easily decorate and modify any existing service or directive. That’s how the ngMobile overrides the ngClick directive to handle transparently the FastClick behaviour.

Here’s an exemple that overrides the $sniffer service and fix the animation detection for older androids devices (landed in ef5bc6c) :

1
2
3
4
5
6
7
8
9
app.config(['$provide', function ($provide) {
  $provide.decorator('$sniffer', ['$delegate', function ($delegate) {
    if (!$delegate.transitions||!$delegate.animations) {
      $delegate.transitions = (typeof document.body.style.webkitTransition=== 'string');
      $delegate.animations = (typeof document.body.style.webkitAnimation === 'string');
    }
    return $delegate;
  }]);
}]);

That’s all for today, feel free to ask and comment below :)

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.