backbone.js: JavaScript MVC

15 Oct 2010 | By Ric Roberts | Comments | Tags data libraries underscore

backbone.js from DocumentCloud is a small (2KB, packed) open-source library which allows you to apply the MVC (Model-View-Controller) principle to your JavaScript applications. It helps provide a bit of structure for rich client side apps, by preventing you from having to tie data directly to the DOM. When models change, the views representing the data can be notified, causing them to automatically re-render.

To define a model, you extend Backbone.Model with your own properties and methods, and the framework provides ways to get and set the attributes, set up validations, serialize the object, detect if it has changed, etc. To save a valid model to the persistence layer, Backbone will delegate to its sync function and make a relevant RESTful request (using JSON by default) to the server.

Backbone proxies to DocumentCloud’s underscore library for dealing with collections of models.

For views, create a custom view class which extends Backbone.view, and then instantiate it, passing some options which can include the model, a collection, the HTML element, etc… You can define a render function on the view to setup the view (with whatever flavour of templating or DOM manipulation you like), and this can be bound to model events.

The documentation is well written and comprehensive, providing good examples, and there’s a test-suite too. Get the code on Github

Let's Make a Framework: NodeList, Collections and Arrays

14 Oct 2010 | By Alex Young | Comments | Tags frameworks tutorials lmaf dom NodeList

Welcome to part 34 of Let’s Make a Framework, the ongoing series about building a JavaScript framework.

If you haven’t been following along, these articles are tagged with lmaf. The project we’re creating is called Turing.

Last week I talked about using querySelectorAll. John-David Dalton noticed that I missed part of the process — converting the resulting NodeList into an Array. This is an important step which I’ll discuss in this part.

NodeList and Collections

DOM Level 1 defines NodeList as an abstraction of ordered collections of nodes. The specification is kept simple to avoid constraining the underlying implementation. That means collections of DOM elements can’t be directly manipulated like an array, although it’s trivial to iterate over each element:

// Get the elements
var elements = document.querySelectorAll('p');

// Iterate over each element with a simple for loop
for (var i = 0; i < elements.length; i++) {
  console.log(elements[i]);
}

To see why NodeList doesn’t do what we want, you’ll notice Array.prototype methods are missing:

document.querySelectorAll('p').push
// returns undefined

Ouch!

Another interesting point about NodeList is it’s an ordered collection. From DOM Level 1 Core:

getElementsByTagName Returns a NodeList of all descendant elements with a given tag name, in the order in which they would be encountered in a preorder traversal of the Element tree.

Over at the Mozilla NodeList documentation, they have this to say:

This is a commonly used type which is a collection of nodes returned by getElementsByTagName, getElementsByTagNameNS, and Node.childNodes. The list is live, so changes to it internally or externally will cause the items they reference to be updated as well. Unlike NamedNodeMap, NodeList maintains a particular order (document order). The nodes in a NodeList are indexed starting with zero, similarly to JavaScript arrays, but a NodeList is not an array.

This isn’t just what Mozilla implementations do, technically all browsers should. This is from the specifications:

NodeLists and NamedNodeMaps in the DOM are “live”, that is, changes to the underlying document structure are reflected in all relevant NodeLists and NamedNodeMaps.

Mozilla’s documentation also points out a gotcha that I’ve run into before:

Don’t be tempted to use for...in or for each...in to enumerate the items in the list, since that will also enumerate the length and item properties of the NodeList and cause errors if your script assumes it only has to deal with element objects.

Converting NodeList into an Array

The simplest approach is probably the best:

function toArray(collection) {
  var results = [];
  for (var i = 0; i < collection.length; i++) {
    results.push(collection[i]);
  }
  return results;
}

The major downside of this is the results will no-longer be live — the original NodeList is a reference to a set of objects rather than a fixed result set.

In the Wild

jQuery has a method called makeArray:

makeArray: function( array, results ) {
  var ret = results || [];

  if ( array != null ) {
    // The window, strings (and functions) also have 'length'
    // The extra typeof function check is to prevent crashes
    // in Safari 2 (See: #3039)
    if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
      push.call( ret, array );
    } else {
      jQuery.merge( ret, array );
    }
  }

  return ret;
}

In this code, push refers to Array.prototype.push.

When Prototype uses querySelectorAll, it wraps the output in $A() and uses .map(Element.extend) to make each element a Prototype Element. This is similar to the above, with the exception of Prototype extending each element.

Some other frameworks wrap the results in their own NodeList class, rather than converting them to an array.

Implementation

The toArray function described above has been added to turing.core.js in the form of turing.toArray and added to turing.dom.get.

References

Node Roundup

13 Oct 2010 | By Alex Young | Comments | Tags node server games screencasts email

Welcome to the Node Roundup. Send in your apps and libraries using our contact form or @dailyjs.

NodeCasts

NodeCasts.org has a screencast about Node by Emerson Macedo, hosted on YouTube with 720p available. He has a Twitter account at @NodeCasts where you can request topics for future casts.

Nodecraft

Have you been playing Minecraft? One of my Minecraft buddies found Nodecraft by Jeremy Apthorp. It’s not intended for general use yet, but there’s some interesting JavaScript in there, like protocol.js. You can see stuff like the server packet structure:

