Presentation Pattern Catalog

Makoto Kuwata <kwa(at)kuwata-lab.com>
last update: $Date: 2005-02-19 23:59:52 +0900 (Sat, 19 Feb 2005) $

Preface

Kwartz is the template system which realized the concept of 'Separation of Presentation Logic and Presentation Data (SoPL/PD).' SoPL/PD enables to use complex presentation logics without breaking HTML design at all.

There are several patterns which help you to separate presentation logic and presentation data well. These patterns are called 'Presentation Patterns.'

This document shows Presentation Patterns.

Table of Contents



Replacement

Replace Element by Value Pattern

You can replace the element with the value of a variable or an expression. This is named 'Replace Element by Value Pattern.'

Presentation Data:

Hello <span id="mark:user">World</span>!

Presentation Logic:

#user {
  plogic: {
    print(username);  // print value of variable 'username' instead of the element
  }
}

Output Script:

### for eRuby
Hello<%= username %>!

### for PHP
Hello<?php echo $username; ?>!

### for JSTL
Hello<c:out value="${username}" escapeXml="false"/>!

Replace Content by Value Pattern

You can also replace only the content of the element in the same way. This is named 'Replace Content by Value Pattern.'

Presentation Data:

<h1 id="mark:title">Example</h1>

Presentation Logic:

#title {
  plogic: {
    @stag;
    print(title);  // print value of a variable 'title' instead of content
    @etag;
  }
}

Output Script:

### for eRuby
<h1><%= title %></h1>

### for PHP
<h1><?php echo $title; ?></h1>

### for JSTL
<h1><c:out value="${title}" escapeXml="false"/></h1>

The 'Replace Content by Value Pattern' is to be described as the following in Kwartz.

Presentation Logic:

#title {
  value: title;  // print value of a variable 'title' instead of content
}

Replace Element by Element Pattern

You can replace the element by other element. This pattern is named 'Replace Element by Element Pattern.'

This pattern is very useful to reuse the element in other place.

Presentation Data:

<div id="mark:links">
 <a href="/">HOME</a> | <a href="/doc">Document</a> | <a href="/faq">FAQ</a>
</div>

<p>Welcome to my Home Page!</p>

<div id="mark:links2">
  Home | Document | FAQ
</div>

Presentation Logic:

#links2 {
  plogic: {
    @element(links);  // replace the element 'links2' by the element 'links'
  }
}

@element(name) represents the element which is marked by id="mark:name" or id="name".

Output Script:

<div>
 <a href="/">HOME</a> | <a href="/doc">Document</a> | <a href="/faq">FAQ</a>
</div>

<p>Welcome to my Home Page!</p>

<div>
 <a href="/">HOME</a> | <a href="/doc">Document</a> | <a href="/faq">FAQ</a>
</div>

In Kwartz, Command-line option '-i file,file2,...' enables you to use elements which are described in other files.

Presentation Data(links.html):

<div id="mark:links">
 <a href="/">HOME</a> | <a href="/doc">Document</a> | <a href="/faq">FAQ</a>
</div>

Presentation Data(page.html):

<div id="mark:links1"> Home | Document | FAQ </div>

<p>Welcome to my Home Page!</p>

<div id="mark:links2"> Home | Document | FAQ </div>

Presentation Logic(page.plogic):

#links1 {
  plogic: {
    @element(links);
  }
}
#links2 {
  plogic: {
    @element(links);
  }
}

Compile:

$ kwartz -l eruby -i links.html -p page.plogic page.html

Output Script:

<div>
 <a href="/">HOME</a> | <a href="/doc">Document</a> | <a href="/faq">FAQ</a>
</div>

<p>Welcome to my Home Page!</p>

<div>
 <a href="/">HOME</a> | <a href="/doc">Document</a> | <a href="/faq">FAQ</a>
</div>

Replace Content by Element Pattern

You can replace content of an element by other element. This pattern is named 'Replace Content by Element Pattern' or 'Placeholder Pattern.'

This pattern is very useful to import elements marked in other presentation data files.

Presentation Data(contents.html):

