Backbone.js Tutorial: Deleting Lists

17 Jan 2013 | By Alex Young | Comments | Tags backbone.js mvc node backgoog

Preparation

Before starting this tutorial, you’ll need the following:

  • alexyoung / dailyjs-backbone-tutorial at commit 0953c5d
  • The API key from part 2
  • The “Client ID” key from part 2
  • Update app/js/config.js with your keys (if you’ve checked out my source)

To check out the source, run the following commands (or use a suitable Git GUI tool):

git clone git@github.com:alexyoung/dailyjs-backbone-tutorial.git
cd dailyjs-backbone-tutorial
git reset --hard 0953c5d

Deleting Lists

We’re now at the end of the complete CRUD implementation for lists. To support deleting items, we just need to hook up the link that we’ve already added and add support for the delete method to gapi.js. You could try doing this yourself for practice.

Open app/js/views/app.js, and add an event binding for the “Delete List” link:

events: {
  'click #add-list-button': 'addList'
, 'click #edit-list-button': 'editList'
, 'click #delete-list-button': 'deleteList'
},

Next, add a method called deleteList to the same class:

deleteList: function() {
  if (confirm('Are you sure you want to delete that list?')) {
    bTask.views.activeListMenuItem.model.destroy();
  }
  return false;
}

Just by making those two changes, the active list will be removed from the interface. Backbone knows how to remove the view when model.destroy is called in deleteList.

Backbone.sync Changes

To persist deleting lists, open app/js/gapi.js and add a case for 'delete' after 'update' (it should be around line 100):

case 'delete':
  requestContent['resource'] = model.toJSON();
  request = gapi.client.tasks[model.url].delete(requestContent);
  Backbone.gapiRequest(request, method, model, options);
break;

Google’s API provides the delete method, otherwise this is identical to the implementation for updating items.

Next

This part was short, so consider this your week off. Go and play with the source and see what you can get the Google Tasks API and Backbone to do! There’s still a lot of things left to cover, however.

Over the last eight weeks you’ve learned how to:

  • Write a custom Backbone.sync method
  • Use the Google Task API with client-side JavaScript
  • Write Backbone models, views, and collections

This could be adapted to work with other Google APIs, or potentially even other APIs that I haven’t considered. Once you have a solid understanding of how Backbone models and syncing data works, then a lot becomes possible.

The next few parts will cover the following:

  • Mocking the Google Tasks API for testing
  • Adding, editing, and deleting the tasks themselves
  • A Bootstrap user interface
  • Customising Bootstrap

Summary

The full source for this tutorial can be found in alexyoung / dailyjs-backbone-tutorial, commit 8d88095.

Node Roundup: 0.8.17, 0.9.6, gelf-node, jsong, Stuff.js

16 Jan 2013 | By Alex Young | Comments | Tags node modules unix cli json sandbox search
You can send in your Node projects for review through our contact form or @dailyjs.

Node 0.8.17, 0.9.6 (Unstable)

Node 0.8.17 was released last week with a security fix for TypedArrays, so you should upgrade if you’re using them:

If user input can affect the size parameter in a TypedArray, an integer overflow vulnerability could allow an attacker to write to areas of memory outside the intended buffer.

The unstable branch also saw a new release with 0.9.6. The streams API has changed slightly again as it continues to be developed: Isaac Schlueter added the readable.push method, and there are also fixes for TypedArrays in this branch too.

gelf-node

I’ve had a lot of luck with ElasticSearch. The last time I used it was on a project that used Node HTTP crawlers to index thousands of sites, and it was all backed by ElasticSearch. It worked extremely well and I actually got paid! If you’re also using ElasticSearch, then you might be interested in the gelf-node module (GitHub: robertkowalski / gelf-node, License: MIT, npm: gelf) by Robert Kowalski. It works with Graylog2, allowing messages to be sent from Node:

var Gelf = require('gelf');
var gelf = new Gelf({
  graylogPort: 12201,
  graylogHostname: '127.0.0.1',
  connection: 'wan',
  maxChunkSizeWan: 1420,
  maxChunkSizeLan: 8154
});

// The readme has an example message
gelf.emit('gelf.log', message);

Graylog2 itself is released under the GPL (version 3).

jsong

jsong (GitHub: textgoeshere / jsong, npm: jsong, License: MIT) by Dave Nolan is a CLI tool and module for filtering JSON. It’s built with streamin and clarinet, and shows full paths to matches:

$ cat my.json | jsong -k 'z\wp'

foo.bar.zip: val1
foo.bar.zap: val2
quux.zip: val

Because it’s built using streams, it should handle large JSON files.

Stuff.js

Here’s another project by Amjad Masad from Codecademy: Stuff.js (GitHub: Codecademy / stuff.js, License: MIT) – an easy way to run arbitrary HTML and JavaScript in an iframe. It uses node-static and uglify-js to create a sandbox for securely running user-contributed code.

There’s an example in Amjad’s blog post that shows how to use it:

stuff(secureIframeUrl, function (context) {
  var html = CodeMirror.fromTextArea($('#html'), {
    onChange: reload
  , mode: 'text/html'
  });
  var js = CodeMirror.fromTextArea($('#js'), {
    onChange: reload
  , mode: 'javascript'
  });
  var css = CodeMirror.fromTextArea($('#css'), {
    onChange: reload
  , mode: 'css'
  });

  var t = null;
  function reload () {
    clearTimeout(t);
    t = setTimeout(function () {
      var code = '<!DOCTYPE html><html><head>';
      code += '<style>'  + css.getValue() + '</style>';
      code += '<body>' + html.getValue();
      code += '<script>' + js.getValue() + '</script>';
      code += '</body></html>';
      context.load(code);
    }, 50);
  }
  reload();
});

jQuery Roundup: 1.9, Touch-box, Elevate Zoom, textareaHelper

15 Jan 2013 | By Alex Young | Comments | Tags jquery plugins images zoom touchscreen textarea
Note: You can send your plugins and articles in for review through our contact form or @dailyjs.

jQuery 1.9

jQuery 1.9 has been released. This version retains legacy browser support, but “slims down” the API somewhat. jQuery 2.0 meanwhile will not support Internet Explorer 6-8, but it will have the same API.

jQuery Migrate can be used to migrate to 1.9 or 2.0.

Touch-box

Dannie Hansen sent in Touch-box (GitHub: danniehansen / Touch-box, License: GPL), a plugin for resizing and dragging elements on touchscreen devices. Although the documentation mentions iPad, I tested it on Android Chrome and both seemed to work well.

Dannie suggested an interesting idea for a gallery, where the resize event could automatically cause higher resolution images to be fetched through a callback:

$('.box').TouchBox({
  resize: true,
  drag: true,
  callback_touches: function(touches) {
  },
  callback_change: function() {
  }
});

Elevate Zoom

Elevate Zoom's tint feature.

