Template Scripting

BACK | UP | NEXT
WebMacro's script language was designed to work fluidly with HTML and XML. It can also be used to generate other formats, such as RTF and WAP. The script syntax is largely orthogonal to XML and HTML, so that it can be used to generate tags and portions of tags witout conflicting with the tag syntax itself.

A WebMacro template is a file containing arbitrary text as well as WebMacro directives and variable references. When executed, the template is passed a Context containing the per-request data that should be displayed via the template.

WebMacro will replace variables in the template with values extracted from the context. There are also a set of directives which can be used to control the contents of the page: repeating blocks, conditional inclusion, including or parsing in other files.

Variables

Variables are the basic way you access information in the context that's been supplied to you. Most are quite simple, though some can be fairly complex. Here are some examples:
   $query
   $Search.Link
   $Ad.Large.findBanner($query).URL
Each of these variables refers to an object somewhere in the context. It's WebMacro's job to figure out how to find the object referred to; it's the application programmers job to make sure that it's there.

The fundamental contract between a template author and a prorammer is a specification of what will appear in the context for a particular template.

The WebMacro servlet environment provides you with a number of standard variables and objects pre-defined, in addition to those that the back end programmer created. Check the WebContext documentation for more information on what's available.

You can cleanly separate your variable from the surrounding text by writing it this way: sometext$(foo)moretext. Also, if you need to write a $ in your text you can escape it: sometext\$foomoretext.

$ is never recognized as a variable if it is followed by a number, so you can safely write $10 in your template.

Directives

Directives are WebMacro statements that perform some operation; conditionally include text; or repeat a block within your template.

Directives all begin with a '#' character, and must be the first thing appearing on a line (they may have optional whitespace in front of them).

Many directives operate on a block. A block begins with a { and continues up until a matching } closes it. The closing } character will only be recognized if it appears at the start of a line.

Alternately, you can use #begin and #end instead of { and }, if you prefer that syntax. As with variables a # is not recognized if it is followed by a number, so you can safely write #10; and also you can use the \ character to escape the # if you need it in some other context.

Here's an overview of the available directives.

## comments

Two (or more) #'s at the start of a line form a comment. The rest of the line is ignored. The comment may be preceeded by some whitespace, but otherwise is only recognized at the start of a line.

Here's an example:

    ## this is a comment

#foreach $thing in list

The #foreach directive is the way you create tables and lists in WebMacro. #foreach iterates through a list, including its output block once for each element in the list.

Here's an example:

   <ul>
   #foreach $link in $searchResult {
      <li>$link.Name lives at $link.URL
   }
   </ul>
Each time through the list the variable $link takes on the value of the next object in the $searchResult list.

You may create the list yourself using the #set statement, or put the list here directly with [] syntax like this:

   #set $list = [ "one", "two", "three" ]
More likely the servlet programmer has provided the list for you by placing it in your context.

You can put anything you like inside the block for your #foreach directive: even more #foreach directives. WebMacro can nest them as deep as you like.

#if (condition) { ... } #else { ... }

Use the #if directive to conditionally include text. The text is included if the condition is true, and not include if it is false.

In WebMacro, a condition is true if it is defined and has a non-null value other than Boolean.FALSE. Since WebMacro automatically converts to and from primitive boolean types, you are encouraged to use boolean values in conditions whenever possible.

#if directive conditions can make use of the boolean operators: && (and), || (or), and the unary operator ! (not). These boolean ooerators mean the same thing they do in Java. They are left-associative, and short circuiting (meaning the right operand is evaluated only if it has to be).

You can also use the boolean operators == (equals) and != to compare objects. These do not behave like Java operators do: they rely on Object.equals() rather than object identity to determine equivalence.

Finally, you can group expressions based on Terms and these five operators using parentheses, as you would expect. Thus the following is a valid condition: (($User && $User.isOK()) || ($Magic == "foo"))

Here's an example:

    #if ( $Customer.owesMoney() && ($Customer.Name != "Fred") ) 
    {
        Pay up, or else!
    } #else {
        Thank you for your patronage.
    }
The #else block is optional--you can leave it off.

#include file

Use the #include directive to read in a file. The contents of the file will not be parsed, so this is a good way to include JavaScript and other things that might conflict with WebMacro.

You can also use it to read in standard block of HTML which you would like to include in every page.

Here is an example:

   #include /web/script/banner.html
If you like you can use a full URL as the target for an #include.

#parse file

The #parse directive includes a target file and parses it as though it were part of the current template.

You can use this to include common template code that may be shared among several different templates.

Here are some examples:

   #parse "/webmacro/library/banner.wm"

   #set $library = "/webmacro/library"
   #parse "$library/banner.wm"
Note that you must normally specify an absolute path to the target, or a URL. This restriction will likely be lifted shortly.

#set $property = value

Just as you can access values in the context, you can set them.

Here is a simple use of the #set keyword:

    #set name = "Fred Flinstone"
    Hi my name is $name
The #set directive is much more poweful than this simple use, however. It can also be used to set properties on complicated objects--if there is a way to do it:
   #set $Customer.name = "Sidney"
   #set $Database.findItem($partNum).Description = $newDescription
Whether or not it is possible for you to set a value depends on the public methods available on the target object. WebMacro will use normal Variable reference evaluation to evaluate all but the last term specified in the left hand side of the #set. Then it will introspect the final object to determine if it's possible to set the value in some way.

Refer to the PropertyOperator documentation for a complete list of the mechanisms by which WebMacro can succeed in setting a value.

Just Rendering Logic

WebMacro's script language is fairly powerful--but it is completely focussed on formatting and laying out a page.

As a designer you will have to learn some simple scripting. However, it should never be very complicated, and it is always related to what you are trying to do: lay out information on a page.

All programming issues, the creation and manipulatio of information, are expected to be handled by the programmer in Java.

As a programmer you may be surprised that WebMacro is lacking more sophisticated programming structures. This is intentional. You have an excellent, full fledged language--Java--in which to write your back end code.

Because Webmacro separates all the programming out of the template, both the program and the HTML templates are much more elegant and understandable than when those two worlds collide in one document.

In addition, because they are separate, programmers and page designers can work on a project simultaneously.


BACK | UP | NEXT