Return-Path: Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 66706 invoked by uid 500); 26 Jul 2003 19:29:09 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 66694 invoked by uid 500); 26 Jul 2003 19:29:09 -0000 Delivered-To: apmail-cocoon-2.1-cvs@apache.org Received: (qmail 66691 invoked from network); 26 Jul 2003 19:29:09 -0000 Received: from icarus.apache.org (208.185.179.13) by daedalus.apache.org with SMTP; 26 Jul 2003 19:29:09 -0000 Received: (qmail 27338 invoked by uid 1544); 26 Jul 2003 19:29:08 -0000 Date: 26 Jul 2003 19:29:08 -0000 Message-ID: <20030726192908.27337.qmail@icarus.apache.org> From: coliver@apache.org To: cocoon-2.1-cvs@apache.org Subject: cvs commit: cocoon-2.1/src/documentation/xdocs/userdocs/flow tutor.xml api.xml book.xml jxforms.xml velocity.xml X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N 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 @@ Function [Boolean] isInfoEnabled()

- Returns whether information message logging is enabled + Returns whether information message logging is enabled.

@@ -710,7 +710,11 @@

Property [String] id

-

Returns the unique string identifier of this continuation.

+

Returns the unique string identifier of this Web Continuation.

+
+ +

Property [Continuation] continuation

+

Returns the JavaScript continuation associated with this Web Continuation.

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 @@ + 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") { .... } @@ -100,11 +100,11 @@

The JXForms tags are defined in the following namespace:

http://apache.org/cocoon/jxforms/1.0

JXForms supports the following controls:

- -

The JXForms <form> element represents the overall form. It also corresponds to a validation phase in your validation rules. It has no direct counterpart in W3C XForms.

+ +

The JXForms <form> element represents one page of the overall form. It also corresponds to a validation phase in your validation rules. It has no direct counterpart in W3C XForms.

Example:

+
@@ -121,13 +121,10 @@
  • id
  • view
  • +
  • action

- The id attribute must match the id Sitemap parameter passed to the jxForm function in <map:call>. The view attribute must match the id of a <phase> element in your Schematron validation rules. -

- - -

The JXForms <error> element has no counterpart in W3C XForms. If present under the form element it serves as a placeholder for validation error messages associated with the entire form. + The id attribute must match the id Sitemap parameter passed to the jxform function in <map:call>. The view attribute must match the id of a <phase> element in your Schematron validation rules. For HTML forms the action attribute specifies the relative URI to which the form will be submitted.

@@ -166,6 +163,13 @@

JXForms <value> element is based on the W3C XForms value element. This element provides a storage value to be used when an item is selected.

Example:

+ + + + Some value + + ]]>

@@ -174,6 +178,17 @@

Example:

+ + + + Some value + + + + Another value + + ]]>

@@ -189,7 +204,7 @@

-

The JXForms <violation> element has no counterpart in W3C XForms. The JXForms generator inserts a violation element for each validation error that occurs into the corresponding <violations> element.

+

The JXForms <violation> element has no counterpart in W3C XForms. The JXForms generator inserts a violation element for each validation error that occurs into the corresponding <violations> element of a form control.

Example:

Assuming you had a Schematron validation rule such as:

class
- +

JXForms <select> is based on the W3C XForms select element.