<html>
  <body>
    
    <p>menu:</p>
    <ul id="mark:menu">
      <li><a href="..." id="mark:menu_item">menu1</a></li>
    </ul>

    <p>article:</p>
    <div id="mark:article">
      <h2>What is Kwartz?</h2>
      <p>Kwartz is a template system, which realized the
         concept <strong>`Separation of Presentation Logic
         and Presentation Data'(SoPL/PD)</strong>.
      </p>
    </div>
    
  </body>
</html>

Presentation Logic(contents.plogic):

#menu {
  plogic: {
    @stag;
    foreach (item in menu_list) {
      @cont;
    }
    @etag;
  }
}

#menu_item {
  value: item['name'];
  attr:  "href" item['url'];
}

Presentation Data(layout.html):

<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="en">
  <head>
    <title id="value:title">...title...</title>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <link rel="stylesheet" type="text/css" href="design.css">
  </head>
  <body>

    <table border="0">
      <tr>
        
        <!-- menu part -->
        <td width="100" valign="top">
          <div class="menu" id="mark:placeholder_menu">
            <ul>
              <li>menu1</li>
              <li>menu2</li>
              <li>menu3</li>
            </ul>
          </div>
        </td>
        
        <!-- article part -->
        <td width="400" valign="top">
          <div class="article" id="mark:placeholder_article">
            aaa<br>
            bbb<br>
            ccc<br>
            ddd<br>
          </div>
        </td>
        
      </tr>

      <!-- footer part -->
      <tr>
        <td colspan="2" class="copyright">
          copyright&copy; 2004-2005 kuwata-lab.com All Rights Reserverd
        </td>
      </tr>
    </table>
    
  </body>
</html>

Presentation Logic(layout.plogic):

#placeholder_menu {
  plogic: {
    @stag;
    @element(menu);   // replace content by other element
    @etag;
 }
}

#placeholder_article {
  plogic: {
    @stag;
    @element(article);   // replace content by other element
    @etag;
  }
}

In Kwartz, the command-line option -i file1,file2,... enables to import elements which are defined in other files.

Compile:

$ kwartz -l eruby  -i contents.html -p contens.plogic,layout.plogic layout.html

Output Script:

<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="en">
  <head>
    <title><%= title %></title>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <link rel="stylesheet" type="text/css" href="design.css">
  </head>
  <body>

    <table border="0">
      <tr>
        
        <!-- menu part -->
        <td width="100" valign="top">
          <div class="menu">
    <ul>
<% for item in menu_list do %>
      <li><a href="<%= item["url"] %>"><%= item["name"] %></a></li>
<% end %>
    </ul>
          </div>
        </td>
        
        <!-- article part -->
        <td width="400" valign="top">
          <div class="article">
    <div>
      <h2>What is Kwartz?</h2>
      <p>Kwartz is a template system, which realized the
         concept <strong>`Separation of Presentation Logic
         and Presentation Data'(SoPL/PD)</strong>.
      </p>
    </div>
          </div>
        </td>
        
      </tr>

      <!-- footer part -->
      <tr>
        <td colspan="2" class="copyright">
          copyright&copy; 2004-2005 kuwata-lab.com All Rights Reserverd
        </td>
      </tr>
    </table>
    
  </body>
</html>


Deletion

Delete Element Pattern

If presentation logic is empty, the element is not printed out. This pattern is named 'Delete Element Pattern' or 'Dummy Element Pattern.'

This pattern enables you to use dummy data in presentation data.

Presentation Data:

<ul>
  <li>foo</li>
  <li id="dummy">bar</li>
</ul>

Presentation Logic:

#dummy {
  plogic: {
    // empty
  }
}

Output Script:

### for eRuby
<ul>
  <li>foo</li>
</ul>

### for PHP
<ul>
  <li>foo</li>
</ul>

### for JSTL
<ul>
  <li>foo</li>
</ul>

Delete Tag Pattern

If you use only @cont and don't use @stag and @cont, you can remove start and end tags of the element. This pattern is named 'Delete Tag Pattern' or 'Dummy Tag Pattern.'

This pattern is very useful if you want to print tags according to condition.

Presentation Data:

<a href="@{url}@" id="mark:next">Next</a>

Presentation Logic:

#next {
  plogic: {
    if (url == null) {
      @cont;   // don't print tags
    } else {
      @stag;
      @cont;
      @etag;
    }
  }
}

