プレゼンテーションパターンカタログ
last update: $Date: 2005-06-29 12:58:35 +0900 (Wed, 29 Jun 2005) $
はじめに
Kwartzは、「プレゼンテーションロジックとプレゼンテーションデータの分離」または「プレゼンテーションロジックの独立」という概念を実現したテンプレートシステムです。 プレゼンテーションロジックとプレゼンテーションデータを分離すると、HTMLデザインをまったく崩すことなく、複雑なプレゼンテーションロジックを利用することができます。 <<<<<<< .mine ======= >>>>>>> .r95
またプレゼンテーションデータとプレゼンテーションロジックとをうまく分離するための、いくつかのパターンが存在します。 これらのパターンを「プレゼンテーションパターン」といいます。
このドキュメントでは、プレゼンテーションパターンを紹介します。
目次
更新履歴
- 2005-06-27
-
- 「Iterate Elementパターン」において出力用スクリプトの間違いを修正([bug:1228301])
- 「Iterate Contentパターン」において<dl></dl>が<ul></ul>となっていたのを修正([bug:1228301])
- 2005-03-21
-
- Kwartzディレクティブについての説明を追加
- すべてのパターンにおいて「説明」「適用場面」「サンプルコード」「補足」の見出しを追加
- 「Replace Element by Valueパターン」の補足を追加
置換
Replace Element by Valueパターン
説明
エレメントを、変数や式の値で置き換えることができます。 これを「Replace Element by Valueパターン」といいます。
適用場面
このパターンは、テキスト中に変数や式の値を出力するときに便利です。
サンプルコード
Hello <span id="mark:user">World</span>!
#user { plogic: { print(username); // エレメントのかわりに変数usernameを出力する } }
### for eRuby Hello <%= username %>! ### for PHP Hello <?php echo $username; ?>! ### for JSTL Hello <c:out value="${username}" escapeXml="false"/>! ### for Velocity Hello $!{username}!
補足
値がnullまたは空文字列のときに、コンテンツテキストをデフォルト値として出力したい場合は次のようにします。 これは「Replace Element by Valueパターン」と「Delete Tagパターン」の組み合わせです。
#user { plogic: { // 変数usernameの値を出力する。 // 値がnullまたは空文字列なら 'guest' と出力する。 if (username == empty) { @cont; // コンテンツテキストを出力する } else { print(username); // 変数の値を出力する } } }
Replace Content by Valueパターン
説明
タグは残したままエレメントの内容だけを式の値で置き換えることができます。 これを「Replace Content by Valueパターン」といいます。
適用場面
エレメントの内容を式の値で置き換える場面は非常に多いため、このパターンはよく使われます。
サンプルコード
<h1 id="mark:title">Example</h1>
#title { plogic: { @stag; print(title); // 内容(@cont)のかわりに変数titleの値を出力する @etag; } }
### for eRuby <h1><%= title %></h1> ### for PHP <h1><?php echo $title; ?></h1> ### for JSTL <h1><c:out value="${title}" escapeXml="false"/></h1> ### for Velocity <h1>$!{title}</h1>
補足
「Replace Content by Valueパターン」は、Kwartzでは次のように書くことができます。
#title { value: title; // 内容のかわりに変数titleの値を出力する }
またディレクティブ「id="value:expression"
」を使うと、
プレゼンテーションデータファイルだけでパターンを使用できます。
<h1 id="value:title">Example</h1>
Replace Element by Elementパターン
説明
エレメントを別のエレメントに交換することができます。 これは「Replace Element by Elementパターン」といいます。
適用場面
このパターンは、ある場所で定義したエレメントを別の場所で再使用するのに便利です。
サンプルコード
<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>
#links2 { plogic: { @element(links); // エレメントlins2をエレメントlinksで置き換える } }
ここで「@element(name)
」は、「id="mark:name"
」や「id="name"
」でマーキングされたエレメントを表しています。
<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>
補足
Kwartzでは、ディレクティブ「id="replace:name"
」を使うと、
プレゼンテーションロジックファイルなしでこのパターンが使用できます。
<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="replace:links"> Home | Document | FAQ </div>
またコマンドラインオプション「-i file,file2,...
」を指定すると、
他のファイルのエレメントを利用できます。
<div id="mark:links"> <a href="/">HOME</a> | <a href="/doc">Document</a> | <a href="/faq">FAQ</a> </div>
<div id="mark:links1"> Home | Document | FAQ </div> <p>Welcome to my Home Page!</p> <div id="mark:links2"> Home | Document | FAQ </div>
#links1 { plogic: { @element(links); } } #links2 { plogic: { @element(links); } }
$ kwartz -l eruby -i links.html -p page.plogic page.html
<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パターン
説明
エレメントの内容を、別のエレメントで置き換えることができます。 これは「Replace Content by Elementパターン」または「Placeholderパターン」といいます。
適用場面
このパターンは、表示するコンテンツと、全体のレイアウトを別にした場合によく利用されます。
サンプルコード
この例では、次のようなファイルを使用します。
- contens.html, contents.plogic - 表示するコンテンツデータを表します。
- layout.html, layout.plogic - 全体のレイアウトを表します。
<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>
#menu { plogic: { @stag; foreach (item in menu_list) { @cont; } @etag; } } #menu_item { value: item['name']; attrs: "href" item['url']; }
<!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© 2004-2005 kuwata-lab.com All Rights Reserverd </td> </tr> </table> </body> </html>
#placeholder_menu { plogic: { @stag; @element(menu); // 内容を別のエレメントで置き換える @etag; } } #placeholder_article { plogic: { @stag; @element(article); // 内容を別のエレメントで置き換える @etag; } }
コンパイルするときには他のファイルのエレメントを読み込むために、
コマンドオプション「-i file1,file2,...
」を指定します。
コンパイル:
$ kwartz -l eruby -i contents.html -p contens.plogic,layout.plogic layout.html
<!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© 2004-2005 kuwata-lab.com All Rights Reserverd </td> </tr> </table> </body> </html>
補足
Kwartzでは、ディレクティブ「id="placeholder:name"
」を使うと、
プレゼンテーションロジックファイル(layout.plogic)なしでこのパターンが使用できます。
プレゼンテーションデータ(layout.html):
: : <!-- menu part --> <td width="100" valign="top"> <div class="menu" id="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="placeholder:article"> aaa<br> bbb<br> ccc<br> ddd<br> </div> </td> : :
削除
Delete Elementパターン
説明
プレゼンテーションロジックの定義を空欄にすると、エレメント全体を出力しないことになります。 これは「Delete Elementパターン」または「Dummy Elementパターン」といいます。
適用場面
このパターンは、プレゼンテーションデータにダミーデータを含めるときに使用します。
サンプルコード
<ul> <li>foo</li> <li id="dummy">bar</li> </ul>
#dummy { plogic: { // empty } }
### for eRuby <ul> <li>foo</li> </ul> ### for PHP <ul> <li>foo</li> </ul> ### for JSTL <ul> <li>foo</li> </ul> ### for Velocity <ul> <li>foo</li> </ul>
補足
Kwartzではディレクティブ「id="dummy:str"
」を使うことで、
プレゼンテーションロジックファイルなしでこのパターンを使用できます。
<ul> <li>foo</li> <li id="dummy:d1">bar</li> </ul>
Delete Tagパターン
説明
プレゼンテーションロジックの定義において、「@cont
」だけを使用し、
「@stag
」と「@stag
」を使わないようにすると、エレメントのタグを削除できます。
これは「Delete Tagパターン」または「Dummy Tagパターン」といいます。
適用場面
このパターンは、ある条件のときだけタグを出力したい場合に使います。
サンプルコード
<a href="..." id="mark:next">Next</a>
#next { attrs: "href" url; plogic: { if (url == null) { @cont; // urlがnullのときはタグを出力しない } else { @stag; @cont; @etag; } } }
### 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> ### for Velocity #if($url) Next#else <a href="$!{url}">Next</a> #end
繰り返し
Iterate Elementパターン
説明
繰り返しの中に「@stag
」と「@cont
」と「@etag
」を含めると、エレメント全体を繰り返すことになります。
これを「Iterate Element」パターンといいます。
適用場面
リストの要素を出力する場面ならどこでも、このパターンが使用できます。
サンプルコード
<table> <tr id="mark:items"> <td>@{item}@</td> </tr> </table>
#items { plogic: { // 開始タグ、内容、終了タグを繰り返す foreach (item in list) { @stag; @cont; @etag; } } }
### for eRuby <table> <% for item in list do %> <tr> <td><%= item %></td> </tr> <% end %> </table> ### for PHP <table> <?php foreach ($list as $item) { ?> <tr> <td><?php echo $item; ?></td> </tr> <?php } ?> </table> ### for JSTL <table> <c:forEach var="item" items="${list}"> <tr> <td><c:out value="${item}" escapeXml="false"/></td> </tr> </c:forEach> </table> ### for Velocity <table> #foreach($item in $list) <tr> <td>$!{item}</td> </tr> #end </table>
補足
Kwartzではディレクティブ「id="foreach:item=list"
」を使うことで、
プレゼンテーションロジックファイルなしでこのパターンを使用できます。
<table> <tr id="foreach:item=list"> <td>@{item}@</td> </tr> </table>
Iterate Contentパターン
説明
繰り返しの中に「@cont
」を含めると、内容だけを繰り返すことになります。
これを「Iterate Content」パターンといいます。
適用場面
これは<dl></dl>の内容だけを繰り返したいときや、テーブルにおいて複数の行を繰り返したい場合に、特に有効です。
サンプルコード
<dl id="mark:items"> <dt>@{item.text}@</dt> <dd>@{item.desc}@</dd> </dl>
#items { plogic: { // 内容だけを繰り返す @stag; foreach (item in list) { @cont; } @etag; } }
### for eRuby <dl> <% for item in list do %> <dt><%= item.text %></dt> <dd><%= item.desc %></dd> <% end %> </dl> ### for PHP <dl> <?php foreach ($list as $item) { ?> <dt><?php echo $item->text; ?></dt> <dd><?php echo $item->desc; ?></dd> <?php } ?> </dl> ### for JSTL <dl> <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> </dl> ### for Velocity <dl> #foreach($item in $list) <dt>$!{item.text}</dt> <dd>$!{item.desc}</dd> #end </dl>
補足
Kwartzではディレクティブ「id="loop:item=list"
」を使うことで、
プレゼンテーションロジックファイルなしでこのパターンを使用できます。
<dl id="loop:item=list"> <dt>@{item.text}@</dt> <dd>@{item.desc}@</dd> </dl>
選択
Select Elementパターン
説明
複数のエレメントからひとつだけを選んで出力する場合は、次のようにします。 これは「Select Elementパターン」といいます。
適用場面
このパターンは、条件に応じて内容を変更したい場合に特に有効です。
サンプルコード
<div id="mark:message"> <span style="color:red" id="mark:error">ERROR!</span> <span style="color:blue" id="mark:warning">Warning:</span> <span style="color:black" id="mark:good">No error.</span> </div>
#message { plogic: { if (status == 'error') { @element(error); // ERROR! } else if (status == 'warning') { @element(warning); // Warning: } else { @element(good); // No error. } } }
### for eRuby <% if status == "error" then %> <span style="color:red">ERROR!</span> <% elsif status == "warning" then %> <span style="color:blue">Warning:</span> <% else %> <span style="color:black">No error.</span> <% end %> ### for PHP <?php if ($status == "error") { ?> <span style="color:red">ERROR!</span> <?php } elseif ($status == "warning") { ?> <span style="color:blue">Warning:</span> <?php } else { ?> <span style="color:black">No error.</span> <?php } ?> ### for JSTL <c:choose><c:when test="${status eq 'error'}"> <span style="color:red">ERROR!</span> </c:when><c:when test="${status eq 'warning'}"> <span style="color:blue">Warning:</span> </c:when><c:otherwise> <span style="color:black">No error.</span> </c:otherwise></c:choose> ### for Velocity #if($status == "error") <span style="color:red">ERROR!</span> #elseif($status == "warning") <span style="color:blue">Warning:</span> #else <span style="color:black">No error.</span> #end
補足
Kwartzではディレクティブ「id="if:condition"
」「id="elseif:condition"
」「id="else:"
」を使うことで、
プレゼンテーションロジックファイルなしでこのパターンを使用できます。
<div> <span style="color:red" id="if:status=='error'">ERROR!</span> <span style="color:blue" id="elseif:status=='warning'">Warning:</span> <span style="color:black" id="else:">No error.</span> </div>
Pick-up Elementパターン
説明
ある特定のエレメントだけを利用するには、利用したいエレメントだけをマーキングし、 プレゼンテーションロジックでそのエレメントだけを利用します。 利用されないエレメントは無視され、出力されません。 これは「Pick-up Elementパターン」といいます。
これは「Dummy Element」パターンと逆の考え方です。 「Dummy Element」パターンでは不要なエレメントをマーキングして削除することで必要なものだけを残しますが、 「Pick-up Element」パターンでは必要なエレメントだけマーキングして取り出すことで不要なものを削除します。
適用場面
このパターンは、ダミーデータが多い場合に使われます。
サンプルコード
<html> <body> <div id="breadcrumbs"> <a href="/" id="mark:crumb">Home</a> <span id="mark:separator">></span> <a href="/aaa/">AAA</a> < <a href="/aaa/bbb/">BBB</a> &lgt; <a href="/aaa/bbb/ccc">CCC</a> &lgt; <strong id="mark:title">@{title}@</strong> </div> </body> </html>
#breadcrumbs { plogic: { foreach (item in list) { @element(crumb); // print <a>...</a> @element(separator); // print '>' } @element(title); // print <b>title</b> } } #crumb { value: item['name']; attrs: "href" item['path']; } #title { value: title; }
### for eRuby <html> <body> <% for item in list do %> <a href="<%= item["path"] %>"><%= item["name"] %></a> > <% end %> <strong><%= title %></strong> </body> </html> ### for PHP <html> <body> <?php foreach ($list as $item) { ?> <a href="<?php echo $item["path"]; ?>"><?php echo $item["name"]; ?></a> > <?php } ?> <strong><?php echo $title; ?></strong> </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> > </c:forEach> <strong><c:out value="${title}" escapeXml="false"/></strong> </body> </html> ### for Velocity <html> <body> #foreach($item in $list) <a href="$!{item["path"]}">$!{item["name"]}</a> > #end <strong>$!{title}</strong> </body> </html>
Extract Elementパターン
説明
プレゼンテーションデータ全体から、ある特定のエレメントだけを抽出し、 ほかは一切表示しないようにすることができます。 このパターンは「Extract Elementパターン」といいます。
適用場面
このパターンを使うと、HTMLデータの一部だけを取り出し、部品化することができます。
サンプルコード
次の例では、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© 2004-2005 kuwata-lab. All Rights Reserved. </div> </body> </html>
#whole { // 全体を表すエレメントwholeを、抽出したいエレメントで置き換える plogic: { @element(copyright); } }
#whole { // 全体を表すエレメントwholeを、抽出したいエレメントで置き換える plogic: { @element(tablist); } } #tabs { plogic: { @stag; foreach (tab in tablist) { klass = current_tabname == tab['name'] ? 'selected' : ''; @element(tab); } @etag; } } #tab { value: tab['name']; attrs: "href" tab['href'], "class" klass; }
#whole { // 全体を表すエレメントwholeを、抽出したいエレメントで置き換える plogic: { @element(menulist); } } #menus { plogic: { @stag; foreach (menu in menulist) { @element(menu); @element(menu_separator); } @etag; } } #menu { value: menu['name']; attrs: "href" menu['cgipath'], "class" klass; plogic: { klass = current_menu == menu['name'] ? 'selected' : ''; @stag; @cont; @etag; } }
### 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
### for eRuby <div align="center" class="copyright"> Copyright© 2004-2005 kuwata-lab. All Rights Reserved. </div> ### for PHP <div align="center" class="copyright"> Copyright© 2004-2005 kuwata-lab. All Rights Reserved. </div>
### 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>
### 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>
補足
Kwartzでは、コマンドラインオプション「--extract=name
」でも、name
でマーキングされたエレメントを抽出できます。