Diving into AngularJS

by Andy Appleton

This weekend I’ve had some spare time and I’ve used it to take a proper look at AngularJS. I’ve used Backbone a lot and find myself defaulting to it as soon as a JavaScript application gets complicated. I realised that I was ignoring everything else because I already know Backbone and that’s not a good place to be. Time to jump into something new.

When all you have is a hammer…

Initially I downloaded the Angular source and launched into trying to build something simple with it but I found this a really frustrating experience. I consider myself a pretty competent JS developer but nothing really worked and the concepts didn’t click. Making me feel stupid is a quick way to turn me off of something.

I took a step back and realised that I was trying so hard to shoehorn what I knew about MVC from Rails and Backbone into the app that I wasn’t letting myself see the bigger picture. I spent an hour watching and coding along with a tutorial video and by the end felt I really understood the basics. Just by investing a small amount of time into learning the fundamentals I’m now really productive with Angular. Making me feel smart is a great way to keep me interested in something!

In less than a day I’ve come to love the declarative nature of the code I’m writing. Everything is so terse and I’m spending zero time writing what I would now consider boilerplate DOM manipulation or event binding code. This is really exciting coming from a world of manual template rendering and zombie events and I love not having to think about that stuff.

Conventions

I listened to an interview with Chad Fowler this week. He spoke about how Rails is not necessarily the best web framework but it offers such a strong set of conventions and has such a strong community that it really allows you to forget about hooking an app together and just focus on the product you’re trying to build.

I feel like Angular offers the same level of convention and I’m really looking forward to getting stuck into a bigger project with it. I don’t want to spend my time writing glue code, clearing up old views, manually re-rendering templates on data change or writing form input handlers. I know there are libraries to handle these things in Backbone, but I also don’t want to be depending on 20 plugins just to get a functioning app.

Step back

These are just my initial thoughts after playing with the framework for a day and maybe I’ll change my mind after I’ve used it more extensively but right now I’m loving Angular and can’t see myself choosing Backbone the next time I start a big front end JS project.

If you’re looking to get started with Angular I’d recommend you check out the following resources:

  • Dan Whalin’s video tutorial really helped me to get the fundamentals of Angular.
  • egghead.io is a great collection of screencasts covering some more specific cases.
  • The AngularJS project homepage (although the docs are not that beginner friendly).

Responsive Web Design is not a war

by Andy Appleton

Recently there’s been a bit of a furore around a post written after we at GoCardless launched our redesigned homepages. I wanted to make a few points – to be clear these are my thoughts, and they’re not necessarily shared by my colleagues.

Responsive Web Design is not always appropriate

Elliot Jay Stocks says “the war has not yet been won”. I think that’s a rather black and white way to look at a much more nuanced issue and that painting it as a war is not especially helpful. As with everything on the web there’s degrees of appropriateness.

In a lot of cases, a well thought out responsive site is awesome. A great example would be a blog (go on, resize the window on this page). In other cases though it’s totally ill-suited.

Take the example of the GoCardless homepage. There’s a fair amount of information here and not everyone wants to see all of it. By setting a small screen’s zoom level to 100% and inlining all of the content we’re forcing the user to scroll (and scroll and scroll) through potentially useless information. In my opinion it’s much better to provide a high level overview and let the user zoom into the interesting sections.

I appreciate that Elliot is arguing that it’s not all about mobile but honestly which device are you using that has a very narrow screen but can’t zoom and pan?

Let’s look at GoCardless on an iPhone as an example:

RWD comparison

Which is a better experience? Which gives the user a quicker understanding of what’s happening?

I think online maps are a good analogy. You wouldn’t open Google Maps, zoom in as far as possible and then start panning around to find the area you want to look at. Instead you look at the overview, pan around until you’re in broadly the right place and then start to focus in.

In many cases, especially marketing and homepages, this is how I would like to use websites on a mobile device and I bet I’m not alone.

Obviously it’s not all bad

That said, there’s clearly a place for responsive design. I’m not saying that it’s a fad and should be ignored. Blogs look great as a phone-width column of text, I wouldn’t want to be zooming and panning around GMail on my phone and that’s just two examples off the top of my head.

All I’m saying is that as with everything there’s a time and a place and that I often find myself wishing I could see the full site rather than the scaled down responsive version I’m presented with. Let’s not go off the deep end with talk of wars and treat this as the nuanced issue that it is.