Output Script:

### for eRuby
<% if url == nil then %>
Next<% else %>
<a href="<%= url %>">Next</a>
<% end %>

### for PHP
<?php if ($url == NULL) { ?>
Next<?php } else { ?>
<a href="<?php echo $url; ?>">Next</a>
<?php } ?>

### for JSTL
<c:choose><c:when test="${url eq null}">
Next</c:when><c:otherwise>
<a href="<c:out value="${url}" escapeXml="false"/>">Next</a>
</c:otherwise></c:choose>


Iteration

Iterate Element Pattern

Iteration which contains @stag, @cont, and @etag represents to iterate the element. This pattern is named 'Iterate Element' pattern.

Presentation Data:

<table>
  <tr id="mark:items">
   <td>@{item}@</td>
  </tr>
</table>

Presentation Logic:

#items {
  plogic: {
    // iterate start tag, content, and end tag
    foreach (item in list) {
      @stag;
      @cont;
      @etag;
    }
  }
}

Output Script:

### for eRuby
<ul>
<% for item in list do %>
  <dt><%= item.text %></dt>
  <dd><%= item.desc %></dd>
<% end %>
</ul>

### for PHP
<ul>
<?php foreach ($list as $item) { ?>
  <dt><?php echo $item->text; ?></dt>
  <dd><?php echo $item->desc; ?></dd>
<?php } ?>
</ul>

### for JSTL
<ul>
<c:forEach var="item" items="${list}">
  <dt><c:out value="${item.text}" escapeXml="false"/></dt>
  <dd><c:out value="${item.desc}" escapeXml="false"/></dd>
</c:forEach>
</ul>

Iterate Content Pattern

Iteration which contains only @cont represents to iterate the content. This pattern is named 'Iterate Content' pattern.

This pattern is very useful when creating <dl></dl> list.

Presentation Data:

<ul id="mark:items">
  <dt>@{item.text}@</dt>
  <dd>@{item.desc}@</dd>
</ul>

Presentation Logic:

#items {
  plogic: {
    // iterate only content
    @stag;
    foreach (item in list) {
      @cont;
    }
    @etag;
  }
}

Output Script:

### for eRuby
<ul>
<% for item in list do %>
  <dt><%= item.text %></dt>
  <dd><%= item.desc %></dd>
<% end %>
</ul>

### for PHP
<ul>
<?php foreach ($list as $item) { ?>
  <dt><?php echo $item->text; ?></dt>
  <dd><?php echo $item->desc; ?></dd>
<?php } ?>
</ul>

### for JSTL
<ul>
<c:forEach var="item" items="${list}">
  <dt><c:out value="${item.text}" escapeXml="false"/></dt>
  <dd><c:out value="${item.desc}" escapeXml="false"/></dd>
</c:forEach>
</ul>


Selection

Select Element Pattern

The following is an example to choose a certain element from some elements. This pattern is named 'Select Element Pattern.'

Presentation Data:

<div id="mark:message">
  <font color="red"   id="mark:error">ERROR!</font>
  <font color="blue"  id="mark:warning">Warning:</font>
  <font color="black" id="mark:good">No error.</font>
</div>

Presentation Logic:

#message {
  plogic: {
    if (status == 'error') {
      @element(error);      // ERROR!
    } else if (status == 'warning') {
      @element(warning);    // Warning:
    } else {
      @element(good);       // No error.
    }
  }
}

Output Script:

### for eRuby
<% if status == "error" then %>
  <font color="red">ERROR!</font>
<% elsif status == "warning" then %>
  <font color="blue">Warning:</font>
<% else %>
  <font color="black">No error.</font>
<% end %>

### for PHP
<?php if ($status == "error") { ?>
  <font color="red">ERROR!</font>
<?php } elseif ($status == "warning") { ?>
  <font color="blue">Warning:</font>
<?php } else { ?>
  <font color="black">No error.</font>
<?php } ?>

### for JSTL
<c:choose><c:when test="${status eq 'error'}">
  <font color="red">ERROR!</font>
</c:when><c:when test="${status eq 'warning'}">
  <font color="blue">Warning:</font>
