With Layout
In this example we show 3 pages that have the same layout: a gray margin, a title, this text,
a menu, and the page's content. The Tapestry way to output all that stuff is to write a
component to do it and use that component as your page's outermost tag. In this example the
component is called together/Layout1 and you can see it being used in the outermost
tag of all 3 pages.
|
Create...
|
|
Review
| Id: |
4 |
| Version: |
7 |
| Name: |
test Bandaa |
| Region: |
East Coast |
| Start Date: |
29/02/2008 |
|
Home
Persons.tml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- We need a doctype to allow us to use special characters like
We use a "strict" DTD to make IE follow the alignment rules. -->
<html t:type="together/Layout1" t:title="literal:With Layout: Filter CRUD" t:chosenOption="literal:Filter CRUD"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd" xmlns:p="tapestry:parameter">
<t:remove>
<!-- At runtime the stylesheet will be provided by the Layout. The link here is only to enable preview. -->
<link rel="stylesheet" type="text/css" href="../../../../css/together/layout1.css"/>
</t:remove>
<a t:type="eventLink" t:event="toCreate" href="#">Create...</a><br/>
<table id="listAndEditor">
<tbody>
<tr>
<!-- This is the left side of the table: a list of Persons -->
<td id="listCell">
<div id="personFilter">
<form t:type="form" t:id="filterForm">
<div>
Person
</div>
<div>
<input t:id="partialName" t:type="TextField" size="15" t:validate="maxLength=15"/>
<input type="submit" value="Filter" title="Filter"/>
</div>
</form>
</div>
<div id="personList">
<table t:type="grid" t:id="list" t:source="listPersons" t:row="listPerson"
t:exclude="id,version,firstName,lastName,region,startDate" t:add="name"
t:rowsPerPage="4" t:pagerPosition="bottom"
t:class="personGrid" t:empty="block:emptyPersons">[Grid here]
<p:nameCell>
<a t:type="eventLink" t:event="selected" t:context="listPerson.id"
class="prop:linkCSSClass" href="#">
${listPerson.firstName} ${listPerson.lastName}
</a>
</p:nameCell>
</table>
</div>
<t:block t:id="emptyPersons">
<div id="noPersons">
(No persons found)
</div>
</t:block>
</td>
<!-- This is the right side of the table: where a Person will be created, reviewed, or updated. -->
<td id="editorCell">
<t:if test="modeCreate">
<h1>Create</h1>
<form t:type="CustomForm" t:id="createForm" >
<t:errors/>
<table>
<tr>
<th><t:label for="firstName"/>:</th>
<td><input t:type="TextField" t:id="firstName" value="editorPerson.firstName"
t:validate="required, maxlength=10" size="10"/></td>
<td>(required)</td>
</tr>
<tr class="err">
<th></th>
<td colspan="2"><t:CustomError for="firstName"/></td>
</tr>
<tr>
<th><t:label for="lastName"/>:</th>
<td><input t:type="TextField" t:id="lastName" t:clientid="clastname"
value="editorPerson.lastName" t:validate="required, maxlength=10"
size="10"/></td>
<td>(required)</td>
</tr>
<tr class="err">
<th></th>
<td colspan="2"><t:CustomError for="lastName"/></td>
</tr>
<tr>
<th><t:label for="region"/>:</th>
<td><input t:type="Select" t:id="region" value="editorPerson.region"
t:validate="required" t:blankOption="ALWAYS"/></td>
<td>(required)</td>
</tr>
<tr class="err">
<th></th>
<td colspan="2"><t:CustomError for="region"/></td>
</tr>
<tr>
<th><t:label for="startDate"/>:</th>
<td><input t:type="DateField" t:id="startDate" t:clientid="cstartdate"
value="editorPerson.startDate" t:format="prop:dateFormat"
t:validate="required" size="10"/></td>
<td>(required, ${datePattern})</td>
</tr>
<tr class="err">
<th></th>
<td colspan="2"><t:CustomError for="startDate"/></td>
</tr>
</table>
<div class="buttons">
<a t:type="eventLink" t:event="cancelCreate" href="#">Cancel</a>
<input type="submit" value="Save"/>
</div>
</form>
</t:if>
<t:if test="modeReview">
<h1>Review</h1>
<t:if test="editorPerson">
<div t:type="if" t:test="deleteMessage" class="error">
${deleteMessage}
</div>
<table>
<tr>
<th>Id:</th>
<td>${editorPerson.id}</td>
</tr>
<tr>
<th>Version:</th>
<td>${editorPerson.version}</td>
</tr>
<tr>
<th>Name:</th>
<td>${editorPerson.firstName} ${editorPerson.lastName}</td>
</tr>
<tr>
<th>Region:</th>
<td>${editorPersonRegion}</td>
</tr>
<tr>
<th>Start Date:</th>
<td><t:output value="editorPerson.startDate" format="prop:dateFormat"/></td>
</tr>
</table>
<div class="buttons">
<a t:type="eventLink" t:event="toUpdate" t:context="editorPerson.id" href="#">Update...</a>
<a t:type="eventLink" t:event="delete" t:context="[editorPerson.id,editorPerson.version]" href="#"
t:mixins="Confirm" t:message="Delete ${editorPerson.firstName} ${editorPerson.lastName}?">Delete...</a>
</div>
</t:if>
<t:if negate="true" test="editorPerson">
Person ${editorPersonId} does not exist.<br/><br/>
</t:if>
</t:if>
<t:if test="modeUpdate">
<h1>Update</h1>
<form t:type="CustomForm" t:id="updateForm">
<t:errors/>
<t:if test="editorPerson">
<!-- If optimistic locking is not needed then comment out this next line. It works because Hidden fields are part of the submit. -->
<t:hidden value="editorPerson.version"/>
<table>
<tr>
<th><t:label for="updFirstName"/>:</th>
<td><input t:type="TextField" t:id="updFirstName" value="editorPerson.firstName"
t:validate="required, maxlength=10" size="10"/></td>
<td>(required)</td>
</tr>
<tr class="err">
<th></th>
<td colspan="2"><t:CustomError for="updFirstName"/></td>
</tr>
<tr>
<th><t:label for="updLastName"/>:</th>
<td><input t:type="TextField" t:id="updLastName" value="editorPerson.lastName"
t:validate="required, maxlength=10" size="10"/></td>
<td>(required)</td>
</tr>
<tr class="err">
<th></th>
<td colspan="2"><t:CustomError for="updLastName"/></td>
</tr>
<tr>
<th><t:label for="updRegion"/>:</th>
<td><input t:type="Select" t:id="updRegion" value="editorPerson.region" t:validate="required"/></td>
<td>(required)</td>
</tr>
<tr class="err">
<th></th>
<td colspan="2"><t:CustomError for="updRegion"/></td>
</tr>
<tr>
<th><t:label for="updStartDate"/>:</th>
<td><input t:type="DateField" t:id="updStartDate" value="editorPerson.startDate"
t:format="prop:dateFormat" t:validate="required" size="10"/></td>
<td>(required, ${datePattern})</td>
</tr>
<tr class="err">
<th></th>
<td colspan="2"><t:CustomError for="updStartDate"/></td>
</tr>
</table>
<div class="buttons">
<a t:type="eventLink" t:event="cancelUpdate" t:context="editorPerson.id" href="#">Cancel</a>
<input t:type="submit" value="Save"/>
</div>
</t:if>
<t:if negate="true" test="editorPerson">
Person ${editorPersonId} does not exist.<br/><br/>
</t:if>
</form>
</t:if>
</td>
</tr>
</tbody>
</table>
<a t:type="pageLink" t:page="Index" href="#">Home</a><br/><br/>
<t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/pages/together/withlayout/filtercrud/Persons.tml"/>
<t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/components/together/Layout1.tml"/>
<t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/components/together/Layout1.java"/>
<t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/css/together/layout1.css"/>
<t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/model/Menu.java"/>
<t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/model/MenuOption.java"/>
</html>
Layout1.tml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- We need a doctype to allow us to use special characters like
We use a "strict" DTD to make IE follow the alignment rules. -->
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
<head>
<title>${title}</title>
<link rel="stylesheet" type="text/css" href="${context:css/together/layout1.css}"/>
</head>
<body>
<table id="page">
<tr>
<td id="top">
<div id="banner">
<h1>With Layout</h1>
<div class="bannerText">
In this example we show 3 pages that have the same layout: a gray margin, a title, this text,
a menu, and the page's content. The Tapestry way to output all that stuff is to write a
component to do it and use that component as your page's outermost tag. In this example the
component is called <em>together/Layout1</em> and you can see it being used in the outermost
tag of all 3 pages.<br/>
</div><br/>
</div>
<!-- Menu style is based on an example at http://www.dynamicdrive.com/dynamicindex1/ddtabmenu.htm -->
<div id="menubar">
<ul>
<li t:type="Loop" t:source="menu.menuoptions" t:value="menuoption">
<a t:type="pagelink" t:page="prop:menuoption.page" class="prop:menuOptionCSSClass">
<span>${menuoption.label}</span>
</a>
</li>
</ul>
</div>
<div id="menubarline"/>
</td>
</tr>
<tr>
<td id="content">
<!-- t:body is a directive that says "output the content that I surround". -->
<t:body/>
</td>
</tr>
</table>
</body>
</html>
Layout1.java
package jumpstart.web.components.together;
import jumpstart.web.annotation.ProtectedPage;
import jumpstart.web.model.Menu;
import jumpstart.web.model.MenuOption;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Property;
@ProtectedPage
public class Layout1 {
private static final String CHOSEN_OPTION_CSS_CLASS = "chosenOption";
// Parameters
@Parameter
@Property
private String title;
@Parameter
@Property
private String chosenOption;
// Screen fields
private Menu menu;
@Property
private MenuOption menuOption;
// The code
public Menu getMenu() {
if (menu == null) {
menu = new Menu();
menu.add(new MenuOption("Hello World", "together/withlayout/HelloWorld"));
menu.add(new MenuOption("Filter CRUD", "together/withlayout/filtercrud/Persons"));
menu.add(new MenuOption("Components CRUD", "together/withlayout/componentscrud/Persons"));
}
return menu;
}
public String getMenuOptionCSSClass() {
return menuOption.getLabel().equals(chosenOption) ? CHOSEN_OPTION_CSS_CLASS : "";
}
}
layout1.css
body, td { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; color: #333;
line-height: 17px; max-width: 1000px; }
.eg { margin: 20px 0; padding: 20px;
border: 1px solid #ddd; border-radius: 4px; -webkit-border-radius: 4px; -mox-border-radius: 4px; }
a { text-decoration: none; color: #3D69B6; }
a:hover { text-decoration: underline; }
table { border-collapse: collapse; border-spacing: 0; }
:root table { border-collapse: separate; } /* Firefox 3 */
th, td { padding: 0; }
form { margin-bottom: 0; } /* IE 7 */
/***************
* Layout elements
***************/
#page { margin: 10px; background-color: white; }
#top { width: 100%; background-color: #eee; padding-top: 0px; }
#banner { background-color: #eee; padding: 0px 10px 10px 10px; }
.bannerText { max-width: 800px; }
/* Based on example 4 at http://www.dynamicdrive.com/dynamicindex1/ddtabmenu.htm minus the images that give rounded corners */
#menubar { padding: 0; width: 100%; background-color: transparent; voice-family: "\"}\""; voice-family: inherit; }
#menubar ul { font: normal 11px Arial, Verdana, sans-serif; margin:0; padding:0; list-style:none; }
#menubar li { display:inline; margin:0 2px 0 0; padding:0; }
#menubar a { float:left; color: white; background: #3d69b6; margin:0 2px 0 0;
padding:0 0 1px 3px; text-decoration:none; letter-spacing: 1px; }
#menubar a span { float:none; display:block; background: transparent; padding: 6px 8px 3px 7px; }
#menubar a:hover { background-color: #8cb85c; }
#menubar a:hover span { background-color: #8cb85c; }
#menubar a.chosenOption, #menubar a.chosenOption span { /*currently selected tab*/ background-color: #809FFF; }
#menubarline { clear: both; padding: 0; width: 100%; height: 8px; line-height: 8px; background: #809FFF;
border-top: 1px solid #fff; /*Remove this to remove border between bar and tabs*/ }
#content { width: 100%; background-color: white; margin: 0; padding: 10px; }
/***************
* Page body elements
***************/
#listAndEditor { width: 800px; border: none; margin: 10px 0; }
#listCell { width: 25%; border: 1px solid white; background-color: #eee; vertical-align: top; }
#personFilter { width: 100%; padding: 5px 0 10px 0; text-align: center; vertical-align: middle;
background-color: #3d69b6; color: white; font-weight: bold; border: 1px solid white; }
/* Add some padding around the list so that we can see the yellow flash when "Highlight zone updates" is on. */
#listZone { padding: 4px; background-color: inherit; /* For IE7: */ background-color: #eee; }
#personList { height: 240px; position: relative; }
#personListInZone { height: 238px; position: relative; }
.personGrid { width: 100%; font-family: Arial, Helvetica, sans-serif; }
.personGrid th { display: none; }
.personGrid td { border: thin solid white; background-color: #eee; }
.personGrid a { width: 100%; line-height: 50px; display: block; text-align: center;
text-decoration: none; color: black; }
.personGrid a:visited { color: inherit; }
.personGrid a:hover { background: #ccc; color: #fff; }
.personGrid a.active { background: #999; color: #fff; }
.personGrid span.current { background-color: #3d69b6; }
#personList .t-data-grid-pager /* Need line-height to work around IE7 hasLayout and missing margins bug */
{ line-height: 24px; position: absolute; left: 4px; bottom: 3px; margin: 0;
font-family: Arial, Helvetica, sans-serif; }
#personListInZone .t-data-grid-pager /* Need line-height to work around IE7 hasLayout and missing margins bug */
{ line-height: 24px; position: absolute; left: 2px; bottom: 0px; margin: 0;
font-family: Arial, Helvetica, sans-serif; }
#noPersons { text-align: center; padding-top: 10px; }
#editorCell { width: 75%; height: 100%; vertical-align: top;
border: 1px solid white; background-color: #eee; padding: 20px; }
#editorZone { background-color: inherit; /* For IE7: */ background-color: #eee; }
#editorCell table { margin: auto; }
#editorCell h1 { font-size: large; text-align: center; }
#editorCell th { padding: 2px 5px; text-align: right; }
#editorCell td { padding: 2px 5px; text-align: left; }
#editorCell tr.err th { padding: 0; }
#editorCell tr.err td { padding: 0; }
#editorCell tr.err td.error-msg-c { padding: 0 0 4px 7px; font-size: 11px; color: red; }
#editorCell .buttons { text-align: center; padding-top: 15px; }
.error { color: red; text-align: center; padding-bottom: 13px; }
.Zsourcecodedisplay { width: 980px; overflow-x: scroll; }
Menu.java
package jumpstart.web.model;
import java.util.ArrayList;
import java.util.List;
/**
* Menu holds a list of MenuOption.
*/
public class Menu {
private List<MenuOption> menuOptions = new ArrayList<MenuOption>();
public Menu() {
}
public void add(MenuOption menuOption) {
menuOptions.add(menuOption);
};
public List<MenuOption> getMenuOptions() {
return menuOptions;
};
}
MenuOption.java
package jumpstart.web.model;
/**
* MenuOption holds a label to display and a logical page name, eg. "Hello World" and "previews/withlayout/HelloWorld".
*/
public class MenuOption {
private String label;
private String page;
public MenuOption(String label, String page) {
this.label = label;
this.page = page;
}
public String getLabel() {
return label;
};
public String getPage() {
return page;
};
}
|