var serverPacketStructure = {
	0x00: [],
	0x01: [int('playerID'), str('serverName'), str('motd')],
	0x02: [str('serverID')],
	0x03: [str('message')],
	0x04: [long('time')],
	0x05: [int('invType'), items('items')],
	0x06: [int('x'), int('y'), int('z')],
	0x0d: [double('x'), double('y'), double('stance'), double('z'),
	       float('rotation'), float('pitch'), bool('flying')],

I have a feeling Node would be a pretty good platform for a game server. I don’t know if Apthorp intends to keep working on this, but it’s still interesting to look at what he’s done so far.

Tempalias

Tempalias (MIT) by Philip Hofstetter is a Node app for generating temporary email addresses. It’s actually used by tempalias.com.

The frontend code is pure HTML/CSS/JavasScript using Sammy for the interesting part of the logic. You will find that in public/*. The beef of the code lies in the SMTP proxy (lib/tempalias_smtp.js) and in the model class representing an alias (lib/tempalias.js). Static webpages are served by the web server (lib/tempalias_http.js) using node-paperboy which is – as are all other dependencies – located in deps/ as a git submodule.

It’s been around for a while, but it looks like it’s still alive. It’s one to file under your ‘full node app’ bookmarks.

jQuery Roundup

12 Oct 2010 | By Alex Young | Comments | Tags jquery plugins

Welcome to the jQuery Roundup 27. You can send your plugins in for review through our contact form or @dailyjs.

jQuery 1.4.3 Release Candidate 1

jQuery 1.4.3 Release Candidate 1 has been released. The areas that have major changes are:

  • CSS handling methods
  • Logic for determining element visibility and toggling of display in animation code
  • Traversing logic (is, filter, closest, find)

There’s no release notes yet (unless you feel like reading through lots of commit logs):

Full details concerning the release are forthcoming – for now we just need your help in catch regressions.

jQuery at Dusk

jQuery at Dusk by James Padolsey is a book about jQuery. It refers to jQuery’s internals a bit like our Let’s Make a Framework series, so if you’re an experienced jQuery hacker but haven’t tinkered under the hood it might be worth reading. The book has been around a while (last update was 29th March), but it’s new to me.

jQuery Placeholder

jQuery Placeholder (MIT and GPL) by Michael J. Ryan adds placeholder text to input fields using a label tag:

This tag will then be absolutely positioned over the text input, so that it displays over the top when the input has no value, and is not focused.

The author has provided some suitable CSS, referencing html5 placeholder support.

jQuery-Placeholder

Almost the same day, Daniel Stocks sent us jQuery-Placeholder. Is there some kind of war of placeholder supremacy going on? Anyway, this one is designed to bring HTML5 placeholder support back to older browsers. Stocks says it supports IE6 as well. There’s a demo with more browser support details.

jQuery Collapse

I noticed the same author also created jQuery-Collapse (available on GitHub) which can be used to make “progressive disclosure” panels, with state saved to cookies.

The plugin has been designed with WAI-ARIA in mind which defines a way to make Web content and Web applications more accessible to people with disabilities.

Functional Koans, Ringo 0.6

11 Oct 2010 | By Alex Young | Comments | Tags technique functional ringo

Functional Koans by David Laing is a way of learning functional JavaScript through testing. Each koan has associated tests that fail, and your job is to correct the code to make them pass. The koans presents a fundamental concept which you must master to be able to fix the code.

The project is based on Ruby Koans by Jim Weirich, which made a fairly big impact amongst Ruby developers. The word Koan is used in reference to Zen Buddhism:

As part of the training of teachers, monks, and students, koan can refer to a story selected from sutras and historical records. They may consist of a perplexing element or a concise but critical word or phrase extracted from the story.

Ringo 0.6

Ringo 0.6 is out, which includes improvements to http server and client libraries, no more extending JavaScript objects (that code is now effectively namespaced), CommonJS unit testing, and bunch of other changes.

The RingoJS tutorial has “App Engine Deployment” listed in the table of contents, but the content hasn’t been written yet. Gabriel Munteanu took this example and extended it to work more like a fully-functional blog, and called it Ringopress. The project’s documentation explains how to configure and deploy App Engine. If you’re new to Ringo or App Engine, this might be a nice project to play around with.

If you haven’t yet looked into App Engine and JavaScript, AppengineJS is a JavaScript port of the Python SDK by George Moschovits.

eyeballs.js, Artisan JS, Markup.io

08 Oct 2010 | By Alex Young | Comments | Tags graphics canvas libraries

eyeballs.js

eyeballs.js (MIT License) by Paul Campbell is an MVC framework that works with a library like jQuery or Prototype, yet provides a layer of features for organising your code.

eyeballs.js can sit on top of an already implemented web app with a well thought out object model. It can also be used to build standalone javascript apps, backed by HTML5 local storage or something like CouchDB.

Models are defined like this:

o_O('Post', function(post) {});

o_O('Post', function(post) {
  post.validates_presence_of('title')
});

var post = Post.initialize({ title: 'All work and no play makes Alex...' });

Now you can see where the library gets its name from. I’m not sure if I’ll get tired of typing o_O, admittedly it made me laugh.

Routing and controllers work using the URL hash, much like many similar frameworks out there. The framework ships with tests and a little Sinatra app so REST can be tested.

Artisan JS

Artisan JS (GPL/MIT) by David Brooks is another Canvas library. It targets Canvas specifically, so it doesn’t work with IE. You might be wondering why you’d bother with such a library when Raphael is cross-browser and very popular; well, it may suit projects when you really do only need to work with Canvas but you’re frustrated with the Canvas API.

Brooks has included support for layered data — graphics can be layered and flattened when rendered, but the data remains. This means the data can continue to be manipulated after it is rendered — read more in Layers in Artisan JS.

The Artisan site has some good documentation, and there’s also a GitHub repository at davidbrooks / Artisan.

Markup.io

I don’t usually feature commercial projects here — this site is more of an open source kind of place. But I was impressed by Markup.io, it’s a web annotation service built using Node, Express and Connect.

Whenever I work with new technology my boss at the time (or client) asks “so what commercial projects are built with this?” I’m going to add Markup.io to my growing list of JavaScript server-side app bookmarks. Please send yours in as well, whether they’re Node, Rhino, Ringo, Narwhal… or something else!

Let's Make a Framework: Feature Detection

07 Oct 2010 | By Alex Young | Comments | Tags frameworks tutorials lmaf

Welcome to part 33 of Let’s Make a Framework, the ongoing series about building a JavaScript framework.

If you haven’t been following along, these articles are tagged with lmaf. The project we’re creating is called Turing.

Last week I wrote about packaging the project using Node scripts. This week I’m going to talk about feature detection.

querySelectorAll

The selector engine we built for the core of turing.dom was based on the way Firefox interprets CSS selectors. I liked the approach for the context of these tutorials, because it’s a very pragmatic approach that’s easy to follow.

Browsers have been shipping with querySelectorAll for a while, which reduces the amount of work required to implement DOM lookups.

That means turing.dom.get could be rewritten:

// Original code minus all the
// magic in the Searcher class and tokenizer
dom.get = function(selector, root) {
  var tokens = dom.tokenize(selector).tokens,
      searcher = new Searcher(root, tokens);
  return searcher.parse();
};

// New selector API
dom.get = function(selector) {
  return document.querySelectorAll(selector);
};

But not all browsers support this yet, so let’s check if it’s available:

dom.get = function(selector) {
  var root = typeof arguments[1] === 'undefined' ? document : arguments[1];
  if ('querySelectorAll' in document) {
    return root.querySelectorAll(selector);
  } else {
    return get(selector, root);
  }
};

In the Wild

jQuery will check for querySelectorAll, but it’ll only use it under certain conditions. This is from jQuery 1.4.2:

if (document.querySelectorAll ) {
  (function(){
    var oldSizzle = Sizzle, div = document.createElement("div");
    div.innerHTML = "<p class='TEST'></p>";

    // Safari can't handle uppercase or unicode characters when
    // in quirks mode.
    if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
      return;
    }

    Sizzle = function(query, context, extra, seed){
      context = context || document;

      // Only use querySelectorAll on non-XML documents
      // (ID selectors don't work in non-HTML documents)
      if ( !seed && context.nodeType === 9 && !isXML(context) ) {
        try {
          return makeArray( context.querySelectorAll(query), extra );
        } catch(e){}
      }

      return oldSizzle(query, context, extra, seed);
    };

    for ( var prop in oldSizzle ) {
      Sizzle[ prop ] = oldSizzle[ prop ];
    }

    div = null; // release memory in IE
  })();
}

The use of an element for capability detection is common in frameworks — sometimes it’s the only reliable way of detecting a browser’s behaviour.

It’s a little bit different in Dojo 1.5, but the same Safari issue is mentioned:

  // some versions of Safari provided QSA, but it was buggy and crash-prone.
  // We need te detect the right "internal" webkit version to make this work.
  var wk = "WebKit/";
  var is525 = (
    d.isWebKit && 
    (nua.indexOf(wk) > 0) && 
    (parseFloat(nua.split(wk)[1]) > 528)
  );

  // IE QSA queries may incorrectly include comment nodes, so we throw the
  // zipping function into "remove" comments mode instead of the normal "skip
  // it" which every other QSA-clued browser enjoys
  var noZip = d.isIE ? "commentStrip" : "nozip";

  var qsa = "querySelectorAll";
  var qsaAvail = (
    !!getDoc()[qsa] && 
    // see #5832
    (!d.isSafari || (d.isSafari > 3.1) || is525 )
  );

  //Don't bother with n+3 type of matches, IE complains if we modify those.
  var infixSpaceRe = /n\+\d|([^ ])?([>~+])([^ =])?/g;
  var infixSpaceFunc = function(match, pre, ch, post) {
    return ch ? (pre ? pre + " " : "") + ch + (post ? " " + post : "") : /*n+3*/ match;
  };

  var getQueryFunc = function(query, forceDOM){
    //Normalize query. The CSS3 selectors spec allows for omitting spaces around
    //infix operators, >, ~ and +
    //Do the work here since detection for spaces is used as a simple "not use QSA"
    //test below.
    query = query.replace(infixSpaceRe, infixSpaceFunc);

    if(qsaAvail){
      // if we've got a cached variant and we think we can do it, run it!
      var qsaCached = _queryFuncCacheQSA[query];
      if(qsaCached && !forceDOM){ return qsaCached; }
    }

    // Snip

Here the browser and version are derived from the user agent string.

has.js

I recently wrote about has.js which is a clever little project that contains a library of feature detection tests.

Browser sniffing and feature inference are flawed techniques for detecting browser support in client side JavaScript. The goal of has.js is to provide a collection of self-contained tests and unified framework around using pure feature detection for whatever library consumes it.

Using has.js as inspiration, we should be able to rewrite the previous code like this:

dom.get = function(selector) {
  var root = typeof arguments[1] === 'undefined' ? document : arguments[1];
  return turing.detect('querySelectorAll') ?
    root.querySelectorAll(selector) : get(selector, root);
};

Feature Detection Implementation

Making a library of feature tests is fairly easy with a plain Object. Tests can be referred to by name and easily looked up at runtime. Also, a cache can be used to store the results of the tests.

The core of this functionality is something inherent to JavaScript programming rather than just browser-related, so I put this in turing.core.js:

var testCache = {},
    detectionTests = {};

turing.addDetectionTest = function(name, fn) {
  if (!detectionTests[name])
    detectionTests[name] = fn;
};

turing.detect = function(testName) {
  if (typeof testCache[testCache] === 'undefined') {
    testCache[testName] = detectionTests[testName]();
  }
  return testCache[testName];
};

The results are cached because they should only be run once. This type of capability detection is intended to be used against the environment, rather than features that might load dynamically in runtime, so I think it’s safe to run the tests once.

Then the jQuery-inspired querySelectorAll test can be added in turing.dom.js:

turing.addDetectionTest('querySelectorAll', function() {
  var div = document.createElement('div');
  div.innerHTML = '<p class="TEST"></p>';

  // Some versions of Safari can't handle uppercase in quirks mode
  if (div.querySelectorAll) {
    if (div.querySelectorAll('.TEST').length === 0) return false;
    return true;
  }

  // Helps IE release memory associated with the div
  div = null;
  return false;
});

Conclusion

Looking through popular JavaScript frameworks made me realise that most of them still use the user agent string to determine what capabilities are available. This might be fine most of the time, but I don’t consider it best practice. The way jQuery tests capabilities using techniques like the dummy DOM element creation seems like a lot of work, but it relies on browser behaviour rather than the user agent string.

I originally wanted to write this article about querySelectorAll and its family of related methods, but adding generic capability detection support became an interesting little rabbit hole. I hope this illustrates how simple tasks can require extra effort to make code highly reusable.

Node Roundup

06 Oct 2010 | By Alex Young | Comments | Tags node server testing sockets

Welcome to the Node Roundup. Send in your apps and libraries using our contact form or @dailyjs.

Faker.js

Faker.js (MIT License) by Marak Squires can be used in Node or a browser. It allows fake data to be generated, for testing or rapid prototyping:

var Faker = require('./Faker');
Faker.Name.findName(); // Maximillia Hodkiewicz
Faker.Internet.email(); // Gabriella.Hermann@bartholome.co.uk

There’s a demo showing the types of data the library can generate.

I like using libraries like this with factories for quickly writing tests (yes, I’m that lazy!)

Nodestream

Nodestream released through LearnBoost under an MIT License is a library used to connect realtime code to templates. It’s built on Jade and Socket.IO and adds a :realtime option to your Jade templates.

The simple example in the documentation demonstrates how to count the number of people viewing your site:

var connections = 0;
var nodestream = io.listen(app).nodestream()
  .on('connect', function(){
    connections++;
    this.emit('connections', connections);
  })
  .on('disconnect', function(){
    connections--;
    this.emit('connections', connections);
  });

Template:

:realtime(repaint: 'connections', local: 'connections')
  .connections
    - if (connections > 1)
      p #{connections} people are editing right now
    - else
      p You're all alone, loser

The Socket.IO library (server, client) supports various transports depending on the browser: WebSocket, Flash, forever iframe, XHR long polling, and XHR multipart encoded. These are abstracted to look like a WebSocket-like API.

Soda

Also from LearnBoost (by TJ Holowaychuk and Adam Christian) is Soda, which is a Selenium adapter for Node. This allows you to script browser tests, like this:

browser
  .chain
  .session()
  .open('/')
  .type('q', 'Hello World')
  .testComplete()
  .end(function(err){
    if (err) throw err;
    console.log('done');
  });

Lingo

Meanwhile, I noticed TJ has released Lingo, which provides inflection support and other string transformations. For example:

en.pluralize('fox');
// foxes

en.singularize('foxes');
// fox

lingo.capitalize('hello there');
// Hello there

There’s i18n support and a bunch of other methods.

STDIN Support for Node

While I was looking through Lingo I saw that TJ also wrote a Node patch to add STDIN args. His patch adds – and —stdin flags to the command line arguments. I didn’t realise Node couldn’t do this already, which is surprising because it’s pretty important for shell scripts.

jQuery Roundup

05 Oct 2010 | By Alex Young | Comments | Tags jquery plugins video html5

Welcome to the jQuery Plugin Roundup 26. You can send your plugins in for review through our contact form or @dailyjs.

jquery-swapable

jquery-swapable (MIT License) by Vadim Kiryukhin is a little bit like Sortable but instead swaps items. Usage is similar to Sortable, except it also requires a cursorAt parameter:

$('#swappable').swappable({
  items: '.itemClass',
  cursorAt: { top: -10 } 
});

It will work with lists, grids, and horizontal rows.

The project is hosted on Google Code: jquery-swapable.

jQuery Templates

I’ve mentioned Scott Guthrie’s Microsoft-supported jQuery plugins before, but now there’s news jQuery Templates will be included with jQuery 1.5.

Read more in jQuery Templates, Data Link, and Globalization Accepted as Official jQuery Plugins.

jquery.sg.video

jquery.sg.video (MPL) by Filippo Pacini is based on Video for Everybody, an idea put forward by Kroc Camen. The plugin uses feature detection from Modernizr, and can provide information on format support through $.support.video. For example, the browser I’m using right now returns this:

{"ogg": "", "h264": "probably", "webm": ""}

If your videos have the same file name with different extensions for each format, you can set up a video like this:

 $('#video-container').video('video_file_name', options);

This is a minimal yet useful plugin — most video plugins attempt to provide a complete solution, with fancy player graphics and other features. This one keeps things simple instead.

A Look Inside Zepto.js

04 Oct 2010 | By Alex Young | Comments | Tags libraries mobile

Zepto.js is a small library for working with mobile WebKit browsers by Thomas Fuchs and released under the MIT License. The library’s API is similar to jQuery, allowing method chaining, and familiar syntax for and element functions. Here are a few examples:

// Return paragraph tags
$('p')

// Change the HTML inside a paragraph
$('p').html('Hello World')

// Change the style too
$('p').html('Hello World').css('background-color: red')

// Iterate over each element
$('div').each(function(element) {
  // element is the actual node
})

// Animate an element using webkit-transform
$('div').anim('rotate(720deg)', 0.5, 10);

Zepto contains a lot of tricks to keep the library size down. Targeting WebKit is one way it keeps a smaller size — if you follow our framework series you’ll know how much work cross-browser support can be.

The first thing I noticed was a lot of void 0, rather than a comparison against undefined or typeof variable === 'undefined'.

The chained API is created by returning fn inside $():

function fn(_){ return fn.dom.forEach(_), fn }

Because $() can accept many different types (Array, String, Element), there’s a complicated set of ternary operators to correctly set up the DOM querying state. It looks confusing at first, but there’s some neat code in there. For example, to check if the function has already been run on the argument, (typeof _ == 'function' && 'dom' in _) will return true. Here the in operator is used to detect a property. Just to illustrate:

'dom' in { 'dom': 'example', 'another': 'example 2' }
// true
'another' in { 'dom': 'example', 'another': 'example 2' }
// true
'example' in { 'dom': 'example', 'another': 'example 2' }
// false

Fuchs has been actively updating Zepto since he announced it. It’s full of interesting tricks to keep space down (like Emile), but use what you learn from these libraries with caution — they’re specifically designed to be small rather than easy for colleagues and collaborators to read!

Fuchs also released JS1k intro: fun with CSS transforms and hardware acceleration today (madrobby / js1k-finals) which is like a mini old school scene demo.

Game Tutorial, has.js, getElementsByTagName Performance

01 Oct 2010 | By Alex Young | Comments | Tags games html5 dom libraries

Tutorial: Simple Game with HTML5 Canvas

Michal Budzynski has written another HTML5 game tutorial. This one is a five part series: here’s part one.

These tutorials are based on Michal’s 10k entry, and cover set up, animation, physics, controls, collisions, scrolling, and game states.

has.js

has.js by Peter E Higgins, tentatively released under three licenses (Academic Free License, New BSD License, and the MIT License), is a library of tests for feature detection. The author’s first example illustrates the intended usage:

mylibrary.trim = has('string-trim') ? function(str) {
    return (str || '').trim();
} : function(str) {
    /* Implement trim here */
}

Tests can be added like this:

has.add("some-test-name", function(global, document, anElement) { });

Higgins mentions that it’s likely that people will use portions of the library rather than the entire thing. The project doesn’t have a build script yet, but I imagine in future their build script will allow the required tests to be specified to.

Take a look at the tests in detect/ to get a feel for the library.

Why is getElementsByTagName() faster that querySelectorAll()?

In Why is getElementsByTagName() faster that querySelectorAll()? Nicholas C. Zakas discusses the performance characteristics of the NodeList object for static and live NodeLists.

The author refers to WebKit source code, so he’s dug into the issue pretty deeply:

Live NodeList objects can be created and returned faster by the browser because they don’t have to have all of the information up front while static NodeLists need to have all of their data from the start. To hammer home the point, the WebKit source code has a separate source file for each type of NodeList: DynamicNodeList.cpp and StaticNodeList.cpp.

Let's Make a Framework: Node Packaging

30 Sep 2010 | By Alex Young | Comments | Tags frameworks tutorials lmaf node packaging

Welcome to part 32 of Let’s Make a Framework, the ongoing series about building a JavaScript framework.

If you haven’t been following along, these articles are tagged with lmaf. The project we’re creating is called Turing.

Last week I wrote about building an event delegation chaining API. This week I’m going to talk about packaging.

Packaging with Node

In part 12 I talked about using Narwhal to create a Jakefile to build and minimise Turing. I thought it would be interesting to look at doing the same thing with Node, because I know a lot of DailyJS’s readers already have Node installed.

I’m using node-jake, available from npm with npm install jake.

Detecting Node or Rhino

At the moment Narwhal uses Rhino. Narwhal and Node have slightly different globals available, so I’m using these to detect the active environment:

if (typeof global.system === 'undefined') {
  nodeTasks();
} else {
  narwhalTasks();
}

If you’re writing your own build tasks I strongly recommend selecting a single build tool (or perhaps one to suit each major platform). My Jakefile only caters for both to support these tutorials, it’s actually rather impractical.

File Concatenation

I’ve made the concat task synchronous to make it easier to read:

task('concat', [], function () {
  var files = ('turing.core.js turing.oo.js turing.enumerable.js '
              + 'turing.functional.js turing.dom.js turing.events.js '
              + 'turing.touch.js turing.alias.js turing.anim.js').split(' '),
      filesLeft = files.length,
      pathName = '.',
      outFile = fs.openSync('build/turing.js', 'w+');

  files.forEach(function(fileName) {
    var fileName = path.join(pathName, fileName),
        contents = fs.readFileSync(fileName);
    sys.puts('Read: ' + contents.length + ', written: ' + fs.writeSync(outFile, contents.toString()));
  });
  fs.closeSync(outFile);    
});

The output file is opened first, then each file is read into it.

Minifier

There’s also a npm package for minimising JavaScript, called node-jsmin. It’s pretty easy to use:

var jsmin = require('jsmin').jsmin;
jsmin(code);

This is based on Crockford’s original script. You might get better results by pasting Turing into Google Closure or Dean Edwards’ Packer.

For now I’m going to stub this task out until there’s a better minifier.

I haven’t found any particularly strong minifiers for Node yet. jQuery actually uses Google’s compiler, as a Jar file. That means they can also run jslint as well, which is useful. These could be run in our Jakefile simply by shelling out. It’s also interesting to note that jQuery will build with unix make, Ruby’s rake and ant (which makes life easier for Windows users).

Organising Tasks

node-jake allows you to run a list of tasks before the current one:

desc('Main build task');
task('build', ['concat', 'minify'], function() {});

This is equivalent to the old Narwhal build task:

jake.task('build', ['concat', 'minify'])

280 North’s Jake is clever enough to realise a function hasn’t been specified, whereas the current version of node-jake will crash if you run: task('build', ['concat', 'minify']);

Running Tasks

After installing node-jake, run it with jake -T to see a list of tasks. To build the project, run jake build.

A default task could be added (called default) but I’d like to use that to generate documentation and I haven’t picked a JavaScript-friendly documentation system to do that yet.

Conclusion

Both node-jake and 280 North’s Jake are largely compatible, and are good choices for your own project. If you’re working on a node or Narwhal project, the choice is obvious, but when you’re building a web-based library it’s really up to you.

Node Roundup

29 Sep 2010 | By Alex Young | Comments | Tags node server benchmarks

Welcome to the Node Roundup. Send in your apps and libraries using our contact form or @dailyjs.

Node.js Memory and GC Benchmarks

In Update on my Node.js Memory and GC Benchmark by Hannes Wallnöfer, the author discusses a conversation with Ryan Dahl about Node’s garbage collection performance in reference to RingoJS vs. Node.js: Runtime Values.

V8 uses a stop-the-world garbage collector, which technically means it will stop execution when performing garbage collection. The intention of V8’s design is to make an accurate and reliable garbage collector. The Design Elements document explains this in more detail.

What Wallnöfer appears to be saying is V8 isn’t perfectly tuned to the types of workloads we see in web applications. I think he makes a good point, but as I haven’t had any gripes about real world performance with Node it’s not something I’m too worried about right now.

Nutshell

Nutshell by Shahriar Haque, available at shahriarhaque / nutshell is a unix shell that runs on Node. The author’s example makes usage pretty clear:

ls -l | filter ""function(file) { return file.size < 2000; }""

In a sh style shell this would be written as follows:

ls -l | awk '{ if ($5 < 2000) { print $0 }}'

Haque’s idea is to try to make the shell more intuitive:

But if the second command is to do anything useful with this input, it has to go and parse it first. That’s what the awk command is doing. It is splitting the output of ls -l ,taking the 5th token of each line, performing the comparison, and printing the whole line if the test succeeds. This is where shell scripting is unproductive. It’s all about parsing output

Why node.js disappoints me

Why node.js disappoints me by Eric Florenzano is a brief critique of Node. I feel like the author might be a little irked by the constant stream of excited coverage (Hacker News loves those Node articles), but I still found the post interesting.

Yet one of Node’s advantages that you’ll hear repeated again and again by its proponents is that you can now code in One Language, and you won’t have to deal with the cognitive load of context switching between different languages.

I personally haven’t heard that sentiment repeated “again and again” — I became interested in Node because I respected the work that went into V8 and enjoy writing JavaScript. My JavaScript skills carry over intuitively and Node builds easily on all of my platforms, so I never really thought about it like that.

He also mentions that people have written libraries for Node that depend on Node, which effectively makes the Node environment a subset of JavaScript. There are libraries out there which are distributed with npm but work in a browser or another JavaScript interpreter. I’m not sure if the author is familiar with CommonJS, but the Node developers certainly don’t work in ignorance of it.

The article has some good comments by the usual suspects (Tim Caswell for example), which are generally not of the screaming-and-pitchfork-waving variety but more like a real conversation.

jQuery Roundup

28 Sep 2010 | By Alex Young | Comments | Tags jquery plugins forms graphics

Welcome to the jQuery Plugin Roundup 25. You can send your plugins in for review through our contact form or @dailyjs.

Lettering.js

Lettering.js by Dave Rupert (and some other folks) can split a container into spans that contain each letter, like this:

$(".fancy_title").lettering();

Which generates:

<h1 class="fancy_title">
  <span class="char1">S</span>
  <span class="char2">o</span>
  <span class="char3">m</span>
  <span class="char4">e</span>
  <span class="char5"></span>
  <span class="char6">T</span>
  <span class="char7">i</span>
  <span class="char8">t</span>
  <span class="char9">l</span>
  <span class="char10">e</span>
</h1>

It’s hard to visualise what kind of effects might be possible with this plugin, but the heading in the blog post is a great example (pictured above).

Word wrap can also be used. The author makes an interesting point about performance in the blog post:

Unfortunately, we found the best solution to avoid/minimize the FOUT caused by this plugin is to put your scripts (jQuery, Lettering.js) in the document . On the one hand, your page will load slower. On the other hand, a flash/restyling makes your site feel slow. Users might ultimately feel the site is faster if they don’t see the FOUT.

This plugin is available on GitHub: davatron5000 / Lettering.js. There’s no licensing information yet.

jSlider

I’ve covered quite a few of these plugins now, but this one is shaping up to be a smart little project. jSlider (GPL/MIT) by Fredrik Forsmo is an extensible image slider. Just run $.jSlider('#container') and you’re done.

The project is on GitHub at Frozzare / jSlider.

Catch My Fame

The Catch My Fame site also has a lot of jQuery gallery plugins. Panel Gallery in particular has a lot of effects and is interesting because it doesn’t require images to be sliced or edited, it’ll shove images into containers appropriately.

JSConf.eu

27 Sep 2010 | By Alex Young | Comments | Tags conferences events

JSConf.eu – 2010 was this weekend, so a lot of interesting things have been going on in the JavaScript community. I wasn’t actually at the conference, but Oleg (who interviewed Ryan Dahl) stopped by, which means we should have more awesome interviews soon.

Videos of the talks haven’t been posted yet, so keep your eyes on @jsconfeu.

JS1k Winners

The JS1k winners were announced at the conference, with Legend Of The Bouncing Beholder by Marijn Haverbeke taking the top prize. This is also one of the demos that most impressed me, in particular the whimsical graphics.

I feel like this contest was a huge success, and has been both well-received and respected by the community. I look forward to the next one!

Slides

I’ve compiled all the slides I could find from the talks:

Announcements

Joyent quietly announced a limited public beta of their Node.js service. The people who have been playing with it seem impressed so far.

Promotejs.com was widely shared during the conference. It’s an attempt to get better search engine results for serious JavaScript documentation (instead of dodgy dotcom-era sites).

Sound bites

‘Does it run JavaScript’ is the new ‘Does it run Linux’ @phiggins

Don’t know about you, but to me, giving a talk with Brendan Eich and Douglas Crockford in the audience is pretty intimidating. :-) @robertnyman

