Monthly Archives: December 2012

Using Backbone with Require

So we’ve done Backbone, we’ve done Require. Let’s put them together. Previously we wrote a pointless little Backbone app. Now, we’re going to Require-ify it.

Require.js is, as you know, all about modularisation. Fortunately, Backbone makes it pretty obvious what makes up a Module. Is it a distinct Backbone entity? A Model, a Collection or a View? Boom. It’s a module.

So with the difficult decision making done, let’s look at how we’d do this.

Starting from the beginning, our require config. You might recognise this from my original require post. That is because I am lazy.

File: js/requireConfig.js

require.config({
	paths: {
		//libraries
		jquery: 'libs/jquery',
		underscore: 'libs/underscore',
		backbone: 'libs/backbone',

		//scripts
		developerModel: 'models/DeveloperModel',
		developerCollection: 'collections/DeveloperCollection',
		developerListView: 'views/DevelopersListView'
	},
	shim: {
		jquery: {
			exports: "$"
		},
		underscore: {
			exports: "_"
		},
		backbone: {
			deps: ['underscore', 'jquery'],
			exports: "Backbone"
		}
	}
});

File: js/index.main.js

require(['requireConfig'], function(){
	require(['developerListView'], function(DeveloperListView){
		var myView = new DeveloperListView();
	});
});

File: index.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<title>One Page Web App</title>

	</head>
	<body>
		<section id="content">
			<h1>Really Useful Dev List App</h1>
			<input type="text" id="name"></input>
			<input type="radio" name="role" id="isUx">UX</input>
			<input type="radio" name="role" id="isDev">Dev</input>
			<button id='add'>Add List item</button>
			<ul></ul>
		</section>

		<script src="js/libs/require.js" data-main="js/index.main">
	</body>
</html>

This is the same html as my Backbone post but with a require script tag instead of an ordinary one.

Right, that’s all the essentially unchanged stuff out the way. Now let’s look at the MOSTLY unchanged stuff. After that we will have run out of stuff.

filename: js/models/DeveloperModel.js

define([
	'underscore',
	'backbone'
], function(_, Backbone){
	var Developer = Backbone.Model.extend({
		defaults: {
			name: 'A Dev'
		}
	});

	return Developer;
});

This is the Model from our earlier Backbone app. It is now a file in its own right wrapped in a define block. It has its dependencies, Backbone and Underscore defined and then establishes a function that creates the concept of a Developer Model and returns it. Note, it is not returning “A developer” it is returning the Developer Model, which can be instantiated as needed.

filename: js/collections/DeveloperCollection

define([
	'underscore',
	'backbone',
	'developerModel'
], function(_, Backbone, Developer){
	var DeveloperCollection = Backbone.Collection.extend({
		model: Developer
	});

	return DeveloperCollection;
});

This is our collection. Again, it returns the idea of a collection of developers, not an actual collection of developers. It may well be possible to remove the dependency on the Developer model by passing it into any calls to the DeveloperModel. I’ll be exploring this and if it turns out to be a good idea and possible, I’ll talk about it.

Finally, our View. For the sake of avoiding this post becoming any more massive than it already is, I’ve snipped out all the logic inside the View, if you want to see it check out my Backbone post. Doing my bit to save your monitor’s ink reservoir.

define([
	'jquery',
	'underscore',
	'backbone',
	'developerCollection',
], function($, _, Backbone, DeveloperCollection){
	var DevelopersListView = Backbone.View.extend({
		...
	});

	return DevelopersListView;
});

On a sidenote, when I wrote this I gave the path names in RequireConfig camel-cased names, starting on lowercase letters but decided to follow the convention of having anything imported into a file start with a capital letter. This was annoying. Don’t do that. Although I am fond of the capital letters for imported objects though. I recommend that.

That’s it, we now have a pointless little Backbone and Require app.

Advertisements
Tagged , , , , ,

Using Backbone.js

Like Require, Backbone has many pre-existing and excellent tutorials. In particular Artur Adib’s tutorial is what made it all become clear to me and Aaron Hardy’s article on JavaScript Architecture continues to make me happy.

Still here? Are there not plenty of links to fit your information needs above? You curious fellow/fellette. Let’s have a crack at an overview of Backbone then.

Backbone’s structure

Backbone introduces four types of Object to your JavaScript. Models, which represent a single entity of data. Collections, which contains multiple Models. Views, which handle the presentation of your data. And Routers which are special and cool and not going to come up again in this post.

