Node Tutorial Part 6

2010-12-20 00:00:00 +0000 by Alex R. Young

Welcome to part 6 of Let's Make a Web App, a tutorial series about
building a web app with Node. This series will
walk you through the major areas you'll need to face when building your
own applications. These tutorials are tagged with

Previous tutorials:

Before starting this tutorial remember to start up a mongo daemon if
your computer doesn't run one automatically.

In the last part we looked at authentication and sessions. We used the
particularly cool concept of middleware to build some seamless access
control. This week I'm going to demonstrate how to make the interface
more interesting using jQuery.

Interface Design

When I design interfaces I usually plan out a rough idea before
developing the app. This is usually known as top-down design. Once the
interface seems workable, I move on to develop the API with a simple
interface and tests, just like we've been doing so far in this tutorial

I like to sketch out interfaces with graph paper, a mechanical pencil,
and a good eraser. I keep the sketches rough so my colleagues know
they're not finished designs, they're ideas that will evolve as we
discuss the project.

A simple sketch of Nodepad suggested the following:


One of the most important things when building interfaces is to cheat as
much as possible. When I'm programming I don't spend hours working on
code that's already available in a well-written library, and the same
can be said for design. I don't need to draw every icon I need, and I
don't need to reinvent the wheel for layouts either.

Today there are a lot of solutions available, from CSS frameworks to
GUI-heavy projects like Cappuccino. For
Nodepad we're going to use jQuery UI which sits
in the middle. It gives us a lot of bang for buck when combined with a
solid theme.

For the theme, I've decided to use
Aristo (demo). It's not necessarily the best theme out there, but I've got a lot of experience
using it and I think it looks great.

Including Aristo and jQuery UI

I've downloaded Aristo from
and put it in
public/stylesheets/aristo. Then we just need to load jQuery
UI and the new stylesheet in the views/layout.jade

link(rel='stylesheet', href='/stylesheets/aristo/jquery-ui-1.8.5.custom.css')
script(type='text/javascript', src='https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js')

Page Structure

Our interface needs two columns, a header, a document body for editing,
and some buttons for document management. In Jade it might look like

div(class='outline-view', id='left')
      - for (var d in documents)
          a(id='document-title-' + documents[d].id, href='/documents/' + documents[d].id)

      a(href='#', id='delete-document')


    textarea(name='d[data]', id='editor')
      =d.data || ''

    a(href='#', id='save-button') Save

The first part, outline-view is a div that contains the
document list. This is the code we've seen before. I've positioned these
with absolute and I'm using some JavaScript on
resize and focus to resize the document list
and button toolbars.

The selected document is displayed using some CSS gradients:

.outline-view ul .selected {
  color: #fff;
  background-color: #8897ba;
  background: -webkit-gradient(linear, left top, left bottom, from(#b2bed7), to(#8897ba));
  background: -moz-linear-gradient(top,  #b2bed7,  #8897ba);

It doesn't matter if browsers don't support CSS3 gradients, it'll look
fine with just the darker colour.

Selecting Documents

Recall that our API requires .json to be appended to the
URL to get JSON data back. We just need some simple jQuery event
handling to load the document from the server:

$('#document-list li a').live('click', function(e) {
  var li = $(this);

  $.get(this.href + '.json', function(data) {
    $('#document-list .selected').removeClass('selected');


This binds a click handler that will fire whenever a document title is
clicked. It fills out the textarea with the
data value from the JSON response. Rather than a normal
event, live is used to set up a delegate in case the
document list changes.

Saving Documents

Something I like to do when creating dynamic interfaces is to set id
attributes based on database IDs, using a simple naming convention. In
Nodepad I've used DOM ids like this:
document-844ce17994ba1b87d359000001. To retrieve the database ID we just need to get the last part, which is easy if we split on the

Once that convention is established, we can use a mini jQuery plugin to
extract item IDs:

$.fn.itemID = function() {
  try {
    var items = $(this).attr('id').split('-');
    return items[items.length - 1];
  } catch (exception) {
    return null;

This makes saving documents when the save button is pressed
straightforward enough:

$('#save-button').click(function() {
  var id = $('#document-list .selected').itemID(),
      params = { d: { data: $('#editor').val(), id: id } };
  $.put('/documents/' + id + '.json', params, function(data) {
    // Saved, will return JSON

There isn't actually a HTTP verb for put in jQuery, so I defined one:

$.put = function(url, data, success) {
  data._method = 'PUT';
  $.post(url, data, success, 'json');


We haven't actually used any jQuery UI so far, but we'll get to that in
the next part. So far we've got a simple little editor that's starting
to look like something more friendly and usable.

I haven't had time to browser test yet, so stick to WebKit or Firefox.

The latest Nodepad commit was

Update: I've changed the Nodepad README to include more details on
library, binary and operating systems that I've tested it against. This
may help people who've been having trouble running it.