jQote2 – Javascript templating revamped

jQote2 is the second major release of jQuery’s most powerful and versatile client-side templating engine. Version 2 now incorporates a faster and more accurate parsing/conversion part that does away with its predecessor’s shortcomings in escaping quotes and multiline support.

If you haven’t used or never heard of jQote before you might want to check out this post first, as it provides a quick insight into jQote’s way of client-side templating.

I’ve set up a repository over at GitHub. That’s where you will find the latest releases.

So, what’s new for v2 you ask? Quite a lot, actually. But let’s see one by one:

1.  jQote2 breaks compatibility with its predecessor

- jQote2 now returns a flat string representation of the converted template whereas its predecessor would give you a jQuery object.

The reason behind this substantial change is mainly speed. Appending the converted string as a whole cuts back greatly on the time it takes to generate the corresponding DOM fragment. On top of that you’ll now gain full control over your template’s outcome, to whom and when you want it to be appended etc.

2.  jQote2 improves on template handling

- jQote2 now provides an interface to precompile your templates to lambda functions.

This is probably the most exiting new feature as it lets you precompile templates during development and simply use them in production afterwards – without the need to dish out your template code to your customers.

- jQote2 now supports on-the-fly template strings.

For quick and dirty templating jQote2 now enables you to process template strings. This will make it easy for you to realize minor templating tasks on-the-fly without added the overhead.

3.  jQote2 is powered by a faster and more robust parsing engine

- jQote2 now offers full multiline and escaping quotes support.

The previous version had issues regarding line breaks within the scope of shorttags which are used to echo out the result of Javascript expressions. jQote2 now fully supports your way of coding style: what goes inbetween the tags (be it shorttags or standard notation) is pure Javascript and you decide how it is layed out.

Pure Javascript support implies proper escaping of quotes, though. And you will have to take care of that yourself. Outside the tags however the engine now correctly escapes qoutes within your markup, thus letting you concentrate on your work rather than the plugin’s internals.

- Speed, speed and again – speed!

Brian Landau has set up a bunch of benchmarks comparing the runtime of Javascript templating libraries. jQote didn’t perform all that bad but in the end couldn’t gain the crown.

With the release of jQote2 though the picture has changed quite a bit: jQote2 is now on a par with Underscore, the former sole sovereign, making both the natural choice for heavy Ajax powered sites. Please note though: Since Underscore internally uses John Resig’s conversion engine it replicates its flawed multiline and escaping quotes handling, leaving you with runtime errors whenever you need to have single quotes (both escaped or unescaped) inside the Javascript parts.

To backup my claims I forked Brian Landau’s benchmarks and put together a single file benchmarking suite at github. To offer you some eye candy I’ve integrated the powerful flot plotting library. Here’s an example of my findings running the benchmark 25 times with a 1000 conversions each in Firefox 3.5.7.

jqote2 benchmarking suite

From left to right: Srender, mustache.js, Underscore, jQote2, Tempest, nano.
Less is better. All times in ms.

As you see Underscore and jQote2 vastly outperform the other contestants and moreover are superior in their ability to embed pure Javascript within the templates.

Enough said! Try it for yourself. Due to repeated requests I have finally set up a repository over at github. You may fetch the latest versions there. So long …

comments

