Jemplate: The JavaScript templating engine made in heaven

Well, I exaggerate … it's made by Ingy, but that's still close enough ;-)

In response to my earlier post, @Naveed pointed me in the direction of Jemplate.

Jemplate allows you to compile Template-Toolkit templates into JavaScript source. In your HTML document, you reference two extra JavaScript files, one for the Jemplate runtime, and one for the JavaScript file containing all your templates in compiled form.

When the time comes to generate content, you retrieve the JSON object that will be used to fill in a template via an Ajax call, ask Jemplate to process it. It can automatically add the content to an element identified by an id, or you can use your favorite DOM manipulation library to insert it in the right place.

In my case, I am inserting slides into a deck.js presentation, so I chose to use callback to insert the slides before initializing the deck.

Using Jemplate does introduce extra steps into the process of "playing around" to discover it: You have to compile and deploy changes to your templates each time. You have to be running a local web server etc. Using something like handlerbars or mustache, you can just put together a skeleton document and play around.

That's not a great disadvantage, however: First, I am already familiar enough with Template-Toolkit that I don't need to play around as much. Second, I like the fact that the HTML served is devoid of template content.

Here is how I tested Jemplate:

Write something to generate the data

Normally, the data would come from a database, but I am just playing around here:

#!/opt/www/perl/bin/perl
use 5.014;
use utf8;
use strict;
use warnings;
use warnings qw(FATAL utf8);
use open qw(:std :utf8);

use CGI::Simple;
use JSON qw( to_json );

sub {
    my $cgi = CGI::Simple->new;

    my $questions = {
        'questions' => [
            {
                'id' => "Q1",
                'text' => "Which one would you use?",
                'answers'=> [
                    { 'id' => "Q1A", 'text' => "Moose" },
                    { 'id' => "Q1B", 'text' => "Moo" },
                    { 'id' => "Q1C", 'text' => "Mo" },
                    { 'id' => "Q1D", 'text' => "moot" },
                ],
            },
            {
                'id' => "Q2",
                'text' => "What do you like most about Perl5?",
                'answers' => [
                    { 'id' => 'Q2A', 'text' => "feature" },
                    { 'id' => 'Q2B', 'text' => "Hashes" },
                    { 'id' => 'Q2C', 'text' => "CPAN" },
                    { 'id' => 'Q2D', 'text' => "m//" },
                ],
            },
        ],
    };

    print $cgi->header(
        -type => 'appplication/json',
        -charset => 'utf-8',
    ), to_json($questions, {utf8 => 1, pretty => 1});
}->()

Write the template

Compile the template and generate the runtime

Next, I compiled the template using jemplate --compile and put the output in js/jemplates.js (if you have more than one template, all of them go into the same file). I am already using JQuery, so I generated the JQuery runtime for Jemplate using jemplate --runtime=jquery and put it in js/Jemplate.js.

Add the necessary pieces to the main document

Finally, I added the following to the HTML for the main document:

<script src="js/Jemplate.js"></script>
<script src="js/jemplates.js"></script>

<script>
    $(function() {
        $.getJSON("/cgi-bin/questions.pl", function(data) {
            $('body.deck-container').prepend(
                Jemplate.process('questions.tmpl.html', data)
            );
            $.deck('.slide');
        });
    });
</script>

And, it worked.

It took longer to type up this post than to put together all the pieces of this proof-of-concept exercise for me. I am sold. Jemplate is great. Thanks Ingy and Andy.