home *** CD-ROM | disk | FTP | other *** search
- <?xml version="1.0" encoding="UTF-8"?>
- <!--
- Copyright 1999-2004 The Apache Software Foundation
-
- Licensed 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.
- -->
- <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "document-v10.dtd">
-
- <document>
- <header>
- <title>Cocoon Forms: Event Handling</title>
- <authors>
- <person name="The Apache Cocoon Team" email="dev@cocoon.apache.org"/>
- </authors>
- </header>
- <body>
- <s1 title="Intro">
- <p>Some types of widgets can emit events. For example, the
- action widget produces ActionEvents and the field widget
- produces ValueChangedEvents. Next to these events, there are
- also ProcessingPhaseEvents, fired in between the various
- phases of the processing of a request.</p>
-
- <p>Handling events can be done in three ways:</p>
-
- <ul>
- <li>by defining event listeners in the form definition (as child
- of wd:on-action for the action widget, or wd:on-value-changed for
- the field widget, ...).</li>
- <li>by adding event listeners dynamically on widget instances.</li>
- <li>by registering a <code>FormHandler</code> on the
- Form object. This FormHandler will receive all events from all widgets.</li>
- </ul>
- </s1>
-
- <s1 title="When are events processed? (Request processing phases)">
- <p>To answer the question "When are events processed?", we have to
- look a bit deeper into how a form request is handled. This is separated
- in a couple of phases, more specifically the following ones:</p>
-
- <ul>
- <li>Any outstanding events are broadcasted to the event listeners.<br/>
- The reason this is done is because events might have been collected while
- the form was loaded with values by the binding framework.</li>
- <li>ProcessingPhaseListeners are informed that the <code>LOAD_MODEL</code> phase has ended.</li>
- <li>All widgets in the widget tree read their value from the request.
- If a widget decides it has to produce an event, it is added to a global
- (i.e. form-level) list (but not yet executed).</li>
- <li>Once all widgets had the opportunity to read their value from the request,
- the events are broadcasted to the event listeners. This assures that event
- listeners have access to the values of all widgets in the tree.</li>
- <li>ProcessingPhaseListeners are informed that the <code>READ_FROM_REQUEST</code> phase has ended.</li>
- <li>It is possible that processing ends now. This usually happens when
- an action widget has caused an event.</li>
- <li>All widgets in the widget tree validate themselves.</li>
- <li>ProcessingPhaseListeners are informed that the <code>VALIDATE</code> phase has ended.</li>
- </ul>
- </s1>
-
- <s1 title="Recursive event loops">
- <p>Event listeners themselves might call methods on widgets which cause
- new events to be generated. You have to be careful not to cause recursive
- event loops by doing this.</p>
-
- <p>For example, calling setValue on a widget
- in a ValueChangedEvent caused by that widget will schedule a new ValueChangedEvent,
- which will then again cause the execution of the event listener
- which will then again call setValue and thus again cause a new event
- to be generated, and so on.</p>
- </s1>
-
- <s1 title="Defining event handlers in the form definition">
- <p>Event handlers can be specified as part of the form definition, as child
- of the various wd:on-xxx elements, such as wd:on-action for the action widget.</p>
-
- <p>Event handlers can be written in either javascript or java.
- The form definition syntax is as follows:</p>
-
- <source><![CDATA[<fd:on-xxxx>
- <javascript>
- ... some inline javascript code ...
- </javascript>
- <java class="..."/>
- </fd:on-xxxx>]]></source>
-
- <p>You can specify as many <code><javascript></code> and/or
- <code><java></code> event listeners as you want.</p>
-
- <s2 title="Javascript event listeners">
- <p>Objects available in the Javascript snippet:</p>
- <ul>
- <li><code>event</code>: a subclass of WidgetEvent. The reference documentation
- of the individual widgets mentions which WidgetEvent subclass they provide
- in their events. You can then check the javadoc for those classes to see
- what they provide.</li>
- <li><code>viewData</code>: any data that is normally passed from the flowlayer
- to the view (pipeline). Exact contents depends on which flowscript API version you use.</li>
- <li>if the form processing was started from a flowscript, then everything
- available from the scope of that flowscript, such as global variables,
- functions and the <code>cocoon</code> object (see also
- <link href="../flow/api.html">Flow Object Model</link>).</li>
- </ul>
-
- <note>It does not make sense to create continuations from the Javascript event
- handler. In other words, do not call <code>cocoon.sendPageAndWait</code> or <code>form.showForm</code>
- from there.</note>
- </s2>
-
- <s2 title="Java event listeners">
- <p>The Java class specified in the class attribute on the java element should
- implement a certain event listener interface. Which interface depends on the type of widget.
- See the documentation of the individual widgets for more information.</p>
- </s2>
- </s1>
-
- <s1 title="Adding event listeners on widget instances">
- <p>Adding event listeners on widgets instances allows to dynamically
- add event listeners at runtime. This is often convenient: as you
- control the creation of the event listeners yourself, you can pass
- them any information you need.</p>
-
- <p>To add an event listener on a widget instance, simply call
- the appropriate method on the widget (e.g. addValueChangedListener)
- with an appropriate listener object as argument. You can of course also remove
- the event listener afterwards (e.g. removeValueChangedListener).</p>
-
- <p>When using flowscript, it is possible to simply assign Javascript
- functions as event listeners. This is a very easy and powerful way
- to create event listeners. See the <link href="api_javascript.html">flowscript
- API section</link> for more information.</p>
- </s1>
-
- <s1 title="Handling events using the FormHandler">
- <p>To handle events using a FormHandler, write a class implementing the following interface:</p>
-
- <source><![CDATA[org.apache.cocoon.woody.event.FormHandler]]></source>
-
- <p>Alternatively you can extend from the following abstract class:</p>
-
- <source><![CDATA[org.apache.cocoon.woody.event.AbstractFormHandler]]></source>
-
- <p>which will split ActionEvents and ValueChangedEvents to two different methods.
- See the javadocs of these interfaces and classes for more details.</p>
-
- <p>Once you created the FormHandler, register it on a form instance by calling
- the method <code>setFormHandler(FormHandler formHandler)</code> on it.</p>
- </s1>
-
- <s1 title="Overview of supported events">
- <p>The figure below shows the 3 types of events we currently support, each
- extending from the common WidgetEvent class.</p>
-
- <figure src="images/forms_event_types.png" alt="Overview of event types"/>
-
- <p>The full types of the event listeners and event objects are:</p>
-
- <source><![CDATA[org.apache.cocoon.forms.event.ValueChangedListener
- org.apache.cocoon.forms.event.ValueChangedEvent
-
- org.apache.cocoon.forms.event.ActionListener
- org.apache.cocoon.forms.event.ActionEvent
-
- org.apache.cocoon.forms.event.ProcessingPhaseListener
- org.apache.cocoon.forms.event.ProcessingPhaseEvent]]></source>
-
- <p>The table below gives an overview of what events are supported on what widgets.</p>
- <table>
- <tr>
- <th>Widget</th>
- <th>Supports ValueChangedEvents</th>
- <th>Supports ActionEvents</th>
- </tr>
- <tr>
- <td>field</td>
- <td><img src="images/yes_mark.png" alt="yes"/></td>
- <td></td>
- </tr>
- <tr>
- <td>multivaluefield</td>
- <td>TODO</td>
- <td></td>
- </tr>
- <tr>
- <td>booleanfield</td>
- <td><img src="images/yes_mark.png" alt="yes"/></td>
- <td></td>
- </tr>
- <tr>
- <td>repeater</td>
- <td></td>
- <td></td>
- </tr>
- <tr>
- <td>output</td>
- <td></td>
- <td></td>
- </tr>
- <tr>
- <td>submit</td>
- <td></td>
- <td><img src="images/yes_mark.png" alt="yes"/></td>
- </tr>
- <tr>
- <td>action</td>
- <td></td>
- <td><img src="images/yes_mark.png" alt="yes"/></td>
- </tr>
- <tr>
- <td>repeater-action</td>
- <td></td>
- <td><img src="images/yes_mark.png" alt="yes"/></td>
- </tr>
- <tr>
- <td>row-action</td>
- <td></td>
- <td><img src="images/yes_mark.png" alt="yes"/></td>
- </tr>
- <tr>
- <td>aggregatefield</td>
- <td>TODO</td>
- <td></td>
- </tr>
- <tr>
- <td>upload</td>
- <td></td>
- <td></td>
- </tr>
- <tr>
- <td>messages</td>
- <td></td>
- <td></td>
- </tr>
- </table>
- </s1>
- </body>
- </document>
-