jQote – client-side templating
PLEASE NOTE:
jQote2 has been released. Please consider upgrading now!!! Click here for a quick summary of what’s new and what’s changed.
jQote (pronounced like Star Trek’s Chakotey) is basically a rewrite of John Resig’s awesome JavaScript Micro-Templating utility. I took his code and ported it to jQuery, overhauled the parsing / conversion part and extended it’s functionality to minimize everyone’s coding efforts.
See the jQote API reference.
PLEASE NOTE:
Version 1.1.0 now gives you the possibility of changing the tag character to something else than <% and %>. Please referr to the jQote API reference to see how to do it.
So, let’s get started writing down a basic template:
<script type="text/html" id="template"> <![CDATA[ <p class="greetings"> Hello <%= this.name %>, how are you doing? May I offer you <% this.is_starving() ? %> some tasty peasant? <% : %> a refreshing Singha? <% ; %> </p> ]]> </script>
This well-mannered code snippet – though it may not seem like much – shows some very special markup, namely <%= expression %> and <% statement %>, respectively (please notice the extra ‘=’ sign on the first one).
As you may have guessed already, the code in-between these tags is mere JavaScript. To simplify things you should use the <%= %> tag whenever you want to directly echo a variable’s value (you may as well call a function or use any other expression, as long as it returns a string).
Pretty self-explanatory so far, hu? But what’s with all that <script type="text/html"> and <![CDATA[ ... ]]> shmoo, you ask? Well let’s cite John Resig here:
“Embedding scripts in your page that have a unknown content-type (such is the case here – the browser doesn’t know how to execute a text/html script) are simply ignored by the browser – and by search engines and screenreaders. It’s a perfect cloaking device for sneaking templates into your page. [...]“
Good news, that is we will be able to put our template code right into our HMTL source files and it won’t show up anywhere but in the sources (btw. thanks to the usage of CDATA it’s perfectly valid markup).
Now for the final part of our little example we’ll need some basic scripting to induce the conversion:
<script type="text/javascript">
var obj= {
name: 'Jabberwocky',
is_starving: function() {
return Math.random() > 0.5;
}
};
$('#template').jqote(obj).appendTo($('body'));
</script>
That’s it, there’s nothing more to it than calling jQote on our template and providing it with some data object to get things started. jQote really is fun to use and cuts down on the time spent trying to inject arbitrary data into your sites. You’ll learn to love it pretty fast, I promise! Give it a try.
One final word: I’d like to thank John Resig for bringing this up. You rock, dude.
comments
30 Responses to “jQote – client-side templating”
Leave a Reply
Are you planning to put this on github or anything?
Any thoughts on how to support single quotes?
I tried to fix the inability to use single quotes in Qote templates, but no luck. Looks like you’re using single quote as reserved parse symbol.
@ JimmyZ
Sorry for not answering that long:
No, I do not plan to host this on github or anything, for now.
@Mike
Mike, you’re totally right, I wasn’t planing for single quotes within html markup in templates, as I usualy stick to double quotes.
Nevertheless, I fixed the problem with the current release. Check it out :D
works great, why not put this in the jquery plugins library, so people can find it more easily?
@chrismarx
Hi Chris,
maybe it’s just me but it’s already there:
http://plugins.jquery.com/project/jqote
cu
I have tried your plugin with jquery 1.3.2
(this shouldn’t be relevant but I am working with mvc and I changed the
tag to ‘~’ to make life easier).
It seems that is working but the is not working – waiting for your comment ! Thanks!
when I tried the example above I got invalid function – when trying to debug
your file :-) – see theredundant ‘;’ in trenary expression (a ? b : c)
var t=[]; t.push('\ \ Hello ', this.name ,'\ May I offer you\ '); this.is_starving() ? t.push('\ some tasty peasant?\ '); : t.push('\ a refreshing Singha?\ '); ; t.push('\ \ \ \ '); return $(t.join(''));I have a problem with posting here because of special characters disappeared
so here my comment again
http://drop.io/jquery_jqote
Thanks!
@Shimon
Sorry for not getting back to you that long.
Well, it looks like the ternary operator – the way you want to use it – is not supported by jQote, yet. You would either have to do it like this (please make sure to have it all on a single line):
.. or stick to plain old if’s and else’s.
I’m planning to do a complete rewrite of the code since there are a couple more issues to be solved. And ternary operator should definetly make it into the plugin.
So long.
aefxx
I would like to add the transformed string
to an element’s innerHtml.
The way I have got it to work is shown below using the
the jquery.toXML plugin.
Is this the best way to do it?
//build transformed html from template
var out = $('#tmpl').jqote({content: content, toggleLabel:toggleLabel}); console.log("out: "+ $(out[0]).toXML());//attach transformed html to element’s innerHtml
I notice jqote cannot transform a template that is not wellformed.
For example a template that just contains a json string like this causes an error:
{"first":"Ryan", "last":"Campbell"}@David
I’m not quite sure what you were trying to achieve but there generally is no such thing as “the best way”. You could argue about performance but this hardly ever carries weight.
Please note some points, though:
1. jQote actually returns a jQuery object – not a “transformed string”
2. every member of this jQuery object again is a jQuery object itself
3. templates with pure scripting and no (x)html whatsoever won’t generate any output at all
So, as for you’re example, I would do it this way:
$(this.element).html($('#tmpl').jqote(obj)[0]);hi,
Thanks for your reply to my post.
Just want to give a quick comment.
Would it be possible to extend templating solution
to generate more than just x(html)? For example a json string.
For a templating solution in javascript, one of the things I would like to use it for is it to pass json data to a javascript object. What I am trying to do is similiar to what is outlined by this post:
http://particletree.com/features/loading-content-with-json/
And so define the json string in a template, and have the javascript object get the json string by using the templating framework.
I wasn’t able to use jqote but I was able to use another template solution based on John Resig microtemplate code
http://weblogs.asp.net/dwahlin/archive/2009/04/17/minimize-code-by-using-jquery-and-data-templates.aspx
Anyways just some feedback for you.
best regards,
David
@David
Having a template system for generating json in javascript seems a bit pointless?
Just create the array structure you want in code and then pass it through the json serializer, no…?
Absolutely brilliant plug-in but whats up with the license?
I know the original script was MIT Licensed by John Resig,
From the license:
1) ‘Version 2, December 2004′ – is this the date of the original John Resig script?
2) ‘Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.’ – is this a bad translation or should I be I be replacing the name – Sam Hocevar, with another? John Resig perhaps?
Also are their any plans to support double quotes in expressions and statements?
I’ll second the request for putting it up on Github so we can track your changes to this library over time. Plus, more eyes might help with bugs/enhancements.
But at the very least, can you add a version number to the releases? It sounds like you are making changes to it, but there’s no way to tell.
Cheers,
p.
Super cool. I’m curious if it would ever be possible to use HAML for the templates? Seems like a long shot, however worthy. Keep up the beautiful work!
@gazbond
I’ll be soon releasing jQote2 – a major overhaul and complete rewrite of jQote’s internals. This won’t use any of Resig’s code anymore, insofar there then shouldn’t be any licensing issues.
jQote2’s license will be DO WHAT THE FUCK YOU WANT TO, as is.
@Phil Oye
With the upcoming release there’ll now be a git repository at Github.
Regarding the versioning issue: I never thought that jQote would make a wave and therefore didn’t put much time into it – until recently. jQote2 will have proper versioning (though I’m not a big fan of the “jquery.jqote-x.x.x.js” naming convention).
@Eric
Glad you like it. I’ve never heard of HAML before but will have a look. BUT please don’t quote me on that :D
I notice that the licence has already been changed to DWTFYWTPL.
Does this mean the version 2 is released?
@Martin
Hello, no jQote2 hasn’t been released, yet. Work just pretty much piles up right now and I won’t be able to release it until the end of the week. Please bear with me.
Sorry for the delay.
Hi,
I was struggling with the problem of how to nest a template into another. my solution is now this:
var container = $('<p>'); $('#tmpl').jqote(data_collection).appendTo(container);you can now easily get the generated html by calling
Since the parent elements html will not be included you can use whatever container tag you want. Of course this is a workaround but it works. It would be great to have some kind of parameter for the jqote function to tell if you want to have the result to be a jquery object or just the plain generated html…
Or have you done this already for jqote2?
Keep on rocking!
Give a try to the real “jquery micro template”, it need no seperate template container:
plugins.jquery.com/project/micro_template
<div id="test1" class="users"> <!for (var i=0;i<users.length;++i) {!> <div onMouseOver="/*=users[i].color?'this.style.color=\''+users[i].color+'\';':''*/" id="user_<!=i!>" class='user'>Name:<a href="<!=users[i].name!>"><!=users[i].name!></a></div> <!} !> <pre>'somthing' else ...</pre> </div> <script> var data1={users:[{name:'name1.1'}, {name:'name1.2', color:'yellow'} ] }; $('#test1').drink(data1); </script>@diyism
Glad you made it here. Hello.
Your plugin works without any “containers” you say.
But isn’t
<div id="test1"...a “container” for your template and wouldn’t that expose the HTML markup within your template to your viewers?Besides that you’ve build your plugin upon John Resig’s micro templating code which has flaws and shortcomings when it comes to code that spans over multiple lines and the correct escaping of quotes.
Regards,
aefxx
Firstly, thanks for developing jqote – it’s excellent.
I want to add the selected=’selected’ attribute to an option at runtime within the template. I have the following code (I am using the older version of jqote but haven’t the time to upgrade just yet):
<option value='’ <#= == this.SubjectId ? “selected=’selected’” : “” #> >
But this is not being templated at all (the code inside the block is being rendered as is).
What gives?
UPDATE: I have also tried:
but this behaves in the same way
Can we leave a bug report here? The example above does not work. I get “appendTo is not a function” error. Probably because jqote does not return jQuery object, which is how appendTo can work.
I got around this by assigning to a variable and inserting that into the document.
@volkan
Hi! You’re right, the jqote method does not return a jQuery object, anymore (this was changed with the release of jQote2). Please refer to jQote2’s API that offers convenience methods to help you with DOM manipulation.
Regards,
aefxx
This utility saved my life… Beautiful work, aefxx!
The example provided doesn’t work:
$(‘#template’).jqote(obj).appendTo($(‘body’));
Reason: $(‘#template’).jqote(obj) returns a string and not a jQuery element.
OK, so the API changed. So with the latest version of jqote2.js it would be.
$(‘body’).append($(‘#template’).jqote(obj));
Can anyone show me a template that handles an array (i.e. one which loops)?