Helma Logo
main list history
previous version  overview  next version

Version 10 by Lehni on 30. March 2006, 16:06

Read *Helma 2 Templates - juerg* for a short overview of my efforts towards a more flexible templating engine in Helma (2).

The JavaScript Tempalte Engine is implemented in Helma 1.5, not Helma 2, but functions as a testcase for exploration of concepts for future releases. This doesn't stop me from using it in real websites as well, and so far it is working very well for me. It actually took away the urge to solve the problem.

The implementation is based on my comments in *06-12-05|http://helma.org/pipermail/helma-dev/2005-December/002461.html*. As far as I know, the implementation is fully backward compatible with Helma 1 skins and macros.

*Download|http://dev.helma.org/static/helma.dev/Wiki/JavaScript%20Template%20Engine/Template.js*

==== Revisions:

0.9  Various speed improvements, leading to an overall decrease of parsing time
      by more than factor 3
 
0.8 10  Added support for HopObject collections More speed improvements, parsing is now around 6-7 times faster than in foreach0.
      Removed regexp filter for if() expressions that sometimes seemed to deadlock
      Fixed a bug with finding the right template in the inheritance chain if it
      was overriden by another one.
 
0.7 9  Fixed problems with error reports. Full stacktraces are now printedVarious speed improvements, and errorsleading to an overall decrease of parsing time
      caused in macros called from the template are now properly detected and reported. by more than factor
      Switched to using Context.evaluateString() instead of eval(), for improve of speed
      and reception of proper exceptions.
0.6  fixed a bug that caused macros in  objects other than 'this' and 'root' to fail.
 
0.5 8  first public release. Added support for HopObject collections in foreach
      Removed regexp filter for if() expressions that sometimes seemed to deadlock
      Fixed a bug with finding the right template in the inheritance chain if it
      was overriden by another one.
 
0.7  Fixed problems with error reports. Full stacktraces are now printed, and errors
      caused in macros called from the template are now properly detected and reported.
      Switched to using Context.evaluateString() instead of eval(), for improve of speed
      and reception of proper exceptions.
 
0.6  fixed a bug that caused macros in  objects other than 'this' and 'root' to fail.
 
0.5  first public release.

The file needs to be placed in the global protoype, it adds one function to the HopObject prototype:

<tt>HopObject.renderTemplate(name, param, out)</tt>

* name is the name of the skin, without the extension. "jstl" is used as extension for the template files, which stands for "JavaScript Template Language".
* param is the optional parameter, which can be accessed from the templates, just like in Helma skins.
* out is the writer object where the whole template is written to. if none is specified, renderTemplate renders into a StringBuffer and returns its value as a string.

====Overview of Statements

* <tt>&lt;% foreach (object in list) %&gt; ... &lt;% end %&gt;</tt>: loops over the list, on purpose not named "for (object in list)", because object won't be the index but the object itself
* <tt>&lt;% if () %&gt;, &lt;% elseif () %&gt;, &lt;% else %&gt;, &lt;% end %&gt;</tt>
* <tt>&lt;% set variable = otherVariable [ + some arithmetic ] %&gt;,</tt> e.g. <tt>&lt;% set count = this.nodes.count() %&gt;</tt>
* <tt>&lt;% macro foo="bar" array=[1,2,3] hash={a:1, b: 2, c:3} %&gt;</tt>: calls the macro, both global macros and object based macros are supported (e.g. this.macro, root.macro, etc.). prefix, suffix, default are supported. It is supposed to be fully backward compatible with Helma 1 skins.
* <tt>&lt;% macro &gt;nested content&lt;/%&gt;</tt>: passes the nested content to the macro, as a second parameter.
* <tt>&lt;% param.value %&gt;</tt>: prints out the value, response, request, sesion, param are suppored, as links to res.data, req.data, session.data, param. This is here for backward compatibility. The prefered way of printing data is:
* <tt>&lt;%= param.object.href() %&gt;</tt>: prints out the value or the result of a function call. response, request, session do NOT link res.data, req.data, session.data.

====Examples

Conditional statements, expressions:

  <% if (session.user != null) %>
    Hello <%= session.user.name %>
  <% else %>
    <a href="/login">Login</a>
  <% end %>

Loops:

  <table>
  <% foreach (topic in param.topics) %>
    <tr class="topic">
      <td><%= topic.renderLink() %></td>
      <td><%= topic.creator.renderLink() %></td>
      <td>
      <% set count = topic.comments.count() - 1 %>
      <% if (count == 1) %>
        1 Post
      <% elseif (count > 1) %>
        <%= count %> Posts
      <% else %>
        &nbsp;
      <% end %>
      </td>
      <td nowrap><%= topic.createDate.format("dd.MM.yy - HH:mm") %></td>
    </tr>
  <% end %>
  </table>

     removed
     added