| <?xml version="1.0"?> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <jx:template xmlns:jx="http://apache.org/cocoon/templates/jx/1.0" xmlns:cinclude="http://apache.org/cocoon/include/1.0" |
| xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns:ft="http://apache.org/cocoon/forms/1.0#template" xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"> |
| <!-- Import the macros that define CForms template elements --> |
| <jx:import uri="resource://org/apache/cocoon/forms/generation/jx-macros.xml"/> |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> |
| <link href="local-resources/dreamteam.css" type="text/css" rel="stylesheet"/> |
| <title>The Dream Team</title> |
| </head> |
| <body> |
| <h1>The Dream Team</h1> |
| <p>Now is the time to choose your dream team.</p> |
| <div class="legend"> |
| <table> |
| <tr> |
| <td><i>Legend</i></td> |
| </tr> |
| <tr> |
| <td> |
| <img src="resources/forms/img/move_up.gif"/> |
| </td> |
| <td>Move this row 1 up</td> |
| </tr> |
| <tr> |
| <td> |
| <img src="resources/forms/img/move_down.gif"/> |
| </td> |
| <td>Move this row 1 down</td> |
| </tr> |
| <tr> |
| <td> |
| <img src="resources/forms/img/delete.gif"/> |
| </td> |
| <td>Delete this row</td> |
| </tr> |
| <tr> |
| <td> |
| <img src="resources/forms/img/new.gif"/> |
| </td> |
| <td>Add a new row below this row</td> |
| </tr> |
| </table> |
| </div> |
| <ft:form-template action="#{$cocoon/continuation/id}.continue" method="POST" ajax="true"> |
| <ft:repeater id="teammembers"> |
| <jx:choose> |
| <jx:when test="${form.getChild('teammembers').getSize() == 0}"> |
| <p> |
| <strong> There is no team yet. </strong> <br/> |
| </p> |
| </jx:when> |
| <jx:otherwise> |
| <table> |
| <thead> |
| <tr> |
| <td class="tableheader"> |
| <ft:repeater-widget-label widget-id="position"/> |
| </td> |
| <td class="tableheader"> |
| <ft:repeater-widget-label widget-id="memberId"/> |
| </td> |
| <td class="tableheader"> |
| <ft:repeater-widget-label widget-id="country"/> |
| </td> |
| <td class="tableheader"> |
| Actions |
| <!--ft:repeater-widget-label widget-id="select"/--> |
| </td> |
| </tr> |
| </thead> |
| <tbody> |
| <!-- The contents of the repeater-rows element |
| is a template that will be applied to each |
| row in the repeater. |
| --> |
| <ft:repeater-rows> |
| <tr> |
| <td> |
| <ft:widget id="position"> |
| <fi:styling submit-on-change="true"/> |
| </ft:widget> |
| </td> |
| <td> |
| <ft:widget id="memberId"> |
| <fi:styling submit-on-change="true"/> |
| </ft:widget> |
| </td> |
| <td> |
| <!-- FIXME: there's a bug below with Ajax, as the i18n:text element surrounds |
| the widget, and is therefore not produced when only the widget is updated |
| (and not the surrounding row) --> |
| <i18n:text><ft:widget id="country"/></i18n:text> |
| </td> |
| <td> |
| <!-- Don't display the "move up" button |
| on the first row |
| --> |
| <jx:choose> |
| <jx:when test="${repeaterLoop.first}"> |
| <img src="resources/forms/img/blank_btn.gif"/> |
| </jx:when> |
| <jx:otherwise> |
| <ft:widget id="up"> |
| <fi:styling type="image" src="resources/forms/img/move_up.gif"/> |
| </ft:widget> |
| </jx:otherwise> |
| </jx:choose> |
| <!-- Don't display the "move down" button |
| on the last row |
| --> |
| <jx:choose> |
| <jx:when test="${repeaterLoop.last}"> |
| <img src="resources/forms/img/blank_btn.gif"/> |
| </jx:when> |
| <jx:otherwise> |
| <ft:widget id="down"> |
| <fi:styling type="image" src="resources/forms/img/move_down.gif"/> |
| </ft:widget> |
| </jx:otherwise> |
| </jx:choose> |
| <ft:widget id="delete"> |
| <fi:styling type="image" src="resources/forms/img/delete.gif"/> |
| </ft:widget> |
| <ft:widget id="add"> |
| <fi:styling type="image" src="resources/forms/img/new.gif"/> |
| </ft:widget> |
| <!--ft:widget id="select"/--> |
| </td> |
| </tr> |
| </ft:repeater-rows> |
| </tbody> |
| </table> |
| </jx:otherwise> |
| </jx:choose> |
| </ft:repeater> |
| <table> |
| <tr> |
| <td style="border: 0px solid;"> |
| <ft:widget id="addmember"/> |
| </td> |
| <td style="border: 0px solid;"> |
| <jx:if test="${widget.getChild('teammembers').getSize() > 0}"> |
| <ft:widget id="removemember"/> |
| </jx:if> |
| </td> |
| </tr> |
| <tr> |
| <td style="border: 0px solid;"> |
| <input type="submit" value="Submit"/> |
| </td> |
| <td style="border: 0px solid;"/> |
| </tr> |
| </table> |
| </ft:form-template> |
| <p class="developer-header"> Developer Notes </p> |
| <h2>Page definition</h2> |
| <p class="developer-note"> This page is defined in <ul class="developer-note"> |
| <li> |
| <b>teamTemplate.jx</b>, the form template, </li> |
| <li> |
| <b>teamDef.xml</b>, the widget definitions and</li> |
| <li> |
| <b>teamBind.xml</b>, the widget binding to Java Beans.</li> |
| </ul> |
| <p class="developer-note"> The pipeline calls the function <i>prot_buildTeam</i> in <b>team.js</b>. There is no |
| naming rule for flow functions, but adding a prefix ('prot_') as a simple kind of security measure to prevent |
| outsiders from directly calling the function. Security by obscurity you might call it. </p> |
| <h2>What happens?</h2> |
| <p class="developer-note"> In <i>prot_buildTeam</i> a list of 'positions' is generated from the information in |
| the Manager class and passed onto the form. </p> |
| <p class="developer-note"> Below is the definition of the <i>position</i> widget. </p> |
| <div class="code"> |
| <div class="codeIndent"> <fd:field id="position"> <div class="codeIndent"> |
| <fd:label>Position</fd:label> </div> |
| <div class="codeIndent"> <fd:datatype base="string"/> </div> |
| <div class="codeIndent"> <fd:selection-list dynamic="true" type="flow-jxpath" |
| list-path="positionList" value-path="value" label-path="label"/> </div> |
| <div class="codeIndent"> <fd:on-value-changed> <div class="codeIndent"> |
| <fd:javascript> <div class="codeIndent"> // this script can be found in team.js<br/> |
| updateNameWidget(event); </div> </fd:javascript> </div> |
| </fd:on-value-changed> </div> </fd:field> </div> |
| </div> |
| <p class="developer-note"> The widget <i>position</i> has a selection-list of type <i>flow-jxpath</i>. The other |
| attributes define the list to use: </p> |
| <ul class="developer-note"> |
| <li> |
| <i>list-path</i> holds the name of the list that is passed in the "viewData" attribute </li> |
| <li> |
| <i>value-path</i> holds the name of the variable or method that returns the value to use </li> |
| <li> |
| <i>label-path</i> holds the name of the variable or method that returns the label for the value </li> |
| </ul> |
| </p> |
| <h2>Internationalization</h2> |
| <p class="developer-note"> The function also shows how to build this list with localized (i.e. i18n) labels. </p> |
| <div class="code"> |
| <div class="codeIndent"> ...<br/> // key = key code for position<br/> // set the label to the localized message |
| using i18n<br/> positionList[i + 1] = {value: key, label: new I18nMessage(key)};<br/> ... </div> |
| </div> |
| <p class="developer-note"> Adding the appropriate code to switch locale is left as an exercise. :-) </p> |
| <h2>Dependency between widgets</h2> |
| <p class="developer-note"> The section <i>on-value-changed</i> holds the javascript that handles the dependency. |
| When the value of the <i>positionlist</i> changes, the <i>memberId</i> widget should get a new list of |
| names.<br/> The script that handles this update can be entered directly between the <i>javascript</i> tags, but |
| adding a descriptive function name there and moving the function to a separate javascript file keeps the widget |
| definition file clearer. Note the <i>event</i> parameter.<br/> Remember to add the |
| <i>submit-on-change="true"</i> attribute to the styling tag! </p> |
| <h2>Repeater validation</h2> |
| <p class="developer-note"> This repeater also has a repeater validation section, which prevents using duplicate |
| names. Again, the script can be entered directly in the widget definition file, but it can also be added to a |
| function that is placed in a separate javascript file. <b>Note:</b> this function takes <i>widget</i> (the |
| current repeater) as parameter and <b>MUST</b> return a boolean value (true = success).<br/> The repeater |
| validation function is called when the <i>Submit</i> button is pressed. If a validation error occurs, the first |
| invalid row will be marked with a blue <font style="color: blue">!</font>. </p> |
| <h2>Some observations</h2> |
| <p class="developer-note"> The samples provide a great set of XSL files to convert the template and styling tags |
| of the widgets into HTML. They start with <b>forms-samples-styling.xsl</b> and can be found in the |
| <i>samples/blocks/forms/resources</i> folders. </p> |
| <p class="developer-note"> |
| <b>Note:</b> when you use these XSL files, remember to use them as the last transformation in your pipeline, or |
| make sure they find the appropriate tags to add some scripts to the html <i><head></i> and |
| <i><body></i> tags. Especially without a reference to the <b>forms-lib.js</b> file, the |
| on-value-changed event will not be sent to the server and therefore no script is executed. </p> |
| <p class="developer-note"> |
| <b>Note:</b> At this moment (2004/10/20) a bug exists that throws a NullPointerException when the javascript in |
| the validation section is executed with the Rhino debugger enabled! </p> |
| <h2>When everything is valid</h2> |
| <p class="developer-note"> When <i>Submit</i> is pressed, and all rows validate, the <i>prot_buildTeam</i> |
| function takes over and hands the selected team to the Manager class for further processing. Finally the |
| function passes flow onto the <i>showteam</i> pipeline. </p> |
| <p> |
| <a href="../">Back to Forms samples</a> |
| </p> |
| </body> |
| </html> |
| </jx:template> |