Starting with a Model

Creating a Model is really easy in Backbone.
var Developer = Backbone.Model.extend();
Boom. A Developer Model. We can get fancy though

var Developer = Backbone.Model.extend({
	defaults: {
		name: 'A Dev'
	}
});

Here we are defining a pair of default attributes. This means that any Developer created will have these attributes set to these values unless specified otherwise. We are not defining a complete list of possible attributes, merely the ones we want all examples of the Model to have and their default values.

There’s more we can do with a Model, but we’re not going to get into that now.

Creating a Collection

If you’re still reeling from creating a Model, then creating your collection can be a bit of a breather for you.

var DeveloperCollection = Backbone.Collection.extend({
	model: Developer
});

Done. We’ve created a collection and told it what it’s a collection of. Again, there’s more fancitude available but we’re not going to touch it today.

Displaying data with a View

Backbone is very close to a Model-View-Controller pattern. The thing it’s missing is a Controller. That’s becuase responsibilty for Control is placed partly in the Collection, but mostly in the View.

The View is responsible for rendering html to display your models and taking in user input. This means that even even at its most basic, there’s a little more to a View than a Model or Collection. Let’s take a look:

var DevelopersListView = Backbone.View.extend({
	el: $('#content'),
	initialize: function(){
		_.bindAll(this,'render', 'appendItem');
		this.collection = new DeveloperCollection();
		this.render();
	},
	render: function(){
		var self = this;
		_(this.collection.models).each(function(item){
			self.appendItem(item);
		});
	},
	appendItem: function(item){
		var template = _.template('<li><%= name %></li>');
		var templateVariables = {
			name: this.model.get('name')
		};
		$('ul', this.el).append(template(templateVariables));
	}
});

The el attribute tells the View where in the page to insert itself. I’m not sure about using a jQuery selector here, I suspect it’s not necessary but it’s what Artur did and I’m not going to argue right now.

The initialize function is run when the View is instantiated. It is doing three things. First, it’s calling bindAll on its functions. bindAll is an Underscore function which fixes the context of functions. What that means is, whenever we call a bound (binded?) function, the value of this is fixed to the object passed as its first parameter. In this case, it’s the View.

Second, initialize instantiates a Collection to use. Third and finally, it calls its own render function.

The render function iterates through the collection using Underscore’s each function and calls its own appendItem function on it.

The appendItem function uses an Underscore template and the contents of the object passed to it, a Model, to add a DOM element to the page. This could and should be a separate file, but for now it can just be a String.

So that’s all very good and lovely, except right now we’re using an empty collection and have no way to add anything to it. Let’s fix that by adding a bit more to the View

var DevelopersListView = Backbone.View.extend({

	el: $('#content'),
	events: {
		'click button#add': 'addItem'
	},
	initialize: function(){
		_.bindAll(this,'render', 'addItem', 'appendItem');
		this.collection = new DeveloperCollection();
		this.collection.bind('add', this.appendItem);
		this.render();
	},
	render: function(){
		var self = this;
		_(this.collection.models).each(function(item){
			self.appendItem(item);
		});
	},
	addItem: function(){
		var nameIn = $('#name').val();
		if (nameIn) {
			this.collection.add({name:nameIn});
		} else {
			this.collection.add();
		}
	},
	appendItem: function(item){
		var template = _.template('<li><%= name %></li>');
		var templateVariables = {
			name: this.model.get('name')
		};
		$('ul', this.el).append(template(templateVariables));
	}
});

So, what’s new here? We’ve added an events object, an addItem function and a couple of extra bindings. Let’s start on the addItem function. We’re looking at the DOM object with id name, taking its value and adding it to the collection. We’ve wrapped this add in an if statement so that if the name input is empty, we’re using a default.

So, how about our new bindings? Well, addItem has been added to the bindAll. Pretty much every function attached to your View should be in the bindAll. We’ve also called bind on an add event for the new collection. Confusingly, this is not an Underscore bind. This is a function of the Backbone collection Object. We’re saying that when an add event is fired by the DeveloperCollection object, then we should run the appendItem function.

Finally, the events object. This defines all the event bindings associated with the View. We’ve said that when a click event is fired on the button with id add, we run the addItem function.

All this needs now is some html including a name input, an add button and a content div

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<title>One Page Web App</title>

	</head>
	<body>
		<section id="content">
			<h1>Really Useful Dev List App</h1>
			<input type="text" id="name"></input>
			<button id='add'>Add List item</button>
			<ul></ul>
		</section>
		<script src="backboneapp.js"></script>

	</body>
