Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2012/07/23

The Quest For Javascript Templating

I first heard about templating several years ago at YAPC::NA 2006, when Ingy döt Net talked about Template Toolkit. I honestly did not get it then. I was putting my HTML in my code at the time, and I just didn't get it.

Soon after, I started working at the Lab, and Lab standard was to use CGI, so I started to do that, and my code went from:
print qq{
    <a href="http://draft.blogger.com/$link">Link</a>
    } ;

to something more like.

print $cgi->a( { href=> $link } , 'Link' ) ;

That example is simple enough, but it gets complicated when you're putting together a large table of tabular data. (I feel I must explain that I'm tables for their proper purpose.) The Lab is now moving toward using Dancer as our framework (we don't have it fully implemented yet, but I have some things very close) and thus use Template Toolkit fairly regularly, and I foresee a day in which I won't need to have massive bricks of code to put together my HTML. At least in Perl.

Javascript, that's another matter.

    $.get(
        apr.chip_url ,
        function ( data ) {

            $( '<fieldset id="chip_field">')
                .addClass( 'narrow_fieldset' )
                .appendTo( chip_div ) ;
            $( '<legend>')
                .text( "Chips" )
                .appendTo( chip_field ) ;

            $( '<div id="select_div" />' )
                .appendTo( chip_field ) ;
            $( '<select name="chip_sel" id="chip_sel">')
                .appendTo( select_div ) ;

            $( '<div id="control_div" />' )
                .text( ' Include Control?: ' )
                .appendTo( chip_field ) ;
            $( '<input type="checkbox" />' )
                .attr('id',"control")
                .attr('name',"control")
                .val("control")
                .prependTo( control_div ) ;

            $( '<div id="submit_div" />' )
                .appendTo( chip_field ) ;
            $( '<div class="button" />' )
                .text( 'Choose Chip' )
                .appendTo( submit_div )
                .click(
                    function () {
                        apr.write_chip() ;
                        }
                    )
                ;

            // Fill the Select
            var d_list = [] ;
            for ( var i in data ) { d_list.push( i ) }
            d_list = d_list.sort() ;
            for ( var d in d_list ) {
                var i = d_list[ d ] ;
                $( '<option/>')
                    .text( data[i].name )
                    .val( i )
                    .appendTo( chip_sel ) ;
                }
            } ,
            'jsonp'
        ) ;

This is some live Javascript I wrote. It uses jQuery, because if you don't use a framework of some sort to handle then differences between browsers, you are asking for trouble, and I've since discovered some ways to do appends better, but this is exactly the big block of ugly stuff that I hated with CGI and made me pledge my babies to Template Toolkit.

So, what I'm in desperate need for is Template.js to go with Template.pm. Or the like. I am sure that this is not just my problem. I am sure that other people have hit this problem and created a solution. Can anybody point to a good solution?

11 comments:

  1. Have you looked at https://github.com/janl/mustache.js/ ?

    ReplyDelete
  2. underscore.js also provides a templating language.

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. If the JavaScript is not dynamically generated then just put it into a file somewhere under your web root (such as /javascript) instead of relying a templating solution.

    Is that JS supposed to be dynamically generated? I don't usually use jQuery so I'm not sure.

    ReplyDelete
  5. If you decide to use mustache.js, you might try ICanHas.js. Somewhat nicer (in my mind) way to make mustache templates despite the bad name. With this you use script blocks to store the raw html instead of having to write the template as a string.

    Alternatively Transparency is a jQuery specific template engine you might consider (since you are using jQuery already). From benchmarks I've seen it has a lot better browser performance than Mustache as well. It uses plain html instead of strings for rendering as well.

    ReplyDelete
  6. When I was looking for a JavaScript templating solution, I ended up deciding Jemplate was wonderful. However, pure deserves a more serious look than I was able to give it.

    ReplyDelete
  7. There's two common solutions:

    One is to use a Javascript template engine, which generally leaves you in the fun situation of doing half the templating in a server-side templating system and half in a client-side templating system. Even if you decide to use Mustache on both ends or some other "common" language, you'll find inconsistencies and annoying bugs. The comments above have plenty of suggestions if you want this route.

    The other solution is to say "to hell with the XML/JSON part of AJAX for this" and just generate the HTML server-side using your existing template engine as a partial snippet and just use Javascript to merge it into the DOM at the appropriate place. This often allows you to reuse fragments of your server-side templates, avoiding issues where you have to maintain multiple forks of code to generate the same output.

    I personally favour the second solution, but have the AJAX API have a format parameter so it can output raw XML/JSON too for third-party use.

    ReplyDelete
  8. Thank you all.

    Olaf: I have looked at Moustache.js and have a note saying "try Moustache.js" on my whiteboard. I haven't set it up.

    Htbaa, james, Sinan, Mark: I will throw underscore and Jemplate and ICanHas into the mix, too.

    Mr M.: The Javascript static and is in a file, but I'm writing several pages of Javascript to pop up a small number of elements, making the code big and brittle, and I'm in need of an alternative.

    ReplyDelete
  9. Illusori: Part of me REALLY likes that idea. It certainly takes away some of the complexity, or at least puts it in the server where it belongs.

    For ease, I could send the HTML as json -- code : "<a href='http://varlogrant.blogspot.com/'>Link to Blog<a>" but it strikes me that sending a lot of that is wasteful. Of course, few of my bits will go further than a short walk away from the server room, so that's less of an issue....

    ReplyDelete
  10. Mr M: I feel I was unclear. I am generating rows of a table over and over again, based (primarily) on the result of an AJAX call to a database-access script. The HTML is dynamic. The Javascript is static.

    ReplyDelete