Intro tour

This is an intro tour taken from the Yeast templates Tutorial that can be downloaded in this link

You can test the examples included in this tour in the Try it yourself! page.

You can see more examples in the examples page.

Table of contents

Overview

Yeast is an attribute based, double-model based, browser-side HTML template system. That is, Yeast templates are processed in the user's browser. The template engine, coded in JavaScript, is located in the browser. Templates are described in HTML but with some non-standard attributes that carry the processing instructions.

A Yeast template looks like the following sample (you can see more samples in the samples section):



Click here to see the template in your browser

As any other HTML template, a Yeast template is an HTML document with "holes" where you can stick values. Yeast is designed to be practical for the generation of HTML Web pages, following the, named by us, Double Model Approach. Read more ...

(^ up to t.o.c. )

Yeast template structure

A Yeast template is a HTML document with the following structure:

<html>
<head>
... Engine inclusion ... Designer's model
</head>

<body> ... the template body </body>
</html>

(^ up to t.o.c. )

Including the engine

<script type="text/javascript" src="yst.js"></script>

(^ up to t.o.c. )

The designer’s model

A Yeast template must include in its head one or two script blocks that hold the designer’s model. It is important to note that, unlike other browser side templating systems, in Yeast you can structure your model as you want. No need to use JSON. 

The optional first script block is devoted to the definition of the data structures used in the template. You must place in it the definition of the JavaScript constructors for objects, the definition of arrays, or whatever constant value needed in the template. It must be marked with the attribute yst with value init. Do not place any dynamic data in this script block.

<script yst="init">
  function Item(name, price) {
    this.name = name;
    this.price = price;
  }

  items = new Array();
</script>

Once the data structures have been defined, the dynamic data section begins. This is a new script block that contains all the variables, array and object initialization statements needed in the template. The idea behind Yeast templates is that every time you need a dynamic data to be inserted in the page, you create a JavaScript variable and assigns a test value to it. This is the place where you must do it. This script block must be marked with the attribute yst with value model.

<script yst="model">
name = "Fran";
age = 35; host = "www.unirioja.es"; link_txt ="The University of La Rioja";
news = ["Fat boy may be put in care",
"23,000 elephants killed each year for ivory",
"Oscars 2009: The internet responds"];

customers = [{name: "Tico", age:24}, {name:"Tuco", age: 33},
{name: "Taco", age: 30}, {name:"Toco", age: 35}];

matrix = [[1,0,0,0,0],[0,2,0,0,0],[0,0,3,0,0],[0,0,0,4,0],[0,0,0,0,5]]; items[0] = new Item('Umbrella',1); items[1] = new Item('Suitcase',18);
</script>

(^ up to t.o.c. )

Yeast expressions

It is a JavaScript expression that may reference a Yeast variable defined in the designer's model. Yeast expressions are enclosed between $$. Yeast expressions may appear as part of the value of HTML elements or attributes. If you need to insert the $ symbol inside an expression, escape it using \$.

I work at <a yst="value" href="http://$host$/index.html">$link_txt$</a>        
I work at $link_txt$

Note that, to be evaluated, Yeast expression must be located inside a Yeast element.

(^ up to t.o.c. )

Non-displayable Yeast expressions

they are Yeast expression that starts with the # character. The expression will be evaluated, but nothing will be displayed. They may be used to perform auxiliary computations or declare auxiliary variables. We will get the most of these expressions when we will describe how to nest Yeast elements in apply andcompapply.

<p yst="value">My name ($name$)$#len = name.length$ is $len$ letters in length.</p>        
My name ($name$)$#len = name.length$ is $len$ letters in length.

(^ up to t.o.c. )

The ystAux attribute

Sometimes, there is no room in the HTML code to insert the $# ...$ Yeast expression. An example of such a situation is when the auxiliary value defined in the non-displayable expression has to be used in an element attribute. You can use the ystAux attribute to do it.