</html>

Ta-Da! That’s it for now, a fully functional if pointless little Backbone app.

Tagged , , , ,

Utilitying With Underscore.js

Underscore.js is a utility library which Backbone depends on. I’m afraid I don’t have a huge amount to say about it though because the only reason we’re using it is so that we can use Backbone. Lovely cuddly Backbone.

What is Underscore for?

It provides functional programming support for your JavaScript. This includes tools for manipulating Objects, Collections and Arrays as well as some generic utility functions.

It also supports some baisc HTML templating. This is the only feature I’ve actively used as it is valuable for producing Backbone Views. As a templater it’s pretty simple, which is probably a good thing. It’s been fit for all my extremely limited needs so far. This is tepid praise but based on inexperience rather than any negative feelings.

So why use Underscore?

So that we can use Backbone and because it makes life easier. A bit like functional jQuery.

Well that was short. Let’s talk about Lodash while we’re here. Lodash is a drop in replacement for Underscore. In theory this means that if you write your code base using Underscore, you can then change your mind and use Lo-Dash.

So Why Use Lo-Dash?

It’s a bit bigger but offers performance enhancements and some extra features. It’s also possible to generate specific subsections of Lo-Dash, so you can just get the bits relevant to Backbone and use that instead of the whole thing.
This link from the comments provides a much better answer to this question than I can. Lo-Dash has been designed to provide a more efficient, more consistent and better tested alternative to Underscore. It has been design with compatibility in mind though, so that if you don’t use the extra Lo-Dash features, the two should indeed be interchangeable.

We haven’t decided between the two yet. Lodash sounds pretty good but the whole thing is 19kb compared to Underscore’s 4kb. Taking just a Backbone version will reduce that but right now I don’t know how much. These enhancements sound great but are they 15kb of download better?
John in the comments has pointed out that the size difference is not as great I originally thought. It’s actually more like half a kilobyte.

The good news is since it drops in to replace, we should be able to build around underscore then swap in lodash to see if things are better.

Tagged , , , , ,

Stucturing with Backbone

Backbone.js is a library for giving structure to your JavaScript. It provides a framework that looks very similar to Model-View-Controller to base your app on.

What is Backbone for?

Combined with Require.js, this means our apps can have a well defined and sensible structure that’s starting to look like Object Orientation. I can barely contian my excitement either. No really, I can’t, this is awesome.

So why use Backbone?

Using Backbone means your code can fit into a consistent and comprehensible format. You keep your data in a Model. You keep your Modles in a Collection and you access your Collection through a View.

We’re developing with a view to produce control widgets that can be reused in different places – specifically desktop, mobile, and a summary screen. Using Backbone we can write the Model and Collection code once, only changing the necessary bits in the View to reuse it.

Backbone also provides a Router feature that decides which scripts to run based on the URL. To facilitate this, it can either use or polyfill for the HTML5 History API. This means you can manipulate the url and browser back/forward behaviour without actually changing the page.

We’re planning on sharing urls between desktop and mobile pages. However this is complicated because some things that share a page on desktop are separate pages on mobile. With Backbone Routers this should be possible.

In summary, backbone provides a structure to your JavaScript that makes it easier to write, maintain and reuse.

Tagged , , , , ,

Setting up Require.js

So last week I went into why we’re using Require.js, yesterday I did the core concepts of Require. Today I’m going to cover how to use it in a project. It will be almost laughably short. I am by no means an advanced user at this point, I have read a lot about Require and done some small demo projects. I haven’t yet used it to do anything one could describe as complex. This means what follows is Require 101, nothing more.

Getting started with Require

You may be used to loading all your JavaScript with a chain of script tags in your html. You may bundle it all up into one file and use a single script tag. Either way, with require it is different.


<script type="text/javascript" src="path/to/require.js" data-main="ponies.js"></script>

Obviously, ponies.js could be called anything. In fact, I really wouldn’t recommend calling it ponies. If you’re going to make a one-page app then you could do worse than just calling it main.js. We’re planning to have a multi-page application and so calling it main would just get confusing. Instead we’re planning to go for the naming convention of pagename.main.js for our Main files.

So, that’s it for JavaScript imports. Let’s take a look inside main.js