</c:when><c:otherwise>
  <font color="black">No error.</font>
</c:otherwise></c:choose>

Pick-up Element Pattern

If you want to use certain elemnts, do marking the elements and use only them in presentation logic. Elements which are not marked are ignored and not printed. This pattern is named 'Pick-up Element Pattern.'

'Pick-up Element' pattern is opposite of 'Dummy Element' pattern. In 'Dummy Element' pattern, dummy elements are marked and removed so that necessary elements are leaved. In 'Pick-up Element' pattern, necessary elements are marked and leaved so that dummy elements are removed.

Presentation Data:

<html>
  <body>
    <div id="breadcrumbs">
      <a href="@{item['path']}@" id="mark:crumb">@{item['name']}@</a>
      <span id="mark:separator">&gt;</span>
      <a href="/aaa/">AAA</a> &lt;
      <a href="/aaa/bbb/">BBB</a> &lgt;
      <a href="/aaa/bbb/ccc">CCC</a> &lgt;
      <b id="mark:title">@{title}@</b>
    </div>
  </body>
</html>

Presentation Logic:

#breadcrumbs {
  plogic: {
    foreach (item in list) {
      @element(crumb);          // print <a>...</a>
      @element(separator);      // print '&gt;'
    }
    @element(title);            // print <b>title</b>
  }
}

Output Script:

### for eRuby
<html>
  <body>
<% for item in list do %>
      <a href="<%= item["path"] %>"><%= item["name"] %></a>
      &gt;
<% end %>
      <b><%= title %></b>
  </body>
</html>

### for PHP
<html>
  <body>
<?php foreach ($list as $item) { ?>
      <a href="<?php echo $item["path"]; ?>"><?php echo $item["name"]; ?></a>
      &gt;
<?php } ?>
      <b><?php echo $title; ?></b>
  </body>
</html>

### for JSTL
<html>
  <body>
<c:forEach var="item" items="${list}">
      <a href="<c:out value="${item['path']}" escapeXml="false"/>"><c:out value="${item['name']}" escapeXml="false"/></a>
      &gt;
</c:forEach>
      <b><c:out value="${title}" escapeXml="false"/></b>
  </body>
</html>

The above example should be described as following.

Presentation Data:

<html>
  <body>
    <div id="breadcrumbs">
      <a href="/" id="mark:crumb">Home</a>
      <span id="mark:separator">&gt;</span>
      <a href="/aaa/">AAA</a> &lt;
      <a href="/aaa/bbb/">BBB</a> &lgt;
      <a href="/aaa/bbb/ccc">CCC</a> &lgt;
      <b id="mark:title">Page Title</b>
    </div>
  </body>
</html>

Presentation Logic:

#breadcrumbs {
  plogic: {
    foreach (item in list) {
      @element(crumb);          // print <a>...</a>
      @element(separator);      // print '&gt;'
    }
    @element(title);            // print <b>title</b>
  }
}
#crumb {
  value: item['name'];
  attr:  "href" item['path'];
}
#title {
  value: title;
}

Extract Element Pattern

It is able to extract a certain element form the whole presentation data. Other element and text strings are not printed. This pattern is named 'Extract Element Pattern.'

This pattern is very useful to extract HTML fragments and make them libraries. The following is an example to extract the HTML fragments 'tablist', 'menulist', and 'copyright' and generates the output scripts for them.

Presentation Data (design.html):

<html id="mark:whole">
  <head>
    <title>Design Examples</title>
    <link rel="stylesheet" href="design.css" type="text/css">
  </head>
  <body>

    <div id="mark:tablist">
      <div class="tabs" id="mark:tabs">
        <a href="/" class="" id="mark:tab">Home</a>
        <a href="/product/" class="selected">Product</a>
        <a href="/download/" class="">Download</a>
        <a href="/support/" class="">Support</a>
      </div>
      <div class="tabsline">
      </div>
    </div>

    <br>

    <div id="mark:menulist">
      <span class="menu_title" id="value:menu_title">MenuList</span>
      <div class="menus" id="mark:menus">
        <a href="/cgi-bin/email.cgi" class="" id="mark:menu">E-Mail</a>
        <span id="mark:menu_separator"><br></span>
        <a href="/cgi-bin/board.cgi" class="selected">MesgBoard</a><br>
        <a href="/cgi-bin/photo.cgi" class="">PhotoAlbum</a><br>
        <a href="/cgi-bin/greeting.cgi" class="">GreetingCard</a><br>
      </div>
    </div>
    <br>
      
    <p> ..... </p>
    <p> ..... </p>
    <p> ..... </p>
    
    <div align="center" class="copyright" id="mark:copyright">
      Copyright&copy; 2004-2005 kuwata-lab. All Rights Reserved.
    </div>
    
  </body>
