jQuery Roundup: 1.7 RC2, jQote2, jquery.factory, Native Fullscreen

01 Nov 2011 | By Alex Young | Comments | Tags jquery plugins fullscreen templating

Note: You can send your plugins and articles in for review through our contact form or @dailyjs.

jQuery 1.7 RC2

jQuery 1.7 RC2 is out, with a Halloween-themed announcement:

In RC2, we fixed a tricky problem that sometimes caused Internet Explorer 8 to go full-zombie when jQuery was loaded. Appropriately enough, the crash was related to creating a detached <body> element that we were using to perform feature detection. IE8 seems frightened to a crashy death when it sees a detached body. If you still see any problems with IE8 crashes, please let us know.

It sounds like IE8 is the new IE7 (which was the new IE6)!

jQote2

jQote2 (GitHub: aefxx / jQote2, License: MIT) by aefxx is a template plugin that works a little bit like .tmpl.

The author has written jQote2 API documentation. I picked out the Fibonacci example because it demonstrates some interesting features of this plugin. Given this HTML:

<ul id="fibonacci">
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

<script type="text/x-jqote-template" id="template">
    <![CDATA[
    <%= ( ( this.n == 0 ) ?
            0 : ( this.n == 1 || this.n == 2 ) ?
                1 : parseInt($.jqote(fn, {n: this.n-1})) +
                        parseInt($.jqote(fn, {n: this.n-2})) ) %>
    ]]>
</script>

… and this JavaScript:

$(function() {
  var lambda = $.jqotec('#template');

  $('#fibonacci li').each(function(i) {
    $(this).text($.jqote(lambda, {n: i}));
  });
});

then an unordered list displaying the Fibonacci sequence will be displayed for the number of list elements in the template.

Despite having some advanced features, this plugin performs well when compared to other templating plugins. The benchmarks compare Srender, mustache.js, Underscore, jQote2, Tempest, and nano, with Underscore and jQote2 coming out on top.

jquery.factory

jquery.factory by iwyg is a class constructor library. Objects can be created using the factory function that has the following signature:

var MyClass = $.factory(ParentClass, constructorFunction, prototypeObject);

It comes with documentation and unit tests. It doesn’t yet offer much that goes beyond prototypal inheritance, but the author only published it two days ago so perhaps there’s more to come.

Native Fullscreen

In Native Fullscreen JavaScript API, John Dyer writes about the history and current state of browser full screen support, complete with a demo and jQuery plugin.

The API is still heavily in flux especially since the W3C joined in this week. I spent some time working through the differences to implement FullScreen in MediaElement.js HTML5 video player, and it’s working great in Safari 5.1+, Chrome 15+, or Firefox Nightly.

The resulting code can be used like this:

if (fullScreenApi.supportsFullScreen) {
  myButton.addEventListener('click', function() {
    fullScreenApi.requestFullScreen(someElement);
  }, true);
}

Five Common JavaScript Misunderstandings

31 Oct 2011 | By Alex Young | Comments | Tags language essays

Over the last few years more people have been drawn to JavaScript thanks to libraries like jQuery and innovative server-side projects like Node. However, JavaScript is deceptively easy to learn for existing developers, and there are a few frustratingly awkward pitfalls for newcomers. I’ve quietly been keeping notes on some of these pitfalls, and have selected a few of my favourites in this post.

Too Many Callbacks!

New Node developers like to complain about callbacks. Deeply nested callbacks don’t read particularly well, but this isn’t necessarily JavaScript’s fault. One way to mitigate this is through flow control techniques, and chainable APIs are probably the most popular technique in this area. For example, consider jQuery where the API feels very “flat”:

$('#foo')
  .slideUp(300)
  .delay(800)
  .fadeIn(400);

If you’re knee-deep in callbacks, check to see if the library you’re using has an alternative chainable API. A lot of popular libraries do, like Underscore.js.

Chainable APIs work by returning this from their methods. It can be quite hard to make some APIs work this way, but masking the underlying complexity is often worth it.

There are plenty of flow control libraries available through npm that solve this (and similar) style problems.

Inheritance

Experienced classical object-oriented developers often get frustrated with JavaScript’s prototypes and recreate traditional class and inheritance patterns. I think the lack of OO-related keywords is the main reason for this. However, there’s no need to shy away from prototypes, and prototypal inheritance is surprisingly easy to learn:

var user;

function Person(name) {
  this.name = name;
}

Person.prototype.greet = function() {
  console.log('Hello', this.name);
};

// Admin inherits from Person

function Admin(name) {
  this.name = name;
}

Admin.prototype = new Person;

user = new Admin('alex');

// This method was defined on Person
user.greet();

The key line is Admin.prototype = new Person;. I only really understood this when I started to think about prototype chains: Inheritance and the prototype chain.

Scope and Callbacks in Loops

I’ve fallen foul of this a few times over the years. When looping over a set of values, people often mistakenly think an anonymous function will capture the current state of the variables in the loop:

var assert = require('assert')
  , names = ['alex', 'molly', 'yuka']
  , name
  , i;

for (i = 0; i < names.length; i++) {
  name = names[i];

  if (name === 'alex') {
    setTimeout(function() {
      assert.equal(name, 'alex');
    }, 10);
  }
}

The callback will execute in the future, at which point the name will have changed because it hasn’t been bound the way it seems like it should. This will work as expected:

var assert = require('assert')
  , names = ['alex', 'molly', 'yuka'];

names.forEach(function(name) {
  if (name === 'alex') {
    setTimeout(function() {
      assert.equal(name, 'alex');
    }, 10);
  }
});

People often use for instead of an iterator when performance is desired, but in certain cases callback-based iteration might be more readable.

this in Nested Functions

What’s the value of this in a nested function?

var user;

function Person(name) {
  this.name = name;
}

Person.prototype.nested = function() {
  console.log(this);

  (function() {
    console.log(this);
  })();
};

user = new Person('alex');
user.nested();

The first console.log will show { name: 'alex' }, but the second will show the global object (window in client-side code). This is why a lot of code sets var self = this at the start of a method.

Future Reserved Words

The ECMA standards define Future Reserved Words that include commonly used words like class, extends, and super. It’s probably a good idea to avoid using these words; check with the specifications if you’re unsure of a particular word.

References

KickJS, Stage3D vs WebGL Performance, Large Commercial Node App

28 Oct 2011 | By Alex Young | Comments | Tags node webgl frameworks libraries games

KickJS

KickJS (GitHub: mortennobel / KickJS, License: New BSD) by Morten Nobel-Jørgensen is a new WebGL game engine. It looks like the author has only been working on it for about a month, but there’s already a snake game example and an interesting shader editor example.

The KickJS API documentation seems fairly complete, and provides an overview of the main functionality. It looks like games are constructed based on KICK.scene.Component objects, and events based on these components. There’s also WebGL abstraction which reminds me a little bit of three.js — there’s a camera class, and classes for lots of other things like textures, materials, lighting, and meshes.

Stage3D vs WebGL Performance

