coliver     2003/07/26 12:29:08

  Modified:    src/documentation/xdocs/userdocs/flow api.xml book.xml
                        jxforms.xml velocity.xml
  Added:       src/documentation/xdocs/userdocs/flow tutor.xml
  Log:
  Added Tony Collen's Flowscript tutorial taken from Cocoon wiki
  
  Revision  Changes    Path
  1.21      +6 -2      cocoon-2.1/src/documentation/xdocs/userdocs/flow/api.xml
  
  Index: api.xml
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/documentation/xdocs/userdocs/flow/api.xml,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- api.xml   20 Jul 2003 05:48:18 -0000      1.20
  +++ api.xml   26 Jul 2003 19:29:07 -0000      1.21
  @@ -695,7 +695,7 @@
           <em>Function</em> <code>[Boolean] isInfoEnabled()</code>
       </p>
       <p>
  -      Returns whether information message logging is enabled
  +      Returns whether information message logging is enabled.
       </p>
       </s3>
       </s2>
  @@ -710,7 +710,11 @@
       </p>
       <s3 title="id">
       <p><em>Property</em> <code>[String] id</code></p>
  -    <p>Returns the unique string identifier of this continuation.</p>
  +    <p>Returns the unique string identifier of this Web Continuation.</p>
  +    </s3>
  +    <s3 title="continuation">
  +    <p><em>Property</em> <code>[Continuation] continuation</code></p>
  +    <p>Returns the JavaScript continuation associated with this Web 
Continuation.</p>
       </s3>
       <s3 title="getParent">
       <p>
  
  
  
  1.10      +1 -0      cocoon-2.1/src/documentation/xdocs/userdocs/flow/book.xml
  
  Index: book.xml
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/documentation/xdocs/userdocs/flow/book.xml,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- book.xml  13 Jul 2003 19:53:14 -0000      1.9
  +++ book.xml  26 Jul 2003 19:29:08 -0000      1.10
  @@ -15,6 +15,7 @@
       <menu-item label="Continuations" href="continuations.html"/>
       <menu-item label="How does it work?" href="how-does-it-work.html"/>
       <menu-item label="Usage" href="using.html"/>
  +    <menu-item label="Tutorial" href="tutor.html"/>
       <menu-item label="Sitemap" href="sitemap.html"/>
       <menu-item label="JavaScript API" href="api.html"/>
       <menu-item label="Views" href="views.html"/>
  
  
  
  1.7       +39 -18    cocoon-2.1/src/documentation/xdocs/userdocs/flow/jxforms.xml
  
  Index: jxforms.xml
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/documentation/xdocs/userdocs/flow/jxforms.xml,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- jxforms.xml       20 Jul 2003 05:48:18 -0000      1.6
  +++ jxforms.xml       26 Jul 2003 19:29:08 -0000      1.7
  @@ -87,7 +87,7 @@
         // process the form's values:
         if (model.method == "cash") {
             ...
  -      } else if (model.method == "credit") {
  +      } else if (model.method == "cc") {
             ....
         } 
      </source>
  @@ -100,11 +100,11 @@
    <p>The JXForms tags are defined in the following namespace:</p>
    <source>http://apache.org/cocoon/jxforms/1.0</source>
    <p>JXForms supports the following controls:</p>
  - <s2 title="form">
  - <p>The JXForms <code>&lt;form&gt;</code> element represents the overall form. It 
also corresponds to a validation <em>phase</em> in your <link 
href="#Validation">validation</link> rules. It has no direct counterpart in W3C 
XForms.</p>
  + <anchor id="form"/><s2 title="form">
  + <p>The JXForms <code>&lt;form&gt;</code> element represents one page of the 