I don’t know an unemployed JavaScript developer. @rmurphey

surrounded by sleepless drunk people listening to crockford – it must be jsconf @aq

Thanks all for making this night so very memorable. @jsconfeu

Son, Sequelize

24 Sep 2010 | By Alex Young | Comments | Tags libraries databases templating

Sequelize

Sequelize by Sascha Depold is an ORM for Node and MySQL. It can be installed with npm install sequelize. Creating mappings to tables is straightforward:

var Project = sequelize.define('Project', {
  title: Sequelize.STRING,
  description: Sequelize.TEXT
})

After defining these structures, Sequelize can create suitable tables:

Project.sync(function(table, error) {
})

This library also supports associations:

Project.hasMany('tasks', Task, 'projects')

And finders with a familiar API:

Project.find(1, function(project) {
})

I like the look of the chainQueries method, which is a query chaining helper.

Son

Son by Tim Farland converts JSON to CSS — it’s a little bit like Sass but designed to be more JavaScript-native. This example is provided in the README:

(function(){
  var myColour = '#ff0000';
  var styles = {
    "#navbar": {
      width: "80%",
      height: "23px",
      ul: {
        list: {
          "style-type":  "none"
         }
      },
      li: {
          "float": "left",
          border: "1px solid " + myColour,
          padding: "10px",
          a: {
              "font-weight": "bold",
              color: myColour
          }
      }
  };

  return styles;
})();

As well as variable support, it also has a mixin helper. The author has written up a list of gotchas and ideas for future features, so it seems like he’s using it actively.

Let's Make a Framework: Event Delegation 2

23 Sep 2010 | By Alex Young | Comments | Tags frameworks tutorials lmaf dom events

Welcome to part 31 of Let’s Make a Framework, the ongoing series about building a JavaScript framework.

If you haven’t been following along, these articles are tagged with lmaf. The project we’re creating is called Turing.

Last week I wrote about event delegation in popular frameworks. This week I’ll demonstrate a simple implementation for Turing.

dom.findElement

This method will make dealing with event delegation much easier. Recall last week’s tutorial:

$('navigation').observe('click', function(event) {
  var element = event.findElement('a');
  if (element) {
    // Handler
  }
});

This Prototype code simply uses the event’s target element to see if it matches a selector. Turing’s delegation API could wrap this up a method with a signature like this:

turing.events.delegate(document, selector, 'click', function(e) {
  // Handler
});

The body of delegate will look a bit like the Prototype example above.

There’s a few obstacles to building findElement with Turing’s event library as it stands though. A few months ago we built a class called Searcher that can recurse through the DOM to match tokenized CSS selectors.

The Searcher class could be reused to implement findElement, the matchesAllRules method in particular is of interest.

Tests

I’d like the following tests to pass (events.js):

given('a delegate handler', function() {
  var clicks = 0;
  turing.events.delegate(document, '#events-test a', 'click', function(e) {
    clicks++;
  });

  should('run the handler when the right selector is matched', function() {
    turing.events.fire(turing.dom.get('#events-test a')[0], 'click');
    return clicks;
  }).equals(1);

  should('only run when expected', function() {
    turing.events.fire(turing.dom.get('p')[0], 'click');
    return clicks;
  }).equals(1);
});

To get there, we need findElement and corresponding tests (dom.js):

given('a nested element', function() {
  var element = turing.dom.get('#dom-test a.link')[0];
  should('find elements with the right selector', function() {
    return turing.dom.findElement(element, '#dom-test a.link', document);
  }).equals(element);

  should('not find elements with the wrong selector',function() {
    return turing.dom.findElement(turing.dom.get('#dom-test .example1 p')[0], 'a.link', document);
  }).equals(undefined);
});

This test depends on the markup in dom_test.html.

Adapting the Searcher Class

After I looked at matchesAllRules, in turing.dom.js I realised it shouldn’t be too hard to make it more generic. It previously took an element and searched its ancestors, but we need to include the current element in the search.

To understand why, consider how findElement should work (this is simplified code):

dom.findElement = function(element, selector, root) {
  while (element) {
    if (matchesAllRules(selector, element)) {
      // We've found it!
      return element;
    }
    // Else try again with the parent
    element = element.parentNode;
  }
};

All I had to do was refactor code that relies on matchesAllRules to pass an element’s parentNode instead of the element itself.

The start of the matchesAllRules method now looks slightly different:

Searcher.prototype.matchesAllRules = function(element) {
  var tokens = this.tokens.slice(), token = tokens.pop(),
      matchFound = false;

The code that refers to the ancestor element has been removed and the element argument is used instead.

The Event Delegation Method

We need to wrap the user’s event handler with one that checks the element is one we’re interested in, and other than that it’s standard Turing event handling:

if (turing.dom !== 'undefined') {
  events.delegate = function(element, selector, type, handler) {
    return events.add(element, type, function(event) {
      var matches = turing.dom.findElement(event.target, selector, event.currentTarget);
      if (matches) {
        handler(event);
      }
    });
  };
}

This code checks to see if dom is available because we don’t want interdependence between the modules. Then it sets up a standard event handler and uses findElement to ensure the event is one we’re interested in.

Conclusion

This implementation is very naive and there’s no easy delegate event removal, but it illustrates the fundamentals: event delegation depends on existing DOM methods and event handling to be developed in a reusable style.

Node Roundup

22 Sep 2010 | By Alex Young | Comments | Tags node server twitter

Welcome to the Node Roundup. Send in your apps and libraries using our contact form or @dailyjs.

Streamie

Streamie (try Streamie here) by Malte Ubl is a Twitter client implemented with Node — the source is released under a Simplified BSD License. The author has tried to make the project as cutting edge as possible, using HTML5 and CSS3. He has also written a great blog post detailing how to get started hacking your own version: I just forked a running website: Streamie.org.

The project uses lots of other interesting things, like Less.js, Require.js, and Socket.IO.

daemon.node

daemon.node is a Node module for creating daemons. The author also wrote a blog post, Writing Daemons in Javascript with node.JS which is informative if you haven’t done that sort of thing before. The process is similar to most languages, and in this instance the module is implemented in C++.

node-video

node-video by Peteris Krumins is a module for encoding Theora/Ogg videos from RGB buffers. The author said the following on his blog, catonmat.net:

I wrote this module for my StackVM startup so that anyone could record virtual machine video screencasts. See StackVM demo video #1 at around 1min 23secs, where I demo this module in action.

jQuery Roundup: UI

21 Sep 2010 | By Alex Young | Comments | Tags jquery plugins forms graphics

Welcome to the jQuery Plugin Roundup 24. You can send your plugins in for review through our contact form or @dailyjs.

In this week’s jQuery Roundup I’m going to review some of my favourite jQuery UI themes and related extensions.

jQuery UI

If you’re not familiar with jQuery UI, it’s a collection of useful abstractions for animations and themeable widgets. The APIs for each component are consistent and easy to learn.

jQuery UI is split into interactions, widgets, and effects. Interactions include things like a drag and drop API, which can be combined with most interface elements to give your application an intuitive feel. Widgets are high-level, with a nice Datepicker and tabs. The effects APIs will be familiar to those of you schooled in Scriptaculous.

The jQuery UI design and planning wiki has a status for current and planned work. There are many useful things in the planning stage, in particular the tree view and even a data visualisation API.

Aristo

Aristo by Tait Brown (demo) is a theme based on Cappuccino’s theme. The look and feel is best described as Mac-like, and you can get great results with little effort.

It’s licensed under Attribution-ShareAlike 3.0 which allows you to remix and share the work. You must attribute the theme, and it’s distributed under permission from 280 North and Pinvoke.

Absolution

Absolution by Michaël Vanderheeren (demo) is another jQuery theme that attempts to go beyond the defaults provided by jQuery UI. The author actively updates the repository (as do the Aristo developers).

Uniform

We’ve covered Uniform before, and it’s not specifically for jQuery UI, but it works well in combination with it. Uniform replaces standard form controls with themed ones which work like real controls but are cross-browser (and arguably look better).

Pixastic, JavaScript TLS

20 Sep 2010 | By Alex Young | Comments | Tags cryptography graphics

Pixastic

Pixastic (MPL) uses the canvas element to apply effects to images. The supported effects include blur, noise, emboss, brightness/contrast, desaturate, and noise removal.

The source code is available on GitHub under jseidelin/pixastic. There’s also a photo editor demo that uses the library.

Like many similar libraries, the core of the plugin relies on getImageData from the canvas API.

A JavaScript TLS Implementation

Forge is a JavaScript TLS implementation. TLS (Transport Layer Security) is a cryptographic protocol for secure client/server communication. Forge currently depends on Flash for sockets, but it could remove the dependency in the future.

The authors have written a detailed background to the library in two parts, including the rationale behind implementing TLS in JavaScript: