Its a long time I miss publishing something interesting (ok, actually, publishing at all!) but this is for two good reasons:
one – I was really involved on Licorize development
two – I spent one month on holidays in Iceland 🙂
three – this is the kind of blog-post that may attract lots of spit
I’m little squeamish, and I tried to delay this moment as much as I can, but Licorize beta is now available and I’ve returned happy, alive and healthy from Iceland.
Damn! I cannot procrastinate any longer.
This history started about two years ago when I found the John Resig micro-templating paper; John’s idea was intriguing even if it seemed hardly original: separate presentation and data. This is an old liet motif for many programming-pattern-book-writers, and this is usually enough to worn me to shun away, but in this case something hit me, say because Resig seems a practical fella or say because the <script type=”text/html” > smells of “beautiful hack”. I don’t know why, but micro-templating remains impressed on my mind.
What is a JavaScript template? In brief it is a way to call a JavaScript function for injecting dynamically html contents client side.
The simplest usage could look like this:
var data={id:1,description:”my item”,price:”123.45”};
var place= document.getElementById(“results”);
results.innerHTML = template(“item_row”, data);
For web 2.0 applications this is a really powerful approach to page generation: send templates to clients, use JSON for communicating with the server, generate contents using templates+data and create the fastest applications you have ever seen! If you add the great support jQuery offers for JSON, this could be a really nice solution.
I didn’t get deep into Resig’ solution at the time, but I kept the JavaScript templating idea in a closet for a while, until last April when I started working on Licorize.
Licorize is an empowered bookmarking system that allows collecting to-dos, ideas, images and much more while you are working on-line, and then organize your work in team. But for the moment what is interesting is that Licorize uses small pieces of html to represent information on a sorted list. Here an example:
The main Licorize requirement was to be a fast web 2.0 application: to me this means use one page only. I know that is not completely true, but coming from a “classical” background of Java-JSP developer, it was a revolutionary approach.
I then recalled the JavaScript templating idea, and started programming around.
A short googling on “javascript templating” left me astonished about the number of JavaScript frameworks already available, so I started trying some of them.
Before you, dear reader, read more I warn that this is the hard core part, if you believe emacs is the best editor for writing web-apps or you think the XML-XSLT is the cleanest approach to produce html pages, leave before its too late! What you will see below is an approach that searches to maximize compatibility of writing code, also HTML, with an IDE.
Ok, so lets me state some of my personal principles concerning programming:
-
a simple rough solution is far better than a powerful but complex one
-
it is incredible stupid to invent new languages/tag/whatever while the existing ones work just fine
-
your designer’s work worth as much as your “dirty code”
-
you cannot nowadays write code without a decent IDE, or better: you cannot write decent code without a great IDE! This is why I use IntelliJ!
-
every trick is legal if it makes your life easier (not only writing code 🙂 )
Taking in mind these points I started exploring the JavaScript template galaxy.
Starting from Resig’s example I noticed that the suggested syntax generates confusion when you use a .jsp to generate the “template” page. JSP standard tags are also used for defining JavaScript variable placeholders:
Actually the following code, from Resig’s example, generates panic in most JSP coders (Example 1):
<script type=”text/html” id=”user_tmpl”>
<% for ( var i = 0; i < users.length; i++ ) { %>
<li><a href=”<%=users[i].url%>”><%=users[i].name%></a></li>
<% } %>
</script>
here “users[i]” is a JavaScript variable not a JSP one!
If you think that generating templates using dynamic pages is useless you are on the wrong path, in good company with those that think that out.print(“<%=users[i].url%>”) could be an acceptable price to pay for using templating – no way!
Analyzing this example I found that is not strictly necessary to have iteration or conditional support in the template definition language: you can narrow the scope of templates and use JavaScript for doing iteration. With this approach you gain flexibility and you do not need strange syntax. See the code above transformed (Example 2):
<script type=”text/html” id=”user_tmpl”>
<li><a href=”<%=users.url%>”><%=users.name%></a></li>
</script><script type=”text/javascript”>
…
for ( var i = 0; i < users.length; i++ ) {
template(“user_tmpl”,users[i]);
}
</script>
The code is a little bit longer, but more readable and flexible (e.g.: if you need to use a different row template in function of user data).
What in Resig’ approach is in the right direction is that the template is mainly written in html, that means that templates can be created by UI guys, using (almost) standard html tags.
If you believe that this is the most obvious approach, and that everybody would start with this, you are wrong: there are lots of libraries where the template is created with “string concatenation”.
Seems peculiar to me that library writers are mostly focused on implementing “for”, “if”, “while” statements inside templates instead of making it easy to write them down. Why they want to waste its time implementing (badly) something already happily existing in JavaScript?
In this category mustache.js , Tempest or nano, but the list is far from being exhaustive.
Some other libraries have the sensibility to propose a way to write html in a more comfortable way; usually they use the trick of “<script type=’text/…..’>” tag, as proposed by Resig or a in a mixed way with “<![CDATA[“ tag
In this category there are jQuery Templates, jQuote, Srender.
A special place in my heart is the pure templating framework. It is at first glance a really clean solution, but going in detail this is a sort of exercise of sadism. Do not misunderstand me, I really appreciate the power of this library and the effort to use standard like css selectors, but are we sure that this stuff is a good thing for humanity?
By the way, the above code and (Example 2) produce almost the same result. Which one is more readable? 😉
As you can guess I left this framework as fast as I could moving to ones closer to html.
After the scary templating tour I got a clearer vision of my requirements:
-
templates’ html MUST be writable in HTML not in JavaScript
-
templates must work with the IDE, not against it
-
in templates it should be possible to include a “<script>” tag
-
templates should be generated dynamically server side
From now on, I will be using jQuery by default in the code.
In Open Lab developers work side by side with graphic designers, so the closer to html is the solution the easier is to interact with each other. Resig’s approach is in the right path, but look what happens inserting his kind of template in a .jsp page:
There is no way for the IDE to distinguish between template-language and jsp-language.
Another problem was the <script> tag used to identify the template that, on Chrome browser only, conflicts with standard <script type=”text/javascript”> tags. Why I need a nested script tag in the template? I’m a little bit reluctant to tell you, but sometime I use old third party server-side components that produce some JavaScript code within the component itself. Bleah! (Still, I’m confident that most of you do just that…). And this would not be allowed.
After testing lots of different solutions, the best one I found is to include my template in a <div> with all the contents inside an HTML comment block. My solution has of course the limitation of forbidding the usage of html comments in templates, but it is an acceptable limitation for us.
Here is how it looks like:
Regarding IDE compatibility, as you can see above, the html comment blocks code completion, syntax checking and hints. A little workaround solved the problem: I built a small java class to print the same template stub:
this solution preserve all IDEs capability as error highlighting, tag matching, JavaScript checking, hints – and my happiness!
Seems peanuts, but this can speed up development a lot!
Here the simple class that wraps template tags:
In order to solve mixing jsp tags with templates, I decided to drop the use of “<% %>” using instead the less disturbing “## ##”.
So a simple template example will look like:
The last blow dealt to “things well-done” was to remove any statement inside the template; so no “for”, “if”, “while” etc.
Maybe you can now argue that this leaves the template too poor and inexpressive, and actually it is true. This is why we added a callback function for “decorating” the resulting html. The decorator is generally not necessary and it is used only for really complicated and hyper-active templates.
We’ll now go in deep on our template solution analyzing each step:
Template definition
Write your template in a page (jsp or plain html) using the stub described above. In case you will use a .jsp page for carrying the template you can use the JST class methods to wrap the template transparently from the IDE point of view.
Here I created a div identified with “stripTemplates” to carry templates; in this example templates are inside my main page in order to minimize requests, but you can easily load templates in a subsequent ajax call.
Load templates in memory (the DOM)
Once the page is loaded you have to load templates in memory. You can have more then one template both in the same html block or in different ones.
A typical usage:
Once templates has been loaded, the container is removed. I tried to keep templates in the page and recall them from there, but it was less performant, so I opted to keep them on a JavaScript variable.
Have now a closer look to the loadTemplate() method:
we get all “.__template__” elements and then the first comment child-element. We support multiple templates for each container. Then the template is loaded in memory end removed from the page.
If you want to load templates in a distinct ajax call something like
should work fine.
Getting data
This is the easiest part: usually you will call your server to obtain a JSON object or JSON array, obviously your data should be “compatible” with the template you are using.
For instance data compatible with templates above could be:
data can be with more properties than required, in this case extra data will be ignored, or with less data and in this case the “##..##” placeholder will be removed before template is rendered.
Rendering a template
Finally we can render the template and draw it somewhere on the page:
“createFromTemplate” will receive JavaScript data and return a jQuery object that you can handle for further refinements or just append somewhere.
Have a look to the rendering function:
code is quite straight: the template (string) is recalled from memory, then for each attribute in “jsonData” we replace “##attributeName##” with its value. Remaining “##…##” are then removed. A jQuery object is then created and returned.
Probably some of you noticed the “decorator” call before returning the object.
Decorators
As I told you before, we decided to remove statements inside template definitions, this does not mean that you never need some “logic rendering” for the template, I only oppose writing logic inside the template, with some bizarre and original syntax! This is why we use a post-processing approach based on classical JavaScript callbacks.
You can define decorators in this way:
your decorator will receive the rendered template and the data, so you have lots of flexibility. Of course here we suppose the decorator is used for fine-tuning the final result not to twist the layout completely: we require layout to be clearly readable on the template itself. If you need a completely different structure depending on data received, simply use multiple templates; this is by far a better solution with respect to making templates excessively complex.
Decorators are the best place where to add event listeners and behaviors on your resulting component.
Conclusions
I know that this is a rough, non-conformist, maybe ugly approach and that this is not suitable for everyone, but it works really well in our group making happy both programmers and designers.
I think this was a great goal! In only sixty lines of code!
Love,
Roberto
P.S.: You can see templates at work here in Licorize.
P.P.S: You reader are probably the only one surviving up to this line, as a prize there is a complete code example here.