require.config({
	paths: {
		//libraries
		jquery: 'libs/jquery',
		underscore: 'libs/underscore',
		backbone: 'libs/backbone',

		//scripts
		developerModel: 'models/DeveloperModel',
		developerCollection: 'collections/DeveloperCollection',
		developerListView: 'views/DevelopersListView',
		developerItemView: 'views/DeveloperItemView'
	},
	shim: {
		jquery: {
			exports: "$"
		},
		underscore: {
			exports: "_"
		},
		backbone: {
			deps: ['underscore', 'jquery'],
			exports: "Backbone"
		}
	}
});

require(['developerListView'], function($, _, Backbone, DeveloperListView){
	var myView = new DeveloperListView();
});

This file can comfortably be divided into two parts, the config and the function. The config can be split out from the file so that it is reusable between main files. This is also valuable for the optimiser and testing in the future.

Splitting it out looks a bit strange because you use a require call to load in Require’s config. That wrinkles my brain, but it works and looks like this:

require(['requireConfig'], function(){
	require(['developerListView'], function($, _, Backbone, DeveloperListView){
		var myView = new DeveloperListView();
	});
});

The thing to note here is that without the require config, it’s not possible to define paths by name so you’ve got to use the full path to your config file here.

This function is the start point for your page’s JavaScript, so from here you kick everything you want to run off. Require will do all the clever business of loading in your dependencies, so you just need to list ’em and use ’em.

Now let’s take a look at the config file we pulled out.

require.config({
	paths: {
		//libraries
		jquery: 'libs/jquery',
		underscore: 'libs/underscore',
		backbone: 'libs/backbone',

		//scripts
		developerModel: 'models/DeveloperModel',
		developerCollection: 'collections/DeveloperCollection',
		developerListView: 'views/DevelopersListView',
		developerItemView: 'views/DeveloperItemView'
	},
	shim: {
		jquery: {
			exports: "$"
		},
		underscore: {
			exports: "_"
		},
		backbone: {
			deps: ['underscore', 'jquery'],
			exports: "Backbone"
		}
	}
});

There are two things going on here. The first part is setting up paths to use throughout my app. Essentially I am creating variables to hold the filepaths I am using. This isn’t necessary, but it makes it easier to write and maintain because I can change my file structure and change the references in one place. Plus, I don’t need to remember where everything is. I hate remembering things.

The second thing is the shim. This is a fix for libraries that are not compliant with the AMD API. Here we are defining global versions of these libraries so that they can act in a way that they are used to, however in the app proper we will still be using local versions so that the whole thing remains coherent and managable. This is just a way to make these libraries behave themselves. I’ve since come to a better understanding of what Shim does thanks to this post from Require.js developer James Burke. A require Module tells Require itself what its dependencies are when it is defined, Shim is a way to tell require what the dependencies of a file are if the file itself doesn’t decalre its dependencies to require. It does not do anything that affects the world outside of require, most notably, shimming something does not cause it to be downloaded.

And that’s it, Require is set up. Just use the main function to run everything you want to on your page. Easy as microwavable pie.

Tagged , , , ,

Using Require.js

So, last week I covered why we’re using Require.js. Today, let’s look at how to use it. This time I’m just going to go into the two functions that are the heart of Require, then next time I’ll go for how to actually put it into your app.

Require()

require(["some", "dependencies"], function(){Console.log("A function")})
The require function takes two parameters. An array of strings, referencing all of the functions dependencies and a function which is run.

What this does is informs the app that in order to run that function, it must have these dependencies loaded. So it will make sure it has them all available before starting to run the function. The array of strings, which must always be an array even if it’s an array of one, can contain either full file paths or references defined by Require.

References defined by Require, what do you mean? I hear you cry, melodramatically. There are two things this can mean, one is names for file paths that can be defined by your Require config. We’ll cover that tomorrow. The other is functions defined with the define function.

Define()

define("myModule", ["some", "dependencies"], function(){Console.log("A function")})

Define is used to define modules that you intend to call again later. The first parameter is optional and is a single String that is your module’s name, to make it easier to call again later. After that, it looks just like a require function.

So, when do you use which? If you want to run a function but make explicit its dependencies, then use require. If you want to create a module that will be called by another function, then use define.

Tomorrow, putting this into practice.

Tagged , , , ,

Modularisation with Require.js

Require.js is well covered ground. Smarter people with more experience working with it have got the basics at very least sorted. I’d recommend reading some or all of the linked articles for your Require hit, really. This one by Aaron Hardy in particular is wonderful, although only the last page actually covers Require, the whole thing is excellent. So, with the caveat that there are better places to get this information in place, what is Require.js?