overall form. It also corresponds to a validation <em>phase</em> in your <link 
href="#Validation">validation</link> rules. It has no direct counterpart in W3C 
XForms.</p>
    <p>Example:</p>
         <source><![CDATA[
  -  <form id="form-feedback" view="userIdentity">
  +  <form id="form-feedback" view="userIdentity" action="">
       <label>Personal Information</label>
       <error>
         <violations class="error"/>
  @@ -121,13 +121,10 @@
    <ul>
      <li><code>id</code></li>
      <li><code>view</code></li>
  +   <li><code>action</code></li>
    </ul>
    <p>
  - The <code>id</code> attribute must match the <code>id</code> Sitemap parameter 
passed to the <link href="#jxForm">jxForm</link> function in <link 
href="#Sitemap">&lt;map:call&gt;</link>. The <code>view</code> attribute must match 
the <code>id</code> of a <code>&lt;phase&gt;</code> element in your Schematron <link 
href="#validation">validation</link> rules.
  - </p>
  - </s2>
  - <s2 title="error">
  - <p>The JXForms <code>&lt;error&gt;</code> element has no counterpart in W3C 
XForms. If present under the <code>form</code> element it serves as a placeholder for 
validation error messages associated with the entire form.
  + The <code>id</code> attribute must match the <code>id</code> Sitemap parameter 
passed to the <link href="#jxform">jxform</link> function in <link 
href="#Sitemap">&lt;map:call&gt;</link>. The <code>view</code> attribute must match 
the <code>id</code> of a <code>&lt;phase&gt;</code> element in your Schematron <link 
href="#validation">validation</link> rules. For HTML forms the <code>action</code> 
attribute specifies the relative URI to which the form will be submitted.
    </p>
    </s2>
    <anchor id="label"/><s2 title="label">
  @@ -166,6 +163,13 @@
    <p>JXForms <code>&lt;value&gt;</code> element is based on the W3C XForms <link 
href="http://www.w3.org/TR/xforms/slice8.html#ui-common-choices-value";>value</link> 
element. This element provides a storage value to be used when an item is selected.</p>
    <p>Example:</p>
         <source><![CDATA[
  +          <select1 ref="/option">
  +            <label>You only have one option</label>
  +            <item>
  +              <label>Your only option</label>
  +              <value>Some value</value>
  +            </item>
  +          </select1>
         ]]></source> 
    <p></p>
    </s2>
  @@ -174,6 +178,17 @@
   
    <p>Example:</p>
         <source><![CDATA[
  +          <select1 ref="/option">
  +            <label>You have two options</label>
  +            <item>
  +              <label>Your first option</label>
  +              <value>Some value</value>
  +            </item>
  +            <item>
  +              <label>Your second option</label>
  +              <value>Another value</value>
  +            </item>
  +          </select1>
         ]]></source> 
    <p></p>
    </s2>
  @@ -189,7 +204,7 @@
    <p></p>
    </s2>
    <anchor id="violation"/><s2 title="violation">
  - <p>The JXForms <code>&lt;violation&gt;</code> element has no counterpart in W3C 
XForms. The JXForms generator inserts a <code>violation</code> element for each 
validation error that occurs into the corresponding <code>&lt;violations&gt;</code> 
element.</p>
  + <p>The JXForms <code>&lt;violation&gt;</code> element has no counterpart in W3C 
XForms. The JXForms generator inserts a <code>violation</code> element for each 
validation error that occurs into the corresponding <code>&lt;violations&gt;</code> 
element of a form control.</p>
    <p>Example:</p>
       <p>Assuming you had a Schematron validation rule such as:</p>
         <source><![CDATA[
  @@ -277,7 +292,7 @@
      <li><code>class</code></li>
    </ul>
    </s2>
  - <s2 title="select">
  + <anchor id="select"/><s2 title="select">
      <p>
       </p>
    <p>JXForms <code>&lt;select&gt;</code> is based on the W3C XForms <link 
href="http://www.w3.org/TR/xforms/slice8.html#ui-selectMany";>select</link> element. 
</p>
  @@ -293,13 +308,18 @@
      <li><code>class</code></li>
    </ul>
    </s2>
  - <s2 title="select1">
  - <p>JXForms <code>&lt;select&gt;</code> is based on the W3C XForms <link 
href="http://www.w3.org/TR/xforms/slice8.html#ui-selectOne";>select1</link> element. It 
supports the following attributes:</p>
  + <anchor id="select1"/><s2 title="select1">
  + <p>JXForms <code>&lt;select1&gt;</code> is based on the W3C XForms <link 
href="http://www.w3.org/TR/xforms/slice8.html#ui-selectOne";>select1</link> element. 
  +This form control allows the user to make a single selection from multiple choices. 
It supports the following attributes:</p>
    <ul>
      <li><code>ref</code></li>
      <li><code>appearance</code></li>
      <li><code>class</code></li>
    </ul>
  + <p>Example:</p>
  +      <source><![CDATA[
  +      ]]></source> 
  + <p></p>
    <p/>
    </s2>
    <s2 title="submit">
  @@ -377,12 +397,12 @@
     </source>
     <p>
     </p>
  -  <anchor id="jxForm"/><s2 title="jxForm">
  +  <anchor id="jxform"/><s2 title="jxform">
         <p> 
  -      The entry point from the Cocoon <link href="#Sitemap">Sitemap</link> to your 
form is the <code>jxForm</code> function:
  +      The entry point from the Cocoon <link href="#Sitemap">Sitemap</link> to your 
form is the <code>jxform</code> function:
         </p>
         <p>
  -      <em>Function</em> <code>jxForm([String] functionName, [String] id, [String] 
validationSchema, [String] validationDocument)</code>
  +      <em>Function</em> <code>jxform([String] functionName, [String] id, [String] 
validationSchema, [String] validationDocument)</code>
         </p>
         <p>
         This function creates a new <code>JXForm</code> object with the provided 
<code>id</code>, <code>validationSchema</code>, and <code>validationDocument</code>, 
and then invokes the function identified by <code>functionName</code> to process the 
form, passing the newly created <code>JXForm</code> object as the argument to the 
function. Currently, the only supported validation schema is <link 
href="http://www.ascc.net/xml/resource/schematron/Schematron2000.html";>Schematron</link>
 which is identified by the namespace <code>http://www.ascc.net/xml/schematron</code>. 
The <code>validationDocument</code> if provided, should be a url that can be resolved 
by the Cocoon source resolver.
  @@ -458,10 +478,10 @@
            src="org.apache.cocoon.generation.JXFormsGenerator"/&gt;
   &lt;/map:generators&gt;
    </source>
  - <p>To invoke your form use the Sitemap's <link 
href="sitemap.html#call">&lt;map:call&gt;</link> operation to invoke the 
<code>jxForm</code> Flowscript function, for example like this:</p>
  + <p>To invoke your form use the Sitemap's <link 
href="sitemap.html#call">&lt;map:call&gt;</link> operation to invoke the 
<code>jxform</code> Flowscript function, for example like this:</p>
   <source><![CDATA[
      <map:match pattern="feedBackWizard">
  -     <map:call function="jxForm">
  +     <map:call function="jxform">
           <map:parameter name="function" value="{1}"/>
           <map:parameter name="id" value="form-feedback"/>
           <map:parameter name="validator-schema-namespace" 
  @@ -473,6 +493,7 @@
   ]]></source>
   
     <p>
  +  The required <code>function</code> parameter specifies the name of a JavaScript 
function that will provide the page flow for your form. The required <code>id</code> 
attribute must match the value of the <code>id</code> attribute of the <link 
href="#form">form</link> element of your form. The optional 
<code>validator-schema-namespace</code> and <code>validator-schema</code> parameters 
identify the the schema namespace and instance document of your validation rules, if 
provided. Currently, only the <link href="#Validation">Schematron</link> assertion 
language is supported.
     </p>
    </s1>  
    <s1 title="Validation"><anchor id="Validation"/>
  
  
  
  1.19      +1 -2      cocoon-2.1/src/documentation/xdocs/userdocs/flow/velocity.xml
  
  Index: velocity.xml
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/documentation/xdocs/userdocs/flow/velocity.xml,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- velocity.xml      20 Jul 2003 05:48:18 -0000      1.18
  +++ velocity.xml      26 Jul 2003 19:29:08 -0000      1.19
  @@ -15,8 +15,7 @@
       <link href="../generators/velocity-generator.html">Generator</link>
       provides access to the immediate properties of the context object passed to
       <link href="api.html#sendPage"><code>cocoon.sendPage</code></link> and
  -    <link 
href="api.html#sendPageAndWait"><code>cocoon.sendPageAndWait</code></link>. In 
addition,
  -    the current <link 
href="api.html#WebContinuation"><code>WebContinuation</code></link>
  +    <link 
href="api.html#sendPageAndWait"><code>cocoon.sendPageAndWait</code></link>. In 
addition, the current <link 
href="api.html#WebContinuation"><code>WebContinuation</code></link>
       is also available as a variable named <code>$continuation</code>. You would 
typically access
       its <code>id</code>:</p>
      <source>
  
  
  
  1.1                  cocoon-2.1/src/documentation/xdocs/userdocs/flow/tutor.xml
  
  Index: tutor.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" 
"../../dtd/document-v10.dtd">
  
  <document>
    <header>
      <title>Advanced Control Flow</title>
      <authors>
        <person name="Ovidiu Predescu" email="[EMAIL PROTECTED]"/>
      </authors>
    </header>
  
    <body>
  
  <s1 title="Tutorial: A Gentle Introduction to Flowscript">
  <p>We will create a simple number guessing game using Cocoon's Flowscript engine.</p>
  
  <p>
  Now that you've got Cocoon 2.1 deployed and running, go to where you have Cocoon 
deployed and create a new subdirectory named <code>game</code>. Cocoon's default main 
sitemap will automatically mount the sitemap in the subdirectory.</p>
  
  <p>Create the following <code>sitemap.xmap</code> in the new subdirectory:</p>
  
  <source><![CDATA[
  
  <?xml version="1.0" encoding="UTF-8"?>
  <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0";>
  
  <map:components>
      <map:generators default="file">
          <!-- in this example we use JXTemplateGenerator to insert 
              Flow variables in page content -->
          <map:generator label="content,data" 
             logger="sitemap.generator.jxt" name="jxt" 
              src="org.apache.cocoon.generation.JXTemplateGenerator"/>
      </map:generators>
      <map:flow-interpreters default="JavaScript"/>
      <map:transformers default="xslt"/>
      <map:serializers default="html"/>
      <map:matchers default="wildcard"/>
      <map:selectors default="browser">
        <map:selector name="exception" 
          src="org.apache.cocoon.selection.XPathExceptionSelector">
          <exception name="invalid-continuation" 
   class="org.apache.cocoon.components.flow.InvalidContinuationException"/>
          <exception class="java.lang.Throwable" unroll="true"/>
        </map:selector>
      </map:selectors>
      <map:actions/>
      <map:pipes default="caching"/>
  </map:components>
  
  <map:views/>
  <map:resources/>
  <map:action-sets/>
  
  <map:flow language="javascript">
      <!-- Flow will use the javascript functions defined in game.js -->
      <map:script src="flow/game.js"/>
  </map:flow>
  
  <map:pipelines>
   <map:component-configurations>
      <global-variables/>
  </map:component-configurations>
  
  <map:pipeline>
      <!-- no filename: call main() in game.js -->
      <map:match pattern="">
          <map:call function="main"/>
      </map:match>
  
      <!-- use JXtemplate to generate page content -->
      <map:match pattern="*.jxt">
          <map:generate type="jxt" src="documents/{1}.jxt"/>
          <map:serialize type="xhtml"/>
      </map:match>
  
      <!-- .kont URLs are generated by the Flow system for continuations -->
      <map:match pattern="*.kont">
          <map:call continuation="{1}"/>
      </map:match>
      
      <!-- handle invalid continuations -->
  
      <!-- this style of handling invalidContinuation is now deprecated: -->
      <!-- this URI will never be called automatically anymore. -->
      <!-- see handle-errors below -->
      <map:match pattern="invalidContinuation">
          <map:generate src="documents/invalidContinuation.xml"/>
          <map:serialize type="xml"/>
      </map:match>
  
      <!-- the new non-hardcoded way of handling invalidContinuation -->
      <map:handle-errors>
          <map:select type="exception">
              <map:when test="invalid-continuation">
                  <map:generate src="documents/invalidContinuation.html"/>
                  <map:serialize type="xhtml"/>
              </map:when>
          </map:select>
      </map:handle-errors>
  
  </map:pipeline>
  
  </map:pipelines>
  </map:sitemap>
  ]]></source>
  <p>
  Inside the new subdirectory, create two more directories, <code>documents/</code> 
and <code>flow/</code>. </p>
  <p>
  Inside <code>documents/</code>, you will store the "views" -- pages to send to the 
player. Create the file <code>guess.jxt</code>, which will be the page the player will 
enter their guess: 
  </p>
  <source><![CDATA[
  <?xml version="1.0"?>
  <html xmlns:jx="http://apache.org/cocoon/templates/jx/1.0";>
  <head>
      <title>cocoon flow number guessing game</title>
  </head>
  <body>
      <h1>Guess the Number Between 1 and 10</h1>
      <h2>${hint}</h2>
      <h3>You've guessed ${guesses} times.</h3>
  
      <form method="post" action="${continuation.id}.kont">
          <input type="text" name="guess"/>
          <input type="submit"/>        
      </form>
  </body>
  </html>
  ]]></source>
  <p>
  You'll also need a page to display when the person chooses the correct number. Name 
it <code>success.jxt</code> (Again in <code>documents/</code>): 
  </p>
  <source><![CDATA[
  <?xml version="1.0"?>
  
  <html xmlns:jx="http://apache.org/cocoon/templates/jx/1.0";>
  <head>
      <title>cocoon flow number guessing game</title>
  </head>
  <body>
      <h1>Success!</h1>
  
      <h2>The number was: ${random}</h2>
      <h3>It took you ${guesses} tries.</h3>
      
      <p><a href="./">Play again</a></p>
  </body>
  </html>
  ]]></source>
  <p>
  You may notice some strange codes inside the files -- namely things like 
<code>${random}</code> and <code>${guesses}</code> . They look like variables, and 
they will be replaced with values when the pages are sent to the client. This is where 
the <link href="jxtemplate.html">JXTemplateGenerator</link> comes in. 
  </p>
  <p>
  Inside <code>flow/</code>, you will store the code that actually controls how this 
application runs. In the "MVC" pattern, the Flow is the "Controller", and it is very 
powerful. 
  </p>
  <p>
  Create the following file named <code>game.js</code>: 
  </p>
  <source><![CDATA[
  function main() {
  
      var random =  Math.round( Math.random() * 9 ) + 1;
  
      var hint = "No hint for you!"
      var guesses = 0;
  
      while (true) {
  
          cocoon.sendPageAndWait("guess.jxt", { "random" : random, 
                                   "hint" : hint, "guesses" : guesses} );
  
          var guess = parseInt( cocoon.request.get("guess") );
          guesses++;
          
          if (guess) {
              if (guess > random) {
                  hint = "Nope, lower!"
              } else if (guess < random) {
                  hint = "Nope, higher!"
              } else {
                  break;
              }
          }
      }
  
      cocoon.sendPage("success.jxt", {"random" : random, 
                         "guess" : guess, "guesses" : guesses} );
  }
  ]]></source>
  <p>
  Alright, now let's follow the execution of this Flow and pipeline: The player 
accesses the URL <code>http://host/cocoon/game/</code> and the &lt;map:match 
pattern=""&gt; matches, and starts the pipeline. 
  </p>
  <p>
  The function <code>main()</code> which is referenced in <code>flow/game.js</code> is 
called, and a new Continuation object is created. Without getting into too much 
detail, the state of the Javascript code is saved, and can be recalled any number of 
times. 
  </p>
  <p>
  
  We now enter the code in <code>game.js</code>: 
  </p>
  <p>
  A random number between 1 and 10 is chosen.
  </p>
  <p> 
  Variables containing a hint for the player and the player's current number of 
guesses are initialized.
  The Flow now enters the <code>while(true)</code> loop which basically keeps the game 
going until the player guesses the correct number. 
  </p> 
  <p>
  We now get to the following line, where things start to get interesting: 
  </p>
  <source>
  cocoon.sendPageAndWait("guess.jxt", { "random" : random, "hint" : hint, "guesses" : 
guesses} );
  </source>
  <p>
  The Flow layer sends the contents of the URI "guess.jxt" which is matched in the 
sitemap (see above). We also pass an inline Javascript object, containing three 
key/value pairs, one named "random" which contains the value of the variable random as 
initialized above, and so on for hint and guesses. The keys are substituted later down 
the line, when the JXTemplateGenerator comes into play. 
  </p>
  <p>
  We could also do the following: 
  </p>
  <source>
  cocoon.sendPageAndWait("guess.jxt", { "foo" : random } );
  </source>
  <p>
  In this case, the value of random would be able to be substituted in our JXTemplate, 
but under the name "foo"" instead -- we'd just have to make sure we have the correct 
keyname in our template. 
  </p>
  <p>
  The Flow Layer also does another interesting thing: it halts the execution of the 
Javascript! Through the magic of continuations, the Flow Layer is able to resume 
execution of the script at the exact line in which it left off. This creates some very 
powerful situations with respect to web programming, and forces the reader to think 
very differently about how web applications are designed. 
  </p>
  <p>
  Picking back up in the script execution, the client is sent through the pipeline 
matching "guess.jxt". Referring back to the sitemap, we match *.jxt, and run the file 
through the JXTemplateGenerator, which substitutes the keynames for the values sent 
from the <link href="api.html#sendPageAndWait">cocoon.sendPageAndWait()</link> 
function. 
  </p>
  <p>
  One thing to note is in the form which is sent back to Cocoon when the player 
submits the guess: 
  </p>
  <source><![CDATA[
  <form method="post" action="${continuation.id}.kont">
  ]]></source>
  <p>
  Here, ${continuation.id} is resolved to a unique identifier which points to the 
current continuation. One can think of this somewhat of a session ID. 
  </p>
  <p>
  When the player submits the form, it is submitted to a unique URL which contains the 
continuation ID, plus ".kont", which we end up matching in the sitemap: 
  </p>
  <source><![CDATA[
  
  <map:match pattern="*.kont">
      <map:call continuation="{1}"/>
  </map:match>
  ]]></source>
  <p>
  When Cocoon sees a URL like this, it attempts to restart the continuation with the 
specified ID, and we re-enter the Javascript code where we left off previously. 
  </p>
  <p>
  
  We are now back in the Javascript at the line after <link 
href="api.html#sendPageAndWait">sendPageAndWait()</link>. We create a new variable (an 
int), which we get from the POST request that was sent by the form. Notice in the form 
we had <code>&lt;input type="text" name="guess"/&gt;</code> and in the Javascript we 
get the request parameter by using <code>cocoon.request.get("guess");</code> 
  </p>
  <p>
  Now we increment the player's guess count, and we test to see if they guessed the 
correct number. If the guess was too high, we set the hint variable telling them to 
guess lower, and we fall through the bottom of the while loop, and we send the guess 
form back to the player. 
  </p>
  <p>
  If the guess was too low, we tell them to guess higher, and we fall through the loop 
as well, sending the player the form again. 
  </p>
  <p>
  If the guess was correct, we break out of the main loop and send the player to a 
different view, this time to "success.jxt", and we give the template not only their 
number and the random number (pointless, yes, because they were the same), but also 
the number of guesses to tell the player how good or bad at guessing numbers they are. 
  </p>
  <p>
  The main point of interest in the Flow script at this point is the use of 
<code>sendPage()</code> instead of <code>sendPageAndWait()</code>. 
<code>sendPage()</code> works exactly the same, except, yes, you guessed it, we don't 
halt execution of code, and keep processing. 
  </p>
  <p>
  At this point, there's no more code left and the game is over, and the Flow stops. 
  </p>
  <p>
  Another thing to note is the &lt;map:handle-errors&gt; tag in the sitemap. 
Previously, when a continuation which did not exist was called, the Flow layer would 
automatically redirect to the URI "invalidContinuation". Now, the Flow layer throws an 
<code>InvalidContinuationException</code>, and you can now handle it as described in 
the handle-errors tag. 
  </p>
  <p>
  And that's it! You have now just made your very first application using the Flow 
layer. 
  </p>
      </s1>
    </body>
  </document>
  
  
  

Reply via email to