Prefilling Backbone model data

by Andy Appleton

The Backbone docs suggest that you should bootstrap data into your page on load. This allows the application to be responsive and ready to use as soon as the JavaScript is loaded. This is not always possible though – for example if the app does not have any kind of server side templating or if it interacts with an external API. (DailyJS has a good example of this kind of application).

In this case the application can seem slow to start as it first loads the JavaScript and then makes one or many API calls to populate the interface with data. Caching can help to a degree but this does not allow for new data to be fetched.

Cache Prefilling

I have a plugin called Backbone fetch cache which provides an in-memory and localStorage cache for Backbone’s fetch method. I’ve recently added a prefill option which will return cached data immediately (where available) but still make the background API request.

This is really nice because it allows us to present the user with a working interface immediately and then update the data in place as the AJAX requests complete. If you’ve ever used the Instagram iPhone app you might notice that it does something similar, presenting an interface with the last available data whilst it makes background API calls to get the latest.

Use

The initial cache hit triggers all of the same events (add, reset, change etc) as an actual call to fetch, but the success callback is not fired until the AJAX call completes. Instead a new callback is available, prefillSuccess:

myModel.fetch({
  prefill: true,
  prefillSuccess: someCallback, // Fires when the cache hit happens
  success: anotherCallback // Fires after the AJAX call
});

If you prefer working with promises, the call to fetch also returns an instance of jQuery’s $.Deferred. A progress event is triggered when the cache hit occurs and the promise is resolved when the AJAX call completes:

var modelPromise = myModel.fetch({ prefill: true });
modelPromise.progress(someCallback); // Fires when the cache hit happens
modelPromise.done(anotherCallback); // Fires after the AJAX call

All in all I think this is a pretty nice solution to the problem of a slow initial page load for a single page JS application. As always the code and tests are available on GitHub.

Backbone fetch cache

by Andy Appleton

Building a Backbone application which interacts with an external API means a lot of calls to model.fetch() and collection.fetch(). This can be pretty inefficient especially if the API does not set cache headers on responses.

Backbone fetch cache is a Backbone plugin which overrides the fetch method on Backbone models and collections to implement caching. Just include the script on your page and start calling fetch with cache: true in the options:

// Return cached data if available, otherwise make an AJAX request
myModel.fetch({ cache: true });

By default responses are cached in memory under Backbone.fetchCache._cache and also persisted to localStorage if available. This can be disabled by setting:

// Cache in memory but not localStorage
Backbone.fetchCache.localStorage = false;

Cached items are saved for 5 minutes by default, but this is also configurable by passing an expires option with a value in seconds to the fetch call:

// Expire this value in 1 minute
myModel.fetch({ cache: true, expires: 60 })

All options are passed through to the actual fetch call so you can still register success and error callbacks for actual AJAX requests. A promise is returned from the fake fetch method so the method signature should be identical whether the data comes from a cache hit or miss.

The code is all available on GitHub along with a full set of tests.

Moving on

by Andy Appleton

A quick personal announcement. I’m leaving my job at Mint Digital on the 19th December and starting as a developer at GoCardless on the 7th January.

I’ve had a blast working with the talented folks at Mint and I’ll be extremely sad to leave but I’m also really excited about the challenge at GoCardless and can’t wait to get started.

CoffeeScript is just JavaScript

by Andy Appleton

Most of the JavaScript I have written over the last year has actually been CoffeeScript. It occurred to me the other day that I’m in the same mental mode whether I’m writing JS or CS and I think that is because at it’s heart CoffeeScript is just a more succinct way to write the same language.

There is very little extra functionality that you get with CoffeeScript that you couldn’t do with plain JS, it’s just nicer to write. A good example is the class keyword, all it does is produce a constructor function with methods on the prototype object – easy enough with JavaScript but more expressive and succinct with CoffeeScript.

class Bacon
  eat: -> 'nom'

Compiles to

function Bacon() {}

Bacon.prototype.eat = function() {
  return 'nom';
};

If I were douchey enough I’d say it was like poetry. Actually I am and it is.

I think the reason for this is that CoffeeScript doesn’t change any of the fundamental rules of the language. this still behaves the same way and you can still use call and apply to invoke functions however you like regardless of where they originate.