</html>

Presentation Logic (copyright.plogic):

#whole {
  // replace the element 'whole' with the element you want to extract
  plogic: {
    @element(copyright);
  }
}

Presentation Logic (tablist.plogic):

#whole {
  // replace the element 'whole' with the element you want to extract
  plogic: {
    @element(tablist);
  }
}

#tabs {
  plogic: {
    @stag;
    foreach (tab in tablist) {
      klass = current_tabname == tab['name'] ? 'selected' : '';
      @element(tab);
    }
    @etag;
  }
}

#tab {
  value: tab['name'];
  attr:  "href" tab['href'], "class" klass;
}

Presentation Logic (menulist.plogic):

#whole {
  // replace the element 'whole' with the element you want to extract
  plogic: {
    @element(menulist);
  }
}

#menus {
  plogic: {
    @stag;
    foreach (menu in menulist) {
      @element(menu);
      @element(menu_separator);
    }
    @etag;
  }
}

#menu {
  value:  menu['name'];
  attr:   "href" menu['cgipath'], "class" klass;
  plogic: {
    klass = current_menu == menu['name'] ? 'selected' : '';
    @stag;
    @cont;
    @etag;
  }
}

Compile:

### copyright
$ kwartz -l eruby -p copyright.plogic design.pdata
$ kwartz -l php   -p copyright.plogic design.pdata

### tablist
$ kwartz -l eruby -p tablist.plogic   design.pdata
$ kwartz -l php   -p tablist.plogic   design.pdata

### menulist
$ kwartz -l eruby -p menulist.plogic  design.pdata
$ kwartz -l php   -p menulist.plogic  design.pdata

Output Script:

### for eRuby
    <div align="center" class="copyright">
      Copyright&copy; 2004-2005 kuwata-lab. All Rights Reserved.
    </div>

### for PHP
    <div align="center" class="copyright">
      Copyright&copy; 2004-2005 kuwata-lab. All Rights Reserved.
    </div>

Output Script:

### for eRuby
    <div>
      <div class="tabs">
<% for tab in tablist do %>
<%   klass = current_tabname == tab["name"] ? "selected" : "" %>
        <a href="<%= tab["href"] %>" class="<%= klass %>"><%= tab["name"] %></a>
<% end %>
      </div>
      <div class="tabsline">
      </div>
    </div>

### for PHP
    <div>
      <div class="tabs">
<?php foreach ($tablist as $tab) { ?>
<?php   $klass = $current_tabname == $tab["name"] ? "selected" : ""; ?>
        <a href="<?php echo $tab["href"]; ?>" class="<?php echo $klass; ?>"><?php echo $tab["name"]; ?></a>
<?php } ?>
      </div>
      <div class="tabsline">
      </div>
    </div>

Output Script:

### for eRuby
    <div>
      <span class="menu_title"><%= menu_title %></span>
      <div class="menus">
<% for menu in menulist do %>
<%   klass = current_menu == menu["name"] ? "selected" : "" %>
        <a href="<%= menu["cgipath"] %>" class="<%= klass %>"><%= menu["name"] %></a>
        <br>
<% end %>
      </div>
    </div>

### for PHP
    <div>
      <span class="menu_title"><?php echo $menu_title; ?></span>
      <div class="menus">
<?php foreach ($menulist as $menu) { ?>
<?php   $klass = $current_menu == $menu["name"] ? "selected" : ""; ?>
        <a href="<?php echo $menu["cgipath"]; ?>" class="<?php echo $klass; ?>"><?php echo $menu["name"]; ?></a>
        <br>
<?php } ?>
      </div>
    </div>

The command-line option --extract=name extracts the element marked with name name.