What is Require.js for?

Require is a JavaScript library for Asynchronous Module Definition. It is by no means the only one available, but it is one of (if not the) most popular. Asynchronous Module Definition is an API for defining distinct modules of JavaScript with explicit dependencies. These dependencies can then be loaded asychronously if that’s your bag, although in the real world I have reservations about this. Powerful and unfounded reservations.

So why use it?

The main attraction to me is project structure. Using Require I can write my JavaScript in small cohesive files without any fuss. Gone are the days of sprawling JavaScript files that keep everything together because of a chain of dependencies and a reluctance to separate files based on some faith that they’ll sort themselves out in the end. With require each file is a sensible module of code and the other modules that it has a relationship with are listed at the top of the file. Lovely.

It also kills the risk of accidentally introducing an unintended dependency. I won’t start referencing things I shouldn’t just because they are available to me because making them available is an action that requires a moment’s thought (and it really is just a moment).

The final thing it brings to the party is asynchronous loading. As the page is loading, Require will establish all the dependencies of your Main Javascript file, including nested dependencies and load them asynchronously. When I say Main here I really mean it in terms similar to a Main file in Java – this should be the single starting point for all your JavaScript on the page so the dependencies and nested dependencies should be all the JavaScript on the page. Since all these files are loading asynchronously it should give you a full suite of JavaScript very quickly. It’ll also cache your modules so if a single module is reused on future pages, its already loaded and don’t need to be grabbed again.

I haven’t done any tests of the actual effect of this in reality yet, so what follows is really nothing but prejudice and a resistance to change. Loading modules asynchronously like this means adding a huge number of extra http GET requests to your page load. Sure each file is coming down quickly, but that goes against everything at least one thing that I’ve been taught about web performance – keeping requests to a minimum. However! Require even has suspicious curmudgeons like me covered too.

Part of the attraction of Require over alternative AMD loaders is its optimizer r.js. This can be used before serving your code up to minify, obfuscate and concatenate your modules. So far my only success has been bundling everything into a single file, but I understand it is possible to configure it so that you produce a site-wide bundle and a separate bundle loaded separately for every page. This is my preferred solution based on no actual testing. Fortunately though, once I’ve worked out how to make it go, it should be easy to try all three of these options without impacting the actual code. This flexibility makes me happier than is reasonable.

Next time: details of how to use Require (Spoiler alert: It’s really easy).

Tagged , , , ,

A Shiny New Dev Stack

We’re starting a project from scratch at work. This is an unusual opportunity to go seeking out new technologies to incorporate without creating a mess trying to integrate it with pre-existing code. To make it even better, we’ve been given a few weeks as a UX Team with nothing to do except explore new toys to use and best practices to follow.

This is a list of the toys we’re planning to use. It’s really a sort of statement of intent – I will at some point post in more detail about all most of these with some chat around why we’re using them and some details of how we’re getting them to work.

JavaScript Libraries

  • JQuery.js – We’ve always used Jquery but its here for completeness. Library for making JavaScript more pleasant to write
  • Zepto.js – A much smaller alternative to Jquery. We’re planning to use this on the mobile site where size is more important and IE is less of a pain
  • Require.js – Dependency Management for modular Javascript
  • Almond.js – Much smaller replacement for Require after all its clever business is dealt with before serving the code
  • Backbone.js – MV* Structure for JavaScript
  • Underscore.js – Collections and templating utilities. A dependency of Backbone
  • Lodash.js – A larger but more performant drop in replacement for underscore. We haven’t actually made a decision between the two yet
  • Modernizr.js – Feature detection to allow us to use advanced features then provide a fallback for older browsers

CSS Tools

  • SASS – A CSS Preprocessor to turn CSS into the language it should always have been
  • Compass – A Framework built on top of SASS to make it even better

Build Tools

  • Grunt.js – A tool made of magic and JavaScript for running tasks
  • NodeJS – Let’s JavaScript run outside a browser. We’re only using it right now because Grunt depends on it, but once we’ve got it I know there are all sorts of things it can do
  • PhantomJS – A Headless webkit browser for running tests
  • Jasmine – Jasmine isn’t new to us but I’m including it for completeness. It’s a JavaScript testing language
  • Saga – A JavaScript test Coverage detection tool
  • Gradle – I don’t really expect to interact with gradle much but will list it here anyway. A build automation tool
Tagged , , ,