There was a brief period where loops would fake a new scope with an inner function but happily that’s gone. In fact the only fundamental change I can think of is that variables are local to the current scope by default and I think most people would agree that loosing var is an improvement.

For me this is why compile to JS languages like Dart and TypeScript are completely uninteresting. I don’t want another language, just a way to write the words function and prototype a little less often and with fewer curly braces and semicolons.

Grunt Coffee Server

by Andy Appleton

TL;DR I wrote a Grunt task to live compile CoffeeScript for local development.

Full story

Somewhat inspired by my colleague Phil’s tweet, I’ve written a Grunt plugin to make it easy to start writing any JavaScript project in CoffeeScript.

It’s a simple static web server with a twist – request a .js file and it will be returned if it exists. If it doesn’t exist then the server will try and find a .coffee version of the file and return the compiled output if it can.

N.B. It does not deal with compilation for deployment, there’s already a plugin for that.

Usage

This is packaged up as a Grunt task so you’ll need to install Grunt from NPM first (might as well do that globally):

npm install -g grunt

Then install the task:

npm install grunt-coffee-server

Next you’ll need a gruntfile:

grunt init:gruntfile

Follow the instructions and take a look in your new grunt.js file. We need to register the new task by adding the following line:

grunt.loadNpmTasks('grunt-coffee-server');

There are also a couple of configuration options available which are read from the server config key:

grunt.initConfig({
  server: {
    port: 1337 // defaults to 3000 if not set
    base: './public' // defaults to ./ if not set
  }
});

Finally run the server:

grunt coffee-server

I’ve written this kind of server manually a few times now for local development so I know it’ll be handy for me – hopefully it’ll be useful for you too.

It’s on GitHub so feel free to fork, pull request etc!

Using Grunt and Jasmine with AMD

by Andy Appleton

Since yesterday’s post on running Jasmine specs with Grunt I have been working to integrate with a project which uses RequireJS. The Grunt Jasmine runner task I am using does not support AMD specs so I have created a fork which is available on GitHub.

To use it you will need to specify the repo URL in your package.json file…

"dependencies": {
  "grunt-jasmine-runner": "git://github.com/mrappleton/grunt-jasmine-runner.git"
}

If the amd flag is set in the grunt.js config file specs will be loaded via an AMD require call. This does not make an assumption about the AMD library being used, you must specify the path to that in the helpers option. Here’s a full example gruntfile:

module.exports = function(grunt) {
  grunt.initConfig({
    jasmine : {
      amd: true,
      // Your Jasmine spec files
      specs : 'specs/**/*spec.js',
      // Your spec helper files
      helpers: [
        '/path/to/require.js',
        '/path/to/requireConfig.js'
      ],
    }
  });

  // Register tasks.
  grunt.loadNpmTasks('grunt-jasmine-runner');

  // Default task.
  grunt.registerTask('default', 'jasmine');
};

This assumes that your spec files are AMD modules which require the source files as necessary, e.g.

define(['/src/myModule.js'], function(MyModule){
  describe('MyModule', function(){
    // etc...
  });
});

The spec runner HTML file will then require each spec file in turn and execute the contents.

Summary

This is not the most flexible implementation, but it works for my use case and I think is worth releasing. I opened a pull request on the main repo which was (quite reasonably) declined as they are apparently already working on AMD support.

I’ll most probably switch back to the original version once AMD support arrives but for now this fork will do nicely for me and I hope it can be useful to others.

Testing your JavaScript with Jasmine and Grunt

by Andy Appleton

I’ve written about clean modular JavaScript and a nice benefit of writing code that way is testability. Recently I’ve been using Jasmine to write JS unit tests having also played with Mocha and Qunit. Jasmine has a clean interface, runs specs inside an HTML page and I find the finished spec files extremely readable thanks to rspec style test nesting.

Jasmine example spec output

Jasmine’s HTML spec runner is great for writing and running tests locally, but it is not very practical for integrating into a CI server – for that we need a command line tool.

Grunt

Grunt is a really cool build tool for JavaScript. By default it includes tasks for linting, concatenating & minifying and running Qunit tests in a headless Phantomjs instance. It has a nice collection of tasks available as modules on NPM including a few for running Jasmine specs.

