Dashboard > Contrib: My Sakai > Widgets Home > Using templating
  Contrib: My Sakai Log In | Signup View a printable version of the current page.  
  Using templating
Added by Nick Desmet, last edited by Ian Boston on Mar 17, 2008  (view change)
Labels: 
(None)

Templating with Widgets.

There are probably 100's of ways of templating HTML markup in Javascript. It is possible to just inject elements into the browser DOM, but in tests we have found this to be painfully slow, and if we used it extensively would probably put too great a load on the browser impacting user reseponsiveness. So we have chosen in general to adopy string based templating where we process a template and replace an innerHTML in a single operation. String processing in javascript is fast and injecting large fagments into the DOM does not have the same overhead as single element manipulation. In addition this method, being more block/transaction structured is less likely to confuse anything watching the DOM for changes.

In the early development of the widget structure we used simple string replacement and you may still see some code based on this within the code base. This was likely to be too slow. We looked on the internet and found TrimPath at Google http://code.google.com/p/trimpath/ which is an extremely simple and fast template processing engine. Its markup will be very familiar to anyone who has seen a PHP application since its based on Smarty templates which is a widely used PHP templating engine. For those in the Java world its almost identical to the Velocity template dialect.

For the development of widgets there are 5 big advantages to TrimPath

  1. Its fast at 0.8ms per template render operation, compared to 50ms for an identical operation using DOM manipulation.
  2. We didn't have to write it, it works, and it has a good level of support.
  3. Its format is quick and easy to learn for those few HTML developers that have never seen Smarty or Velocity.
  4. It was designed to run on both the server and the client, so the templates which require no DOM support can work in the simplest javascript environment. This means that with minimal work by a java programmer a widget could be rendered on the client.
  5. It is available under and Apache license.

Having said that, you can use any templating techniques you want to or any non conflicting libraries. You also don't have to use client side html generation if you don't want to and could get the server to generate html fragments. Its entirely up to you, we just found this approach worked for us at Cambridge.

TrimPath templates in widgets.

For a detailed description of the TrimPath template language you can consult http://code.google.com/p/trimpath/wiki/JavaScriptTemplates but here are some simple constructs

Templates in trim path are processed by merging the template with a JSON object, and replacing markers with values from the JSON Object.

JSON Object
{
   name : "Ian Boston",
   homepage : "http://www.tfd.co.uk"
}

merged with

TrimPath template
<div id="whoami_template" style="display:none" >
   My name is ${name} and my home page is ${homepage}
</div>

will become

Rendered result
<div id="whoami" >
   My name is Ian Boston and my home page is http://www.tfd.co.uk
</div>

In addition to simple replacement, there are flow control structures with if, then, elseif else endif, and foreach loops. It is also possible to perform variable manipulation, but we strongly discorage this.

In widget development, we have added some support in SData to make the rendering of templates faster, and easier. We recommend that you embed you tempalates inside a comment block, so that the HTML in the page is valid. In the following example we are performing some operations to element attributes that makes the template invalid XHTML, so we embed it in a comment block.

Invalid XTML template
<div id="whoami_template" style="display:none" >
   My Name is 
   <a 
{if ajaxcall }
     href="#"
     onclick="MyWidget.checkName();"
{else}
     href="/checkwhoami?n=${encodeURIComponent(name)}"
{/if}
    >${name}</a> and my Home page is ${homepage}
</div>

The above template exposed to HTML would invalidate the document, so we encapsulate the whole template inside a comment block.

Safe Complex XHMLT template
<div id="whoami_template" style="display:none" ><!--
   My Name is 
   <a 
{if ajaxcall }
     href="#"
     onclick="MyWidget.checkName();"
{else}
     href="/checkwhoami?n=${encodeURIComponent(name)}"
{/if}
    >${name}</a> and my Home page is ${homepage}
-->
</div>

It important not to leave any space before the comment, so that the comment is the first child of the containing div.

To make templates as easy as possible to use we have added support in the SData library. Here we use SData.Template.render to render the template held in the div with id= helloworld_template1, then we append the rendered result to the innerHTML of the target div, helloworld_message.

Simple Template Rendering
var HelloWorld = function() {
     return {
         click = function() {
            // what is the date now ?
            var datenow = new Date();
            var context = {
                timenow : datenow
            };
            // evaluate the tempalte in div helloworld_template1 with context
            var r = SData.Template.render("helloworld_template1",context);
            
            // append the result to the div helloworld_message
	    document.getElementById("helloworld_message").innerHTML += r;				
         }
     };


}();

Site running on a free Atlassian Confluence Open Source Project License granted to Sakai Foundation. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.5.5 Build:#811 Jul 25, 2007) - Bug/feature request - Contact Administrators