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

28 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

  12. Riley Dutton on October 10th, 2010

    I have used jQote2 for quite some time now and love it!

    When the new jQuery Templates plugin came out, I of course wanted to compare, so I rewrote the benchmark to include the new plugin. Here are the results:

    http://rileydutton.com/post/1286080073/jquery-templates-vs-jqote-2

    jQote2 is incredibly fast! Keep up the great work!

  13. aefxx on October 11th, 2010

    @Riley

    Thanks for the compliment. I will have a look at your findings, I promise.

    Have a nice day.

  14. fschwiet on October 21st, 2010

    Nice work on jQote2. I realized though that when I include text via it is not html encoded, so if I get some malicious data that script could be injected. Do you have any guidance on how best to html encode text include with ?

  15. fschwiet on October 21st, 2010

    Sorry, I should have realized the example markup would have been removed. I think you understand though, variables rendered in the template are not HTML encoded. Is there a good way to HTML encode them? I’d like jQote to encode them by default, if that is possible.

  16. aefxx on October 21st, 2010

    @fschwiet

    Since v.0.9.6 jQote2 offers another, a second short hand tag (<%! %>) that safely escapes all occurrences of &, ", ', < and > within your (possibly tainted) data. You’d use it just like its “unsafe” counterpart:

    <script type="text/x-jqote-template" id="template">
        <![CDATA[
        <div class="comment">
            <%! this.untrusted %>
        </div>
        <div class="comment">
            <%= this.untrusted %>
        </div>
        ]]>
    </script>

    The blue line now safely escapes any untrusted data to help protect against XSS / XSRF, whereas the pink one just passes it on.

    Hope, you’ll like it.
    aefxx

  17. fschwiet on October 30th, 2010

    well done, thank you.

  18. shamus on November 1st, 2010

    There is a reference error in jqotenc() in v0.9.7. Line 174 should be “return str.toString()”, not “return s.toString()”. After fixing, encoding works great… thank you!

  19. aefxx on November 2nd, 2010

    @shamus

    Thanks for the note. I should write more tests, I suppose?

  20. J on December 2nd, 2010

    Cool!

    I haven’t seen any examples of complex forms being built with this. Has anyone explored what it would take to i.e. add a row, some part of a whole template, to accommodate a new element in the form’s bound a object’s array? The template would include templating the element indexes of arrays and could be properly serialized for POSTing. But I’m having trouble thinking it all through. The goal is InfoPath-like functionality. (I’m aware of the various existing infopath features and infopath alternatives.)

  21. ub on December 3rd, 2010

    Hi

    Do you have a exemple of template to make a table with header and value

    How to make the for each or other solution

    thank’s

  22. Aaron S on January 10th, 2011

    Am I the only one in two editions of this code who has noticed the incorrect spelling of the word quote? :P Any particular reason for that choice of spelling?

    Nice library though – and the speed benchmarks are very impressive.

  23. Aaron S on January 18th, 2011

    Nice work with jQote! Less than an hour to get it set up with our web app, and now all our popup dialogs are unobtrusive templates :)

    Aside: Am I the only one in two revisions of this code to notice the typo in the name jQote? Any particular reason for spelling it that way?

    Aaron

  24. aefxx on February 5th, 2011

    @Aaron

    Hehe, nope, it’s not a typo. jQote stands for: jQuery’s oven-ready templating engine.

  25. Steve Lacey on March 5th, 2011

    Only just came across jQuote from a StackOverflow answer, grasped that quickly, easily, noticed related article ‘jQuote2′. Spent 10 minutes reading through this page and the API reference… have no idea how you’re telling me I should even define a template… can you provide some basic examples? All I need is a non-shit way of marking up an object’s properties..

    Saw you said they no longer need be in markup, yet all the examples in the reference seem to imply they should be?

    Ta,
    Steve

  26. aefxx on March 7th, 2011

    @Steve Lacey

    Hi Steve,
    I’m sorry you couldn’t figure out how to exactely define/deploy a template or its compiled lambda. I guess you must have overlooked the hint on this site’s top where I refer anyone not familiar with jQote to its introductory post: jQote – client-side templating. There you will see a very basic example on how to write a template and induce its conversion with some sample data.

    Once you outgrow the idea of embedding your templates within the HTML sources, you should make use of jQote2’s ability to precompile templates into plain JavaScript functions which you may use just like their hand-written brethren. As soon as I can spare some time I will write down a tutorial that deals with both, basic embedded templating and a more mature approach (aka build system). So, please bear with me.

    All the best,
    aefxx

  27. vbarrier on April 19th, 2011

    Hello,

    I didn’t find any solution to “embed” javascript inside the template. This javascript must be evaluated right after the insertion (not at the templating time so not in

    The main goal is to add logic associated to the template in an app that use a lot of ajax call etc…

    So I made a simple hack :

    add any javascript inside :

    alert(‘hello world’)

    and in jQote2 I have added this :

    return this.each(function() {

    //custom begin
    str = str.replace(//g, ‘<script type=”text/javascript”>’);
    str = str.replace(//g, ‘</script>’);
    //custom end

    var dom = $$(str);
    $(this)[method](dom);

    ( dom[0].nodeType === 3 ?
    $(this) : dom ).trigger(‘jqote.’+name, [dom, regexp]);
    });

    What do you think of this ?

  28. Steve on October 9th, 2012

    Definitely looks faster. Nice work on this update!

    Is there any way to get all the sections (Srender, mustache.js, etc.) to load asynchronously, or do they do that already?

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