To get up and running we need to install Grunt, Phantomjs and the Grunt Jasmine runner task from the command line (I’m assuming you have node and NPM installed):

$ cd /path/to/project
$ npm install grunt
$ npm install grunt-jasmine-runner

If you’re on a Mac and use Homebrew you can grab PhantomJS:

$ brew install phantomjs

For other platforms there are a number of pre built binaries available.

Now all we need to do is add the appropriate configuration to a grunt.js file in the project’s root…

module.exports = function(grunt) {
  grunt.initConfig({
    jasmine : {
      // Your project's source files
      src : 'src/**/*.js',
      // Your Jasmine spec files
      specs : 'specs/**/*spec.js',
      // Your spec helper files
      helpers : 'specs/helpers/*.js'
    }
  });

  // Register tasks.
  grunt.loadNpmTasks('grunt-jasmine-runner');

  // Default task.
  grunt.registerTask('default', 'jasmine');
};

…and run the tests!

$ grunt jasmine

Jasmine command line output

Backbone has made me a better programmer

by Andy Appleton

I saw Jeremy Ashkenas retweet this and it really struck a chord with me. I started playing with Backbone about a year ago and have since used it on large and small projects at work and for fun.

These last two weeks I have been refactoring some JavaScript on StickyGram and I was really surprised at the state of the code I had written not all that long ago. I have been rewriting it to use a number of design patterns that I have (somewhat) inadvertently picked up from Backbone (and underscore).

One object one responsibility

We all write clean encapsulated object oriented JavaScript right? Guys? No me neither – it’s so easy to just fire off an event, nest a few levels of callbacks and be done with it.

Here’s an example. We get some data via an xhr request, append it with a fade effect and then remove some other element.

$.ajax({
  url: '/wherever',
  success: function(data, status, xhr) {
    $('selector').append($(data).hide().fadeIn(function(){
      $('other-selector').remove();
    }));
  }
});

This is simple to write initially, but it becomes very tricky to extend. Say we also want to update another part of the document with a notice to say that the request was successful:

$.ajax({
  url: '/wherever',
  success: function(data, status, xhr) {
    $('selector').append($(data).hide().fadeIn(function(){
      $('other-selector').remove();
    }));
    $('yet-another-selector').text('Request successful');
  }
});

That success callback is gradually getting to be responsible for a lot of different things and is starting to get pretty tricky to read. This only gets worse as other developers come to the code and just need to add a small bit of extra functionality. I find myself cursing them later for the messy code when actually it’s my fault for writing it this way in the first place.

Here’s a much nicer way to deal with this:

function DataModel() {
  this.url = '/wherever';
}

DataModel.prototype.getData = function() {
  $.ajax({
    url: this.url,
    context: this,
    success: this.onSuccess
  });
};

DataModel.prototype.onSuccess = function(data) {
  $(window).trigger('DataModel:success', data);
};

var dataModel = new DataModel();

Now we have a dataModel object which is concerned only with making the request. It triggers an event when it is done which we can listen for in other objects.

function ListView(el) {
  this.$el = $(el);
  this.bindEvents();
}

ListView.prototype.bindEvents = function() {
  $(window).on('DataModel:success', $.proxy(this.addData, this));
};

ListView.prototype.addData = function(data) {
  this.$el.append($(data).hide().fadeIn(this.removeOtherThing));
};

ListView.prototype.removeOtherThing = function(data) {
  this.$el.find('other-selector').remove();
};

var listView = new ListView('selector');

Right now we have more lines of code, but what we also have is two separate objects each performing a discrete function. Each object has a number of methods and the methods each do one thing. It’s worth noting that we could easily write unit tests for this code – try doing that for the first example…

So now when we need to add another callback to the AJAX completion all we need to do is create a new object type which will listen for the same DataModel:success event and do its thing independently of our listView. That’s pretty awesome and it means that our original code can stay responsible for the one task it was designed.

Thanks, Backbone!

This example follows the same Model/View pattern as Backbone without actually using the library. Actually it’s just well structured code but it’s often easy to take the (seemingly) quicker option.

I’m spending more time up front thinking about the structure and maintainability of my code in the expectation that it will prevent it from getting to that tangled spaghetti-mess that we all hate coming back to and that is definitely a good thing.