Elevate Zoom (GitHub: elevateweb / elevatezoom, License: MIT/GPL) by Andy Eades is an image zoom plugin that has FancyBox support. It has some cool features like “tinting”, where the unzoomed portion of the image is tinted – demos are available for each of the main features.

textareaHelper

textareaHelper by Amjad Masad and Codecademy transparently copies a textarea’s contents into a div, so it can be manipulated in ways not supported by textarea. It will try to copy the styles from the textarea as well, and can fetch the caret’s position.

Mocha tests have been included, which includes a setSelectionRange implementation to test the caret handling.

Framer, ModelFactory, Mongo Edit

14 Jan 2013 | By Alex Young | Comments | Tags testing backbone.js mongodb
Note: You can send your plugins and articles in for review through our contact form or @dailyjs.

Framer

Framer

Framer (GitHub: koenbok / Framer, License: MIT) by Koen Bok is a prototyping tool aimed at designers who can write basic JavaScript. It uses hardware acceleration and a simple JavaScript API for working with a subset of view types that are reminiscent of the ones used in Apple’s iOS frameworks.

The example on the site creates the iPhone container view, so you could adapt it to show something else if you wanted. The author suggests using Framer in conjunction with Cactus and Ratchet for creating rapid prototypes of iOS applications.

Backbone.ModelFactory

Backbone.ModelFactory (License: MIT) by Pat O’Neill generates model constructors that never produce multiple instances of a model with the same unique identifier. This is intended to make sharing models between views easier. This steps around Backbone’s built-in behaviour, and was based on Building the Next SoundCloud – an internal cache of model instances can be created based on their IDs:

Almost all views are instantiated only with the id of its model, so it’s quite possible that the data for that model hasn’t been loaded yet. To solve this, we use a construct we call the instance store. This store is an object which is implicitly accessed and modified each time a constructor for a model is called. When a model is constructed for the first time, it injects itself into the store, using its id as a unique key. If the same model constructor is called with the same id, then the original instance is returned.

Mongo Edit

Mongo Edit (License: MIT, npm: mongo-edit) from tldr.io is a simple editor for data in MongoDB. It’s built with Express, and the ACE editor.

If you’re looking for examples of Express applications, this one is built with route separation, and includes some simple Mocha tests.

Catalyst, Teacup, Makery

11 Jan 2013 | By Alex Young | Comments | Tags sponsored-content testing templates
Note: You can send your plugins and articles in for review through our contact form or @dailyjs.

Catalyst

Catalyst

Learning JavaScript? Join Catalyst! Full-time, in-person training and job placement services over 12 weeks in San Francisco. Instructors and speakers from Twitter, OkCupid, Adobe, Meteor, and more.

For more information, visit catalystclass.com.

Teacup

Teacup (GitHub: goodeggs / teacup, License: MIT, npm: teacup) by Good Eggs is a CoffeeScript templating language. It comes with middleware that can be used alongside connect-assets for compiling the templates, and the language kind of reminds me of CoffeeScript crossed with Jade:

{renderable, js, css, html, head, body} = require 'teacup'

module.exports = renderable ->
  html ->
    head ->
      js 'app'
      css 'app'
    body ->
      # ...

It works in browsers, has Mocha tests, and also has a gem for Rails: Teacup::Rails. The author wrote a blog post about it here: Teacup: CoffeeScript Templates for Developer Happiness.

Makery

Makery (License: MIT, npm: makery) by Leonardo Garcia Crespo is a module for making objects to aid with testing – the author says it works well for testing Backbone models. The API looks like this:

Makery.blueprint(MyConstructor, function() {
  return {
    id: this.unique(),
    aProperty: 'Some value',
    anotherProperty: 'Another value'
  };
});

var obj = MyConstructor.make();

Jasmine tests have been included, and it can be used in browsers as long as Underscore is present.

Backbone.js Tutorial: Editing Lists

10 Jan 2013 | By Alex Young | Comments | Tags backbone.js mvc node backgoog

Preparation

Before starting this tutorial, you’ll need the following:

  • alexyoung / dailyjs-backbone-tutorial at commit 465523f
  • The API key from part 2
  • The “Client ID” key from part 2
  • Update app/js/config.js with your keys (if you’ve checked out my source)

To check out the source, run the following commands (or use a suitable Git GUI tool):

git clone git@github.com:alexyoung/dailyjs-backbone-tutorial.git
cd dailyjs-backbone-tutorial
git reset --hard 465523f

Active List

Last week I demonstrated how to make a custom Backbone.sync “create” implementation, and suitable views and templates for adding new lists. If you recall, I created a view for editing lists as well, because it was so similar to AddListView it made sense to inherit from it.

Before a list can be edited, we need a way of selecting lists. It makes sense to always have an active list in this application, so there should be a way of saving this state somewhere. Also, when loading the lists from the server, a default list should be selected on the user’s behalf.

To be consistent with the patterns employed to track collections and views, we should add a models object for tracking instances of models. One of these can be the activeList.

Open app/js/app.js and add a models property as well as setting the activeModel after the lists have loaded:

App.prototype = {
  views: {},
  collections: {},
  models: {},
  connectGapi: function() {
    var self = this;
    this.apiManager = new ApiManager(this);
    this.apiManager.on('ready', function() {
      self.collections.lists.fetch({ data: { userId: '@me' }, success: function(res) {
        self.models.activeList = self.collections.lists.first();
        self.views.listMenu.render();
      }});
    });
  }
};

Now open app/js/views/lists/menu.js and make it check if the activeModel is the model currently being used to render the navigation list element:

renderMenuItem: function(model) {
  var item = new ListMenuItemView({ model: model });
  this.$el.append(item.render().el);

  if (model.get('id') === bTask.models.activeList.get('id')) {
    item.open();
  }
},

If the model does match, then it’ll trigger an open on the view. Now open app/js/views/lists/menuitem.js and make the ListMenuItemView track the activeModel:

open: function() {
  bTask.models.activeList = this.model;
  return false;
}

Now the application is able to track the selected list. This will make adding tasks easier, because in order to add tasks we need to know which tasklist to add it to.

Edit List Form

Open app/js/views/app.js. The goal of this exercise is to make the edit form appear, filled out with the correct values, when the “Edit List” link is clicked. It’s going to be similar to last week’s addList method, so you can try doing this part yourself if you want.

First, make it load the EditListView class:

define([
  'text!templates/app.html'
, 'views/lists/add'
, 'views/lists/edit'
],

function(template, AddListView, EditListView) {

Next, add the #edit-list-button to the events:

events: {
  'click #add-list-button': 'addList'
, 'click #edit-list-button': 'editList'
},

Finally, add the editList method to instantiate an EditListView form based on the activeList:

editList: function() {
  var form = new EditListView({ model: bTask.models.activeList });

  this.$el.find('#list-editor').html(form.render().el);
  form.$el.find('input:first').focus();

  return false;
}

This is very similar to the addList method – they could easily use the same method, just with different models:

listForm: function(form) {
  this.$el.find('#list-editor').html(form.render().el);
  form.$el.find('input:first').focus();

  return false;
},

addList: function() {
  return this.listForm(new AddListView({ model: new bTask.collections.lists.model({ title: '' }) }));
},

editList: function() {
  return this.listForm(new EditListView({ model: bTask.models.activeList }));
}

DRY!

Saving Changes

The Backbone.sync method needs to be updated to cope with updating items. This is very similar to creating items (in app/js/gapi.js):

// Around line 97, after 'create'
case 'update':
  requestContent['resource'] = model.toJSON();
  request = gapi.client.tasks[model.url].update(requestContent);
  Backbone.gapiRequest(request, method, model, options);
break;

A slight complication is Google’s API requires a tasklist property in the object passed to update. This isn’t very clearly documented (you’ll notice the tasklists/update reference doesn’t have a JavaScript example).

Rather than making the Backbone models somehow aware of this, it’s better to put the logic in Backbone.sync. That way all of the Google-related stuff is in the same place.

Add another switch statement to insert the required ID parameters, based on the type of model being operated on:

Backbone.sync = function(method, model, options) {
  var requestContent = {};
  options || (options = {});

  switch (model.url) {
    case 'tasks':
      requestContent.task = model.get('id');
    break;

    case 'tasklists':
      requestContent.tasklist = model.get('id');
    break;
  }

The lists should now be editable, but there’s one thing left to do – show that the selected list is “active”.

Selecting Lists

Open app/js/views/lists/menuitem.js and change open to track the active menu view, and add a class name to the view’s element:

open: function() {
  if (bTask.views.activeListMenuItem) {
    bTask.views.activeListMenuItem.$el.removeClass('active');
  }

  bTask.models.activeList = this.model;
  bTask.views.activeListMenuItem = this;
  this.$el.addClass('active');

  return false;
}

Whenever a view is opened, bTask.views.activeListMenuItem will be used to store a reference to it. Notice how I’ve used this.$el? Most experienced Backbone developers will tell you to do this, rather than using jQuery’s $() to find elements based on a selector. The idea is to use minimal jQuery and be more declarative with Backbone.

Does keeping a reference to bTask.views.activeListMenuItem beat $('.list-menu-item').removeClass('active')? It’s hard to say – I’ve often noticed people dipping into jQuery where it makes sense.

This begs the question: should we really track the active list using a reference to a model? The ListMenuItemView already contains a reference to the model, and most of the Backbone code is really concerned with modeling the user interface, rather than an additional internal state. Let’s try removing the reference to bTask.models.

Open app/js/app.js and remove the models object, and then remove the line that sets activeList. Next, go to app/js/views/lists/menuitem.js and change the open method to only refer to views:

open: function() {
  if (bTask.views.activeListMenuItem) {
    bTask.views.activeListMenuItem.$el.removeClass('active');
  }

  bTask.views.activeListMenuItem = this;
  this.$el.addClass('active');

  return false;
}

Next open the AppView class, in app/js/views/app.js, and make sure editList uses bTask.views.activeListMenuItem.model. Finally, make app/js/views/lists/menu.js activate the default item (the first list):

renderMenuItem: function(model) {
  var item = new ListMenuItemView({ model: model });
  this.$el.append(item.render().el);

  if (!bTask.views.activeListMenuItem) {
    bTask.views.activeListMenuItem = item;
  }
  
  if (model.get('id') === bTask.views.activeListMenuItem.model.get('id')) {
    item.open();
  }
},

I feel like avoiding tracking an internal application state is a mistake in Backbone, and instead the views should be made to work harder. Is this a good idea? It probably depends on the nature of the application.

To make the interface clearer, you can add li.active { font-weight: bold } to app/css/app.css.

Summary

In this part we’ve built on the code in Part 6 to allow lists to be edited. Even though this is fairly simple, the application had to change to track the currently active list.

The general rule of thumb in Backbone is to use cached jQuery (or Zepto) objects, which is why you’ll see a lot of calls to this.$el rather than $(). I suggest another rule that complements this: make views do the work, and avoid relying on state external to views.

The full source for this tutorial can be found in alexyoung / dailyjs-backbone-tutorial, commit 0953c5d.

Node Roundup: AsyncMachine, require-directory, sayeasy

09 Jan 2013 | By Alex Young | Comments | Tags node modules audio express async
You can send in your Node projects for review through our contact form or @dailyjs.

AsyncMachine

AsyncMachine (License: MIT, npm: asyncmachine) by Tobiasz Cudnik is a state machine for declaring asynchronous logic. It’s written in TypeScript, and supports state definition using an object-oriented API.

Transitions between states are exposed using an EventEmitter, and promises are supported for “deferred state changes”. Although the project is written with TypeScript, the documentation includes a plain JavaScript example.

AsyncMachine isn’t based on a formalised state machine design, but it has an interesting blend of concepts from other finite state machine implementations, asynchronous programming in Node, and object-oriented design. It’s definitely got a lot of ideas on how to deal with state in an asynchronous environment.

require-directory

require-directory (License: MIT, npm: require-directory) by Troy Goode allows directories to be loaded with require as if an index.js file had been used.

If you’ve got a project with an index.js file – let’s say it’s in routes/, and it looks like this:

module.exports = {
  auth: require('./auth')
, products: require('./products')
, categories: require('./categories')
};

When it’s loaded using require('./routes'), you’ll get an object with auth, products, and categories. Troy argues that this can cause maintenance problems, and prefers to write the index.js file like this: module.exports = require('require-directory')(module);.

Files can also be blacklisted and whitelisted, and index.js will be automatically ignored.

sayeasy

sayeasy (License: MIT, npm: sayeasy) by Clay Smith is a RESTful wrapper around Mac OS X’s say command, created with Express. The author is using it to speak notifications in a continuous integration environment – you could have a sayeasy server in your office that speaks when tests start to fail.

It also has a command-line wrapper, allowing messages to be sent to a central sayeasy server.

jQuery Roundup: ParamQuery Grid, Backbone.ViewDSL, Events Demo

08 Jan 2013 | By Alex Young | Comments | Tags jquery plugins backbone.js
Note: You can send your plugins and articles in for review through our contact form or @dailyjs.

ParamQuery Grid

ParamQuery

ParamQuery Grid (GitHub: paramquery / grid, License: MIT) by Paramvir Dhindsa is a table grid plugin that’s based on jQuery UI widgets. It supports sorting, row and cell selection, built-in and custom editing, resizing, and pagination.

The author has written full API documentation for ParamQuery, and an introductory tutorial. Additional data formats can be supported with the dataModel API, but it works with XML and JSON out of the box.

Backbone.ViewDSL

Backbone.ViewDSL (GitHub: andreypopp / backbone.viewdsl, License: BSD3) by Andrey Popp is a DSL for defining Backbone.View hierarchies. Views can be automatically loaded (AMD is supported), instantiated, and interpolated.

The author’s example compares a ViewDSL class with a standard Backbone class:

class App extends Backbone.ViewDSL.View
  template: """
    <h1></h1>
    <view name="app.views.Sidebar" id="sidebar" />
    <view name="app.views.Content" id="content" />
    <div class="footer"> by </div>
    """

In that example, app.views.Sidebar refers to another Backbone.View. A view attribute is also supported, and views can be accessed with Backbone.ViewDSL.View.from. Although Andrey describes the library as ‘tiny’, it packs in other features including conditional DOM removal, and there are some PhantomJS-powered Mocha tests as well.

Events Demo

Events Demo (GitHub: liouh / js-events-demo) by Henry Liou is an interactive demo that shows how each property works on the event object jQuery passes to .on. It uses nested elements so you can see how target and relatedTarget change depending on which element the event was triggered on.

Given how many people confuse the target properties, it made me wonder if this would be better than the official jQuery documentation. This project was sent in by Anthony Ettinger.

OOGL, Jot, Conference

07 Jan 2013 | By Alex Young | Comments | Tags webgl text editor

OOGL

oogle.js

OOGL (GitHub: 71104 / oogl.js, License: MIT) by Alberto La Rocca is a thin object-oriented library to make WebGL easier to work with. It has asynchronous shader loading, texture and attribute array management, and a render loop implemented with requestAnimationFrame and a setInterval fallback.

The author has written an API reference for oogl.js, and there are some oogle.js demos as well.

Jot

Jot

Jot (GitHub: boutell / jot, License: MIT, npm: node-jot) by Tom Boutell is a text editor built with Express and some client-side libraries like Rangy, and has some options for MongoDB as well.

Media files like photos and videos are supported, using a widgets system:

Jot introduces “widgets,” separate editors for rich media items like photos, videos, pullquotes and code samples. Jot’s widgets handle these items much better than a rich text editor on its own.

Also, Jot can be configured to send uploaded files to Amazon S3 or a custom backend solution. It uses ImageMagick to process image files.

It has the usual rich text editing features as well, and supports major browsers from IE7 up.

The author has provided instructions on how to integrate Jot with another Express application.

Conference

Conference (GitHub: axemclion / conference, License: MIT/GPL) by Parashuram Narasimhan is a Backbone.js application that provides an example schedule for a conference. Designed to alleviate the symptoms of bad conference wi-fi, Conference stores the data about the conference locally to avoid requiring a data connection once it has been initially loaded.

I’ve seen conferences that use custom native mobile apps to do a similar thing, but this version would be suitable for a mobile browser as well (and free as it’s released under a permissive license). Anyway, it’s an interesting use of Backbone.js, and Parashuram would like to help conferences adopt it.

Inverted, controldeck.js, xlsx

04 Jan 2013 | By Alex Young | Comments | Tags libraries excel spreadsheets presentations oo

Inverted

Inverted (GitHub: philmander / inverted, License: MIT, npm: inverted) by Phil Mander is an inversion of control container. Used in conjunction with AMD, Inverted uses a separate configuration file to express how classes are instantiated and how they interact. Once these defaults and relationships have been defined, an application context can be created, and instances of the classes can be used.

Phil has provided several examples on the Inverted site that use AMD, but he’s also included a CommonJS example that could be used with Node. The API is mostly based around callbacks. For example, fetching an instance is performed with appContext.getProto('name', fn), where fn receives the instance as the first argument.

JavaScript module loading systems such as the CommonJS and AMD manage the loading of your application’s dependencies, but they don’t actually inject dependencies and wire your code together. Inverted uses a separate application configuration file to define how your Javascript ‘classes’ interact without needing to add any library specific code within your modules.

controldeck.js

One of the controldeck.js demos.

controldeck.js (GitHub: dfcb / controldeck.js, License: MIT) from Draftfcb in Chicago is a small Node web application that provides a remote control for HTML presentations. This offers a simple way of using a mobile phone to control a slideshow.

Socket.IO is used to communicate between the controller and the slides, and the authors have demos running on AppFog.

xlsx

xlsx (GitHub: Niggler / js-xlsx, License: MIT, npm: xlsx) by Niggler is an implementation of the ISO 29500 Office Open XML specification. The author states that it has been tested with some simple Excel 2011 files, but is still a nascent attempt at supporting the format.

It’s designed to work with Node and browsers, and the project’s homepage has a browser-based demo. This project was created in response to Stephen Hardy’s xlsx.js project – there was a lengthy discussion on the license of the project which some felt is ambiguous: stephen-hardy / xlsx.js, issue #8: Use a more permissive license.

Backbone.js Tutorial: Creating Lists

03 Jan 2013 | By Alex Young | Comments | Tags backbone.js mvc node backgoog

Preparation

Before starting this tutorial, you’ll need the following:

  • alexyoung / dailyjs-backbone-tutorial at commit 82fe08e
  • The API key from part 2
  • The “Client ID” key from part 2
  • Update app/js/config.js with your keys (if you’ve checked out my source)

To check out the source, run the following commands (or use a suitable Git GUI tool):

git clone git@github.com:alexyoung/dailyjs-backbone-tutorial.git
cd dailyjs-backbone-tutorial
git reset --hard 82fe08e

List CRUD

The last few parts of this tutorial series have demonstrated how to talk to Google’s Tasks API and authenticate with OAuth. At this point, you should be able to sign in and see a list of task lists.

As we’ve seen, Backbone.js is based around RESTful APIs that speak in terms of CRUD (create, read, update and delete). In Part 4, I explained how to write a custom Backbone.sync method that can communicate with Google’s APIs, but so far we’ve only implemented “read” functionality, which fetches task lists using gapi.client.tasks.

Now we really need to implement the full set of CRUD operations so users can manage lists. Part 4 showed how Google’s API maps to Backbone’s sync operations:

Google Tasks APIBackbone.sync MethodDescription
insertcreateCreate a new task.
updateupdateUpdate an existing task.
deletedeleteDelete a task.
listreadGet a list of tasks.

In this part we’ll add support for “create”, but as you’ll see the principles are very similar to the “read” implementation.

Creating Lists

In order to create lists, several new components are required:

  1. Suitable buttons
  2. A form template
  3. Add and edit views
  4. Controller code

In Backbone.js, models and collections emit events. We’ve already created code to manage list item views, so all we need to do is hook this up to the event that fires when a new model is created and added to the TaskLists collection.

Mastering and exploiting events in this way is one of the tricks to writing manageable Backbone.js code.

Backbone.sync

So far, Backbone.sync can only read lists from Google’s API. To make it capable of creating items we’ll need a little bit of extra code. This will build upon what we’ve already written, so it’ll be short and sweet.

Go back to app/js/gapi.js and change Backbone.sync to call gapiRequest when the create operation is invoked:

Backbone.sync = function(method, model, options) {
  var requestContent = {};
  options || (options = {});

  switch (method) {
    case 'create':
      requestContent['resource'] = model.toJSON();
      request = gapi.client.tasks[model.url].insert(requestContent);
      Backbone.gapiRequest(request, method, model, options);
    break;

This looks a lot like the “read” code. There is one more thing we need to do in this file – change Backbone.gapiRequest to deal with single resources. I’ve put the full code for the method below because it’s still short with the modifications for this tutorial:

Backbone.gapiRequest = function(request, method, model, options) {
  var result;
  request.execute(function(res) {
    if (res.error) {
      if (options.error) options.error(res);
    } else if (options.success) {
      if (res.items) {
        result = res.items;
      } else {
        result = res;
      }
      options.success(result, true, request);
    }
  });
};

This looks to see if an array of items has been returned by Google’s API, or simply a single object. There’s an important lesson here though: Backbone.sync is sandwiched between other Backbone code, and is capable of providing Backbone with properties that will be used to set model attributes later on. This code doesn’t look like it does much, but the success callback will receive result, which will have an id property when models are created. Backbone will see this id property and use it to set the model’s id attribute, automatically!

Many Bothans died to bring us this information.

Template Junk

Open app/js/templates/app.html and update the signed-in-container div to contain a list and another container div:

<ul class="nav nav-tabs" id="top-nav">
  <li class="buttons">
    <div class="btn-group">
      <a href="#" class="btn" id="add-list-button"><i class="icon-plus">Add List</i></a>
      <a href="#" class="btn" id="edit-list-button"><i class="icon-cog">Edit List</i></a>
      <a href="#" class="btn delete-list" id="delete-list-button"><i class="icon-trash">Delete List</i></a>
    </div>
  </li>
</ul>
<div id="content-container">
  <div id="list-editor"></div>
  <div id="tasks-container"></div>
</div>

This has the “Add List” button that you’ll be able to use by the end of this tutorial, and it also has a div that’ll contain the list add/edit form.

Now open app/js/templates/lists/form.html and paste this in:

<fieldset>
  <legend>
    <span class="form-title">Edit List</span>
    <a href="#" class="pull-right delete-list btn"><i class="icon-trash"></i></a>
  </legend>
  <div class="control-group">
    <label class="control-label" for="list_title">Title</label>
    <div class="controls">
      <input type="text" class="input-xlarge" name="title" id="list_title" value="" placeholder="The list's title">
    </div>
  </div>
</fieldset>
<div class="form-actions">
  <button type="submit" class="btn btn-primary">Save Changes</button>
  <button class="cancel btn">Close</button>
</div>

This is the body of a form that will be used to add or edit lists. It uses the variable interpolation features we’ve already seen in this tutorial series.

Add and Edit Views

I’m only going to cover adding lists in this tutorial, we’ll get to the other functionality later (mainly because I’ve been writing this for three hours and I have client work to do and I need to pay the bills). Bill-paying aside, what’s the difference between an “add” and “edit” view? The form.html template can be reused by both, so why don’t we create an edit view and just inherit from it to make the list add view?

Open app/js/views/lists/edit.js and add this new view:

define(['text!templates/lists/form.html'], function(template) {
  var EditListView = Backbone.View.extend({
    tagName: 'form',
    className: 'form-horizontal well edit-list',
    template: _.template(template),

    events: {
      'submit': 'submit'
    , 'click .cancel': 'cancel'
    },

    initialize: function() {
      this.model.on('change', this.render, this);
    },

    render: function() {
      var $el = $(this.el);
      $el.html(this.template(this.model.toJSON()));

      if (!this.model.get('id')) {
        this.$el.find('legend').html('Add List');
      }

      return this;
    },

    submit: function() {
      var self = this
        , title = this.$el.find('input[name="title"]').val()
        ;

      this.model.save({ title: title }, {
        success: function() {
          self.remove();
        }
      });

      return false;
    },

    cancel: function() {
      this.$el.hide();
      return false;
    }
  });

  return EditListView;
});

In this class, I’ve declared events for submitting and closing the form, and bound them to suitable methods. I’ve also bound the change event on the view’s model to render, so changes to the model will automatically get displayed. This will be important later on.

Notice that in render, the legend will be changed when the model doesn’t yet have an id. In other words, when the model is new and hasn’t been saved, show a different title and hide the delete button.

Now compare this file to app/js/views/lists/add.js:

define([
'models/tasklist'
, 'views/lists/edit'
],

function(TaskList, EditListView) {
var AddListView = EditListView.extend({
  submit: function() {
    var self = this
      , title = this.$el.find('input[name="title"]').val()
      ;

    this.model.save({ title: title }, { success: function(model) {
      // Add the updated model to the collection
      bTask.collections.lists.add(model);
      self.remove();
    }});

    return false;
  }
});

return AddListView;
});

This file uses RequireJS to load EditListView, and then inherits from it. The submit method is replaced because creating lists is slightly different to updating them. When lists are created, it’ll receive an updated model from the server in the success callback, which can be added to the global lists collection. The view removes itself afterwards.

Add List Button

A link for adding lists was added to the main app.html template earlier on. To hook it up, open app/js/views/app.js and add a new method called addList:

addList: function() {
  var list = new bTask.collections.lists.model({ title: '' })
    , form = new AddListView({ model: list })
    , self = this
    ;

  this.$el.find('#list-editor').html(form.render().el);
  form.$el.find('input:first').focus();

  return false;
}

This will render the AddListView template and focus on the title field. You’ll also have to change the top of the file to load AddListView:

define([
  'text!templates/app.html'
, 'views/lists/add'
],

function(template, AddListView) {

Finally, add the events bindings somewhere in AppView:

events: {
  'click #add-list-button': 'addList'
},

Summary

Adding Lists

If you run node server and visit http://localhost:8080, you should now be able to add lists. The project doesn’t look particularly cool yet, but I’ll get to that soon.

The full source for this tutorial can be found in alexyoung / dailyjs-backbone-tutorial, commit 465523f.

Node Roundup: 0.9.5, juxt, email-templates

02 Jan 2013 | By Alex Young | Comments | Tags node modules email express functional
You can send in your Node projects for review through our contact form or @dailyjs.

Node 0.9.5

Node 0.9.5 (unstable) is out, and Isaac said weekly releases will be the norm for the near future:

For the next month at least, the primary focus will be on bug fixing and performance. Expect nearly-weekly releases until v0.10 is ready.

Amongst the raft of bug fixes, the updated stream module has some tweaks as well:

  • stream: fix to emit end event on http.ClientResponse (Shigeki Ohtsu)
  • stream: fix event handler leak in readstream pipe and unpipe (Andreas Madsen)

juxt

juxt (License: WTFPL, npm: juxt) by Azer Koculu is a small module that takes in functions and outputs a new function that stitches them together:

function inc1(n) { return n+1 };
function inc2(n) { return n+2 };
function inc3(n) { return n+3 };

juxt(inc1, inc2, inc3)(314); // returns [315, 316, 317]

It also has an asynchronous API, and will intelligently collate arguments into arrays or objects.

email-templates

email-templates (License: MIT, npm: email-templates) by Nick Baugh is a module for rendering email templates using ejs and “email-friendly” inline CSS. When I make Node web applications, I usually treat emails as an afterthought, rendering them with Jade or ejs. However, there are times when more attention to design is required, and this is made difficult in email due to the way certain major email clients treat CSS.

Juice from LearnBoost is used to generate suitable style attributes based on your CSS, making the task of inlining CSS less messy. The module will also generate a text version of the email if a suitable template is provided. The author has provided a full example with Nodemailer.

Nick also sent in a few of his other interesting modules, including express-cdn (GitHub: niftylettuce / express-cdn, License: MIT, npm: express-cdn) which automatically optimises assets in Express applications. The assets will be delivered using Amazon S3 and CloudFront, so you can create your own CDN.

jQuery Roundup: jKit, ZinoUI, jQuery.ajax.fake

01 Jan 2013 | By Alex Young | Comments | Tags jquery plugins frameworks ui ajax testing
Note: You can send your plugins and articles in for review through our contact form or @dailyjs.

jKit

jKit's site includes demos of every effect and component.

jKit (GitHub: FrediBach / jQuery-jKit, License: MIT) by Fredi Bach is a relatively small (47 KB) UI toolkit. It can work with data attributes, so adding data-jkit attributes to the relevant elements will invoke various components.

There are a lot of effects and components, including tooltips, charts, parallax scrolling, and a lightbox. The project has detailed documentation on each of the bundled plugins, and a simple introduction for non-programmers.

ZinoUI

The ZinoUI TreeView component.

Coincidentally, Dimitar Ivanov also sent in a UI toolkit of sorts: the ZinoUI Framework (License: CC BY-NC 3.0). This framework requires commercial licensing starting at $50 per site, and includes advanced widgets more comparable to jQuery UI, like a calendar and tree view.

ZinoUI is WAI-ARIA compatible, so may suit projects with stricter accessibility requirements. It has been tested with Google Chrome 12+, Firefox 4+, Safari 5+, Opera 11+, and IE8+.

jQuery.ajax.fake

jQuery.ajax.fake (GitHub: anasnakawa / jquery.ajax.fake, License: MIT, component: anasnakawa/jquery.ajax.fake) by Anas Nakawa can be used to mock jQuery $.ajax calls. A mocked call will be made when passing fake: true as an option to $.ajax. It can be disabled globally, and works with deferred calls.

JS101: A Primer on Strings and String Encodings

31 Dec 2012 | By Alex Young | Comments | Tags js101 tutorials language beginner

What is a JavaScript string? It depends on the context. For instance, a string is a primitive value – a value represented at the “lowest level” of the language’s implementation.

Strings are also members of the type String. Strings can be created with the String constructor. Running new String('hello') creates an instance of String.

Finally, String literals are found in the program’s source: var name = 'alex'.

Given that there are many ways to represent strings, what is the underlying encoding in JavaScript? Both the third and fifth editions of ECMAScript state that strings are represented as 16-bit unsigned integers:

Each integer value in the sequence usually represents a single 16-bit unit of UTF-16 text. However, ECMAScript does not place any restrictions or requirements on the values except that they must be 16-bit unsigned integers.

String Encoding

Ultimately a string is just a sequence of characters. In other words, an array of units of information that correspond to digits, letters, and so on. Characters are represented as byte sequences.

When working on client-side JavaScript and HTML, we’re used to seeing charset=UTF-8. UTF-8 is a system for encoding characters, and is actually “variable width”, which means the bytes used to represent an individual character can vary in length.

I said earlier that JavaScript strings are 16-bit, so how does this relate to UTF-8? In extremely simplified terms for the purposes of a beginner’s article, you can think about it like this: JavaScript engines use a fixed 16-bit representation of characters that makes it easier to manage strings internally.

So, even though a browser’s JavaScript engine internally represents characters as 16-bit numbers, we don’t usually need to know about this. Writing the strings to form controls with the DOM or using XMLHTTPRequest should convert the string to the right encoding. Ideally the server should have sent the Content-Type header set to UTF-8, so the browser will know what to do.

More About Encodings

Even if you’re a client-side developer that doesn’t care about string encodings, Joel Spolsky’s The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets is worth reading because it explains the history behind string encodings. Understanding the history behind what can be a frustrating topic makes it easier to understand.

If you need to work on string encodings in JavaScript, Johan Sundström’s post Encoding / decoding UTF8 in javascript from back in 2006 explains how to encode and decode UTF-8.

Monsur Hossain went on to write UTF-8 in JavaScript which goes into unescape and encodeURIComponent in more detail.

CampJS, euh.js, node-startup

28 Dec 2012 | By Alex Young | Comments | Tags conferences events node

CampJS

CampJS

CampJS is a weekend-long JavaScript “hack retreat” taking place in Gold Coast Hinterland, Queensland, Australia, from February 15th to the 18th. Early bird tickets are $270, and then prices go up to $470 by the 1st of February.

Some well-known developers will be there, including Dominic Tarr and James Halliday (substack).

The event is organised by Tim Oxley, Nigel Rausch, and Geoffrey Donaldson. For more about the event, follow @campjsnews.

euh.js

euh.js (License: MIT, npm: euh.js) by Cristian Tincu is a console implementation that supports the usual log, warn, and error methods.

It’s exposed as the ø object, and has a chainable API. It can be installed with npm and ender (ender build euh.js).

node-startup

node-startup (License: MIT) by Anthony Ettinger is an init script for managing Node applications. The script itself, init.d/node-app, implements the usual start, stop, and restart commands, and will manage processes using PID files.

It’s exactly the kind of thing you can’t find when you need it, so it’s probably worth starring on GitHub if you’re the kind of developer that doesn’t typically have to deal with sysadmin tasks. I wrote about using Upstart for managing Node apps last year on DailyJS.

Backbone.js Tutorial: List Views

27 Dec 2012 | By Alex Young | Comments | Tags backbone.js mvc node backgoog

Preparation

Before starting this tutorial, you’ll need the following:

  • alexyoung / dailyjs-backbone-tutorial at commit fcd653ec6
  • The API key from part 2
  • The “Client ID” key from part 2
  • Update app/js/config.js with your keys (if you’ve checked out my source)

To check out the source, run the following commands (or use a suitable Git GUI tool):

git clone git@github.com:alexyoung/dailyjs-backbone-tutorial.git
cd dailyjs-backbone-tutorial
git reset --hard fcd653ec6

Wireframe

The application we’re building has several main interface elements:

  • A two column layout for displaying task lists and tasks
  • Forms for adding and editing each item type
  • Buttons for invoking the forms, deleting items, and clearing complete items
  • Task state control (done checkbox)

The image below shows the basic layout.

The application's wireframe.

In this tutorial we’ll start implementing the interface by using an unordered list to represent task lists.

List Items

Despite being relatively simple, implementing a navigable list of task lists involves several Backbone.js elements:

  • HTML templates
  • Backbone views: ListMenuView, ListMenuItemView
  • Backbone collection: TaskLists

The ListMenuView contains the task list menu, and the ListMenuItemView is the navigation item for each task list itself. This can be modeled as a ul and a set of li elements.

Create a new directory called app/js/views/lists to store the task list-related Backbone.View classes, and another called app/js/templates/lists for the corresponding templates.

View: ListMenuView

This view resides in app/js/views/lists/menu.js:

define(['views/lists/menuitem'], function(ListMenuItemView) {
  var ListMenuView = Backbone.View.extend({
    el: '.left-nav',
    tagName: 'ul',
    className: 'nav nav-list lists-nav',

    events: {
    },

    initialize: function() {
      this.collection.on('add', this.render, this);
    },

    render: function() {
      // TODO
    }
  });

  return ListMenuView;
});

It loads views/lists/menuitem which we’ll create in a moment. Then it binds itself to the .left-nav element which was created by AppView and its corresponding template. The menu itself is an unordered list, and it uses some class names that will become more relevant once styles are added.

Notice that this view expects a collection. Collections can be passed to views during instantiation. For example, new ListMenuView({ collection: lists }) will pass the lists collection to an instance of this view.

The render method should look like this:

render: function() {
  var $el = $(this.el)
    , self = this;

  this.collection.each(function(list) {
    var item, sidebarItem;
    item = new ListMenuItemView({ model: list });
    $el.append(item.render().el);
  });

  return this;
}

The view’s element is used as the container for each ListMenuItemView which is passed a model by iterating over the collection.

View: ListMenuItemView

The app/js/views/lists/menuitem.js is similar to the previous view, but makes use of a template and Backbone’s declarative event binding feature.

define(['text!templates/lists/menuitem.html'], function(template) {
  var ListMenuItemView = Backbone.View.extend({
    tagName: 'li',
    className: 'list-menu-item',

    template: _.template(template),

    events: {
      'click': 'open'
    },

    initialize: function() {
      this.model.on('change', this.render, this);
      this.model.on('destroy', this.remove, this);
    },

    render: function() {
      var $el = $(this.el);
      $el.data('listId', this.model.get('id'));
      $el.html(this.template(this.model.toJSON()));
      return this;
    },

    open: function() {
      var self = this;
      return false;
    }
  });

  return ListMenuItemView;
});

The template is app/js/templates/lists/menuitem.html:

<a href="#" class="list-title" data-list-id=""></a>

Notice that curly braces are used to insert values. This is provided by Underscore’s built-in template system.

The view’s open method is bound to click events, and I’ve also bound change and destroy model events to the view as well – these will come in handy later.

The template’s values are inserted by using the template method in render:

$el.html(this.template(this.model.toJSON()));

The model’s raw JSON is passed to template so title and id will be resolved to the correct values.

Invoking ListMenuView

Open app/js/app.js and add ListMenuView to the list of define requirements:

define([
  'gapi'
, 'views/app'
, 'views/auth'
, 'views/lists/menu'
, 'collections/tasklists'
],

function(ApiManager, AppView, AuthView, ListMenuView, TaskLists) {

Last week I added a console.log to print out the name of each list. Remove that code and change it to render the ListMenuView:

connectGapi: function() {
  var self = this;
  this.apiManager = new ApiManager(this);
  this.apiManager.on('ready', function() {
    self.collections.lists.fetch({ data: { userId: '@me' }, success: function(res) {
      self.views.listMenu.render();
    }});
  });
}

Go back up to the App constructor function to make it instantiate listMenu by passing the relevant collection:

var App = function() {
  this.views.app = new AppView();
  this.views.app.render();
  this.views.auth = new AuthView(this);
  this.views.auth.render();
  this.collections.lists = new TaskLists();
  this.views.listMenu = new ListMenuView({ collection: this.collections.lists });

  this.connectGapi();
};

Running It

Now if you run node server and visit http://localhost:8080/, you should see your task lists displayed in a simple unordered list.

Summary

The app is now communicating with Google, allowing users to sign in, and also displays the user’s task lists. It still doesn’t look too exciting because we haven’t yet applied any styles, but you should be able to adapt the code you’ve seen so far to work with other Google APIs and similar services.

This tutorial’s code is available in commit 82fe08e on GitHub.

Node Roundup: 0.9.4, screener, Jyql

26 Dec 2012 | By Alex Young | Comments | Tags node modules
You can send in your Node projects for review through our contact form or @dailyjs.

Node 0.9.4

Node 0.9.4 has been released, and this version is a milestone because it features the new streams API. There are the usual platform-specific bug fixes and other improvements to core modules.

The new streams API documentation was published as part of this release.

node-screener

node-screener (License: BSD, npm: screener) by Damian Kaczmarek is a module for validating objects, and the author notes it works with Mongoose:

var screen = require('screener').screen;
var object = {
  _id: "503cb6d92c32a8cd06006c53",
  user: { name: "Joe Doe", birthdate: "04.07.1980"},
  location: { lat: 16.5015636, lon: 52.1971881 }
};

var result = screen(object, {
  user: {
    name: 'string', // same effect would be if passed /.*/ regexp
    birthdate: /\d\d\.\d\d\.\d\d\d\d/
  }
  location: {lat: 'number', lon: 'number'}
});

Jyql

Jyql (License: MIT, npm: jyql) by Gianfranco Cecconi is a Node module and browser library for working with the Yahoo! Query Language engine. The Node module uses the request module by Mikeal Rogers to automatically fetch a suitable resource to be processed with YQL.

jQuery Roundup: jquery.columns, stackable.js

25 Dec 2012 | By Alex Young | Comments | Tags jquery plugins columns responsive tables
Note: You can send your plugins and articles in for review through our contact form or @dailyjs.

jquery.columns

jquery.columns (License: MIT) by Cedric Ruiz extends the $.css method to support viewport-percentage lengths, basically making it a lot easier to work with responsive grids.

The plugin provides a $.columns method, but passing sizes with vw units to $.css will work as well.

There’s a demo here: jquery.columns demo.

stacktable.js

stacktable.js (GitHub: johnpolacek / stacktable.js, License: MIT/GPL) by John Polacek is a plugin for stacking tables on small screens. It’s designed to work in responsive layouts by using media queries.

To make tables fit smaller screens, this plugin stacks each column vertically in order. The headers will be placed in the correct order as well. Behind the scenes, tables are actually replaced with the stacked version – by passing a specific class name to the plugin responsive layouts can be supported.

JavaScript Developer Survey 2012: Results

24 Dec 2012 | By Alex Young | Comments | Tags community surveys

The JavaScript Developer Survey has now closed. As always the results are available to the community for further analysis:

Meteor seems to be struggling to gain traction.

98% of readers write client-side JavaScript, which is unchanged from last year. I included Meteor because it’s had so much press this year, but it seems like it’s still not very popular, at 2%.

I’ve always felt like this survey could be useful to those who are looking to create open source projects and even commercial services aimed at the JavaScript community. With that in mind, it’s interesting that 57% of respondents said they don’t currently write Node but are interested in learning about it. Only 9% were not interested. There are solid educational resources for Node out there, but it seems like people are hungry for more.

71% of respondents don’t use a language that compiles to JavaScript. This surprised me, because this year it certainly felt like more of our project submissions (for both client-side and server-side) were written in CoffeeScript.

Speaking of CoffeeScript, it was the most popular compile-to-JavaScript language, at 82%. TypeScript was second, at 14%, which is ahead of Dart by 10%.

There are plenty of worn out semicolon keys out there.

I thought the question “What JavaScript stylistic choices do you prefer?” may have resulted in controversy, but thankfully we got some interesting results. At 85%, most respondents use semicolons. And, 67% use commas at the end. 53% use spaces, with 39% tabbing instead. I would have thought spaces were more popular, but I’ve seen a lot of open source client-side projects that use tabs, so the JavaScript community isn’t as settled on tabs vs. spaces as some other popular languages.

My philosophy on this is to always match the style of the project you’re working on, and you’ll see me doing this in some planned DailyJS eBooks for 2013.

Testing and Benchmarking

51% of respondents don’t write tests – down from 58% last year.

Jasmine is the most popular testing library, at 45%, with Mocha close behind at 41%. QUnit is also very popular with 31%. For reference, these were last year’s test library results:

Jasmine (44%) has edged out QUnit (41%)! Vows is also doing well with 13%. Express/Mocha scored 11%, slightly ahead of Nodeunit at 8%.

Vows is now down to 7%, and Mocha has risen by a staggering 30%. It’s natural for some libraries to rank higher if they work in both browsers and Node.

JSLint is down to 56% from 67%, but it’s still the most popular static analysis tool. JSHint is close behind at 55%.

uglify is the most popular minimiser, which isn’t surprising given that it’s bundled with many other tools.

WebKit Inspector is the most popular debugging tool, at 79%. 500 people said they debug using node --debug, which is interesting because this is an area that I still feel needs work when developing with Node.

80% of respondents benchmark with client-side tools (1372 people). That’s probably not surprising, but given the performance-obsessed nature of certain prominent Node developers I’d have expected to see more people ticking “Benchmark scripts using a benchmarking library”.

44% of readers also write PHP, down slightly from 46% last year. C, Java, Python, and Ruby all rank around 20%, with Java edging the others out. Are there any Android developers out there?

Loading

RequireJS is the most popular module loading system – 1237 people use it. Given the sheer amount of documentation it has and the high quality site, it’s not surprising that it’s popular. Others that I didn’t mention included YUI, LABjs, and ExtJS.

Google Ajax Libraries is the most popular CDN, and it was interesting to see CloudFlare at 11%.

Project Hosting

GitHub dominates when it comes to project hosting.

At 91%, I wondered if GitHub might be at its peak. It was at 81% last year. I know there are many fellow freelancers who appreciate Bitbucket’s free private hosting, and at 20% I suspect there are people out there using both for the same reasons as me. Google Code is at 3%, so Google has got its work cut out if it wants to compete for open source projects.

Also, at 83%, GitHub was the most popular ‘project discovery’ site. This is higher than news sites (22%), which surprised me because it seems like there’s an interesting JavaScript project on Hacker News every other day.

Summary

Apart from a few surprises, 2012 has seen similar trends to last year. The new questions from Todd Bashor, Tyler Larson, and Adam Alexander were excellent, and I’m looking forward to seeing if semicolon use changes over time.

Thanks to everyone who took part in the survey!

New Streaming API for Node, Components Tutorial, Holler, GruntStart

21 Dec 2012 | By Alex Young | Comments | Tags components grunt node streams

New Streaming API for Node

In New Streaming API for Node, Isaac Schlueter outlines the issues found in Node’s current streaming API, and presents the new Node 0.10 API that addresses these problems. Although the documentation makes it clear that the stream API is “unstable”, it’s notable for two reasons: it’s built on EventEmitter, and many of Node’s core modules have stream interfaces. Streams are an integral part of Node, and it’s becoming clear that many problems are best solved with streams.

The 0.10 version of streams will cause backward compatibility issues, but this has been considered and mitigated:

For backwards compatibility with older Node programs, Readable streams switch into “old mode” when a 'data' event handler is added, or when the pause() or resume() methods are called.

Isaac has included the new stream API’s documentation in the post, and if you’re working with Node at all it’s worth reading. If you’re struggling to understand the motivation behind the changes, it boils down to pause() not really pausing, and the potential for 'data' events to be dropped before they’re ready to be consumed. I liked Isaac’s practical example of this issue:

'data' events come right away (whether you’re ready or not). This makes it unreasonably difficult to do common tasks like load a user’s session before deciding how to handle their request.

So, read A New Streaming API for Node v0.10 carefully even if you’re not working with streams directly. I’m of the opinion that you should be thinking about streams when designing Node programs, and if Node’s core developers can get them right for version 0.10 it’ll be a huge win for the platform.

Components Tutorial

The date picker from the tutorial

TJ Holowaychuk has written up a detailed tutorial on Components, about building a date picker. I’m a believer of the Components idea, and at the moment good tutorials are lacking in this area, so it’s good to see TJ writing up detailed examples like this.

There are also some screencasts available: Creating components, and Web Components - Introduction.

Holler.js

Holler.js (GitHub: bitpshr / holler, License: WTFPL, npm: holler) by Paul Bouchon is a real-time notification service. It’s distributed as a Node module with client-side code that builds on alertifyjs.

The real-time communication is handled by Faye. Paul has made a brief demonstration video to show how it works.

GruntStart

GruntStart

GruntStart (GitHub: tsvensen / GruntStart, License: MIT, GPL) by Tim Svensen is a Grunt task for building optimised websites using HTML5 Boiler Plate, jQuery, Modernizr and Respond.js. It includes a task that watches for file changes and automatically generates optimised assets.

The client-side scripts are all included, so all you need to do to get started is download GruntStart from GitHub.