@@ -293,13 +308,18 @@
  • class
  • - -

    JXForms <select> is based on the W3C XForms select1 element. It supports the following attributes:

    + +

    JXForms <select1> is based on the W3C XForms select1 element. +This form control allows the user to make a single selection from multiple choices. It supports the following attributes:

    • ref
    • appearance
    • class
    +

    Example:

    + +

    @@ -377,12 +397,12 @@

    - +

    - The entry point from the Cocoon Sitemap to your form is the jxForm function: + The entry point from the Cocoon Sitemap to your form is the jxform function:

    - Function jxForm([String] functionName, [String] id, [String] validationSchema, [String] validationDocument) + Function jxform([String] functionName, [String] id, [String] validationSchema, [String] validationDocument)

    This function creates a new JXForm object with the provided id, validationSchema, and validationDocument, and then invokes the function identified by functionName to process the form, passing the newly created JXForm object as the argument to the function. Currently, the only supported validation schema is Schematron which is identified by the namespace http://www.ascc.net/xml/schematron. The validationDocument 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"/> </map:generators> -

    To invoke your form use the Sitemap's <map:call> operation to invoke the jxForm Flowscript function, for example like this:

    +

    To invoke your form use the Sitemap's <map:call> operation to invoke the jxform Flowscript function, for example like this:

    - +

    + The required function parameter specifies the name of a JavaScript function that will provide the page flow for your form. The required id attribute must match the value of the id attribute of the form element of your form. The optional validator-schema-namespace and validator-schema parameters identify the the schema namespace and instance document of your validation rules, if provided. Currently, only the Schematron assertion language is supported.

    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 @@ Generator provides access to the immediate properties of the context object passed to cocoon.sendPage and - cocoon.sendPageAndWait. In addition, - the current WebContinuation + cocoon.sendPageAndWait. In addition, the current WebContinuation is also available as a variable named $continuation. You would typically access its id:

    1.1 cocoon-2.1/src/documentation/xdocs/userdocs/flow/tutor.xml Index: tutor.xml ===================================================================
    Advanced Control Flow

    We will create a simple number guessing game using Cocoon's Flowscript engine.

    Now that you've got Cocoon 2.1 deployed and running, go to where you have Cocoon deployed and create a new subdirectory named game. Cocoon's default main sitemap will automatically mount the sitemap in the subdirectory.

    Create the following sitemap.xmap in the new subdirectory:

    ]]>

    Inside the new subdirectory, create two more directories, documents/ and flow/.

    Inside documents/, you will store the "views" -- pages to send to the player. Create the file guess.jxt, which will be the page the player will enter their guess:

    cocoon flow number guessing game

    Guess the Number Between 1 and 10

    ${hint}

    You've guessed ${guesses} times.

    ]]>

    You'll also need a page to display when the person chooses the correct number. Name it success.jxt (Again in documents/):

    cocoon flow number guessing game

    Success!

    The number was: ${random}

    It took you ${guesses} tries.

    Play again

    ]]>

    You may notice some strange codes inside the files -- namely things like ${random} and ${guesses} . They look like variables, and they will be replaced with values when the pages are sent to the client. This is where the JXTemplateGenerator comes in.

    Inside flow/, 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.

    Create the following file named game.js:

    random) { hint = "Nope, lower!" } else if (guess < random) { hint = "Nope, higher!" } else { break; } } } cocoon.sendPage("success.jxt", {"random" : random, "guess" : guess, "guesses" : guesses} ); } ]]>

    Alright, now let's follow the execution of this Flow and pipeline: The player accesses the URL http://host/cocoon/game/ and the <map:match pattern=""> matches, and starts the pipeline.

    The function main() which is referenced in flow/game.js 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.

    We now enter the code in game.js:

    A random number between 1 and 10 is chosen.

    Variables containing a hint for the player and the player's current number of guesses are initialized. The Flow now enters the while(true) loop which basically keeps the game going until the player guesses the correct number.

    We now get to the following line, where things start to get interesting:

    cocoon.sendPageAndWait("guess.jxt", { "random" : random, "hint" : hint, "guesses" : guesses} );

    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.

    We could also do the following:

    cocoon.sendPageAndWait("guess.jxt", { "foo" : random } );

    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.

    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.

    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 cocoon.sendPageAndWait() function.

    One thing to note is in the form which is sent back to Cocoon when the player submits the guess:

    ]]>

    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.

    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:

    ]]>

    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.

    We are now back in the Javascript at the line after sendPageAndWait(). 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 <input type="text" name="guess"/> and in the Javascript we get the request parameter by using cocoon.request.get("guess");

    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.

    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.

    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.

    The main point of interest in the Flow script at this point is the use of sendPage() instead of sendPageAndWait(). sendPage() works exactly the same, except, yes, you guessed it, we don't halt execution of code, and keep processing.

    At this point, there's no more code left and the game is over, and the Flow stops.

    Another thing to note is the <map:handle-errors> 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 InvalidContinuationException, and you can now handle it as described in the handle-errors tag.

    And that's it! You have now just made your very first application using the Flow layer.