jQote2 API reference
jQote2’s internals are quite a bit different from its predecessor’s. Thus, please make sure to double-check the new API as it breaks backward compatibility!
The three biggest changes with jQote2’s API are:
- it now returns a “stringified” representation of your generated HTML markup
- it’s now possible to precompile your templates to closures (no need to deliver template markup within your documents anymore)
- it now supports on-the-fly templating strings
Here’s a quick overview of jQote2 ’s new interface:
- .jqote(data[, tag])
- .jqoteapp(template, data[, tag])
- .jqotepre(template, data[, tag])
- .jqotesub(template, data[, tag])
$(template).jqote(data[, tag]) : function
jQote2 is able to operate on an arbitrary number of templates, each of which may process an arbitrary number of data objects, thus effectively allowing you to trigger n:m conversions with a single call.
Each time a template of yours is run, it is passed a couple of auxiliary variables:
-
two counting variables
iandj
(the former iterating over the processed templates, the latter iterating over your data objects array) -
the data objects array
dataitself -
the current processed template’s compiled lambda
fn
(which comes in handy with recursive calls)
To not be forced to use data[j] to access a template’s current data object, its compiled lambda is fired in the context of the data object, so you may just as well use the this keyword to reference your data.
Additionally, during the process of conversion (the execution of the lambda, that is) you may access the by then converted output using the out variable. This gives you total control over the output even from within a template at any time.
By the way: all of the above is also true for any of the jqoteXXX convenience methods explained below.
Returns
out : string (the processed outcome)
Parameters
data : object | array of object
One or more objects that carry the template’s dynamic data. Each data object that’s passed in here will get merged with any of the templates you called the conversion upon.
tag : string (optional, defaults to "%")
You may use the optional tag parameter to specify different template tag character(s) for a single conversion. Keep in mind though that whatever char(s) C you opt for here will result in <C ... C>.
Called upon
template : jQuery object
Every template within the jQuery collection will be merged with any of your data objects.
Example
The infamous and obligatory “Hello World” … generated with a different start- and ending tag (the * star).
Note: data[j] is essentially the same as this!
<p id="example"></p>
<script type="text/x-jqote-template" id="template">
<![CDATA[
I said <strong><*= this.greet + " " + data[j].who *></strong> !!!
<* out = out.replace(/John/, 'World'); *>
]]>
</script>
<script type="text/javascript">
// let's do some jQote magic
$('#example').append(
$('#template').jqote({greet: 'Hello', who: 'John'}, '*')
);
</script>
I said Hello World !!!
$(elem).jqoteapp(template, data[, tag]) : function
This is one of three convenience methods jQote2 has to offer. It allows you to append the processed template’s outcome directly to any DOM element that is part of the jQuery object.
Returns
jQuery : jQuery object
The returned jQuery object keeps the method chain intact. It is the same object that you called the convenience method upon.
Parameters
template : jQuery object | jQuery selector |
DOM element | array of DOM element |
lambda | array of lambda |
template string
This parameter can be passed as about anything you possibly could think of. It’ll work with a collection of template elements (either as jQuery object or array of DOM elements) as well as single template elements (again jQuery object or DOM element).
Furthermore you could pass it a single or multiple (just wrap them up in an array) precompiled lambda which gets you the best performance as it will skip the compilation and execute right away.
For quick and dirty on-the-fly templating you may also choose to supply a template string which won’t get cached but other than that behaves just as any other template.
data : object | array of object
tag : string (optional)
Called upon
elem : jQuery object
The outcome of the conversion will be appended to every single DOM element within the jQuery object.
Example
The “Hello World” example from above rewritten.
<p id="example"></p>
<script type="text/html" id="template">
<![CDATA[
I said <strong><%= this.greet + " " + this.who %></strong> !!!
<% out = out.replace(/John/, 'World'); %>
]]>
</script>
<script type="text/javascript">
// let's do some jQote magic
$('#example').jqoteapp('#template', {greet: 'Hello', who: 'John'});
</script>
I said Hello World !!!
Example
This makes use of the on-the-fly templating support.
<ul id="example"></ul>
<script type="text/javascript">
$('#example').jqoteapp(
'<li><<%= this.tag %>>Styled!</<%= this.tag %></li>',
[ {tag: 'strong'}, {tag: 'em'} ]
);
</script>
- Styled!
- Styled!
$(elem).jqotepre(template, data[, tag]) : function
This is jqoteapp’s counterpart as it behaves just the same way with one major difference: it prepends the outcome rather than appends it.
Returns
jQuery : jQuery object
Parameters
template : jQuery object | jQuery selector |
DOM element | array of DOM element |
lambda | array of lambda |
template string
data : object | array of object
tag : string (optional)
Called upon
elem : jQuery object
$(elem).jqotesub(template, data[, tag]) : function
If you need to substitute an element’s “innerHTML” more than once, this function is for you. It replaces whatever resides within a DOM element with the outcome of your template’s processing.
Returns
jQuery : jQuery object
Parameters
template : jQuery object | jQuery selector |
DOM element | array of DOM element |
lambda | array of lambda |
template string
data : object | array of object
tag : string (optional)
Called upon
elem : jQuery object
Example
Replace the target’s “innerHTML” with something more “up to date” …
<p id="up_to_date"></p>
<script type="text/javascript">
$(function() {
var now = function() {
return new Date().toString().replace(/ GMT.*$/, '');
};
$('#up_to_date').bind('uptodate', function() {
var self = $(this);
setTimeout(function() {
self.jqotesub('<%= this.date %>', {date: now()})
.triggerHandler('uptodate');
}, 1000);
}).triggerHandler('uptodate');
});
</script>
$.jqote(template, data[, tag]) : function
This basically offers the same functionality as its object associated counterpart with the added possibility to have it process precompiled lambdas or on-the-fly template strings.
Returns
out : string (the processed outcome)
Parameters
template : jQuery object | jQuery selector |
DOM element | array of DOM element |
lambda | array of lambda |
template string
data : object | array of object
tag : string (optional)
Example
Calculating the famous Fibonacci sequence (using just a small n due to Javascript’s limited recursion stack).
<ul id="fibonacci">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script type="text/x-jqote-template" id="template">
<![CDATA[
<%= ( ( this.n == 0 ) ?
0 : ( this.n == 1 || this.n == 2 ) ?
1 : parseInt($.jqote(fn, {n: this.n-1})) +
parseInt($.jqote(fn, {n: this.n-2})) ) %>
]]>
</script>
<script type="text/javascript">
$(function() {
var lambda = $.jqotec('#template');
$('#fibonacci li').each(function(i) {
$(this).text($.jqote(lambda, {n: i}));
});
});
</script>
$.jqotec(template[, tag]) : function
This is jQote2’s heart, its engine that powers the template parsing and lambda generation. It transforms a single template into a compiled function that – once processed – is cached internally to speed up successive usage.
You may assign the returned lambda to a variable and/or pass it to any of the before mentioned functions or let jQote2 fetch it from its internal cache for you (just pass the associated DOM element in this case).
Please note that on-the-fly template strings won’t get cached as there’s no element to associate the lambda to. Moreover, if for whatever reason you need to recompile a cached template, jQote2 makes sure to replace the cached lambda for you.
Returns
lambda : function
The compiled lambda is merely a Javascript function like any other. Once called and fired in the context of a data object the lambda returns a “stringified” representation of your template’s and data object’s merge. In most cases this will be an “HTML string”, though it could be anything that goes into a string (i.e. plain text or a JSON string etc.).
The lambda’s signature is defined as: ?(i, j, data, fn), where fn is a reference to ? (this is important when you need to have recursion within your templates).
For an explanation of what each paramter stands for, see this paragraph.
Parameters
template : jQuery object | jQuery selector |
DOM element |
template string
Please note that only the very first template of a set of matched templates within a supplied jQuery object (or selected by means of a jQuery selector) is chosen for compilation.
tag : string (optional)
Example
See what the lambda of above’s “Hello World” example looks like once it’s been compiled.
<pre id="lambda"></pre>
<script type="text/x-jqote-template" id="template">
<![CDATA[
I said <strong><*= this.greet + " " + this.who *></strong> !!!
<* out = out.replace(/John/, 'World'); *>
]]>
</script>
<script type="text/javascript">
$(function() {
$('#lambda').text(
$.jqotec('#template', '*').toString()
);
});
</script>
$.jqotefn(template) : function
jQote2 exposes its internal cache $.jqotecache and gives access to a template’s compilate by means of the its DOM element’s internal cache ID (just a plain integer starting at zero and running up). This cache ID is assigned to the template’s DOM element and may be read with elem.jqote or $(template selector)[0].jqote.
As it is a tedious task to type in $.jqotecache[$('#mytmpl')[0].jqote] over and over, you may as well just use the more convenient way: $.jqotefn('#mytmpl') !!!
Returns
lambda : function (or false if nonexistent)
Parameters
template : jQuery object | jQuery selector |
DOM element
$.jqotetag(string) : function
Calling this function you will be able to permanently alter jQote2’s default tag char from being % to something more suitable to your needs.
Returns
void
Parameters
tag : string
You aren’t forced to have a single tag char, at all. You might just as well use some crazy ass string like ^^. Keep in mind though, that whatever char(s) you opt for you always have to prepend/append angle brackets within your templates!
comments
28 Responses to “jQote2 API reference”
Leave a Reply
Can you explain how one might create and manage numerous templates without having script tags all over the place? I”m using EJS right now which fetches a template with ajax which is great because i can create as many .ejs template files as I want and I never muddy up my html source with script tags. I’m looking for something more jquery friendly however as I’d like to start associating data with my dom elements as they’re rendered. Can you provide a sample of how this might be achieved? or does one always need a tag in order to use jqote?
@Brad
Hi Brad. No, those script tags aren’t required at all. They’re just a handy way to embed templates within your pages without being rendered or indexed by search engines. You could just as well wrap a div around your templates and use the tag’s display property to hide it.
Anyways, you asked for a way to remotely include your templates. There are quite a bunch of options to choose from, mostly depending on the way you organize your templates. To list them here would go beyond the scope of a single post, but to get you started consider the following:
A template file foo.tpl that contains a single template …
<h1>Hello world!</h1> <p> My name is <%= this.name %> and I really love <%= this.what %>. </p>… and some Javascript to let it run …
Nice. This was easy, wasn’t it? A one file per template approach gives the benefit of not having to wrap up your template markup with some kind of dummy container.
However, if you need to combine several templates within a single file, you would have to put these in a container (you may use any tag for this, even custom ones) and assign an ID or at least a class name to be able to select these later on.
From an email I once wrote to a jQote2 user:
<template id="tmpl_1"> // some template markup </template> <template id="tmpl_2"> // some template markup </template> ...Ok, I think you’ll grasp the concept. Hope this gets you started.
Regards.
Hi! How about introducing
<%! value %>to mimic the current<%= value %>and switching<%= possibly_unescaped_value %>to always perform HTML escaping so it can be safely used?TIA,
–Vladimir (via GitHub)
I really like your examples showing how to use multiple templates loaded via ajax calls but I find there is a problem with jquery parsing the retrieved html and replacing the template tags (<%) with html entities (<). I've tried all sorts of ways to get around this but can't find a solution. Have you successfully used this template loading method in a test?
I’m getting “Uncaught ReferenceError: ” in Chrome… it doesn’t report a useful line number (line 2).
I’m stumped. What should I be looking for?
Cheers
@Rich
The latest release of jQote2 (i.e. v0.95) provides some basic error handling. All you need to start debugging is a decent JavaScript debugger (preferably Firebug or Firebug lite, in your case). Some quick hints on how to debug:
Wrap the method invocation in a try/catch block like so:
try { .... $('div.my_container').jqoteapp(...); } catch (e) { console.dir(e); }This provides you with an error object that contains the call stack, the lambda (i.e. converted template function), the arguments that were passed to your template and a type variable that indicates what kind of jQote2 error has been raised.
Of particular interest are the template function and the type variable: if you get a “TemplateCompilationError” than your template could not be compiled which indicates that there’s some sort of syntax error within your template’s source. A “TemplateExecutionError” on the other hand is most likely caused by some sort of unresolvable reference(s) or runtime errors, in which case you should examine the compiled template itself using the error object mentioned earlier. To see what’s causing the compiled template to fail you could copy the lambda’s source and use it like any other JavaScript function like so:
<script type="text/x-jqote-template" id="err_tmpl"> <![CDATA[ <p>What's the problem here, <%= that.name %>?</p> ]]> </script> <script type="text/javascript"> // First, let's get the compiled template's source // which we'll be copying to the clipboard and ... console.log( // I may be commented out after my source was leaked :) $.jqotec('err_tmpl').toString() ); // ... pasting into our site's source, renaming it to // something descriptive and removing the try/catch block function bugged(i, j, data, fn) { //try { var out = "<p>What's the problem here, "; out += that.name; out += "?</p>"; return out; /*} catch (e) { e.type = "TemplateExecutionError"; e.args = arguments; e.template = arguments.callee.toString(); throw e; }*/ } // Now, we will provide the buggy lambda with some // sample data to have it choke on and generate // a decent JavaScript exception var dummy = {name: 'Kenneth'}; bugged.call(dummy, 0, 0, [dummy], bugged); </script>Happy debugging.
Regards,
aefxx
OK, thanks!
One more question.
I now have this working beautifully in the browser. However I’d like to use it in an Adobe Air app.
Air has a sandbox restriction where you can’t call “new Function” after the onload event.
So, to use templates in an Air app, I figure the best way is to pre-compile the templates?
Would you be so kind as to give an example of using this plugin to pre-compile and render templates?
many thanks
never mind i figured it out…
// to precompile a template
TEMPLc = $.jqotec($(‘#templ_id’))
// returns templated output as string
$.jqote(TEMPLc, data)
I have the following problem that I would like to solve with jQote2.
data: [ { set: 1, tmpl: 'a', .. }, { set: 2, tmpl: 'b', .. }, { set: 3, tmpl: 'a', .. }, { set: 4, tmpl: 'c', .. } .. and so on ]; <script type="text/x-jqote-template" id="tmpl_a"></script> <script type="text/x-jqote-template" id="tmpl_b"></script> <script type="text/x-jqote-template" id="tmpl_c"></script>I would like to render the above within one div so it looks like so
tmpl_a output with set 1
tmpl_b output with set 2
tmpl_a output with set 3
tmpl_c output with set 4
..
and so on
In other words, I have a sequence of data sets that I want to render with set-specific templates. Can this be done?
never mind… I figure it out… ;-)
for (var i = 0; i < data.length; i++) { $('#example').append( $('#' + LCA.data[i].tmpl).jqote(LCA.data[i]) ); }Hi. I’ve been using jqote for a couple months now and it’s a great tool. I’m in the process of changing my app to load my templates dynamically and am pretty stumped. Basically, none of the template tags are being parsed at all. Here’s an example of a simple template that is working when it’s embedded locally:
CURRENT PLAYLIST:
<% for(i=0; i
<option value="”>
After running it through $.jqotec I get this:
function anonymous(i, j, data, fn) {
var out=”";out+=’ CURRENT PLAYLIST: ‘; return out;
}
Which I notice has converted some characters in their html entity equivalents. I’m sure I must be missing something pretty simple. Anyone point me in the right direction?
@Gabriel and @Joe,
I ran into the same problem; ended up keeping the original, embedded format (<script type=”text/html” id=”tpl” />, etc) and using an at (@) sign as my jqote tag. This did the trick for me.
Cheers,
Evan
Hi Aefxx,
I’d like to congratulate you for the great job on this plugin!
I have a simple question, is it possible to separate the templates in a separate definition file, and still use $(‘#pax_hdr’).jqote({ code: cod }) within the main html file?
My worry is merely to make my html file more readable.
Thanks in advanced and keep up the great work.
Regards, Bruno.
Hello Aefxx,
Thank you so much for the wonderful plugin. I just started using it and it works awesome for my project. Could you please direct me in a right way of implementing this?
I am trying to check if canSelect is true, then i need to add a column. Otherwise, i ignore it.
Thanks again!
—-template—-
<script type="text/x-jqote-template" id="questions_tpl"> <![CDATA[ <tr id=""> <% if(this.canSelect){ <input type="checkbox" name="question" value="" /> }%> ]]> </script>—-JavaScript—-
$('tbody#questions').append( $('#questions_tpl').jqote( [{id: 1, label: Q1, canSelect:false}, {id: 1, label: Q1, canSelect:true}] ); );Hi Vani.
You’re almost there, just some minor changes and you’re set. Let’s see:
If you want to have your input elements on different columns (sure it’s not rows?) you’d have to have a table row set in your HTML to contain the columns:
—-HTML—-
<table> <tbody> <tr id="questions"></tr> <!-- Everything else goes here --> </tbody> </table>—-template—-
<script type="text/x-jqote-template" id="questions_tpl"> <![CDATA[ <% if ( this.canSelect ) { %> <td> <input type="checkbox" name="question" value="" /> </td> <% } %> ]]> </script>—-JavaScript—-
var data = [ {id: 1, label: Q1, canSelect:false}, {id: 1, label: Q1, canSelect:true} ]; // Use jQote2's append method here (it's easier and less error prone) $('tr#questions').jqoteapp('#questions_tpl', data);Otherwise, if what you’re after is having each “canSelect”able on its own row then consider these minor changes:
—-template—-
<script type="text/x-jqote-template" id="questions_tpl"> <![CDATA[ <% if ( this.canSelect ) { %> <tr id=""> <input type="checkbox" name="question" value="" /> </tr> <% } %> ]]> </script>—-JavaScript—-
var data = [ {id: 1, label: Q1, canSelect:false}, {id: 1, label: Q1, canSelect:true} ]; // Use jQote2's append method here (it's easier and less error prone) $('tbody#questions').jqoteapp('#questions_tpl', data);Here you go. Let me know in case you’re stuck (just email me with some sample code and I will have a look).
Good luck.
How do you debug errors in templates?
How hard to use something other than angle brackets for the tags?
I would like to use something that doesn't need to be encoded inside an attribute, perhaps curly braces e.g. {# #}
I am using Asp.Net MVC and the Html helpers automatically html encode attributes. This causes errors when attempting to execute a template.
my html comes out looking like this:
<input name="<#= this.name #>">
If I modify this line in jquery.jqote.js
arr = tmpl.replace(/\s*<!\[CDATA\[\s*|\s*\]\]>\s*|[\r\n\t]/g, '')
.split('<'+t).join(t+'>\x1b')
.split(t+'>');
would that work?
just fyi, I have tried the change mentioned above and it is so far working like a charm.
sorry for the spam.
Hi Aefxx,
Thank you so much for helping me out. It works perfect for me. I did quite a lot of research about jQuery template engines before I decided to go with yours. It’s very easy to learn, in fact i was able to use it in my project with in 2 hours of reading the API reference. And in 2 weeks i finished a major project which was estimated for 4 weeks.
Great job and thanks again,
Vani
Aefxx,
Dude, your plugin blows me away!! I’m building a web app, and this will save soo much bandwith.
Have a quick question for you though. Can I trigger an event to re-render the template? Say if a user is logged out and I need to display different things to him once he’s logged out? The pages in Jquery mobile never really refresh, it’s mostly ajax, so that’s why I need it. Thanks!
and one more – is there any way to nest the templates?
sorry to bug you man, but getting a problem one of the other commenters had when trying to use get to pull in the template file. it decodes the and I can’t figure out how to convert them back. any ideas?
Thanks so much
Hi aefxx, and thanks for an excellent template engine! I’m just starting a Backbone project or two, and will most likely use jQote2 as the template engine.
As one of the requirements of these projects is to be better able to organize code, I also wanted to be able to save templates into ‘collections’ (several templates per file). In your response to Brad on June 24th, 2010, you gave a very good example on how to go about accomplishing just that. As I’ve been testing such setup tonight, I noticed that when jqotec is applied against the templates filtered into an array from the file, the templates fail to compile. This is because the template data is retrieved as innerHTML which jQuery automatically escapes so that, for instance, becomes <%= this.name %>
To avoid this I converted an old Prototype escape plugin to jQuery plugin and applied it to the template content retrieved from the file before it reaches jqotec, like this:
templates[this.id] = $.jqotec($.unescapeHTML(this.innerHTML));
After doing this, everything’s working perfectly! Perhaps there a more elegant way to go about this, but this does the trick.
Here’s the simple unescapeHTML plugin code:
(function($) {
$.fn.unescapeHTML = function(string) {
return $.unescapeHTML(string);
}
$.unescapeHTML = function(str) {
var str = str.replace(/\<\;/g, ”).replace(/\"\;/g, ‘”‘).replace(/\&\;/g, “&”);
return str;
}
})(jQuery);
* The sentence above:
This is because the template data is retrieved as innerHTML which jQuery automatically escapes so that, for instance, becomes
should’ve read (without WP’s censorship):
This is because the template data is retrieved as innerHTML which jQuery automatically escapes so that, for instance, becomes & l t ; %= this.name % & g t ;
(added some spaces to prevent auto-editing :-).
Also, the unescapeHTML is on jsfiddle at http://jsfiddle.net/vwal/kFAtd/
Can you please take a look at these two questions on StackOverflow and put any answers you may have!
http://stackoverflow.com/questions/8067909/how-to-pass-extra-variables-and-parameters-to-jqote2
http://stackoverflow.com/questions/7690453/json-element-is-null-resulting-in-uncaught-typeerror-unknown-message-template
Many thanks!
Something I just noticed. Had a method in a class that throw an exception from within the template. The error I get is:
Uncaught ReferenceError: JQOTE2_TMPL_EXEC_ERROR is not defined
I redefined those exception variables to outside the (function(){})() scope (so the end up in window scope) and that fixed it. Not really a very nice file. Probably a better fix it concat those exceptions into the functions at compile time. From the line where I got the exception, something like:
‘}catch(e){e.type=”‘ + JQOTE2_TMPL_EXEC_ERROR + ‘”;e.template=arguments.callee.toString();throw e;}’;
this is from within chromium 14.0.835 Unbuntu linux. Didn’t test in other browsers.
rishimaharaj,
I’ve replied to your question on stackoverflow. Please see here.
Hi,
I wrote a comment yesterday but it seems that it disappeared…
So I try to write it again :)
Thanks for the jQote2 templates. Its great. But few days ago I ran into problems: I have some complex json object which contain another json objects which may contain another objects. For example: School -> classes -> students.
I need to render template for the parent object (eg “school”), then inside it render template for nested objects (eg “school class”), then for every nested object I need to render template for its nested objects (if there are any).
I have no idea how to call template from inside another template.
Tell me please if it is possible and if so then be so kind and provide me some basic examples.
Thank you very much.
David Votrubec