Even More Snow

At this rate, no one is going to believe me when I say New York doesn't get very wintery ;-)

/blog/entries/2011/01/27/even_more_snow/snow1-5b657673a6f6.min.jpg /blog/entries/2011/01/27/even_more_snow/snow2-423d1674e032.min.jpg /blog/entries/2011/01/27/even_more_snow/snow3-bacd7da07970.min.jpg /blog/entries/2011/01/27/even_more_snow/snow4-080e81fc3f38.min.jpg /blog/entries/2011/01/27/even_more_snow/snow5-681d1e7524d3.min.jpg

Snow 2.0

It snowed again last night and when I woke up the snow was still fresh. Taking more pictures seemed like the right thing to do:

/blog/entries/2011/01/21/snow_2_0/snow1-beac919b08f7.min.jpg /blog/entries/2011/01/21/snow_2_0/snow2-02b3aef69402.min.jpg /blog/entries/2011/01/21/snow_2_0/snow3-4b8bc602d305.min.jpg /blog/entries/2011/01/21/snow_2_0/snow4-6003e76907ba.min.jpg /blog/entries/2011/01/21/snow_2_0/snow5-6117e3d584ce.min.jpg

How to change Chrome's User-Agent string (redux)

As another brief addendum to a different post (the one about changing Chrome's user-agent string), if you use Google Chrome Portable to masquerade as an iPhone then you can have both a fake-iphone-chrome and a normal-chrome. This is handy for when you want to be able to use the non-iPhone versions of various websites while you're testing.

Don't Try to Reminplement HTML in your Rectangle of Joy (redux)

As a brief addendum to my previous post about HTML, I just thought I'd point out that Google's Webmaster Tools work on my phone while Bing's do not.

Obviously, checking on your website from your phone may not be a core use case (after all, the only reason I know it works on my phone is that I've been travelling and just happened to try it out while away from my "real" computer) but phones and other mobile devices are an increasingly important way people use web applications. Consequently, if your web app lives inside a Flash or Silverlight rectangle you're cutting off an entire class of uses.

JavaScript Templates (redux)

In the spirit of code kata (the origional problem was a kata) here is an alternative solution to the JavaScript templating problem:

var template = (function(){
    var grammar = parsec.grammar([
        parsec.token("placeholder", "[$]\\w+"),
        parsec.token("literal", "[^$]+")

        root("template", placeholder.or(literal).repeated().then(eof));

    return {
        render: function render(source, context){
            var handlers = {
                literal: function(node){
                    return node.v;

                placeholder: function(node){
                    var key = node.v.substring(1);
                    return context[key] || "";

                template: function(node){
                    return $.map(node.children, evaluate).join("");

            function evaluate(node){
                return handlers[node.type](node);

            var root = grammar.parse(source);
            return evaluate(root);

It's a bunch longer. It's not quite ten time's longer, but it's kind of close... and it passes exactly the same test suite and has the same features, so what, if anything is good about it?

For one thing, it uses a completely different approach. It builds a recursive descent parser using a parsing library that I put together that's based on Parsec. The basic idea of Parsec, and other parser combinator libraries, is that you define simple parsers and then compose them into more complicated parsers using combinators. What this means is that, while it is not necessary here, this approach can handle much more complicated languages than the regex based approach.

Oh, and there was one little nugget of joy in there that deserves special mention. You, might have missed it, so I'll show it again:

    root("template", placeholder.or(literal).repeated().then(eof));

That's right, a with statement. I bet you never though you would see somebody actually try to use one of those. Sure, with statements are widely reviled, they are not one of the good parts, and they're dead in EC5 strict mode... but embedded DSLs are one of the places where you're allowed to cheat like there's not tomorrow. 'sides, $.extend(window, grammar); is your other option for scope manipulation and that's just plain evil.