http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3187a094/src/manual/en_US/book.xml ---------------------------------------------------------------------- diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml index f635e88..88fc289 100644 --- a/src/manual/en_US/book.xml +++ b/src/manual/en_US/book.xml @@ -30,38874 +30,53 @@ <titleabbrev>Manual</titleabbrev> - <productname>Freemarker 2.3.26</productname> + <productname>Freemarker 3.0.0</productname> </info> <preface role="index.html" xml:id="preface"> - <title>What is Apache FreeMarker?</title> + <title>TODO</title> - <para>FreeMarker is a <emphasis>template engine</emphasis>: a generic tool - to generate text output (HTML web pages, e-mails, configuration files, - source code, etc.) based on templates and changing data. It's not an - application for end-users in itself, but a Java library, a component that - programmers can embed into their products.</para> + <para>TODO... Eventually, we might copy the FM2 Manual and rework + it.</para> - <para>Templates are written in the FreeMarker Template Language (FTL). - It's a simple, specialized language, <emphasis>not</emphasis> a full-blown - programming language like PHP. You are meant to prepare the data to - display in a real programming language, like issue database queries and do - business calculations, and then the template displays that already - prepared data. In the template you are focusing on how to present the - data, and outside the template you are focusing on what data to - present.</para> + <para>Anchors to satisfy Docgen:</para> - <mediaobject> - <imageobject> - <imagedata fileref="figures/overview.png"/> - </imageobject> - </mediaobject> + <itemizedlist> + <listitem> + <para xml:id="app_versions">app_versions</para> + </listitem> - <para>This approach is often referred to as the <link - linkend="gloss.MVC">MVC (Model View Controller) pattern</link>, and is - particularly popular for dynamic web pages. It helps in separating web - page designers (HTML authors) from developers (Java programmers usually). - Designers won't face complicated logic in templates, and can change the - appearance of a page without programmers having to change or recompile - code.</para> + <listitem> + <para xml:id="app_license">app_license</para> + </listitem> - <para>While FreeMarker was originally created for generating HTML pages in - MVC web application frameworks, it isn't bound to servlets or HTML or - anything web-related. It's used in non-web application environments as - well.</para> + <listitem> + <para xml:id="exp_cheatsheet">exp_cheatsheet</para> + </listitem> - <para>FreeMarker is <link - xlink:href="http://www.fsf.org/philosophy/free-sw.html">Free</link>, - released under the Apache License, Version 2.0.</para> + <listitem> + <para xml:id="ref_directive_alphaidx">ref_directive_alphaidx</para> + </listitem> - <para><emphasis role="bold">Disclaimer: </emphasis><emphasis>Apache - FreeMarker is an effort undergoing incubation at The Apache Software - Foundation (ASF), sponsored by the <link - xlink:href="http://incubator.apache.org">Apache Incubator</link>. - Incubation is required of all newly accepted projects until a further - review indicates that the infrastructure, communications, and decision - making process have stabilized in a manner consistent with other - successful ASF projects. While incubation status is not necessarily a - reflection of the completeness or stability of the code, it does indicate - that the project has yet to be fully endorsed by the - ASF.</emphasis></para> - </preface> - - <part xml:id="dgui"> - <title>Template Author's Guide</title> - - <chapter xml:id="dgui_quickstart"> - <title>Getting Started</title> - - <para>This chapter is a very rough introduction to FreeMarker. The - chapters after this will go over things in much greater detail. - Nonetheless, once you have read this chapter, you will be able to write - simple but useful FreeMarker templates.</para> - - <section xml:id="dgui_quickstart_basics"> - <title>Template + data-model = output</title> - - <para>Let's assume that you need a HTML page on a website, similar to - this:</para> - - <programlisting role="output"><html> -<head> - <title>Welcome!</title> -</head> -<body> - <h1>Welcome <emphasis>John Doe</emphasis>!</h1> - <p>Our latest product: - <a href="<emphasis>products/greenmouse.html</emphasis>"><emphasis>green mouse</emphasis></a>! -</body> -</html></programlisting> - - <para>But the user's name ("John Doe" above) depends on who the - logged-in user is, and the latest product information should come from - a database. Because this data changes, you cannot you cannot use - static HTML. Instead, you can use a <emphasis - role="term">template</emphasis> of the desired output. The template is - the same as the static HTML would be, except that it contains some - instructions to FreeMarker that makes it dynamic:</para> - - <programlisting role="template" xml:id="example.first"><html> -<head> - <title>Welcome!</title> -</head> -<body> - <h1>Welcome <emphasis>${user}</emphasis>!</h1> - <p>Our latest product: - <a href="<emphasis>${latestProduct.url}</emphasis>"><emphasis>${latestProduct.name}</emphasis></a>! -</body> -</html></programlisting> - - <para>The template is stored on the Web server, usually just like the - static HTML page would be. But whenever someone visits this page, - FreeMarker will step in and transform the template on-the-fly to plain - HTML by replacing the - <literal>${<replaceable>...</replaceable>}</literal>-s with up-to-date - content, and send the result to the visitor's Web browser. So the - visitor's Web browser will receive something like the first example - HTML (i.e., plain HTML without FreeMarker instructions), and it will - not perceive that FreeMarker is used on the server. (Of course, the - template file stored on the Web server is not changed by this; the - substitutions only appear in the Web server's response.)</para> - - <para>Note that the template doesn't contain the programming logic to - find out who the current visitor is, or to query the database to get - the latest product. The data to be displayed is prepared outside - FreeMarker, usually by parts written in some <quote>real</quote> - programming language like Java. The template author needn't know how - these values were calculated. In fact, the way these values are - calculated can be completely changed while the templates can remain - exactly the same, and also, the look of the page can be completely - changed without touching anything but the template. This separation of - presentation logic and business logic can be especially useful when - the template authors (designers) and the programmers are different - individuals, but also helps managing application complexity if they - are the same person. Keeping templates focused on presentation issues - (visual design, layout and formatting) is a key for using template - engines like FreeMarker efficiently.</para> - - <para><indexterm> - <primary>data-model</primary> - </indexterm>The totality of data that was prepared for the template - is called the <emphasis role="term">data-model</emphasis>. As far as - the template author is concerned, the data-model is a tree-like - structure (like folders and files on your hard disk), which, in this - case, could be visualized as:</para> - - <programlisting role="dataModel">(root) - | - +- <emphasis>user</emphasis> = "Big Joe" - | - +- <emphasis>latestProduct</emphasis> - | - +- <emphasis>url</emphasis> = "products/greenmouse.html" - | - +- <emphasis>name</emphasis> = "green mouse"</programlisting> - - <note> - <para>The above is just a visualization; the data-model is not in a - textual format, it's from Java objects. For the Java programmers, - the root is perhaps a Java object with <literal>getUser()</literal> - and <literal>getLatestProduct()</literal> methods, or maybe a Java - <literal>Map</literal> with <literal>"user"</literal> and - <literal>"latestProducts"</literal> keys. Similarly, - <literal>latestProduct</literal> is perhaps a Java Object with - <literal>getUrl()</literal> and <literal>getName()</literal> - methods.</para> - </note> - - <para>Earlier, you have picked values from this data-model, with the - <literal>user</literal> and <literal>latestProduct.name</literal> - expressions. If we go on with the analogy that the data model is like - a file system, then <quote>(root)</quote> and - <literal>latestProduct</literal> correspond to directories (folders), - and <literal>user</literal>, <literal>url</literal> and - <literal>name</literal> are files in those directories.</para> - - <para>To recapitulate, a template and a data-model is needed for - FreeMarker to generate the output (like the HTML shown first):</para> - - <para><phrase role="markedTemplate">Template</phrase> + <phrase - role="markedDataModel">data-model</phrase> = <phrase - role="markedOutput">output</phrase></para> - </section> - - <section xml:id="dgui_quickstart_datamodel"> - <title>The data-model at a glance</title> - - <para>As you have seen, the data-model is basically a tree. This tree - can be arbitrarily complicated and deep, for example:</para> - - <programlisting role="dataModel" - xml:id="example.qStart.dataModelWithHashes">(root) - | - +- animals - | | - | +- mouse - | | | - | | +- size = "small" - | | | - | | +- price = 50 - | | - | +- elephant - | | | - | | +- size = "large" - | | | - | | +- price = 5000 - | | - | +- python - | | - | +- size = "medium" - | | - | +- price = 4999 - | - +- message = "It is a test" - | - +- misc - | - +- foo = "Something"</programlisting> - - <para>The variables that act like directories (the root, - <literal>animals</literal>, <literal>mouse</literal>, - <literal>elephant</literal>, <literal>python</literal>, - <literal>misc</literal>) are called <emphasis - role="term">hashes</emphasis>. Hashes store other variables (the so - called <anchor xml:id="topic.dataModel.subVar"/><emphasis>sub - variables</emphasis>) by a lookup name (e.g., <quote>animals</quote>, - <quote>mouse</quote> or <quote>price</quote>).</para> - - <para>The variables that store a single value - (<literal>size</literal>, <literal>price</literal>, - <literal>message</literal> and <literal>foo</literal>) are called - <emphasis role="term">scalars</emphasis>.</para> - - <para><anchor xml:id="topic.qStart.accessVariables"/>When you want to - use a subvariable in a template, you specify its path from the root, - and separate the steps with dots. To access the - <literal>price</literal> of a <literal>mouse</literal>, you start from - the root and go into <literal>animals</literal>, and then go into - <literal>mouse</literal> then go into <literal>price</literal>. So you - write <literal>animals.mouse.price</literal>.</para> - - <para>Another important kind of variables are <emphasis - role="term">sequences</emphasis>. They store subvariables like hashes, - but here subvariables doesn't have a name, they are just items in a - list. For example, in this data-model, <literal>animals</literal> and - <literal>misc.fruits</literal> are sequences:</para> - - <programlisting role="dataModel" - xml:id="example.qStart.dataModelWithSequences">(root) - | - +- animals - | | - | +- (1st) - | | | - | | +- name = "mouse" - | | | - | | +- size = "small" - | | | - | | +- price = 50 - | | - | +- (2nd) - | | | - | | +- name = "elephant" - | | | - | | +- size = "large" - | | | - | | +- price = 5000 - | | - | +- (3rd) - | | - | +- name = "python" - | | - | +- size = "medium" - | | - | +- price = 4999 - | - +- misc - | - +- fruits - | - +- (1st) = "orange" - | - +- (2nd) = "banana"</programlisting> - - <para>To access a subvariable of a sequence you use a numerical index - in square brackets. Indexes start from 0 (it's a programmer tradition - to start with 0), thus the index of the 1st item is 0, the index of - the 2nd item is 1, and so on. So to get the name of the first animal - you write <literal>animals[0].name</literal>. To get the second item - in <literal>misc.fruits</literal> (the string - <literal>"banana"</literal>) you write - <literal>misc.fruits[1]</literal>. (In practice, you usually just walk - through sequences in order, not caring about the index, but that will - be <link linkend="topic.tutorial.list">shown later</link>.)</para> - - <para>Scalars can be further divided into these categories:</para> - - <itemizedlist> - <listitem> - <para>String: Text, that is, an arbitrary sequence of characters - such as ''m'', ''o'', ''u'', ''s'', ''e'' above. For example the - <literal>name</literal>-s and <literal>size</literal>-s are - strings above.</para> - </listitem> - - <listitem> - <para>Number: It's a numerical value, like the - <literal>price</literal>-s above. The string - <literal>"50"</literal> and the number <literal>50</literal> are - two totally different things in FreeMarker. The former is just a - sequence of two characters (which happens to be readable as a - number for humans), while the latter is a numerical value that you - can use in arithmetical calculations.</para> - </listitem> - - <listitem> - <para>Date-like: Either a date-time (stores a date with time of - the day), or a date (no time of day), or a time (time of day, no - date).</para> - </listitem> - - <listitem> - <para>Boolean: A true/false (yes/no, on/off, etc.) thing. Like - animals could have a <literal>protected</literal> subvariable, - which store if the animal is protected or not.</para> - </listitem> - </itemizedlist> - - <para>Summary:</para> - - <itemizedlist> - <listitem> - <para>The data-model can be visualized as a tree.</para> - </listitem> - - <listitem> - <para>Scalars store a single value. The value can be a string or a - number or a date-time/date/time or a boolean.</para> - </listitem> - - <listitem> - <para>Hashes are containers that store other variables and - associate them with a unique lookup name.</para> - </listitem> - - <listitem> - <para>Sequences are containers that store other variables in an - ordered sequence. The stored variables can be retrieved via their - numerical index, starting from 0.</para> - </listitem> - </itemizedlist> - - <note> - <para>There are other, more advanced value types that we don't cover - here, such as methods and directives.</para> - </note> - </section> - - <section xml:id="dgui_quickstart_template"> - <title>The template at a glance</title> - - <para>The simplest template is a plain HTML file (or whatever text - file; FreeMarker is not confined to HTML). When the client visits that - page, FreeMarker will send that HTML to the client as is. However if - you want that page to be more dynamic then you begin to put special - parts into the HTML which will be understood by FreeMarker:</para> - - <itemizedlist> - <listitem> - <para><literal>${<replaceable>...</replaceable>}</literal>: - FreeMarker will replace it in the output with the actual value of - the expression inside the curly brackets. They are called - <emphasis role="term">interpolation</emphasis>s.</para> - </listitem> - - <listitem> - <para><emphasis role="term">FTL tags</emphasis> (for FreeMarker - Template Language tags): FTL tags are a bit similar to HTML tags, - but they are instructions to FreeMarker and will not be printed to - the output. The name of these tags start with - <literal>#</literal>. (User-defined FTL tags use - <literal>@</literal> instead of <literal>#</literal>, but they are - an advanced topic.)</para> - </listitem> - - <listitem> - <para><emphasis role="term">Comments:</emphasis> Comments are - similar to HTML comments, but they are delimited by - <literal><#--</literal> and <literal>--></literal>. Unlike - HTML comments, FTL comments won't get into the output (won't be - visible in the page source for the visitor), because FreeMarker - skips them.</para> - </listitem> - </itemizedlist> - - <para>Anything not an FTL tag or an interpolation or comment is - considered static text and will not be interpreted by FreeMarker; it - is just printed to the output as-is.</para> - - <para>With FTL tags you refer to so-called <emphasis - role="term">directives</emphasis>. This is the same kind of - relationship as between HTML tags (e.g.: - <literal><table></literal> and - <literal></table></literal>) and HTML elements (e.g., the - <literal>table</literal> element) to which you refer to with the HTML - tags. (If you don't understand this difference then consider "FTL tag" - and "directive" synonyms.)</para> - - <note> - <para>You can easily try writing templates on <link - xlink:href="http://freemarker-online.kenshoo.com/">http://freemarker-online.kenshoo.com/</link></para> - </note> - - <section> - <title>Some basic directives</title> - - <para>Here we will look at some of the most commonly used directives - (<link linkend="ref_directives">but there are much - more</link>).</para> - - <section> - <title>The if directive</title> - - <para>With the <literal>if</literal> directive you can - conditionally skip a section of the template. For example, assume - that in the <link linkend="example.first">very first - example</link> you want to greet your boss, Big Joe, differently - than other users:</para> - - <programlisting role="template"><html> -<head> - <title>Welcome!</title> -</head> -<body> - <h1> - Welcome ${user}<emphasis><#if user == "Big Joe"></emphasis>, our beloved leader<emphasis></#if></emphasis>! - </h1> - <p>Our latest product: - <a href="${latestProduct.url}">${latestProduct.name}</a>! -</body> -</html></programlisting> - - <para>Here you have told FreeMarker that the <quote>, our beloved - leader</quote> should be there only if the value of the variable - <literal>user</literal> is equal to the string <literal>"Big - Joe"</literal>. In general, things between <literal><#if - <replaceable>condition</replaceable>></literal> and - <literal></#if></literal> tags are skipped if - <literal><replaceable>condition</replaceable></literal> is false - (the boolean value).</para> - - <para>Let's look at - <literal><replaceable>condition</replaceable></literal> more - closely: <literal>==</literal> is an operator that tests if the - values at its left and right side are equivalent, and the results - is a boolean value, true or false accordingly. On the left side of - <literal>==</literal> I have <link - linkend="topic.qStart.accessVariables">referenced a - variable</link> with the syntax that should be already familiar; - this will be replaced with the value of the variable. In general, - unquoted words inside directives or interpolations are treated as - references to variables. On the right side I have specified a - literal string. Literal strings in templates must - <emphasis>always</emphasis> be put inside quotation marks.</para> - - <para>This will print <quote>Pythons are free today!</quote> if - their price is 0:</para> - - <programlisting role="template"><#if animals.python.price == <emphasis>0</emphasis>> - Pythons are free today! -</#if></programlisting> - - <para>Similarly as earlier when a string was specified directly, - here a number is specified directly (<literal>0</literal>). Note - that the number is <emphasis>not</emphasis> quoted. If you quoted - it (<literal>"0"</literal>), FreeMarker would misinterpret it as a - string literal, and because the price to compare it to is a - number, you get an error.</para> - - <para>This will print "Pythons are not free today!" if their price - is not 0:</para> - - <programlisting role="template"><#if animals.python.price <emphasis>!=</emphasis> 0> - Pythons are not free today! -</#if></programlisting> - - <para>As you probably guessed, <literal>!=</literal> means - <quote>not equals</quote>.</para> - - <para>You can write things like this too (using <link - linkend="example.qStart.dataModelWithHashes">the data-model used - to demonstrate hashes</link>):</para> - - <programlisting role="template"><#if <emphasis>animals.python.price < animals.elephant.price</emphasis>> - Pythons are cheaper than elephants today. -</#if></programlisting> - - <para>With the <literal><#else></literal> tag you can - specify what to do if the condition is false. For example:</para> - - <programlisting role="template"><#if animals.python.price < animals.elephant.price> - Pythons are cheaper than elephants today. -<emphasis><#else></emphasis> - Pythons are not cheaper than elephants today. -</#if></programlisting> - - <para>This prints <quote>Pythons are cheaper than elephants - today.</quote> if the price of python is less than the price of - elephant, or else it prints <quote>Pythons are not cheaper than - elephants today.</quote> You can refine this further by using - <literal>elseif</literal>:</para> - - <programlisting role="template"><#if animals.python.price < animals.elephant.price> - Pythons are cheaper than elephants today. -<emphasis><#elseif animals.elephant.price < animals.python.price></emphasis> - Elephants are cheaper than pythons today. -<#else> - Elephants and pythons cost the same today. -</#if></programlisting> - - <para>If you have a variable with boolean value (a true/false - thing) then you can use it directly as the - <literal><replaceable>condition</replaceable></literal> of - <literal>if</literal>:</para> - - <programlisting role="template"><#if animals.python.protected> - Pythons are protected animals! -</#if></programlisting> - </section> - - <section> - <title>The list directive</title> - - <anchor xml:id="topic.tutorial.list"/> - - <para>This is needed when you want to list something. For example - if you merge this template with the <link - linkend="example.qStart.dataModelWithSequences">data-model used - earlier to demonstrate sequences</link>:</para> - - <programlisting role="template"><p>We have these animals: -<table border=1> - <emphasis><#list animals as animal></emphasis> - <tr><td>${<emphasis>animal</emphasis>.name}<td>${<emphasis>animal</emphasis>.price} Euros - <emphasis></#list></emphasis> -</table></programlisting> - - <para>then the output will be:</para> - - <programlisting role="output"><p>We have these animals: -<table border=1> - <emphasis><tr><td>mouse<td>50 Euros - <tr><td>elephant<td>5000 Euros - <tr><td>python<td>4999 Euros</emphasis> -</table></programlisting> - - <para>The generic form of the <literal>list</literal> directive - is:<literal> <#list <replaceable>sequence</replaceable> as - <replaceable>loopVariable</replaceable>><replaceable>repeatThis</replaceable></#list></literal>. - The <literal><replaceable>repeatThis</replaceable></literal> part - will be repeated for each item in the sequence that you have - specified with - <literal><replaceable>sequence</replaceable></literal>, one after - the other, starting from the first item. In all repetitions - <literal><replaceable>loopVariable</replaceable></literal> will - hold the value of the current item. This variable exists only - between the <literal><#list - <replaceable>...</replaceable>></literal> and - <literal></#list></literal> tags.</para> - - <para>The <literal><replaceable>sequence</replaceable></literal> - can be any kind of expression. For example we could list the - fruits of the example data model like this:</para> - - <programlisting role="template"><ul> -<emphasis><#list misc.fruits as fruit></emphasis> - <li>${fruit} -<emphasis></#list></emphasis> -</ul></programlisting> - - <para>The <literal>misc.fruits</literal> expression should be - familiar to you; it <link - linkend="topic.qStart.accessVariables">references a variable in - the data-model</link>.</para> - - <para>A problem with the above example is that if we happen to - have 0 fruits, it will still print an empty - <literal><ul></ul></literal> instead of just nothing. - To avoid that, you can use this form of - <literal>list</literal>:</para> - - <programlisting role="template"><#list misc.fruits> - <ul> - <emphasis> <#items as fruit></emphasis> - <li>${fruit} - <emphasis> </#items></emphasis> - </ul> -</#list></programlisting> - - <para>Here, the <literal>list</literal> directive represents the - listing as a whole, and only the part inside the - <literal>items</literal> directive is repeated for each fruit. If - we have 0 fruits, everything inside <literal>list</literal> is - skipped, hence we will not have <literal>ul</literal> tags in - case.</para> - - <para>Another frequent listing-related task: let's list the fruits - separating them with something, like a comma:</para> - - <programlisting role="template"><p>Fruits: <#list misc.fruits as fruit>${fruit}<emphasis><#sep>, </emphasis></#list></programlisting> - - <programlisting role="output"><p>Fruits: orange, banana</programlisting> - - <para>The section covered by <literal>sep</literal> (which we - could be written like this too: - <literal><replaceable>...</replaceable><#sep>, - </#sep></#list></literal>) will be only executed when - there will be a next item. Hence there's no comma after the last - fruit.</para> - - <para>Here again, what if we have 0 fruits? Just printing - <quote>Fruits:</quote> and then nothing is awkward. A - <literal>list</literal>, just like an <literal>if</literal>, can - have an <literal>else</literal>, which is executed if there were 0 - list items:</para> - - <programlisting role="template"><p>Fruits: <#list misc.fruits as fruit>${fruit}<#sep>, <emphasis><#else>None</emphasis></#list></programlisting> - - <note> - <para>As a matter of fact, this simplistic example could be - written like this, but it uses language devices that are off - topic here:</para> - - <programlisting role="template"><p>Fruits: ${fruits?join(", ", "None")}</programlisting> - </note> - - <para>All these directives (<literal>list</literal>, - <literal>items</literal>, <literal>sep</literal>, - <literal>else</literal>) can be used together:</para> - - <programlisting role="template"><#list misc.fruits> - <p>Fruits: - <ul> - <#items as fruit> - <li>${fruit}<#sep> and</#sep> - </#items> - </ul> -<#else> - <p>We have no fruits. -</#list></programlisting> - - <note> - <para>You can read more about these directives <link - linkend="ref_directive_list">in the Reference</link>.</para> - </note> - </section> - - <section> - <title>The include directive</title> - - <para>With the <literal>include</literal> directive you can insert - the content of another file into the template.</para> - - <para>Suppose you have to show the same copyright notice on - several pages. You can create a file that contains the copyright - notice only, and insert that file everywhere where you need that - copyright notice. Say, you store this copyright notice in - <literal>copyright_footer.html</literal>:</para> - - <programlisting role="template"><hr> -<i> -Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>, -<br> -All Rights Reserved. -</i></programlisting> - - <para>Whenever you need that file you simply insert it with the - <literal>include</literal> directive:</para> - - <programlisting role="template"><html> -<head> - <title>Test page</title> -</head> -<body> - <h1>Test page</h1> - <p>Blah blah... -<emphasis> <#include "/copyright_footer.html"></emphasis> -</body> -</html></programlisting> - - <para>and the output will be:</para> - - <programlisting role="output"><html> -<head> - <title>Test page</title> -</head> -<body> - <h1>Test page</h1> - <p>Blah blah... -<emphasis><hr> -<i> -Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>, -<br> -All Rights Reserved. -</i></emphasis> -</body> -</html></programlisting> - - <para>If you change the <literal>copyright_footer.html</literal>, - then the visitor will see the new copyright notice on all - pages.</para> - - <note> - <para>A much more powerful way of reusing snippets is using - macros, but that's an advanced topic <link - linkend="dgui_misc_userdefdir">discussed later</link>.</para> - </note> - </section> - </section> - - <section> - <title>Using directives together</title> - - <para>You can use directives as many times on a page as you want, - and you can nest directives into each other freely. For example, - here you nest <literal>if</literal> directive inside a - <literal>list</literal> directive:</para> - - <programlisting role="template"><emphasis><#list animals as animal></emphasis> - <div<emphasis><#if animal.protected></emphasis><emphasis> </emphasis>class="protected"<emphasis></#if></emphasis>> - ${animal.name} for ${animal.price} Euros - </div> -<emphasis></#list></emphasis></programlisting> - - <para>Note that since FreeMarker does not interpret text outside FTL - tags, interpolations and FTL comments, above you could use the FTL - tags inside HTML attributes without problem.</para> - </section> - - <section> - <title>Using built-ins</title> - - <para>The so-called built-ins are like subvariables (or rather like - methods, if you know that Java term) that aren't coming from the - data-model, but added by FreeMarker to the values. In order to make - it clear where subvariables comes from, you have to use - <literal>?</literal> (question mark) instead of <literal>.</literal> - (dot) to access them. <anchor - xml:id="topic.commonlyUsedBuiltIns"/>Examples with some of the most - commonly used built-ins:</para> - - <itemizedlist> - <listitem> - <para><literal>user?upper_case</literal> gives the upper case - version of the value of <literal>user</literal> (like - <quote>JOHN DOE</quote> instead of <quote>John - Doe</quote>)</para> - </listitem> - - <listitem> - <para><literal>animal.name?cap_first</literal> give the - <literal>animal.name</literal> with its first letter converted - to upper case (like <quote>Mouse</quote> instead of - <quote>mouse</quote>)</para> - </listitem> - - <listitem> - <para><literal>user?length</literal> gives the number of - <emphasis>characters</emphasis> in the value of - <literal>user</literal> (8 for <quote>John Doe</quote>)</para> - </listitem> - - <listitem> - <para><literal>animals?size</literal> gives the number of - <emphasis>items</emphasis> in the <literal>animals</literal> - sequence (3 in our example data-model)</para> - </listitem> - - <listitem> - <para>If you are between <literal><#list animals as - animal></literal> and the corresponding - <literal></#list></literal> tag:</para> - - <itemizedlist> - <listitem> - <para><literal>animal?index</literal> gives the 0-based - index of <literal>animal</literal> inside - <literal>animals</literal></para> - </listitem> - - <listitem> - <para><literal>animal?counter</literal> is like - <literal>index</literal>, but gives the 1-based index</para> - </listitem> - - <listitem> - <para><literal>animal?item_parity</literal> gives the - strings <quote>odd</quote> or <quote>even</quote>, depending - on the current counter parity. This is commonly used for - coloring rows with alternating colors, like in - <literal><td - class="${animal?item_parity}Row"></literal>.</para> - </listitem> - </itemizedlist> - </listitem> - </itemizedlist> - - <para>Some built-ins require parameters to specify the behavior - more, for example:</para> - - <itemizedlist> - <listitem> - <para><literal>animal.protected?string("Y", "N")</literal> - return the string <quote>Y</quote> or <quote>N</quote> depending - on the boolean value of - <literal>animal.protected</literal>.</para> - </listitem> - - <listitem> - <para><literal>animal?item_cycle('lightRow', - 'darkRow')</literal> is the more generic variant of - <literal>item_parity</literal> from earlier.</para> - </listitem> - - <listitem> - <para><literal>fruits?join(", ")</literal>: converts the list to - a string by concatenating items, and inserting the parameter - separator between each items (like <quote>orange, - banana</quote>)</para> - </listitem> - - <listitem> - <para><literal>user?starts_with("J")</literal> gives boolean - true of false depending on if <literal>user</literal> starts - with the letter <quote>J</quote> or not.</para> - </listitem> - </itemizedlist> - - <para>Built-in applications can be chained, like - <literal>fruits?join(", ")?upper_case</literal> will first convert - the list a to a string, then converts it to upper case. (This is - just like you can chain <literal>.</literal>-s (dots) too.)</para> - - <para>You can find the <link linkend="ref_builtins">full set of - built-ins in the Reference</link>.</para> - </section> - - <section> - <title>Dealing with missing variables</title> - - <para>The data-model often has variables that are optional (i.e., - sometimes missing). To spot some typical human mistakes, FreeMarker - doesn't tolerate references to missing variables unless you tell - explicitly what to do if the variable is missing. Here we will show - the two most typical ways of doing that.</para> - - <para><phrase role="forProgrammers">Note for programmers: A - non-existent variable and a variable with <literal>null</literal> - value is the same for FreeMarker. The "missing" term used here - covers both cases.</phrase></para> - - <para>Wherever you refer to a variable, you can specify a default - value for the case the variable is missing by following the variable - name with a <literal>!</literal> and the default value. Like in the - following example, when <literal>user</literal> is missing from data - model, the template will behave like if <literal>user</literal>'s - value were the string <literal>"visitor"</literal>. (When - <literal>user</literal> isn't missing, this template behaves exactly - like with <literal>${user}</literal>):</para> - - <programlisting role="template"><h1>Welcome ${user<emphasis>!"visitor"</emphasis>}!</h1></programlisting> - - <para>You can ask whether a variable isn't missing by putting - <literal>??</literal> after its name. Combining this with the - already introduced <literal>if</literal> directive you can skip the - whole greeting if the <literal>user</literal> variable is - missing:</para> - - <programlisting role="template"><#if <emphasis>user??</emphasis>><h1>Welcome ${user}!</h1></#if></programlisting> - - <para>Regarding variable accessing with multiple steps, like - <literal>animals.python.price</literal>, writing - <literal>animals.python.price!0</literal> is correct only if - <literal>animals.python</literal> is never missing and only the last - subvariable, <literal>price</literal>, is possibly missing (in which - case here we assume it's <literal>0</literal>). If - <literal>animals</literal> or <literal>python</literal> is missing, - the template processing will stop with an "undefined variable" - error. To prevent that, you have to write - <literal>(animals.python.price)!0</literal>. In that case the - expression will be <literal>0</literal> even if - <literal>animals</literal> or <literal>python</literal> is missing. - Same logic goes for <literal>??</literal>; - <literal>animals.python.price??</literal> versus - <literal>(animals.python.price)??</literal>.</para> - </section> - - <section xml:id="dgui_quickstart_template_autoescaping"> - <title>Escaping for HTML, XML and other markup</title> - - <para>Let's say the template generates HTML, and you insert values - with <literal>${<replaceable>...</replaceable>}</literal> that are - plain text (not HTML), like company names coming from a database. - Characters that has special meaning in HTML must be - <emphasis>escaped</emphasis> in such values, like if - <literal>name</literal> is <quote>Someone & Co.</quote> then - <literal>${name}</literal> should print <quote>Someone - <emphasis>&amp;</emphasis> Co.</quote>.</para> - - <para>FreeMarker automatically escapes all values printed with - <literal>${<replaceable>...</replaceable>}</literal> <emphasis>if - it's properly configured</emphasis> (that's the responsibility of - the programmers; <link - linkend="pgui_config_outputformatsautoesc">see here how</link>). The - recommended practice is using <literal>ftlh</literal> file extension - to activate HTML auto-escaping, and <literal>ftlx</literal> file - extension to activate XML auto-escaping.</para> - - <para>You can try if auto-escaping is on like - <literal>${"<"}</literal> and then checking the raw output (for - HTML or XML escaping). If it's not, and the configuration won't be - adjusted, add this as the very first line of the template:</para> - - <programlisting role="template"><#ftl output_format="HTML"></programlisting> - - <para>(Use <literal>"XML"</literal> instead of - <literal>"HTML"</literal> above if you generate XML.)</para> - - <para>If the string value to print deliberately contains markup, - auto-escaping must be prevented like - <literal>${<replaceable>value</replaceable>?no_esc}</literal>.</para> - - <para>You can find out much more about auto-escaping and output - formats <link linkend="dgui_misc_autoescaping">here...</link></para> - - <note> - <para>The kind of automatic escaping described here requires at - least FreeMarker 2.3.24. If you have to use an earlier version, - use the deprecated <link - linkend="ref_directive_escape"><literal>escape</literal> - directive</link> instead.</para> - </note> - </section> - </section> - </chapter> - - <chapter xml:id="dgui_datamodel"> - <title>Values, Types</title> - - <section xml:id="dgui_datamodel_basics"> - <title>Basics</title> - - <note> - <para>It is assumed that you have already read the <xref - linkend="dgui_quickstart"/> chapter.</para> - </note> - - <para>Understanding the concept of values and types is crucial for the - understanding of data-models. However, the concept of values and types - is not confined to data-models, as you will see.</para> - - <section xml:id="topic.value"> - <title>What is a value?</title> - - <indexterm> - <primary>value</primary> - </indexterm> - - <para><phrase role="forProgrammers">Real programmers can safely skip - this section.</phrase></para> - - <para>Examples of <emphasis>values</emphasis> as you know the term - from the everyday math are 16, 0.5, and so on, i.e. numbers. In the - case of computer languages the value term has a wider meaning, as a - value needn't be a number. For example, take this data-model:</para> - - <programlisting role="dataModel" xml:id="example.stdDataModel">(root) - | - +- user = "Big Joe" - | - +- today = Jul 6, 2007 - | - +- todayHoliday = false - | - +- lotteryNumbers - | | - | +- (1st) = 20 - | | - | +- (2st) = 14 - | | - | +- (3rd) = 42 - | | - | +- (4th) = 8 - | | - | +- (5th) = 15 - | - +- cargo - | - +- name = "coal" - | - +- weight = 40 -</programlisting> - - <para>We say that the <emphasis>value</emphasis> of the the - <literal>user</literal> variable is "Big Joe" (a string), the - <emphasis>value</emphasis> of <literal>today</literal> is Jul 6, - 2007 (a date), the <emphasis>value</emphasis> of - <literal>todayHoliday</literal> is false (a boolean, ie. a yes/no - thing). The <emphasis>value</emphasis> of - <literal>lotteryNumbers</literal> is the sequence that contains 20, - 14, 42, 8, 15. Surely <literal>lotteryNumbers</literal> is multiple - values in the sense that it <emphasis>contains</emphasis> multiple - values (for example, the 2nd item in it is a the - <emphasis>value</emphasis> 14), but still, - <literal>lotteryNumbers</literal> itself is a single value. It's - like a box that contains many other items; the whole box can be seen - as a single item. Last not least we also have the - <emphasis>value</emphasis> of <literal>cargo</literal>, which is a - hash (a box-like thing again).So, a value is something that can be - stored in a variable (e.g., in <literal>user</literal> or - <literal>cargo</literal> or <literal>cargo.name</literal>). But a - value need not be stored in a variable to be called a value, for - example we have the value 100 here:</para> - - <programlisting role="template"><#if cargo.weight < <emphasis>100</emphasis>>Light cargo</#if></programlisting> - - <para>The temporaly result of a calculations are also called values, - like 20 and 120 when this template is executed (it will print - 120):</para> - - <programlisting role="template">${cargo.weight / 2 + 100}</programlisting> - - <para>Explanation for this last: As the result of dividing the two - values, 40 (the weight of the cargo) and 2, a new value 20 is - created. Then 100 is added to it, so the value 120 is created. Then - 120 is printed - (<literal>${<replaceable>...</replaceable>}</literal>), and the - template execution goes on and all these values gone.</para> - - <para>Certainly now you feel what the value term means.</para> - </section> - - <section> - <title>What is type?</title> - - <para>Values have an important aspect, their type. For example the - type of the value of the <literal>user</literal> variable is string, - and the type of the value of the <literal>lotteryNumbers</literal> - variable is sequence. The type of a value is important because it - determines to a large extent how and where you can use the value. - Like <literal>${user / 2}</literal> is an error, but - <literal>${cargo.weight / 2}</literal> works and prints 20, since - division only does make sense for a number, but not for a string. - Or, using dot like in <literal>cargo.name</literal> does make sense - only if <literal>cargo</literal> is a hash. Or, you can list with - <literal><#list <replaceable>...</replaceable>></literal> - sequences only. Or, the condition of <literal><#if - ...></literal> must be a boolean. And so on.</para> - - <note> - <para>A little terminology... Saying "a boolean" or "a boolean - value" or "a value of type boolean" are all the same.</para> - </note> - - <para xml:id="topic.multitype"><indexterm> - <primary>Multi-typed value</primary> - </indexterm>A value can have multiple types at the same time, - although it's rarely utilized. For example in the data-model below - <literal>mouse</literal> is both a string and a hash:</para> - - <programlisting role="dataModel">(root) - | - +- mouse = "Yerri" - | - +- age = 12 - | - +- color = "brown"</programlisting> - - <para>If you merge this template with the above data-model:</para> - - <programlisting role="template">${mouse} <#-- uses mouse as a string --> -${mouse.age} <#-- uses mouse as a hash --> -${mouse.color} <#-- uses mouse as a hash --></programlisting> - - <para>the output will be:</para> - - <programlisting role="output">Yerri -12 -brown</programlisting> - </section> - - <section> - <title>The data-model is a hash</title> - - <para>Looking at the various data-model examples you may already - realized: the thing marked as "(root)" is just a value of type hash. - When you write something like <literal>user</literal>, that means - that you want the "user" variable stored in the root hash. Like if - you were writing <literal>root.user</literal>, except that there is - no variable called "root" so that wouldn't work.</para> - - <para>Some may get confused by the fact that our example data-model, - that is, the root hash, contains further hashes and sequences - (<literal>lotteryNumbers</literal> and <literal>cargo</literal>). - There is nothing special in that. A hash contains other variables, - and those variables have a value, which can be a string, a number, - etc., and of course it can be a hash or sequence as well. Because, - as it was explained earlier, a sequence or a hash is just a value, - like a string or a number is.</para> - </section> - </section> - - <section xml:id="dgui_datamodel_types"> - <title>The types</title> - - <para>The suppored types are:</para> - - <itemizedlist spacing="compact"> - <listitem> - <para><link linkend="dgui_datamodel_scalar" - os="">Scalars:</link></para> - - <itemizedlist spacing="compact"> - <listitem> - <para>String</para> - </listitem> - - <listitem> - <para>Number</para> - </listitem> - - <listitem> - <para>Boolean</para> - </listitem> - - <listitem> - <para>Date-like (date, time, or date-time)</para> - </listitem> - </itemizedlist> - </listitem> - - <listitem> - <para><link - linkend="dgui_datamodel_container">Containers:</link></para> - - <itemizedlist spacing="compact"> - <listitem> - <para>Hash</para> - </listitem> - - <listitem> - <para>Sequence</para> - </listitem> - - <listitem> - <para>Collection</para> - </listitem> - </itemizedlist> - </listitem> - - <listitem> - <para>Subroutines:</para> - - <itemizedlist spacing="compact"> - <listitem> - <para><link linkend="dgui_datamodel_method">Methods and - functions</link></para> - </listitem> - - <listitem> - <para><link linkend="dgui_datamodel_userdefdir">User-defined - directives</link></para> - </listitem> - </itemizedlist> - </listitem> - - <listitem> - <para>Miscellaneous/seldom used:</para> - - <itemizedlist spacing="compact"> - <listitem> - <para><link linkend="dgui_datamodel_node">Node</link></para> - </listitem> - - <listitem> - <para><link linkend="dgui_datamodel_markupoutput">Markup - output</link></para> - </listitem> - </itemizedlist> - </listitem> - </itemizedlist> - - <section xml:id="dgui_datamodel_scalar"> - <title>Scalars</title> - - <anchor xml:id="topic.designer.scalarVariable"/> - - <para>These are the basic, simple kind of values. They can - be:</para> - - <itemizedlist> - <listitem> - <para><indexterm> - <primary>string</primary> - - <secondary>the FTL value type</secondary> - </indexterm>String: It is simple text, e.g., the name of a - product.</para> - - <para>If you want to give a string value directly in the - template, rather than use a variable that comes from the data - model, you write the text between quotation marks, e.g., - <literal>"green mouse"</literal> or <literal>'green - mouse'</literal>. (More details regarding the syntax can be - found <link linkend="dgui_template_exp_direct_string" - xml:lang="">later</link>.)</para> - </listitem> - - <listitem> - <para><indexterm> - <primary>number</primary> - - <secondary>the FTL value type</secondary> - </indexterm>Number: For example the price of a product. - <phrase role="forProgrammers">Whole numbers and non-whole - numbers are not distinguished; there is only a single number - type. So for example 3/2 will be always 1.5, and never 1. Just - like if you are using a calculator.</phrase></para> - - <para>If you want to give a numerical value directly in the - template, then you write for example: <literal>150</literal> or - <literal>-90.05</literal> or <literal>0.001</literal>. (More - details regarding the syntax can be found <link - linkend="dgui_template_exp_direct_number" - xml:lang="">later</link>.)</para> - </listitem> - - <listitem> - <para><indexterm> - <primary>boolean</primary> - - <secondary>the FTL value type</secondary> - </indexterm>Boolean: A boolean value represents a logical true - or false (yes or no). For example, if a the visitor has been - logged in or not. Typically you use booleans as the condition of - the <literal>if</literal> directive, like <literal><#if - loggedIn - ><replaceable>...</replaceable></#if></literal> or - <literal><#if price == - 0><replaceable>...</replaceable></#if></literal>; in - the last case the result of the <literal>price == 0</literal> - part is a boolean value.</para> - - <para>In the templates you can directly specify a boolean with - the reserved words <literal>true</literal> and - <literal>false</literal>.</para> - </listitem> - - <listitem> - <para><indexterm> - <primary>date</primary> - - <secondary>the FTL value type</secondary> - </indexterm><indexterm> - <primary>time</primary> - - <secondary>the FTL value type</secondary> - </indexterm><indexterm> - <primary>date-time</primary> - - <secondary>the FTL value type</secondary> - </indexterm>Date: A date-like value stores date/time related - data. It has three variations:</para> - - <itemizedlist> - <listitem> - <para>Date: Like April 4, 2003. Day precision, no time of - day part.</para> - </listitem> - - <listitem> - <para>Time: Like 10:19:18 PM. Millisecond precision, no date - part.</para> - </listitem> - - <listitem> - <para>Date-time (sometimes called "time stamp") as April 4, - 2003 10:19:18 PM. Both date and time, with millisecond - precision.</para> - </listitem> - </itemizedlist> - - <para>Unfortunately, because of the limitations of the Java - platform, FreeMarker sometimes can't decide which parts of the - date are in use (i.e., if it is date-time, a date or a time). - The solution for this problem is an advanced topic that will be - discussed <link - linkend="ref_builtin_date_datetype">later</link>.</para> - - <para>It is possible to define date-like values directly in - templates, but this is an advanced topic that will be explained - <link linkend="ref_builtin_string_date">later</link>.</para> - </listitem> - </itemizedlist> - - <para>Bear in mind that FreeMarker distinguishes strings from - numbers, booleans and date-like values. For example, while the - string <literal>"150"</literal> looks like the number - <literal>150</literal>, a string is still just arbitrary sequence of - characters, and you can't do arithmetic with it, can't compare it - with another number, etc.</para> - </section> - - <section xml:id="dgui_datamodel_container"> - <title>Containers</title> - - <remark>Re-explanation of hashes and sequences from a more - ''professional'' viewpoint as earlier, and some meditation about - them.</remark> - - <para>These are the values whose purpose is to contain other - variables; they are just containers. The contained variables are - often referred as <emphasis>sub variables</emphasis>. The container - types are:</para> - - <itemizedlist> - <listitem> - <para><indexterm> - <primary>hash</primary> - - <secondary>the FTL value type</secondary> - </indexterm>Hash: Associates a unique lookup name with each of - its sub variables. The name is an unrestricted string. A hash - <emphasis>doesn't define an ordering</emphasis> for the sub - variables in it. That is, there is no such thing as the first - subvariable, and the second subvariable, etc.; the variables are - just accessed by name.</para> - </listitem> - - <listitem> - <para><indexterm> - <primary>sequence</primary> - - <secondary>the FTL value type</secondary> - </indexterm>Sequence: Associates an integer number with each - of its sub variables. The first subvariable is associated with - 0, the second with 1, the third to 2, and so on; the sub - variables are ordered. These numbers are often called the - <emphasis>indexes</emphasis> of the sub variables. Sequences are - usually dense, i.e., all indexes up to the index of the last - subvariable have an associated subvariable, but it's not - strictly necessary. The type of the subvariable values need not - be the same.</para> - </listitem> - - <listitem> - <para><indexterm> - <primary>collection</primary> - - <secondary>the FTL value type</secondary> - </indexterm>Collection: A collection, from the viewpoint of - the template author, is a restricted sequence. You cannot access - its size or retrieve its sub variables by index, but they can be - still listed with the <link - linkend="ref.directive.list"><literal>list</literal> - directive</link>.</para> - </listitem> - </itemizedlist> - - <para>Note that since <link linkend="topic.multitype">a value can - have multiple types</link>, it is possible for a value to be both a - hash and a sequence, in which case it would support index-based - access as well as access by lookup name. However, typically a - container will be either a hash or a sequence, not both.</para> - - <para>As the value of the variables stored in hashes and sequences - (and collections) can be anything, it can be a hash or sequence (or - collection) as well. This way you can build arbitrarily deep - structures.</para> - - <para>The data-model itself (or better said the root of it) is a - hash.</para> - </section> - - <section> - <title>Subroutines</title> - - <section xml:id="dgui_datamodel_method"> - <title>Methods and functions</title> - - <anchor xml:id="topic.designer.methodVariable"/> - - <indexterm> - <primary>method</primary> - - <secondary>the FTL value type</secondary> - </indexterm> - - <para>A value that is a method or a function is used to calculate - another value, influenced by the parameters you give to it.</para> - - <para><phrase role="forProgrammers">For programmer types: - Methods/functions are first-class values, just like in functional - programming languages. This means that functions/methods can be - the parameters or return values of other functions/methods, you - can assign them to variables, and so on.</phrase></para> - - <para>Suppose that programmers have put the method variable - <literal>avg</literal> in the data-model that can be used to - calculate the average of numbers. If you give the 3 and 5 as - parameters when you access <literal>avg</literal>, then you get - the value 4.</para> - - <para>The usage of methods will be explained <link - linkend="dgui_template_exp_methodcall">later</link>, but perhaps - this example helps to understand what methods are:</para> - - <programlisting role="template">The average of 3 and 5 is: ${avg(3, 5)} -The average of 6 and 10 and 20 is: ${avg(6, 10, 20)} -The average of the price of a python and an elephant is: -${avg(animals.python.price, animals.elephant.price)}</programlisting> - - <para>this will output:</para> - - <programlisting role="output">The average of 3 and 5 is: 4 -The average of 6 and 10 and 20 is: 12 -The average of the price of a python and an elephant is: -4999.5</programlisting> - - <para>What is the difference between a method and a function? As - far as the template author is concerned, nothing. Well not really - nothing, as methods typically come from the data-model (<phrase - role="forProgrammers">as they reflect the methods of Java - objects</phrase>), and functions are defined in templates (with - the <link - linkend="ref.directive.function"><literal>function</literal> - directive</link> -- an advanced topic), but both can be used on - the same way.</para> - </section> - - <section xml:id="dgui_datamodel_userdefdir"> - <title>User-defined directives</title> - - <indexterm> - <primary>macro</primary> - - <secondary>the FTL value type</secondary> - </indexterm> - - <indexterm> - <primary>directive</primary> - - <secondary>the FTL value type</secondary> - </indexterm> - - <indexterm> - <primary>user-defined directive</primary> - - <secondary>the FTL value type</secondary> - </indexterm> - - <para>A value of this type can be used as user-defined directive - (with other words, as FreeMarker tag). An user-defined directive - is a subroutine, something like a little reusable template - fragment. But this is an advanced topic that will be explained - <link linkend="dgui_misc_userdefdir">later</link> in its own - chapter.</para> - - <para><phrase role="forProgrammers">For programmer types: - user-defined directives (such as macros), are first-class values - too, just like functions/methods are.</phrase></para> - - <para>Just to get an idea about user-defined directives (so just - ignore this if you won't understand), assume we have a variable, - <literal>box</literal>, whose value is a user-defined directive - that prints some kind of fancy HTML message box with a title bar - and a message in it. The <literal>box</literal> variable could be - used in the template like this (for example):</para> - - <programlisting role="template"><@<emphasis>box</emphasis> title="Attention!"> - Too much copy-pasting may leads to - maintenance headaches. -</@<emphasis>box</emphasis>></programlisting> - </section> - - <section> - <title>Function/method versus user-defined directive</title> - - <para>This is for advanced users again (so ignore it if you don't - understand). It's a frequent dilemma if you should use a - function/method or an user-defined directive to implement - something. The rule of thumb is: Implement the facility as - user-defined directive instead of as function/method if:</para> - - <itemizedlist> - <listitem> - <para>... the purpose of it is generating a piece of the - output that's not just a single value, and typically involves - markup. The template language was designed for printing to the - output directly, piece by piece, as it goes though - <literal>list</literal> loops, <literal>if</literal>-s, etc. - Building up a string value in a variable then returning it is - much less convenient.</para> - </listitem> - - <listitem> - <para>... it's the side-effect that is important and not the - return value. For example, a directive whose purpose is to add - an entry to the server log is like that. (In fact you can't - have a return value for a user-defined directive, but some - kind of feedback is still possible by setting non-local - variables.)</para> - </listitem> - - <listitem> - <para>... it will do flow control on the caller side (like for - example <literal>list</literal> or <literal>if</literal> - directives do). You just can't do that with a - function/method.</para> - </listitem> - - <listitem> - <para>... you are using legacy escaping via the - <literal>escape</literal> directive (instead of <link - linkend="dgui_misc_autoescaping">auto-escaping</link>), and - the result contains markup. When you print the result with - <literal>${<replaceable>...</replaceable>}</literal>, the - markup will be escaped and thus ruined, but if it's printed by - a directive call - (<literal><@<replaceable>...</replaceable>></literal>), - it won't be.</para> - </listitem> - </itemizedlist> - - <para>The Java methods of FreeMarker-unaware Java objects are - normally visible as methods in templates, regardless of the nature - of the Java method; you have no choice there.</para> - </section> - </section> - - <section> - <title>Miscellaneous</title> - - <section xml:id="dgui_datamodel_node"> - <title>Nodes</title> - - <indexterm> - <primary>node</primary> - - <secondary>the FTL value type</secondary> - </indexterm> - - <para>Node variables represent a node in a tree structure, and are - used mostly with <link linkend="xgui">XML processing</link>, which - is an advanced, and specialized topic.</para> - - <para>Still, a quick overview <emphasis>for advanced - users</emphasis>: A node is similar to a sequence that stores - other nodes, which are often referred as the children nodes. A - node stores a reference to its container node, which is often - referred as the parent node. The main point of being a node is the - topological information; other data must be stored by utilizing - that a value can have multiple types. Like, a value may be both a - node and a number, in which case it can store a number as the - "pay-load". Apart from the topological information, a node can - store some metainformation as well: a node name, a node type - (string), and a node namespace (string). For example, if the node - symbolizes a <literal>h1</literal> element in an XHTML document, - then its name could be <literal>"h1"</literal>, it's node type - could be <literal>"element"</literal>, and it's namespace could be - <literal>"http://www.w3.org/1999/xhtml"</literal>. But it's up to - the designer of the data-model if what meaning these - metainformations have, and if they are used at all. The way of - retrieving the topological and metainformations is described <link - linkend="ref_builtins_node">in a later chapter</link> (that you - don't have to understand at this point).</para> - </section> - - <section xml:id="dgui_datamodel_markupoutput"> - <title>Markup output</title> - - <indexterm> - <primary>markup output</primary> - - <secondary>the FTL value type</secondary> - </indexterm> - - <para>This type is related to <link - linkend="dgui_misc_autoescaping">auto-escaping mechanism</link> - introduced FreeMarker 2.3.24; you can <link - linkend="dgui_misc_autoescaping_movalues">read about this type - there</link>. But in short, this is a value that stores text - that's already in the output markup format (like HTML, XML, RTF, - etc.), and hence must not be auto-escaped.</para> - - <para>Values of this type are usually produced inside the - templates (like with <link - linkend="ref_builtin_no_esc"><literal>no_esc</literal> - built-in</link> or <link linkend="ref_directive_assign">output - capturing assignments</link>), but can also be part of the - data-model. Such values in the data-model are useful for example - if you have message resources that sometimes contain the message - in HTML format, rather than in plain text. If the data-model uses - HTML markup output values for those messages instead of strings, - then the template author need not know which messages contain HTML - and which plain text, as double escaping will be avoided - automatically when the message is inserted with - <literal>${<replaceable>...</replaceable>}</literal>.</para> - </section> - </section> - </section> - </chapter> - - <chapter xml:id="dgui_template"> - <title>The Template</title> - - <indexterm> - <primary>template</primary> - </indexterm> - - <note> - <para>It is assumed that you have already read the <xref - linkend="dgui_quickstart"/> and the <xref linkend="dgui_datamodel"/> - chapter.</para> - </note> - - <section xml:id="dgui_template_overallstructure"> - <title>Overall structure</title> - - <para>Templates are in fact programs you write in a language called - <indexterm> - <primary>FTL</primary> - </indexterm><emphasis role="term">FTL</emphasis> (for FreeMarker - Template Language). This is a quite simple programming language - designed for writing templates and nothing else.</para> - - <para>A template (= FTL program) is a mix of the following - sections:</para> - - <itemizedlist> - <listitem> - <para><emphasis role="term">Text</emphasis><indexterm> - <primary>text</primary> - </indexterm>: Text that will be printed to the output as - is.</para> - </listitem> - - <listitem> - <para><emphasis role="term">Interpolation</emphasis><indexterm> - <primary>interpolation</primary> - </indexterm>: These sections will be replaced with a calculated - value in the output. Interpolations are delimited by - <literal>${</literal> and <literal>}</literal> (or with - <literal>#{</literal> and <literal>}</literal>, but that shouldn't - be used anymore; <link - linkend="ref_depr_numerical_interpolation">see more - here</link>).</para> - </listitem> - - <listitem> - <para><emphasis role="term">FTL tags</emphasis><indexterm> - <primary>FTL tag</primary> - </indexterm>: FTL tags are a bit similar to HTML tags, but they - are instructions to FreeMarker and will not be printed to the - output.</para> - </listitem> - - <listitem> - <para><emphasis role="term">Comments</emphasis><indexterm> - <primary>comment</primary> - </indexterm><indexterm> - <primary><#--...--></primary> - </indexterm><indexterm> - <primary>#</primary> - </indexterm>: Comments are similar to HTML comments, but they - are delimited by <literal><#--</literal> and - <literal>--></literal>. Comments will be ignored by FreeMarker, - and will not be written to the output.</para> - </listitem> - </itemizedlist> - - <para>Let's see a concrete template. I have marked the template's - components with colors: <phrase role="markedText">text</phrase>, - <phrase role="markedInterpolation">interpolation</phrase>, <phrase - role="markedFTLTag">FTL tag</phrase>, <phrase - role="markedComment">comment</phrase>. With the <phrase - role="markedInvisibleText">[BR]</phrase>-s I intend to visualize the - <link linkend="gloss.lineBreak">line breaks</link>.</para> - - <programlisting role="template"><phrase role="markedText"><html><phrase - role="markedInvisibleText">[BR]</phrase> -<head><phrase role="markedInvisibleText">[BR]</phrase> -  <title>Welcome!</title><phrase role="markedInvisibleText">[BR]</phrase> -</head><phrase role="markedInvisibleText">[BR]</phrase> -<body><phrase role="markedInvisibleText">[BR]</phrase> -  <phrase role="markedComment"><#-- Greet the user with his/her name --></phrase><phrase - role="markedInvisibleText">[BR]</phrase> -  <h1>Welcome <phrase role="markedInterpolation">${user}</phrase>!</h1><phrase - role="markedInvisibleText">[BR]</phrase> -  <p>We have these animals:<phrase role="markedInvisibleText">[BR]</phrase> -  <ul><phrase role="markedInvisibleText">[BR]</phrase> -  <phrase role="markedFTLTag"><#list animals as animal></phrase><phrase - role="markedInvisibleText">[BR]</phrase> -    <li><phrase role="markedInterpolation">${animal.name}</phrase> for <phrase - role="markedInterpolation">${animal.price}</phrase> Euros<phrase - role="markedInvisibleText">[BR]</phrase> -  <phrase role="markedFTLTag"></#list></phrase><phrase - role="markedInvisibleText">[BR]</phrase> -  </ul><phrase role="markedInvisibleText">[BR]</phrase> -</body><phrase role="markedInvisibleText">[BR]</phrase> -</html></phrase></programlisting> - - <para>FTL distinguishes upper case and lower case letters. So - <literal>list</literal> is good directive name, while - <literal>List</literal> is not. Similarly <literal>${name}</literal> - is not the same as <literal>${Name}</literal> or - <literal>${NAME}</literal></para> - - <para>It is important to realize that <phrase - role="markedInterpolation">interpolations</phrase> can be used in - <phrase role="markedText">text</phrase> (and in string literal - expressions; see <link - linkend="dgui_template_exp_stringop_interpolation">later</link>) - only.</para> - - <para>An <phrase role="markedFTLTag">FTL tag</phrase> can't be inside - another <phrase role="markedFTLTag">FTL tag</phrase> nor inside an - <phrase role="markedInterpolation">interpolation</phrase>. For example - this is <emphasis>WRONG</emphasis>: <literal><#if <#include - 'foo'>='bar'>...</#if></literal></para> - - <para><phrase role="markedComment">Comments</phrase> can be placed - inside <phrase role="markedFTLTag">FTL tags</phrase> and <phrase - role="markedInterpolation">interpolations</phrase>. For - example:</para> - - <programlisting role="template"><phrase role="markedText"><h1>Welcome <phrase - role="markedInterpolation">${user <phrase role="markedComment"><#-- The name of user --></phrase>}</phrase>!</h1><phrase - role="markedInvisibleText">[BR]</phrase> -<p>We have these animals:<phrase role="markedInvisibleText">[BR]</phrase> -<ul><phrase role="markedInvisibleText">[BR]</phrase> -<phrase role="markedFTLTag"><#list <phrase role="markedComment"><#-- some comment... --></phrase> animals as <phrase - role="markedComment"><#-- again... --></phrase> animal></phrase><phrase - role="markedInvisibleText">[BR]</phrase></phrase> -<replaceable>...</replaceable></programlisting> - - <note> - <para>For those of you who have tried the above examples: You may - notice that some of spaces, tabs and line breaks are missing from - the template output, even though we said that <phrase - role="markedText">text</phrase> is printed as is. Don't bother with - it now. This is because the feature called ''white-space stripping'' - is turned on, and that automatically removes some superfluous - spaces, tabs and line breaks. This will be explained <link - linkend="dgui_misc_whitespace">later</link>.</para> - </note> - </section> - - <section xml:id="dgui_template_directives"> - <title>Directives</title> - - <indexterm> - <primary><#...></primary> - </indexterm> - - <indexterm> - <primary>#</primary> - </indexterm> - - <anchor xml:id="term.designer.directive"/> - - <remark>Note that the Expressions chapter depends on this chapter, and - Interpolations chapter depends on Expressions chapter. Thus Directives - must be the first chapter after Basics.</remark> - - <para><indexterm> - <primary>directive</primary> - </indexterm>You use FTL tags to call <emphasis - role="term">directives</emphasis>. In the example you have called the - <literal>list</literal> directive. Syntactically you have done it with - two tags: <literal><#list animals as animal></literal> and - <literal></#list></literal>.</para> - - <para><indexterm> - <primary>FTL tag</primary> - </indexterm>There are two kind of FTL tags:</para> - - <itemizedlist> - <listitem> - <para>Start-tag: - <literal><#<replaceable>directivename</replaceable> - <replaceable>parameters</replaceable>></literal></para> - </listitem> - - <listitem> - <para>End-tag: - <literal></#<replaceable>directivename</replaceable>></literal></para> - </listitem> - </itemizedlist> - - <para>This is similar to HTML or XML syntax, except that the tag name - starts with <literal>#</literal>. If the directive doesn't have nested - content (content between the start-tag and the end-tag), you must use - the start-tag with no end-tag. For example you write <literal><#if - <replaceable>something</replaceable>><replaceable>...</replaceable></#if></literal>, - but just <literal><#include - <replaceable>something</replaceable>></literal> as FreeMarker knows - that the <literal>include</literal> directive can't have nested - content.</para> - - <para>The format of the - <literal><replaceable>parameters</replaceable></literal> depends on - the - <literal><replaceable>directivename</replaceable></literal>.</para> - - <para>In fact there are two types of directives: <link - linkend="gloss.predefinedDirective">predefined directives</link> and - <link linkend="gloss.userDefinedDirective">user-defined - directives</link>. For user-defined directives you use - <literal>@</literal> instead of <literal>#</literal>, for example - <literal><@mydirective - <replaceable>parameters</replaceable>><replaceable>...</replaceable></@mydirective></literal>. - Further difference is that if the directive has no nested content, you - must use a tag like <literal><@mydirective - <replaceable>parameters</replaceable> /></literal>, similarly as in - XML (e.g. <literal><img <replaceable>...</replaceable> - /></literal>). But user-defined directives is an advanced topic - that will be discussed <link - linkend="dgui_misc_userdefdir">later</link>.</para> - - <para>FTL tags, like HTML tags, must be properly nested. So the code - below is wrong, as the <literal>if</literal> directive is both inside - and outside of the nested content of the <literal>list</literal> - directive:</para> - - <programlisting role="template"><ul> -<emphasis><#list animals as animal></emphasis> - <li>${animal.name} for ${animal.price} Euros - <emphasis><#if user == "Big Joe"></emphasis> - (except for you) -<emphasis></#list></emphasis> <#-- WRONG! The "if" has to be closed first. --> -<emphasis></#if></emphasis> -</ul></programlisting> - - <para>Note that FreeMarker doesn't care about the nesting of HTML - tags, only about the nesting of FTL tags. It just sees HTML as flat - text, it doesn't interpret it in any way.</para> - - <para>If you try to use a non-existing directive (e.g., you mistype - the directive name), FreeMarker will decline to use the template and - produce an error message.</para> - - <para>FreeMarker ignores superfluous <link - linkend="gloss.whiteSpace">white-space</link> inside FTL tags. So you - can write this:</para> - - <programlisting role="template"><phrase role="markedText"><phrase - role="markedFTLTag"><#list<phrase role="markedInvisibleText">[BR]</phrase> -  animals       as<phrase role="markedInvisibleText">[BR]</phrase> -     animal<phrase role="markedInvisibleText">[BR]</phrase> -></phrase><phrase role="markedInvisibleText">[BR]</phrase> -<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase - role="markedInterpolation">${animal.price}</phrase> Euros<phrase - role="markedInvisibleText">[BR]</phrase> -<phrase role="markedFTLTag"></#list    ></phrase></phrase></programlisting> - - <para>You may not, however, insert white-space between the - <literal><</literal> or <literal></</literal> and the directive - name.</para> - - <para>The complete list and description of all directives can be found - in the <xref linkend="ref_directives"/> (but I recommend that you look - at the chapter about expressions first).</para> - - <note> - <para>FreeMarker can be configured to use <literal>[</literal> and - <literal>]</literal> instead of <literal><</literal> and - <literal>></literal> in the FTL tags and FTL comments, like - <literal>[#if user == "Big - Joe"]<replaceable>...</replaceable>[/#if]</literal>. For more - information read: <xref - linkend="dgui_misc_alternativesyntax"/>.</para> - </note> - - <note> - <para>FreeMarker can be configured so that it understands predefined - directives without <literal>#</literal> (like <literal><if user - == "Big - Joe"><replaceable>...</replaceable></if></literal>). - However we don't recommend the usage of this mode. For more - information read: <xref linkend="ref_depr_oldsyntax"/></para> - </note> - </section> - - <section xml:id="dgui_template_exp"> - <title>Expressions</title> - - <para><indexterm> - <primary>expression</primary> - </indexterm>When you supply values for interpolations or directive - parameters you can use variables or more complex expressions. For - example, if x is the number 8 and y is 5, the value of <literal>(x + - y)/2</literal> resolves to the numerical value 6.5.</para> - - <para>Before we go into details, let's see some concrete - examples:</para> - - <itemizedlist> - <listitem> - <para>When you supply value for interpolations: The usage of - interpolations is - <literal>${<replaceable>expression</replaceable>}</literal> where - expression gives the value you want to insert into the output as - text. So <literal>${(5 + 8)/2}</literal> prints <quote>6.5</quote> - to the output (or possibly <quote>6,5</quote> if the language of - your output is not US English).</para> - </listitem> - - <listitem> - <para>When you supply a value for the directive parameter: You - have already seen the <literal>if</literal> directive in the - Getting Started section. The syntax of this directive is: - <literal><#if - <replaceable>expression</replaceable>><replaceable>...</replaceable></#if></literal>. - The expression here must evaluate to a boolean value. For example - in <literal><#if 2 < 3></literal> the <literal>2 < - 3</literal> (2 is less than 3) is an expression which evaluates to - <literal>true</literal>.</para> - </listitem> - </itemizedlist> - - <section xml:id="exp_cheatsheet"> - <title>Quick overview (cheat sheet)</title> - -
<TRUNCATED>