<a yst="value" ystAux="$# val=Math.random()$" 
   href="http://yeasttemplates.org/index.html?x=$val$">Send me a value</a>
Send me a value

Note that the previous is only an example. You could have done the same directly: <a yst="value" href="http://yeasttemplates.org/index.html?x=$Math.random()$">. A more complex and real example can be found here.

The ystAux attribute is evaluated before any other element attribute, with the sole exception of ystSet attribute (see The ystSet attribute).

(^ up to t.o.c. )

Yeast elements

In a Yeast Template, HTML elements may have non-standard attributes. The most important Yeast attribute is yst. Its value specifies the type of processing that the element that carries it must undergo. We call HTML elements marked with this yst attribute Yeast elements. There are eight possible values for yst, which cover evaluations (value), conditionals (if), iterations (apply, compApply), sub-template inclusions (declare, include) and AJAX interactions (ajax). The rest of this intro tour is dedicated to explaining this several possibilities.

Yeast elements may be nested.

(^ up to t.o.c. )

Removing values (ignore)

Elements including the yst="ignore" attribute will be removed from the processed template.

The first prototype for the template designed by the graphic designer is likely to be an only HTML page. The designer does not need to remove definitely the HMTL elements used to create the page. They can be marked with the yst="ignore" processing instruction.

Hello <span yst="ignore">John</span><span yst="value">$name$</span>.
Hello Fran$name$.

(^ up to t.o.c. )

Inserting values (value)

The template engine evaluates all the Yeast expressions in the Yeast element and recursively in all its children. Resulting values replace Yeast expressions.

<p yst="value">$name$, there are $news.length$ news items for you. 
The first is <em>"$news[0]$"</em>.
I work at <a yst="value" href="http://$host$/index.html">$link_txt$</a> </p>
$name$, there are $news.length$ news items for you. The first is "$news[0]$".
I work at $link_txt$"

(^ up to t.o.c. )

Making decisions (if)

An element carrying the yst="if" attribute will be included and processed only if the value of the conditional expression contained in an auxiliary Yeast attribute named ystTest is evaluated to true. When the if element has not got a ystTest attribute, then a default ystTest with true value is assumed.

The ystTestattribute must always carry a JavaScript Boolean expression. Expressions inside ystTest are not Yeast expressions. It is not allowed to surround the ystTest expression with $ symbols.

<p yst="value">$name$, there are $news.length$ news items for 
you<span yst="if" ystTest="news.length>2">, too many to be read in a minute</span>.</p>
$name$, there are $news.length$ news items for you, too many to be read in a minute.

If the news array was

<script yst="model">  
news = ["Fat boy may be put in care",
"23,000 elephants killed each year for ivory"];
</script>

then the result would be

$name$, there are $news2.length$ news items for you, too many to be read in a minute.

(^ up to t.o.c. )

Boolean atributes

Some HTML elements can have boolean attributes, such as checked, selected or disabled. To set boolean attributes in Yeast-elements you can use the ystBool attribute. The ystBool attribute must carry a JavaScript object literal expression (or a JSON expression) specifying an object whose property names name the boolean attributes to set, and whose property values specify the conditions (boolean expressions) that determine the actual presence of the attribute. For example: a checkbox that must be checked if the value of age is lower than 40 will be coded with the following Yeast-element:

<input type="checkbox" name="younger40" value="younger40" yst="value" 
ystBool="{checked:age<40}" /> You are younger than 40
You are younger than 40.

In the example, the expression specified in ystBool ({checked:age<40}) corresponds to an object, using object literal notation, with one property (checked, just the name of the boolean attribute to set); the value of this property is age<40, the condition that determines if the attribute is definitely present (that is, if the checkbox is actually checked).

Note that, using the same attribute ystBool, you can configure several boolean attributes simultaneously, as in the following example:

<input type="checkbox" name="younger40" value="younger40" yst="value" 
ystBool="{disabled:typeof age=='undefined', checked:typeof age!='undefined' && age<40}" /> 
You are younger than 40
You are younger than 40.

See more ystBool examples.

(^ up to t.o.c. )

Iterating (apply)

It is used to repeat an HTML element a number of times. There are two versions for the apply processing instruction:

  • One is used to iterate over the elements of an array specified in an auxiliary Yeast attribute named ystSet.
  • The other one is used to repeat a certain element a given number of times specified in the auxiliary Yeast attribute ystUpTo

There are three implicit variables associated to the underlying iteration process that can be used in the inner Yeast expressions. When apply comes with ystSet these implicit variables are: values, the iterated set; i, the iteration index, ranging from 0 to values.length-1; e the iteration value, that is, e=values[i]. In the case of using ystUpTo, the implicit variables are: i, the iteration index; e the same as i.

(^ up to t.o.c. )

Using ystSet

The ystSet attribute is processed before any other attribute of the Yeast element. Apply iterates over the full array specified in ystTest. If you need to iterate over a more reduced subset of array components, you will have to use compApply instead of apply. Likewise, note that apply affects only to an HTML element, which is replicated for each value of the ystSet array. If you need to replicate several HTML elements for each value of the ystSet array you will have to use compApply instead of apply.

<p>My customers are</p>
<ul>
<li yst="apply" ystSet="customers">$i+1$ - $e.name$, $e.age$ years old </li>
</ul>
My customers are
  • $i+1$ - $e.name$, $e.age$ years old

(^ up to t.o.c. )

Using ystUpTo

It must contain an integer JavaScript expression that will be the number of times that the apply element will be repeated. The attribute content is always a JavaScript expression, not a Yeast expression. It is not allowed to surround the ystUpTo expression by $ symbols. In the same way that with ystSet, the ystUpTo attribute is processed before any other attribute of the Yeast element.

<p>My customers are</p>
<ul>
<li yst="apply" ystUpTo="customers.length"> $i+1$ - $customers[i].name$, $customers[i].age$ years old </li>
</ul>
My customers are
  • $i+1$ - $customers[i].name$, $customers[i].age$ years old

(^ up to t.o.c. )

Performing auxiliary computations along the iteration process

The designer's model:

<script yst="init">
function Book(title, author, price) {
this.title = title;
this.author = author;
this.price = price;
}
books = new Array(); total = 0;
</script>

<script yst="model">
books[0] = new Book('Web Services', 'R. Alonso', 18.8);
books[1] = new Book('JavaScript. The definitive Guide', 'David Flanagan', 22.1);
books[2] = new Book('The Camel Club', 'David Baldacci', 8.49);
books[3] = new Book('Labyrinth', 'Kate Mosse', 5.99);
books[4] = new Book('Dynamic HTML', 'Danny Goodman', 23.8);
</script>

A table of books, with the total price at the bottom. Using non-displayable Yeast expressions we can compute the total.

<table border="1">
<tr><th>Num.</th><th>Title</th><th>Author</th><th>Price ($)</th></tr>
<tr yst="apply" ystSet="books"> <td>$i+1$ of $values.length$</td><td>$e.title$</td> <td>$e.author$</td><td>$e.price$ \$ $# total += e.price$ </td> </tr>
<tr>
<td colspan="3" align="right"><b>Total:</b></td><td yst="value"><b>$total$ \$</b></td>
</tr>
</table>
Num.TitleAuthorPrice ($)
$i+1$ of $values.length$$e.title$ $e.author$$e.price$ \$ $# total += e.price$
Total:$total$ \$

(^ up to t.o.c. )

Iterating over several sets

Remind that you can structure your designer's model as you want. Perhaps, the model for the previous example could have been:

<script yst="init">
  titles = new Array();
  authors = new Array();
  prices = new Array();