11 Responses to “jQote2 – Javascript templating revamped”

  1. Fizz on April 2nd, 2010

    Hi aefxx.

    I love jqote! Thanks for a great templating library! I just learned about it a few days before you released jqote2, which I’ve now upgraded to.

    A quick question about precompiling templates: I’m not sure if my approach is what you had in mind. I’m compiling them with
    var t_somehtml_c = $.jqotec('some html') which yields an anonymous function, and then shipping them as naked vars in a templates_c.js file in production and using them with $.jqote(t_somehtml_c, {key:val}). Is this right?

  2. aefxx on April 5th, 2010

    @Fizz

    Yep, that’s perfectly legal use. I’m glad you like it.

    Regards.

  3. Chris on April 9th, 2010

    Just trying to use JQote. Very cool indeed.

    I was wondering how you would handle adding DOM events to the template?
    I was hoping to be able to add JQuery object as part of the data and it would keep the Events which were bound to it, however it seems that Jqote only works with strings.

    Any ideas?

    Thanks,

  4. aefxx on April 9th, 2010

    @Chris

    If I get you right the thing you ask for can’t be done the way you were thinking of. Since all jQote2 returns is merely a string and events are limited to be bound to DOM elements, there’s literaly no way of “cloning” a jQuery object’s event to the outcome of a processed template.

    But then again, once you turn that string into a DOM element, you may benefit of jQuery’s live events capability. Take a look at this example:

    <ul id="menu">
        <li><a href="about.htm">About</a></li>
        <li><a href="contact.htm">Contact</a></li>
    </ul>
    
    <script type="text/x-jqote-template" id="template">
        <![CDATA[
        <li>
            <a href="<%= this.href %>"><%= this.link %></a>
        </li>
        ]]>
    </script>
    <script type="text/javascript">
        $(function() {
            var $tmpl = $('#template');
    
            // Use live events to hook onto clicks
            $('#menu li a').live('click', function() {
                alert( "You've just clicked on " + $(this).text() );
                return false;
            });
    
            // Now let's add a Sitemap to our menu
            $('#menu').jqoteapp($tmpl, {
                href: 'sitemap.htm',
                link: 'Sitemap'
            });
        });
    </script>

    Hope I could help you here.

    All the best,
    aefxx

  5. Alex Angas on June 21st, 2010

    I’d love to use this library but why is it using ASP.NET delimiters? I can’t risk needing to fix bugs because of the problems it could cause. Please change this!

  6. aefxx on June 21st, 2010

    @Alex

    Hi Alex,
    sorry to hear that the existing delimiters would keep you from using the library. Actually, I never thought of this being a problem (as I don’t code in .NET on the one hand) and still don’t think it is: jQote2 has a number ways to alter the delimiters to suit your needs.

    - Global delimiters change:

    $(function() {
        // Globally change the delimiters to  < $ .. $>
        // right after the DOM has loaded
        $.jqotetag( '$' );
    
        // From now on jQote2's delimiters defaults to < $ ... $>
    });

    - On a per call basis:

    $(function() {
        // Imagine that some of your templates are coming
        // from different sources, built with different delimiters
        $('#menu').jqoteapp('#menu_item_tmpl', data, '$');
        ....
        $('#widget').jqotesub('#widget_news_tmpl', data, '#');
    });

    - Go and change the sources (I do not recommend this, though):

    --- a/jquery.jqote2.js
    +++ b/jquery.jqote2.js
    @@ -15,7 +15,7 @@
            STR = '[object String]';
    
        var n = 0,
    -       tag = '%',
    +       tag = '$',
            type_of = Object.prototype.toString;
    
        $.fn.extend({
    --
    

    As you can see, changing the delimites is just a matter of seconds. I hope you will now be able to use jQote2.

    Have a nice day.
    aefxx

  7. Robert on June 25th, 2010

    Servus aus Kalifornien !

    And many thanks for your excellent upgrade to Resigs engine. I have been using it for a project and really like the ability to intermix javascript with html.

    Couple of things I noticed/suggestions:

    would it be possible to automatically wrap the stuff inside in parens ?
    I noticed that things like

    <%= name!='' ? 'a' : 'b' %> or <%= b - a %>
    can cause parse errors, but protecting like this works:

    <%= (name!='' ? 'a' : 'b') %>
    <%= (b-a) %>
    

    Perhaps the engine can do this automatically since it seems easy to do, harmless and likely to avoid pilot errors.

    The other question is whether some kind of improved error messages would be possible in case the templates contain bad code. Might not be easy, I know, but debugging with “rip a bit of code out”, “rerun”, “rip another bit of code out”, “rerun” ends up being very time consuming.

    Perhaps a js error handler around the eval and IF an error is found (so you don’t slow down evaluation in the non-error case), piecewise evals so at least a mysql like “error near blabla” could be issued via console.log() or similar.

    Thanks again,
    Robert

  8. aefxx on June 25th, 2010

    @Robert

    Thanks for your comment, Robert.
    You’ve asked for “improved error messages” to better debug erroneous template code … well, good news, the “develop” branch over at github features built in error support (and new special events, by the way). It’s tagged as beta but will get merged back into the master branch this weekend and thus become the stable version 0.95. Give it try.

    Concerning the automatic bracketing of shorthand tag expressions: it sounds quite feasible … I will have a look at it and eventually add it.

    Regards,
    aefxx

  9. Tony on June 25th, 2010

    Is there a specific problem with jQote and IE6? The library works like a dream with other browsers and versions of IE – but on IE6 the page rendering just stops when it hits [...]

    Edit by aefxx
    Tony boiled the problem down to IE6’s crappy implementation of the CSS display property. Thus, IE6 may still be viewed as 100% usable with jQote2 (who cares about this anyway, I wonder).

  10. Robert on July 2nd, 2010

    Love the exception handling !
    With latest trunk, wrap your calls to jQote2 and you get at least some idea of what is going on:

    try {
        $new_page.jqotesub( template, data );
    } catch(e) {
        alert('jQote2 instantiation of template "' + id + '" failed:\n' + e);
    }


    also, this is a particularly gnarly one to find:

    Notice how the single else statement does not have { }? Thats valid js but in the context of templates , something wiggy happens because it says contacts is unknown. Anyway, easy fix (if you know it :) is to always put an abundance of { } in your js inclusions (and, as previously mentioned, ( ) for type inclusions).
    Unfortunately the cannot be fixed by slapping cautionary { } around everything in the jQote2 engine because that would change var scoping destructively.

    Cheers
    Robert

    Edit by aefxx
    There’s no need to wrap “type inclusions” (aka shorthand tag expressions) in parens anymore as this is done automagically within jQote2’s conversion part (which was inspired by Robert Seidl, btw).

  11. Robert on July 10th, 2010

    another handy feature that would be (I think) fairly easy to add:

    // style comments
    currently cause parse errors (I assume because of concatenations)
    /* */ still work by the way

    but they are handy and I often “forget” I am in a template and just write regular commented javascript.

    Not to bloat jqot too much (or slow it down, I know you like it fast) – but perhaps if a line contains a ‘//’, strip out the comment up to EOL. If you use indexOf instead of regex its probably a negligible slowdown.

    Robert

Leave a Reply




  • About me

    Hello my friend, please call me aefxx.
    I'm a 31 year old software engineer and web developer. Born in Munich, Germany I am currently located at Freiburg im Breisgau.

  • Contact me

    I am available as a freelancer, so feel free to get in touch with me.

    email ... sam@aefxx.com
    icq ... 179630229 // ae.fxx

copyright © 2009 once upon my code • powered by WordPress • modified Whitespace theme by Brian Gardner