Highlight zone updates? This shows you which zones are updated by the Ajax response.

Create...

Review

Id: 3
Version: 8
Name: toto Momma
Region: East Coast
Start Date: 11/02/2007
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 &nbsp; 
     We use a "strict" DTD to make IE follow the alignment rules. -->
     
<html t:type="together/Layout2" t:title="literal:With Layout 2: Graceful AJAX Filter CRUD" t:chosenOption="literal:Graceful AJAX 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/layout2.css"/>
    </t:remove>
    
    <form t:type="form" t:id="preferencesForm">
        <noscript class="js-recommended">
            ${message:javascript_recommended}
        </noscript>     
        Highlight zone updates? 
         <input t:type="checkbox" t:id="highlightZoneUpdates" value="highlightZoneUpdates" onclick="this.form.submit()"/>
        This shows you which zones are updated by the Ajax response.
    </form><br/>

    <a t:type="eventLink" t:event="toCreate" t:zone="editorZone" href="#">Create...</a><br/>
    
    <table id="listAndEditor">
        <tbody>
            <tr>

                <!-- This is the left side of the table: a list of Persons -->

                <td id="listCell">
                    <t:zone t:id="listZone" id="listZone" t:update="prop:zoneUpdateFunction">
    
                        <!-- We can't use the form's id in the css because the Zone messes with it, so we add a div with its own id. -->
                        <div id="personFilter">
                            <form t:type="form" t:id="filterForm" t:zone="^">
                                <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="personListInZone">
                            <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" t:inplace="ajax">[Grid here]
                                <p:nameCell>
                                    <a t:type="eventLink" t:event="selected" t:context="listPerson.id" class="prop:linkCSSClass" t:zone="^" href="#">
                                        ${listPerson.firstName} ${listPerson.lastName}
                                    </a>
                                </p:nameCell>
                            </table>
                        </div>
                        
                        <t:block t:id="emptyPersons">
                            <div id="noPersons">
                                (No persons found)
                            </div>
                        </t:block>
                        
                    </t:zone>
                </td>
                
                <!-- This is the right side of the table: where a Person will be created, reviewed, or updated. -->
        
                <td id="editorCell">
                    <t:zone t:id="editorZone" id="editorZone" t:update="prop:zoneUpdateFunction">
    
                        <t:if test="modeCreate">
                            <h1>Create</h1>
                            
                            <form t:type="CustomForm" t:id="createForm" t:zone="^" >
                                <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" t:zone="^" 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" t:zone="^" href="#">Update...</a>
                                    <a t:type="eventLink" t:event="delete" t:context="[editorPerson.id,editorPerson.version]" t:zone="^" href="#">
                                        <!-- The Confirm mixin can't cancel an EventLink that specifies a Zone, so we put the Confirm inside the EventLink. -->
                                        <!-- See http://tapestry-users.832.n2.nabble.com/Confirm-mixin-won-t-cancel-when-in-zone-td5048950.html#a5048950 -->
                                        <span t:type="any" t:mixins="Confirm" t:message="Delete ${editorPerson.firstName} ${editorPerson.lastName}?">
                                            Delete...
                                        </span>
                                    </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:context="editorPersonId" t:zone="^">
                                <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="editorPersonId" t:zone="^" 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>

                        <t:if test="modeConfirmDelete">
                            <h1>Delete</h1>
                            
                            <form t:type="form" t:id="confirmDeleteForm" t:zone="^">
                                <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"/>
                    
                                    <div class="buttons">
                                        Delete ${editorPerson.firstName} ${editorPerson.lastName}?<br/><br/>
                                        
                                        <a t:type="eventLink" t:event="cancelConfirmDelete" t:context="editorPerson.id" t:zone="^" href="#">Cancel</a>
                                        <input type="submit" value="Delete"/>
                                    </div>
                                </t:if>
                                            
                            </form>
                    
                            <t:if negate="true" test="editorPerson">
                                Person ${editorPersonId} does not exist.<br/><br/>
                            </t:if>
                            
                        </t:if>

                        <!-- This is needed to clear the zone. -->
                        <t:if test="modeNull">
                            <!-- The space character is needed only to make the zone update highlight visible. -->
                            &nbsp;
                        </t:if>

                    </t:zone> 
                </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/withlayout2/gracefulajaxfiltercrud/Persons.tml"/>
    <t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/components/together/Layout2.tml"/>
    <t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/components/together/Layout2.java"/>
    <t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/css/together/layout2.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>

Layout2.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 &nbsp; 
     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/layout2.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 2 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/Layout2</em> and you can see it being used in the outermost 
                        tag of both 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>

Layout2.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 Layout2 {
    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("Graceful AJAX Filter CRUD", "together/withlayout2/gracefulajaxfiltercrud/Persons"));
            menu.add(new MenuOption("Graceful AJAX Components CRUD", "together/withlayout2/gracefulajaxcomponentscrud/Persons"));
        }

        return menu;
    }

    public String getMenuOptionCSSClass() {
        return menuOption.getLabel().equals(chosenOption) ? CHOSEN_OPTION_CSS_CLASS : "";
    }

}

layout2.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; }

.js-recommended     { color: red; display: block; margin-bottom: 14px; }

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;
    };
}