</script>
<script yst="model">
titles = ['Web Services', 'JavaScript. The definitive Guide', 'The Camel Club', 'Labyrinth', 'Dynamic HTML'];
authors = ['R. Alonso', 'David Flanagan', 'David Baldacci', 'Kate Mosse', 'Danny Goodman'];
prices = [18.8, 22.1, 8.49, 5.99, 23.8];
</script>

You need to iterate over several sets. One of them must be the main set (titles in the example):

<table border="1">
<tr><th>Title</th><th>Author</th><th>Price ($)</th></tr> <tr yst="apply" ystSet="titles"> <td>$e$</td> <td>$authors[i]$</td> <td>$prices[i]$ \$</td> </tr>
</table>
TitleAuthorPrice ($)
$e$$authors[i]$ $prices[i]$ \$

(^ up to t.o.c. )

Nesting Yeast Elements

You can use the implicit pseudo-variables e, values, i in nested elements.

<script yst="model">
matrix = [[1,0,0,0,0], [0,2,0,0,0], [0,0,3,0,0], [0,0,0,4,0], [0,0,0,0,5]];
</script>
<table border="1">
 <tr yst="apply" ystSet="matrix"> <!-- e represents a matrix row -->
  <td yst="apply" ystSet="e">$e$</td> <!-- now e represents a matrix cell -->
 </tr>
</table>
$e$

Be careful when nesting elements. Pseudo-variables of inner elements hide the pseudo-variables of outer-elements. If you have to refer to outer pseudo-variables you have to store them using non-displayable expressions. This is the case in the following example

<table border="1">
 <tr yst="apply" ystSet="matrix" ystAux="$# i_ext=i$">
  <td yst="apply" ystSet="e">
    <span yst="if" ystTest="i==i_ext"><b>$e$</b></span>
    <span yst="if" ystTest="i!=i_ext">$e$</span>
  </td>
 </tr>
</table>
$e$ $e$

Complex iterations (compApply)

The apply processing instruction operates on a single HTML element. When you need to repeat several elements you have to use compApply instead. A compApply always have a container element in which you specify the elements to repeat. This is the compApply context. All the elements contained in the compApply context must specify the yst="compApply" attribute, but only the first hast to specify the ystSet or ystUpTo attributes. If other elements inside the compApply context does not specify the yst="compApply" they will be moved to the end of the processed block.

Example:

We what to list the news array content placing a <hr/> separator among the news items. The wrong way is using apply:

<div yst="apply" ystSet="news">$i+1$. $e$</div> 
<hr yst="apply" ystSet="news">
$i+1$. $e$

Using complApply, the separator is inserted among the news:

<div>
  <div yst="compApply" ystSet="news">$i+1$. $e$</div> 
<hr yst="compapply"> </div>
$i+1$. $e$

Specifying conditions

You can specify conditions (ystTest) in the elements inside the compApply context, in such a way that, at each iteration step only the elements for which the condition evaluates to true are included in the final result. Imagine that you want to remove the last separator of the above example. You can specify a condition for the <hr/> element:

<div>
  <div yst="compApply" ystSet="news">$i+1$. $e$</div> 
<hr yst="compapply" ystTest="i != values.length-1"> </div>
$i+1$. $e$

Process a subset of the ystSet array

To only show the first two news items:

<div yst="compApply" ystSet="news" ystTest="i<2">$i+1$. $e$</div>
$i+1$. $e$

Supporting different processing options

You can use compApply with conditions in cases where there are different processing options for different elements of the ystSet array, or different values of the iteration counter (ystUpTo).

The example shows a table in which odd and even rows must be in different color.

<table border="1">
<tr> <th>Number</th> <th>Heading</th></tr>
<tr yst="compApply" ystSet="news" ystTest="i%2!=0">
<td><em>$i$</em></td> <td>$e$</td> </tr>
<tr yst="compApply" ystTest="i%2==0" bgcolor="#FFFF99">
<td><em>$i$</em></td> <td>$e$</td> </tr>
</table>
Number Heading
$i$ $e$
$i$ $e$

