I saw some buzz today about Meteor, a new set of technologies for building JavaScript applications which blurs the lines between server code and client code.  I’ve had a notion like this bouncing around in my head for the last year or so, and so I was keen to jump in and try it.  I watched the screencast, installed the app, and installed the leaderboard example.  The installation went flawlessly, and I was able to start the example app and bring it up in my browser without any trouble.  I was off to a great start!

One of the interesting features of Meteor is that when you update a source file, the update is pushed down to clients immediately.  I made some minor changes to the template and was pleased to see the changes getting pushed down as advertised.  Very cool.

The leaderboard example page suggested some changes to get familiar with Meteor.  The first was to add a button which would toggle sorting by score or by name.  I felt confident that this should be a straightforward task, and started in with changes.  First I added a button to the template.  Meteor uses handlebars as its template engine (with more engine support promised), so I was able to dynamically change the button’s caption:

<button id="sort">Sort by {{#if sort_by_name}}Score{{else}}Name{{/if}}</button>
view raw sortbutton.html hosted with ❤ by GitHub

Saving this broke the front-end when it auto-reloaded because the template doesn’t have a sort_by_name yet.  This was easily corrected:

Template.leaderboard.sort_by_name = function () {
return Session.get("sort_by_name");
};
view raw sortfunction.js hosted with ❤ by GitHub

I then followed the pattern of the existing click handler for adding points to create my click handler:

Template.leaderboard.events = {
'click input.inc': function () {
Players.update(Session.get("selected_player"), {$inc: {score: 5}});
},
'click #sort': function () {
Session.set("sort_by_name", !Session.get("sort_by_name"));
}
};
view raw events.js hosted with ❤ by GitHub

Finally I updated the players function to return a list sorted in accordance with this new session setting:

Template.leaderboard.players = function () {
var sort = Session.get("sort_by_name") ?
{name: 1, score: -1} :
{score: -1, name: 1};
return Players.find({}, {sort: sort});
};
view raw playerlist.js hosted with ❤ by GitHub

With the run of successes to this point, and the fact that this seemed like a trivial update I hit save, switched to my browser, was greeted with the new Sort button.  I clicked it expecting a complete success.

Nothing happened.

Maybe the click event didn’t fire…  I clicked it again – a dozen more times – strangely nothing worked.  No matter how quickly or violently I clicked, nothing happened.  I added a breakpoint to the event handler.  Nothing.  I added a console.log() call in case the running JavaScript was in a different file from the one I was looking at, but still nothing happened.  I went on like this for longer than I care to admit trying to get that button to do something without any joy.

So I took a desperate leap of desperation and consulted the documentation.  There it was in glorious bold red lettering – a documented bug in event handling: “If an event is filtered by a selector, then it will never be delivered to a top-level node in a template.

My button was a top level node in its template.  I wrapped that sucker in a <div> tag, hit save, switched to my browser window, clicked it and was rewarded with a sorted list!  Ecstasy.

As I attempt the other challenges suggested for the leaderboard example, I won’t be so slow to consult the excellent documentation.  As frustrating as this was, the fact that the bug was so clearly documented, and the fact that everything else went so smoothly makes me confident that the Meteor project will be very successful.  I’ll let you know how it goes.

Advertisement