In Stage3D vs WebGL Performance, Felix Turner compares Flash 11’s Stage3D API with WebGL. Two demos of equivalent code are compared, and both can run so you can see how they perform on your own hardware. It’s interesting to see how the code compares, because Felix has used three.js and the API doesn’t seem too different to Stage3D.

The post has a good discussion as well, with contributions from three.js’s author.

Large Commercial Node App

Sam Fresco who works at an agency called Clock sent me some interesting PR about a project built with Node called Eat Out that his company has developed for The Times and Sunday Times. I searched high and low to actually try this project, but when I found Sam’s blog post I realised it’s only accessible to Times subscribers until 2012, when it should be released to a wider audience. More details are available in his blog post: There’s Never Been A Better Time To Eat Out.

Clock’s technical blog also has posts on working with Node, including one on deploying Node apps.

Why do I bring this up? Well, it’s always interesting to hear about large commercial projects that use Node, and also because it helps answer the dreaded boss/client question: “what popular sites use Node, anyway?”

Asynchronous Resource Loading Part 5

27 Oct 2011 | By Alex Young | Comments | Tags frameworks tutorials lmaf network

Let’s Make a Framework is an ongoing series about building a JavaScript framework from the ground up.

These articles are tagged with lmaf. The project we’re creating is called Turing. Documentation is available at turingjs.com.

Previous parts:

Creating a Preloading API

Last week I fleshed out turing.request so it can handle preloading with XMLHttpRequest. It’s time to look at how to build an API that will allow scripts to load based on the required order.

I thought a lot about this and decided that an array is a good way to model dependencies between scripts. Given this array:

[
  'framework.js',
  ['plugin.js', 'plugin2.js'],
  'app.js']
]

then the following actions should occur:

  • framework.js is downloaded and executed
  • plugin.js and plugin2.js are downloaded asynchronously, but only executed when framework.js is ready
  • Finally, app.js is executed

These scripts can be loaded at any time, as long as they’re executed in the specified order. If the scripts are local, they can be preloaded with XMLHttpRequest.

Preloading Test

To break this down into something implementable, I created a test first:

'test async queue loading': function() {
  $t.require([
    '/load-me.js?test9=9',
    ['/load-me.js?test4=4', '/load-me.js?test5=5'],
    ['/load-me.js?test6=6', '/load-me.js?test7=7'],
    '/load-me.js?test8=8'
  ]).on('complete', function() {
    assert.ok(true);
  }).on('loaded', function(item) {
    if (item.src === '/load-me.js?test9=9') {
      assert.equal(typeof test4, 'undefined');
    }

    if (item.src === '/load-me.js?test4=4') {
      assert.equal(test9, 9);
      assert.equal(test4, 4);
      assert.equal(typeof test6, 'undefined');
      assert.equal(typeof test8, 'undefined');
    }

    if (item.src === '/load-me.js?test6=6') {
      assert.equal(test9, 9);
      assert.equal(test4, 4);
      assert.equal(test6, 6);
      assert.equal(typeof test8, 'undefined');
    }
  });

I originally wrote this with a callback like the old require signature implied, but I realised that different types of callbacks are required, so it felt natural to use something based on events.

Using this event-based approach should make it easier to build internally, but also makes a pretty rich API.

Modifying require

To work with this new signature (and event-based API), last week’s require implementation will have to be updated. Recall that a setTimeout method was used to delay loading until the head part of the document is ready. That makes returning a value — and thus chaining off require — impossible.

To get around this, I extracted the setTimeout part and made it into a method:

function runWhenReady(fn) {
  setTimeout(function() {
    if ('item' in appendTo) {
      if (!appendTo[0]) {
        return setTimeout(arguments.callee, 25);
      }

      appendTo = appendTo[0];
    }

    fn();
  });
}

When an array is passed to require we can safely assume queuing is necessary. The old method signature is still available. In the case when an array has been passed, a Queue object can be returned to enable chaining:

turing.require = function(scriptSrc, options, fn) {
  options = options || {};
  fn = fn || function() {};

  if (turing.isArray(scriptSrc)) {
    return new Queue(scriptSrc);
  }

  runWhenReady(function() {
    // Last week's code follows

The Queue Class

The Queue class is based on turing.events.Emitter which is a simple event management class, created in Let’s Make a Framework: Custom Events. The basic algorithm works like this:

  1. Queue.prototype.parseQueue: Iterate over each item in the array to work out which scripts require preloading, and group them together based on the array groupings. Single script items will be added to a group that contains one item, so the array of arrays becomes normalised into something easy to manage.
  2. Queue.prototype.enqueue: Whenever parseQueue finds a script, call enqueue to add it to a sequentially indexed object.
  3. runQueue: Iterate over each group and preload each local script using XMLHttpRequest. Add an event emitter to the XMLHttpRequest callback to signal a preload event has completed.
  4. preload event: When this event is fired, mark the group item as ‘preloaded’ and start executing scripts if the whole group has finished preloading.
  5. complete event: This event is fired when all items have executed.

I’ll explain these methods and events below.

Initialization Queue and Maintaining the Chain

To allow the on methods to be called after turing.require, Queue has to use runWhenReady itself, and proxy calls to turing.events.Emitter and return this:

function Queue(sources) {
  this.sources = sources;
  this.events = new turing.events.Emitter();
  this.queue = [];
  this.currentGroup = 0;
  this.groups = {};
  this.groupKeys = [];
  this.parseQueue(this.sources, false, 0);

  this.installEventHandlers();
  this.pointer = 0;

  var self = this;
  runWhenReady(function() {
    self.runQueue();
  });
}

Queue.prototype = {
  on: function() {
    this.events.on.apply(this.events, arguments);
    return this;
  },

  emit: function() {
    this.events.emit.apply(this.events, arguments);
    return this;
  },

  // ...

Parsing the Queue

The array of script sources must be parsed into something that’s easy to execute sequentially. The enqueue method helps sort items into groups, and flags if they’re suitable for preloading:

enqueue: function(source, async) {
  var preload = isSameOrigin(source),
      options;

  options = {
    src: source,
    preload: preload,
    async: async,
    group: this.currentGroup
  };

  if (!this.groups[this.currentGroup]) {
    this.groups[this.currentGroup] = [];
    this.groupKeys.push(this.currentGroup);
  }

  this.groups[this.currentGroup].push(options);
},

The actual job of queuing is fairly simple, but care must be taken to increment the currentGroup counter as groups are added:

parseQueue: function(sources, async, level) {
  var i, source;
  for (i = 0; i < sources.length; i++) {
    source = sources[i];
    if (turing.isArray(source)) {
      this.currentGroup++;
      this.parseQueue(source, true, level + 1);
    } else {
      if (level === 0) {
        this.currentGroup++;
      }
      this.enqueue(source, async);
    }
  }
},

The reason the level variable is used is to differentiate between grouped items and single scripts.

Running the Queue

Each script item is iterated over in sequence, and XMLHttpRequest is used to preload scripts:

runQueue: function() {
  var i, g, group, item, self = this;

  for (g = 0; g < this.groupKeys.length; g++) {
    group = this.groups[this.groupKeys[g]];
    
    for (i = 0; i < group.length; i++ ) {
      item = group[i];

      if (item.preload) {
        (function(groupItem) {
          requireWithXMLHttpRequest(groupItem.src, {}, function(script) {
            self.emit('preloaded', groupItem, script);
          })
        }(item));
      }
    }
  }
}

The anonymous function wrapper helps keep the right item around (because I’ve used for loops instead of a callback-based iterator).

As each request comes back and preloaded is fired, the event handler will check to see if the entire group has been loaded, and if so, execute each item.

Conclusion

When I had the idea to use events to manage script loading, I thought I was onto something and the code would be very simple. However, the Queue class I wrote for this tutorial ended up becoming quite complex, and it only handles local scripts at this stage.

I’ll attempt to add support for remote preloading as well (where available), and also add support for script tag insertion as a last resort.

This week’s code is in commit 74a0f7f. If you’ve got any feedback, post a comment (or fork) and I’ll see if I can incorporate it.

Node Roundup: 0.5.10 and 0.6, MCMS, EventStream, RSS Tutorial

26 Oct 2011 | By Alex Young | Comments | Tags node modules events cms

You can send your node modules and articles in for review through our contact form or @dailyjs.

0.5.10 and 0.6

Node 0.5.10 has been released. This version changes the build system, adds performance improvements, and it looks like there’s been a lot of documentation improvements.

Node 0.6 was also formally announced on the official Node blog:

The API changes between v0.4.12 and v0.5.10 are 99% cosmetic, minor, and easy to fix. Most people are able to migrate their code in 10 minutes. Don’t fear.

Sounds good to me!

MCMS

MCMS (npm: mcms, License: MIT) by Oleg Podsechin is a content management system built with Common Node. Actually, Common Node is just part of the story:

By being built on top of the CommonJS Filesystem/A and JSGI 0.3 specs, it runs on multiple server side JavaScript platforms, such as Node.js (via Common Node) and RingoJS.

Oleg has provided installation instructions for both Node and RingoJS.

MCMS is more like a static site generator than a traditional CMS, and serves as an interesting example of how to build something using Common Node while still being able to deploy to other CommonJS-compatible environments.

EventStream

Streams are like Arrays, but laid out in time, rather than in memory.

EventStream (npm: event-stream) by Dominic Tarr is a library for manipulating “through streams”, which is the author’s terms for streams that are both readable and writable:

// pretty.js

if (!module.parent) {
  var es = require('event-stream');

  es.connect(                          // connect streams together with `pipe`
    process.openStdin(),               // open stdin
    es.split(),                        // split stream to break on newlines
    es.map(function(data, callback) { // turn this async function into a stream
      callback(null
        , inspect(JSON.parse(data)))   // render it nicely
    }),
    process.stdout                     // pipe it to stdout!
  );
}

// On the terminal:
// curl -sS registry.npmjs.org/event-stream | node pretty.js

The library provides many interesting ways to enhance native objects and functions with streams. The author has even created a list of compatible Node modules, which includes popular modules like sax-js and request.

RSS with NodeJS and Socket.IO

French-speaking readers may appreciate RSS with NodeJS Socket.IO and Express which is a full tutorial on how to build an RSS reader with Express and Socket.IO. I had a go at reading it with Google Translate, and I was able to follow it (for the most part).

jQuery Roundup: 1.7 RC1, $.Callbacks, jquery.rss, sessionTimeout

25 Oct 2011 | By Alex Young | Comments | Tags jquery plugins rss events

Note: You can send your plugins and articles in for review through our contact form or @dailyjs.

jQuery 1.7 RC1

jQuery 1.7 RC1 has been released. Meanwhile, the jQuery Standards Team has been created, which aims to represent jQuery users to standards bodies such as the W3C and TC39.

The jQuery Standards Team is driven by jQuery team members Yehuda Katz and Paul Irish who some of you may know. Yeuhda and Paul have extenstively worked with standards bodies and browser vendors in a number of capacities over the years.

Demystifying jQuery 1.7’s $.Callbacks

In Demystifying jQuery 1.7’s $.Callbacks, Addy Osmani explains the origins of $.Callbacks and provides detailed examples on how to use it.

The general idea behind pub/sub (the Observer pattern) is the promotion of loose coupling in applications. Rather than single objects calling on the methods of other objects, an object instead subscribes to a specific task or activity of another object and is notified when it occurs.

Looking at the source in in jQuery 1.7 is interesting because $.Callbacks is now used in several places. For example, the new deferred.js is built with it, and ajax.js is as well.

I was trying to compare Node’s EventEmitter with $.Callbacks and discovered Comparison Between Different Observer Pattern Implementations by Miller Medeiros, which is an interesting post on this subject.

jquery.rss

jquery.rss (License: MIT) by Sascha Depold and DaWanda GmbH is an RSS reading and transformation library. It uses the Google Feed API to download feeds straight from the browser. It comes complete with support for simple templates and filtering:

$("#rss-feeds").rss("http://feeds.feedburner.com/premiumpixels", {
  // how many entries do you want? default: 4
  limit: 10,

  // will request the API via https; default: false
  ssl: true,

  // template for the html transformation
  // default: "<ul>{entry}<li><a href='{url}'>[{author}@{date}] {title}</a><br/>{shortBodyPlain}</li>{/entry}</ul>"
  template: "<div class='feed-container'>{entry}<p>{title}</p>{/entry}</div>",

  // additional token definition for in-template-usage
  // default: {}
  tokens: {
    foo: 'bar',
    bar: function(entry, tokens) { return entry.title }
  }
});

sessionTimeout

sessionTimeout (Source: jquery.sessionTimeout.1.0.js) is a simple plugin for handling session timeouts in the browser. It will poll a URL, and show a jQuery UI dialog when the time limit has been reached.

$.sessionTimeout({
  message :     'Your session is about to expire.'
, keepAliveUrl: '/sessions/alive'
, redirUrl:     '/sessions/timed-out'
, logoutUrl:    '/sessions/destroy'
, warnAfter:    900000
, redirAfter:   1200000
})

Backbone.js Screencasts, XDate, JavaScript BigInteger Library

24 Oct 2011 | By Alex Young | Comments | Tags libraries time date screencasts backbone.js maths

Backbone.js Screencasts

Backbone.js Screencasts is a commercial set of Backbone.js tutorials from 30 Cubits that costs $9 (until November 9th, then $18 thereafter) for 106 minutes of videos. The videos cover the core Backbone.js functionality like views, routers, events, models, collections, and also how to use other JavaScript techniques alongside your Backbone.js code.

There’s a preview of the content on Vimeo here: Backbone.js Quickly – Preview.

XDate

XDate (GitHub: arshaw / xdate, License: dual MIT and GPL) by Adam Shaw is a wrapper around Date that provides improved date parsing, formatting, and manipulation. XDate format strings really help with formatting dates, which I find myself doing a lot lately in Node or single page applications.

Here’s an example of XDate’s formatting method:

new XDate(2011, 0, 1, 6, 0).toString('d/M/yy h(:mm)TT');

Another useful feature of this library is the set of XDate diffing methods. They provide a friendly API around date subtraction.

Most of XDate’s methods return an XDate, so it’s chainable too:

d1 = new XDate();
d2 = d1.clone()
       .setUTCMode(true)
       .setDate(1)
       .addMonths(1)
       .addYears(2);

JavaScript BigInteger Library

The JavaScript BigInteger Library (GitHub: silentmatt / javascript-biginteger, License: MIT) by Matthew Crumley is a BigInteger library for JavaScript. The author has written detailed blog posts on how the library works and the algorithms behind it:

If you look at the source, you’ll probably notice that I’m actually using base 10000000, not base 10. I’m using decimal in these examples because it makes things clearer but everything works pretty much exactly the same way in any base. Using a larger base just makes things more efficient because you get 7 digits in each array entry.

Matthew created this library to support his Google Chrome Scientific Calculator.

WebGL X-Wing, JS Test Runner, Lists.js

21 Oct 2011 | By Alex Young | Comments | Tags webgl html testing

WebGL X-Wing

It’s not impossible! I used to bullseye womp rats in my T-16 back home, they’re not much bigger than two meters.

WebGL X-Wing is a simple game demo where an X-wing is piloted through the Death Star trench run. It’s created by @oosmoxiecode, and the author has a whole load of other WebGL demos here: OutsideOfSociety WebGL demos.

JS Test Runner

JS Test Runner (License: Apache License 2.0) by Christopher Hunt runs tests in a browser simulator (PhantomJS), and works well with JUnit so it’s easy to integrate with Maven’s Surefire plugin. The author notes that the project doesn’t depend on Maven, but should work well with anything that can run JUnit tests.

If you’re used to working with Eclipse then JS Test Runner should fit into your workflow very well.

Sample usage of JS Test Runner looks like this:

import org.codehaus.jstestrunner.junit.JSTestSuiteRunner;
import org.junit.runner.RunWith;

/**
 * Run all JS tests associated with this project.
 */
@RunWith(JSTestSuiteRunner.class)
public class SuiteUT {
}

Lists.js

Lists.js (GitHub: javve / list, License: MIT) by Jonny Strömberg is a small library for adding extra filtering options to HTML lists. It’s native JavaScript rather than framework-dependent, so the API is a simple class:

new List('list', { valueNames: [ 'name', 'city' ] });

There are some interesting Lists.js examples which include references to LucasArts games — proof, if any is needed, that the author is a man of impeccable taste.

Asynchronous Resource Loading Part 4

20 Oct 2011 | By Alex Young | Comments | Tags frameworks tutorials lmaf network

Let’s Make a Framework is an ongoing series about building a JavaScript framework from the ground up.

These articles are tagged with lmaf. The project we’re creating is called Turing. Documentation is available at turingjs.com.

Previous parts:

Loading with XMLHttpRequest

In last week’s tutorial I hinted at a technique script loading libraries use to preload local scripts using XMLHttpRequest. By requesting scripts this way, the contents can be placed into a queue then executed through a script element’s .text property when required. This allows libraries like LABjs to schedule execution based on the user’s requirements.

Now we’re starting to go beyond script insertion and into the realms of preloading and scheduling. With that in mind, I’ve redesigned the code for this module to be easier to test.

Designing for Testability

Production-ready script loaders will dynamically decide on the best strategy for preloading a given script. That makes them easy to use, but potentially makes them hard to test. I want to write tests like this:

$t.require('/load-me.js?test0=0', { transport: 'scriptInsertion' }, function() {
  assert.equal(window.test0, 0);
});

$t.require('/load-me.js?test3=3', { transport: 'XMLHttpRequest' }, function() {
  assert.equal(window.test3, 3);
});

Given a server-side test harness — which I’ve already written in test/functional/ajax.js — we should be able to specify which method is used to load a script, and get the expected results.

The transport option in the previous example allows us to control which loading strategy is used. The scriptInsertion transport is what we created in the previous tutorials. The new one is XMLHttpRequest, which gives us more potential for preloading and scheduling scripts.

Implementation

To build this, I’ve broken the problem up into several functions:

  • isSameOrigin determines if a given src is local or remote, so we don’t get same origin errors in the browser
  • createScript creates a new script tag and applies an Object of options
  • insertScript inserts the script tag into the document
  • requireWithScriptInsertion loads scripts using insertion
  • requireWithXMLHttpRequest loads scripts using XMLHttpRequest

A lot of this code was originally in require, but when I realised I was doing the same thing in the XMLHttpRequest loader I decided to break it up.

This method loads the script using our built-in XMLHttpRequest support:

  /**
   * Loads scripts using XMLHttpRequest.
   *
   * @param {String} The script path
   * @param {Object} A configuration object
   * @param {Function} A callback
   */
  function requireWithXMLHttpRequest(scriptSrc, options, fn) {
    if (!isSameOrigin(scriptSrc)) {
      throw('Scripts loaded with XMLHttpRequest must be from the same origin');
    }

    if (!turing.get) {
      throw('Loading scripts with XMLHttpRequest requires turing.net to be loaded');
    }

    turing
      .get(scriptSrc)
      .end(function(res) {
        // Here's where the magic happens.  This callback is what will get scheduled in future versions.
        options.text = res.responseText;
        
        var script = createScript(options);
        insertScript(script);
        appendTo.removeChild(script);
        fn();
      });
  }

Which means the public method, require, now has to decide which transport to use:

/**
 * Non-blocking script loading.
 *
 * @param {String} The script path
 * @param {Object} A configuration object.  Options: {Boolean} `defer`, {Boolean} `async`
 * @param {Function} A callback
 */
turing.require = function(scriptSrc, options, fn) {
  options = options || {};
  fn = fn || function() {};

  setTimeout(function() {
    if ('item' in appendTo) {
      if (!appendTo[0]) {
        return setTimeout(arguments.callee, 25);
      }

      appendTo = appendTo[0];
    }

    switch (options.transport) {
      case 'XMLHttpRequest':
        return requireWithXMLHttpRequest(scriptSrc, options, fn);

      case 'scriptInsertion':
        return requireWithScriptInsertion(scriptSrc, options, fn);

      default:
        return requireWithScriptInsertion(scriptSrc, options, fn);
    }
  });
};

Conclusion

I’ve tested this in IE 6, 7, Firefox, Chrome, and Safari. A future version of this module will have to decide which loading method to use by default, depending on the scheduling requirements (which we have yet to start work on).

There are actually more script loading techniques to look at before I can get to scheduling. As I’ve said before, if you’re interested in this area take a look at RequireJS and LABjs to jump ahead.

This week’s code can be found in commit 649f882.

Node Roundup: hotcode, fbgraph, browser

19 Oct 2011 | By Alex Young | Comments | Tags node modules scraping facebook social

You can send your node modules and articles in for review through our contact form or @dailyjs.

hotcode

hotcode (License: MIT, npm: hotcode) by Mathias Pettersson is a small Express app that watches for changes on a given path, then reloads an associated app when files change.

To use it, follow the instructions in the project’s README file. When hotcode is run it’ll print out a link to some JavaScript (it should be http://127.0.0.1:8080/static/injected.js) — this will need to be added to your project to get automatic reloading in the browser.

Projects can be configured in ~/.hotcode so the path doesn’t need to be entered each time hotcode is started. This can be set per-domain as well.

One of the interesting things about hotcode is it can be run against practically any app in any language. If you’re sick of having to restart your app and refresh the browser every time you make a change, then you’re going to love this.

fbgraph

fbgraph (GitHub: criso / fbgraph, License: MIT, npm: fbgraph) by Cristiano Oliveira provides consistent access to the Facebook graph API. According to the author:

All calls will return json. Facebook sometimes decides to just return a string or true or redirects directly to an image.

Given suitable configuration options, people can be authorised using getOauthUrl:

var graph = require('fbgraph')
  , authUrl = graph.getOauthUrl({
      'client_id':    conf.client_id
    , 'redirect_uri': conf.redirect_uri
  });

Once the Facebook dialog has been displayed, graph.authorize is called to complete the process and get the access token.

API calls are made with graph.get or graph.post, so most of the API is oriented around HTTP methods:

graph.get('zuck', function(err, res) {
  console.log(res); // { id: '4', name: 'Mark Zuckerberg'... }
});

graph.post(userId + '/feed', wallPost, function(err, res) {
  // returns the post id
  console.log(res); // { id: xxxxx}
});

This is a clean, well-documented, and well-tested Facebook library, which is surprisingly refreshing.

browser

browser (License: MIT, npm: browser) by Shin Suzuki is an event-based library for browsing and scraping URLs, whilst maintaining cookies. Requests are built up using the library’s object, and then triggered with .run():

var $b = require('browser');
$b.browse('https://example.com/');
$b.run();

Building up a sequence of events is possible with the after method:

var $b = require('browser');

$b.browse('https://example.com/sign-in');

$b.browse('https://example.com/account')
  .after(); // browse after previously registered function

$b.run();

Event callbacks can also be registered:

$b.on('end', function(err, res) {
});

Now load up jsdom and you’ll be able to scrape faster than you can say “deep-linking lawsuit”!

jQuery Roundup: 1.7 Beta 2, Counter, Templator

18 Oct 2011 | By Alex Young | Comments | Tags jquery plugins templates

Note: You can send your plugins and articles in for review through our contact form or @dailyjs.

jQuery 1.7 Beta 2

jQuery 1.7 Beta 2 is out. It’s worth skimming over the whole change log in the announcement to check for things that may affect your scripts. This release includes a lot of IE fixes and improvements, for example:

  • #6485 — Solution for HTML5 issues in IE
  • #10267 — IE8 and window is(':visible') crashes
  • #10429 — IE7 – invalid procedure call or argument when calling .removeAttr('contenteditable');
  • #9033 — (Deferred) try { } finally { } error in IE8
  • #6170jQuery(window).scroll(); causes IE* to scroll to 0,0
  • #6319 — Regression: stopPropagation inside change handlers in IE is incorrectly applied to keydown event
  • #6593 — IE8: DOM 0 event handler called twice when a separate handler is attached via jQuery
  • #6667 — submit event doesn’t delegate in IE* under certain conditions
  • #6942jQuery.event.fix causes unnecessary reflows in IE when handling key events
  • #7161 — Submit event on a form element not unbound properly in IE
  • #7444 — Submitting form with “Enter” instead of button click on IE8 or IE7 triggers live submit event twice
  • #8157 — Focusing an already focused text field will prevent the change event from firing in IE
  • #8866 — IE8 input[type=file] delegated change event files only on blur
  • #9593 — Delegated submit event is not instanceof jQuery.Event in IE
  • #9570 — Selector $('form[name=".."]') returns zero elements in IE8 under some conditions

There are 68 fixes and improvements altogether; 15 are for IE support.

jQuery Word and Character Counter

Counter (License: MIT) by Wilkins Fernandez is a word and character counting plugin that works a little bit like Twitter. $(selector).counter(); will add a character counter to a textarea. It supports lots of options — it’s possible to enforce the word or character limit by preventing more text from being entered, or to simply count forever:

// This will simply print the character count forever
$(selector).counter({
  goal: 'sky'
});

$(selector).counter({
  type: 'word'
, goal: 'sky'
});

The thing I’ve always found challenging about word counting algorithms is supporting other languages. A naive word count implementation is likely to get Japanese and Chinese word counts wrong. It would be interesting to see this supported here (or your favourite JavaScript algorithm for doing this in the comments).

Templator

Templator (License: AOL) by Nijiko Yonskai is a template manager, and currently supports a wide range of template languages. It depends on jQuery, and includes support for mustache.js, jSmart, TrimPath Template, YAJET, and more (look at Template/lib/ to see what template languages are supported).

It also comes with a caching system:

var Template = new Templator({
    language: 'jSmart', // Supported Languages: jSmart, EJS, Moustache, Trimpath, YAJET, JST, or Empty
    cache: {
        enabled: false,
        life: 32000,
        tick: 1000
    }
});

And has a chainable API:

var Template = new Templator({ language: 'yajet' })
   .storeElement('tmpl', '.tmpl', { foo: 'Hello', bar: 'World!' })
   .partialElement({ partial: '.partial' }, {}, 'tmpl')
   .on('.this')
   .render('tmpl');

It can also be used in a rudimentary fashion without a template language:

var Template = new Templator({ language: '' });
Template.renderRaw('Hello {name}!', { name: 'World' });

Code Review: Oliver Caldwell's EventEmitter

17 Oct 2011 | By Alex Young | Comments | Tags code-review node events

Code Review is a series on DailyJS where I take a look at an open source project to see how it’s built. Along the way we’ll learn patterns and techniques by JavaScript masters. If you’re looking for tips to write better apps, or just want to see how they’re structured in established projects, then this is the tutorial series for you.

After a previous Code Review of EventEmitter2 by hij1nx in Code Review: EventEmitter2, Oliver Caldwell asked me to take a look at his EventEmitter (GitHub: Wolfy87 / EventEmitter, License: MIT and GPL).

This library places special focus on browser support, supporting all major browsers and even IE 5+. A minimised version is also supplied to further support client-side developers.

Usage

This EventEmitter implementation is used the same way as Node’s:

// Initialise the EventEmitter
var ee = new EventEmitter();

function myListener() {
}

// Add the listener
ee.addListener('event', myListener);

// Emit the event
ee.emit('event');

// Remove the listener
ee.removeListener('event', myListener);

Structure

As with most browser-based libraries, I expected to see a self-executing anonymous function. However, in this implementation the author has opted to wrap everything in a regular function, declaring methods inside the function’s scope:

function EventEmitter() {
  var listeners = {},
      instance = this;

  instance.Event = function(type, listener, scope, once) {
  };

  instance.eachListener = function(type, callback) {
  };

  // Etc.
}

The Event class is used to encapsulate an event, and instantiated Event objects are pushed onto arrays indexed by type on listeners.

This style of encapsulation reminds me of how TJ Holowaychuk likes to model his runtime objects (the Request and Response classes in Express for example). Also, it demonstrates high-level object oriented principles without resorting to creating classical-OO-style classes in JavaScript.

Implementation

Like the other EventEmitter libraries, listeners are stored in an Object. The newListener event has been retained, which I thought shows good attention to detail. Most of the core methods are extremely short, which I like to see. For example, emit is implemented like this:

instance.emit = function(type, args) {
  instance.eachListener(type, function(currentListener) {
    return currentListener.fire(args);
  });

  // Return the instance to allow chaining
  return instance;
};

Extracting eachListener seems like a good idea. Rather than having a lot of loops throughout the code, eachListener gets reused by removeListener and emit, making these methods more readable.

The code is also clearly commented, and the build process is included as part of the Makefile.

Performance

The last time I looked at serious JavaScript loop benchmarks, optimised for loops performed extremely well, which I suspect is why EventEmitter and EventEmitter2 don’t use the callback-based iterators Oliver has used. He hasn’t included benchmarks so I can’t easily say how well this implementation performs, but I did find this code easier to follow than the other EventEmitters that I’ve looked at.

Tests

Oliver has included QUnit tests, which do the job admirably:

test('Emitting events', function() {
  var ee = new EventEmitter();

  ee.addListener('emittingTest', function() {
    // Listener
    ok(true, 'First called');
  });

  ee.addListener('emittingTest', function() {
    // Another listener for the same event
    ok(true, 'Second called');
  });

  ee.addListener('differentEvent', function() {
    // Another listener for the same event
    ok(false, 'Wrong event called');
  });

  ee.emit('emittingTest');
});

I think these tests could benefit from being able to assert on how many assertions are expected before the test completes, like assert.expect in nodeunit.

Conclusion

Yet another EventEmitter implementation, but this one still manages to differentiate itself from the others I’ve looked at. I liked the way the author has explored readability rather than purely performance; it offers a hackable alternative that might suit certain projects. And the code uses OO concepts without feeling too heavy handed.

Check it out yourselves on GitHub: Wolfy87 / EventEmitter

Milkshake, An Introduction to WebGL, MapsGL

14 Oct 2011 | By Alex Young | Comments | Tags webgl animation google opera

Milkshake

Milkshake (GitHub: gattis / milkshake, License: LGPL) by Matt Gattis is a WebGL audio visualiser that uses SoundCloud’s API to play audio. It’ll play lots of tracks and cycle through tonnes of visualisations based on MilkDrop.

I particularly like the way the visualiser presets are JSON files, and how everything is client-side — this thing can be uploaded to GitHub Pages or Dropbox and shared easily.

The choice of tracks really made me want to get some Girl Talk out (Feed the Animals is a great way to start the weekend!)

An Introduction to WebGL

In An Introduction to WebGL, Luz Caballero explains the basics behind WebGL, including: browser support, the rendering pipeline, WebGL libraries, and example code using PhiloGL.

MapsGL

MapsGL from Google is a new way to view Google Maps using WebGL. To use it, load up Google Maps in the latest Chrome or Firefox 8+ and look for the “What to try something new?” button on the bottom left-hand-side:

MapsGL uses new technology called WebGL (Web-based Graphics Library) to enhance the Google Maps experience. WebGL brings 3D graphics to your browser without the need to install additional software. This allows us to provide seamless transitions between various levels of imagery and different map views.

I really like the 45 degree view mode, but I could only get it working around Rome for some reason. It’s also slightly weird that when MapsGL is enabled the Google Earth option still requires a plugin. However, it does feel extremely slick, particularly zooming right in which automatically transitions to street view mode.

Asynchronous Resource Loading Part 3

13 Oct 2011 | By Alex Young | Comments | Tags frameworks tutorials lmaf network

Let’s Make a Framework is an ongoing series about building a JavaScript framework from the ground up.

These articles are tagged with lmaf. The project we’re creating is called Turing. Documentation is available at turingjs.com.

Previous parts:

HTML5 Asynchronous Loading Support

In the last part I created this simple API for loading scripts asynchronously:

$t.require('/load-me.js', function() {
  // Loaded
});

The next step is to look at how to handle execution order control. The script element gets two new attributes in HTML5: async and defer. Technically defer was present in HTML4:

When set, this boolean attribute provides a hint to the user agent that the script is not going to generate any document content (e.g., no “document.write” in javascript) and thus, the user agent can continue parsing and rendering.

From: HTML4 Scripts

That means there are the following possible states:

  • async: Execute the script asynchronously as soon as it is available
  • defer: Execute the script when the page has finished parsing, thereby allowing other scripts to download and execute
  • async and defer: Use async if available, else legacy browsers will fall back to defer (from: Using HTML 5 for performance improvements)
  • If neither are present, the script is fetched and executed immediately before the page has finished parsing

Out of interest, I tried setting these attributes on the generated script elements, and it didn’t cause IE6 to break. I suspect this should really use feature detection to be safe.

In order to support the baseline HTML5 API, I added some options to the require method:

$t.require('/load-me.js', { async: true, defer: true }, function() {
  assert.equal(loadMeDone, 1);
});

And this just sets the properties as you’d expect:

function require(scriptSrc, options, fn) {
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = scriptSrc;

  if (options.async) {
    script.async = options.async;
  }

  if (options.defer) {
    script.defer = options.defer;
  }

Execution Order and Preloading

Now require works as asynchronously as possible, have we solved the problem of asynchronous resource loading? Not by a long shot. Although execution order could now be controlled through callbacks, this wouldn’t do what we really want to do:

// This is wrong:
$t.require('/library-a.js', function() {
  $t.require('/library-b.js', function() {
    $t.require('/app-code.js', function() {
      // Done!
    });
  });
});

Why is this wrong? It fails to distinguish between loading and executing scripts. Libraries like LABjs utilise multiple strategies for managing script execution order. Going back to Loading Scripts Without Blocking by Steve Souders, we can find six techniques for downloading scripts without blocking. Steve even includes a table to compare the properties of each of these approaches, and it shows that only three techniques can be used to control execution order.

There are more techniques available — many libraries use object or img to preload scripts. A script element is used once the script has loaded, effectively rerequesting the script when it’s required, and therefore hitting the cache. This preloading approach is fairly widely used, but has to account for a lot of browser quirks. In some cases it can cause scripts to be loaded twice.

XMLHttpRequest Loading

LABjs has a whole load of code for managing loading scripts with XMLHttpRequest. Why? Well, it makes preloading possible and avoids loading scripts twice. However, it can only be used to load local scripts due to the same origin policy.

Dynamic Script Execution Order

In Dynamic Script Execution Order, an extension to the behaviour of the async attribute is considered. This proposal is known as async=false:

If a parser-inserted script element has the `async` attribute present, but its value is exactly “false” (or any capitalization thereof), the script element should behave EXACTLY as if no `async` attribute were present.

This would allow our script loader to set scriptTag.async = false when execution order is important, else scriptTag.async = true could be used to load it and run it whenever possible.

Conclusion

Despite script loading libraries like LABjs and RequireJS existing for a few years, the problem still hasn’t been completely solved, and we still need to support legacy browsers. Simply loading non-blocking JavaScript by inserting script tags is possible, but controlling execution order requires an inordinate amount of effort.

If you’ve ever wondered why LABjs is around 500 lines of code, then I hope you can now appreciate the lengths the author has gone to!

The HTML5 support I added can be found in commit c007251.

References

Node Roundup: Cluster, Node 0.5.9 and 0.6, French Node Blogs

12 Oct 2011 | By Alex Young | Comments | Tags node blogs

You can send your node modules and articles in for review through our contact form or @dailyjs.

Node Cluster

I saw a Tweet in which Ryan Dahl mentioned this commit to Node: introduce node cluster, 87339a2. It adds a command line option to run a script using multiple processes. The obvious criticism of this is it’s possible to build this at a higher level, but I agree with Daniel Ennis’ comment on the commit:

While it may seem high level, I’d much rather have an officially supported method of doing it that’s maintained […]

Node 0.5.9 and 0.6

Node 0.5.9 has been released, and Node 0.6 is getting close. This means 0.6 will be the new stable branch, and Ryan recommended testing modules against 0.5.9.

I apologize that it’s taken so long to reach a new stable release – porting to Windows took longer than expected. In the future we will try to keep dev/stable cycles to 6 weeks.

I thought this was a very humble statement given the herculean effort that’s been put into Windows support. I’m looking forward to 0.6!

More French Node Blogs

I recently featured a French Node blog in the Node Roundup, and reader Sebastien Chopin sent in two more:

jQuery Roundup: Notificon, stickySectionHeaders, jQuery.suggest, smartTruncation

11 Oct 2011 | By Alex Young | Comments | Tags jquery plugins Canvas truncation

Note: You can send your plugins and articles in for review through our contact form or @dailyjs.

Notificon

Notificon (GitHub: makeable / Notificon, License: BSD) by Matt Williams dynamically changes a site’s favicon to include a notification value. This works by generating link elements with data URIs using a canvas:

var changeFavicon = function changeFavicon(canvas) {
  var link = document.createElement('link');
  link.type = 'image/x-icon';
  link.rel = 'icon notificon';
  link.href = canvas.toDataURL("image/png");
  removeNotificon();
  document.getElementsByTagName('head')[0].appendChild(link);
};

It’s a cool hack, and it made me wonder about Internet Explorer support. IE8 apparently supports link elements with base64 encoded data, so perhaps something like ExplorerCanvas could be used to get broader browser support?

stickySectionHeaders

stickySectionHeaders (GitHub: polarblau / stickySectionHeaders, License: GPL and MIT) by Polarblau is a jQuery plugin that can help create iOS-style sticky headers in a list. All that’s needed is a simple call:

$('#sticky-list').stickySectionHeaders({
  stickyClass     : 'sticky',
  headlineSelector: 'strong'
});

The author has provided some iOS-style CSS as well.

jQuery.suggest

jQuery.suggest (GitHub: polarblau / suggest, License: GPL and MIT) also by Polarblau is an autocomplete plugin that works a little bit like native elements, with greyed out text.

While it’s true there’s a lot of autocomplete plugins out there, how many of them are written this cleanly and come with tests?

smartTruncation

Finally, smartTruncation (GitHub: polarblau / smarttruncation, License: GPL and MIT) is another plugin by Polarblau. This one truncates text within its parent element. It can also truncate from the centre: “Hello World” becomes “Hel…rld”.

Text truncation in client-side code is a source of fascination for me because I’ve attempted it a few times without a huge amount of success. Polarblau’s algorithm creates a cache of font size values and then adds characters to an element until it has filled the desired size. It also takes file name extensions into account.

It’s pretty easy to use:

$('.files li').smartTruncation({
  'protectExtensions' : true // "myimagefile.jpg" -> "myimagef...jpg"
});

It’s worth noting that each of these plugins by Polarblau is clearly licensed, includes tests, and has its own project web site (hosted by GitHub). This is how you distribute plugins!

Mozilla Secure Coding Guidelines, Raphaël 2.0, cryptico.js

10 Oct 2011 | By Alex Young | Comments | Tags libraries documentation graphics cryptography security

Mozilla Secure Coding Guidelines

Mozilla’s WebAppSec/Secure Coding Guidelines is a set of coding guidelines for developing secure applications. There’s a lot information about securing application layer communications, but there’s also some JavaScript-specific advice. JavaScript input validation is considered, along with preventing XSS attacks, and uploads as a JavaScript-based XSS attack vector.

Mozilla also introduced Aurora 9 recently, which includes a JavaScript interface for Do Not Track, and the addition of type inference.

Raphaël 2.0

Dmitry Baranovskiy has released Raphaël 2.0 (GitHub: DmitryBaranovskiy / raphael). Dmitry wrote a post on February 10th about the planned features for Raphaël 2.0. The GitHub history indicates that this version has a new VRML version, and the project has been split up into three files: raphael.svg.js, raphael.vml.js, and raphael.core.js.

If you want to figure out the other changes, either look through Raphaël’s documentation or try to read more of the history on GitHub.

cryptico.js

cryptico.js (Google Code: cryptico, License: New BSD License) is a public key cryptography library that can generate RSA key pairs, encrypt and decrypt messages.

Keys can be generated with cryptico.generateRSAKey(passPhrase, 1024), and messages can be encrypted with cryptico.encrypt(message, publicKeyString).

The cryptico documentation includes notes on the library’s implementation:

A hash is generated of the user’s passphrase using the SHA256 algorithm found at webtoolkit.info. This hash is used to seed David Bau’s seedable random number generator. A (seeded) random RSA key is generated with Tom Wu’s RSA key generator with 3 as a hard-coded public exponent.

W3C Game Development Course, dyn.js, ShapeWright

07 Oct 2011 | By Alex Young | Comments | Tags webgl games graphics language

W3C Game Development Course

W3C recently announced a new online course, Game Development in HTML5, all about creating browser-based multiplayer games. The course aims to review the state of JavaScript game development, explore how new HTML5 elements can be used for building games, and even covers deploying games to app stores.

The tickets are €225, but there are a limited number of seats available at the early bird rate of €145. Registration is here: W3C Training: Game Development in HTML5.

dyn.js

dyn.js (GitHub: dynjs / dyn.js) is an invokedynamic-based JavaScript implementation. Why is this interesting and potentially big news? Well, this quote from an interview with Douglas Campos sums it up:

Rhino is an truly piece of art – back when Rhino was born, the JVM was not cool as today, so they really made miracles getting performance by hand-crafting almost all aspects of their runtime. So dyn.js is kinda like we were starting Rhino again in 2011 – with a much powerful JVM and not worrying about backward compatibility.

If you’d like to read more about this subject, Charles Oliver Nutter wrote a phenomenal explanation back in 2008 called A First Taste of InvokeDynamic.

ShapeWright

ShapeWright is an experimental “mass customization” platform that uses WebGL for visualisation. One of the experiments, Ship generates 3D spaceships and allows VRML object downloads and purchasing of 3D prints.

Is there really not a JavaScript/WebGL multiplayer Elite clone yet?

Changing Perceptions of JavaScript

06 Oct 2011 | By Alex Kessinger | Comments | Tags essays language

Alex Kessinger is a programmer who lives in the Bay Area. He strives to make websites, cook, and write a little bit better each day. You can find more from Alex at his blog, on Twitter, and Google+.

JavaScript is weird. There’s the obvious weirdness of prototypal inheritance, == vs. ===; but those are just surface issues. One feature that boggles non-JavaScript programmers is space optimizations. JavaScript is unique in this fact. Much of our insane syntax flows from the fact that the code goes over the wire. Space saving optimizations are not just acceptable — they are encouraged.

Think about that for a moment. How long has it been since programmers have had to worry about the size of their code? Front-end developers do this all the time, but to anyone else it’s crazy.

At Yahoo I got really good at space optimizations. There were a bundle of internal documents you could turn to that would offer tricks, and rules for making your code smaller. The importance placed on these syntax rules turned code reviews into a checking off process. Every time we passed the list we patted ourselves on the back. We thought it was the best use of our time, and we plodded on, writing the same code over and over. It was prettier, smaller, and well documented, but there wasn’t a ton of original thought that went into it. At least on my part there wasn’t. I am embarrassed to say this now, but I felt like I was at my JavaScript zenith during this time. Oh man, was I wrong.

I don’t think like that anymore. My rubric for good code is how well others can readily understand it. I no longer consider something useful until someone else has successfully modified it. And still, the finish line keeps speeding away from me. There is always a way to be better.

When I moved from a large place like Yahoo, where I rarely had other kinds of engineers looking at my code, my code habits had to change. Other kinds of engineers — especially more polyglot engineers — were looking at my code. I found I had to explain myself constantly.

Their acceptance of my crazily optimised code was tepid. Over time, the craziness started to wear on me. Every time another programmer had to interact with my code I had to explain everything to them. I felt like a baboon pounding my chest then leaning over and saying “see, it’s simple, right?” — it wasn’t! And I had to admit, the blame did not lie with the language or the environment. I am sure that I had become lax in my syntax, and my code wasn’t as clean as it used to be. When there is no one to call you on your habits, you slide a little.

I was the only front-end developer for a while, but even that wasn’t the worst part. The biggest failure was forcing other kinds of engineers to accept the craziness, and not taking their code habits into consideration. I thought that was how it has always been done, and will forever be done. My coworkers enlightened me. In a small but diverse team, shared code habits might be the most important key to understandable code.

With shared code habits in mind, we set about mixing and matching a front-end system that was more understandable to everyone. I had to learn how others would see the front-end system. We went about encapsulating things in a way that would make more sense to others. Some engineers think of JavaScript as something that needs to disappear, like in GWT, but our reformulation was more like a blending of technology that kept the good parts of JavaScript.

During the transition I began to realize the reasons other programmers reel away from front-end code. Engineers who are fully capable of writing code for the web will be turned off by the syntax. It might even stop them from writing web code. Then, even if they do write some code, they switch off their analytical brains when using something they don’t like. They’ll just do what they need to do to get the job done. You won’t get them to help you make the code better. In the end you took someone who could have been a net positive on code quality, and created a net negative on code quality. And for what; smaller code?

One of the best things we did was to switch to intermediaries. Uglify.js is a great example of an intermediary code processor. We have begun to use a number of these tools. Basically, you can use something like Uglify.js or CoffeScript to bridge the gap of understanding. You can turn something that people found ugly, into something beautiful. And then you start to switch the editorial part of their brain on.

None of this means that I don’t care about optimizing code, or keeping things small. This is important for everyone, and especially so for high-traffic websites like Yahoo. It is not a means to an end. It’s that 90% of my checklist has been replaced by code compressors like Uglify.js. I don’t know what I would have done at Yahoo code reviews if we started using Uglify.js. It would have been a lot of latte sipping, and crying as the company crumbled around me.

We should have used better tools, and spent more of our time learning better ways to code.

Node Roundup: Scalable Network Programs, tap, Gittyup

05 Oct 2011 | By Alex Young | Comments | Tags node modules essays deployment

You can send your node modules and articles in for review through our contact form or @dailyjs.

An Easy Way to Build Scalable Network Programs

An Easy Way to Build Scalable Network Programs is a short essay by Ryan Dahl, that helps address some recent criticism of Node:

Node has a clear purpose: provide an easy way to build scalable network programs. It is not a tool for every problem. Do not write a ray tracer with Node. Do not write a web browser with Node. Do however reach for Node if tasked with writing a DNS server, DHCP server, or even a video encoding server.

I’ve noticed several high-profile Node developers say similar things recently, even before the community at large was attacked by certain readers of sites like Hacker News and Reddit. What summed it up for me was this tweet by TJ Holowaychuk:

I love how rails people keep coming to node, expecting a rails-like framework. Why not just use…. rails?

It’s nice to have options, and we have enough high quality high-level programming languages and libraries to keep everyone happy. Be nice!

tap

tap (License: MIT, npm: tap) by Isaac Z. Schlueter is essentially a collection of packages that forms a TAP-compliant test framework. Presumably the reason Isaac is interested in this is to encourage Node developers to generate machine-consumable test output for use with npm’s npat option.

Using the tap package as a test framework looks a lot like other Node test frameworks — there’s an object passed to each test that can be used to run assertions and call a method that denotes the test has finished (useful for asynchronous testing). I noticed that it uses a slightly different approach to the CommonJS Unit Testing module, but this might be because Isaac’s examples demonstrate testing inline rather than through a test runner.

The best thing about tap is the way it’s been split up into lots of smaller packages. There are currently 8 packages, and each one is based around either generating or consuming TAP streams. That means it’s possible to generate TAP output from existing frameworks, or they could even be sewn together in new ways to form your own Frankenstein’s monster of test frameworks.

Gittyup

Gittyup (npm: gittyup) by Craig Condon is a deployment library aimed at Node. It supports rollback, testing before deployment, and making slugs of apps. It’s based around JavaScript files rather than a configuration language or DSL:

// Deploy from a git repository
gittyup.app('myApp').checkout('git@github.com:crcn/gittyup-test.git', function(err, result) {
});

// Or from a local path
gittyup.app('myApp').checkout('/some/local/path', function(err, result) {

});