NOTE: the same visual effect can be obtained without using compApply, but resorting to dynamically determined styles in an apply Yeast element:

<style type="text/css">
.colored {background: #FFFF99;}
</style> <table border="1">
<tr> <th>Number</th> <th>Heading</th></tr>
<tr yst="apply" ystSet="news" class="$i%2==0?'colored':''$">
<td><em>$i$</em></td> <td><b>$e$</b></td></tr>
</table>
Number Heading
$i$ $e$

Other examples

Note that the code of the following examples is more easily developed if ystBool is used to set the checked or selected attributes. The examples are shown only with the intention of demonstration.

<script yst="model">
continents = ['Africa','America','Asia','Europe','Oceania'];
myContinent = 'Europe';
</script>
<select>
<option value="0">- Choose -</option>
<option yst="compApply" ystSet="continents" ystTest="e==myContinent" value="$i$" selected>$e$</option>
<option yst="compApply" ystTest="e!=myContinent" value="$i$">$e$</option>
</select>

<form>
  <label yst="compApply" ystSet="continents" ystTest="e==myContinent">
<input type="radio" name="c" value="$i$" checked>$e$<br/>
</label>
<label yst="compApply" ystTest="e!=myContinent">
<input type="radio" name="c" value="$i$">$e$<br/>
</label>
</form> or <form>
<label yst="apply" ystSet="continents">
<input type="radio" name="c" yst="if" ystTest="e==myContinent" value="$i$" checked>
<input type="radio" name="c" yst="if" ystTest="e!=myContinent" value="$i$">$e$<br/>
</label>
</form>
or

The same examples using ystBool

<form>
  <select>
<option value="0">- Choose -</option>
<option yst="apply" ystSet="continents" ystBool="{selected:e==myContinent}" value="$i$">$e$</option>
</select> <br/> <label yst="apply" ystSet="continents">
<input type="radio" name="c" value="$i$" ystBool="{checked:e==myContinent}">$e$<br/>
</label>
</form>

(^ up to t.o.c. )

Sub-templates

A Yeast sub-template is a piece of Yeast code, or simply HTML code, that once declared can be included as many times as needed in the template document (before or after the template declaration).

Sub-template declaration

Using yst="declare" in a container element. The container element is not part of the sub-template definition. You must assign an identifier to the sub-template (using the id attribute). Sub-templates can accept parameters. To implement parameter Yeast use a new implicit variable called params. This variable is an object that will encapsulate any of the parameters that the template needs. Anywhere a formal parameter must be used, you must place a reference to params.<param_name>.

<div yst="declare" id="combo">
<select yst="value" name="$params.name$">
<option value="0">- Choose one -</option>
<option yst="apply" ystSet="params.options" ystBool="{selected:params.selected == e}" value="$e$">$e$</option>
</select>
</div>

Sub-template inclusion

Use yst="include", select the id of the template to include and provide a params object .

<div yst="include" ystIdRef="combo" 
ystParams="{name:'continent', options:continents, selected:'Europe'}"></div> <div yst="include" ystIdRef="combo"
ystParams="{name:'gender', options:['Male','Female'], selected:null}"
></div>

(^ up to t.o.c. )

Updating template elements

The execution of a script in the page may change the value of data of the template's model. As a result of these changes, certain elements may need to be re-processed.

To reprocess an element, you must assign a unique identifier to it (with the id HTML attribute), and mark it with the attribute yst="live".

<div id=”updatable” yst=”live”>I  am <span yst=”value”>$age$</span> years old.</div>   

Once the script that changes the model data is executed, call the following Yeast API method to reprocess the element:

function change() {
  age = 50;
  YST.Util.updateNode("updatable");
} 

(^ up to t.o.c. )

Yeast and AJAX

See Yeast and AJAX.

(^ up to t.o.c. )