Author: mrdon Date: Sat Jan 21 14:00:28 2006 New Revision: 371121 URL: http://svn.apache.org/viewcvs?rev=371121&view=rev Log: Reorganized examples to use new Ruby on Rails-style controllers, fixed redirects to be true redirects, changed remote flow calls to use continuations to access controller methods and values
Added: struts/flow/trunk/src/examples/WEB-INF/classes/ struts/flow/trunk/src/examples/WEB-INF/classes/commons-logging.properties struts/flow/trunk/src/examples/WEB-INF/classes/simplelog.properties struts/flow/trunk/src/examples/WEB-INF/guess/flow/ struts/flow/trunk/src/examples/WEB-INF/guess/flow/NumberGuess.js (with props) struts/flow/trunk/src/examples/WEB-INF/guess/jsp/ struts/flow/trunk/src/examples/WEB-INF/guess/jsp/endGame.jsp (with props) struts/flow/trunk/src/examples/WEB-INF/guess/jsp/play.jsp (with props) struts/flow/trunk/src/examples/WEB-INF/remote/flow/ struts/flow/trunk/src/examples/WEB-INF/remote/flow/NumberGuess.js (with props) struts/flow/trunk/src/examples/WEB-INF/remote/jsp/ struts/flow/trunk/src/examples/WEB-INF/remote/jsp/endGame.jsp (with props) struts/flow/trunk/src/examples/WEB-INF/remote/jsp/play.jsp (with props) struts/flow/trunk/src/examples/WEB-INF/templates/flow/ struts/flow/trunk/src/examples/WEB-INF/templates/flow/NumberGuess.js (with props) struts/flow/trunk/src/examples/WEB-INF/templates/jt/ struts/flow/trunk/src/examples/WEB-INF/templates/jt/endGame.jt (with props) struts/flow/trunk/src/examples/WEB-INF/templates/jt/play.jt (with props) struts/flow/trunk/src/examples/WEB-INF/wizard/flow/ struts/flow/trunk/src/examples/WEB-INF/wizard/flow/Registration.js (with props) struts/flow/trunk/src/examples/WEB-INF/wizard/flow/wizard.js (with props) struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/ struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/hobbies-form.jsp (with props) struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/name-form.jsp (with props) struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/summary-form.jsp (with props) struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/template.js - copied unchanged from r360243, struts/flow/trunk/src/examples/templates/template.js Removed: struts/flow/trunk/src/examples/WEB-INF/guess/guess.jsp struts/flow/trunk/src/examples/WEB-INF/guess/numberguess.js struts/flow/trunk/src/examples/WEB-INF/guess/struts-config.xml struts/flow/trunk/src/examples/WEB-INF/guess/success.jsp struts/flow/trunk/src/examples/WEB-INF/rails/ struts/flow/trunk/src/examples/WEB-INF/remote/guess.jsp struts/flow/trunk/src/examples/WEB-INF/remote/numberguess.js struts/flow/trunk/src/examples/WEB-INF/remote/struts-config.xml struts/flow/trunk/src/examples/WEB-INF/remote/success.jsp struts/flow/trunk/src/examples/WEB-INF/struts-config.xml struts/flow/trunk/src/examples/WEB-INF/templates/guess.jt struts/flow/trunk/src/examples/WEB-INF/templates/numberguess.js struts/flow/trunk/src/examples/WEB-INF/templates/struts-config.xml struts/flow/trunk/src/examples/WEB-INF/templates/success.jt struts/flow/trunk/src/examples/WEB-INF/wizard/hobbies-form.jsp struts/flow/trunk/src/examples/WEB-INF/wizard/name-form.jsp struts/flow/trunk/src/examples/WEB-INF/wizard/struts-config.xml struts/flow/trunk/src/examples/WEB-INF/wizard/summary-form.jsp struts/flow/trunk/src/examples/WEB-INF/wizard/wizard-flow.js struts/flow/trunk/src/examples/WEB-INF/wizard/wizard.js Modified: struts/flow/trunk/src/examples/index.html struts/flow/trunk/src/java/org/apache/struts/flow/FlowAction.java struts/flow/trunk/src/java/org/apache/struts/flow/FlowPlugIn.java struts/flow/trunk/src/java/org/apache/struts/flow/Forward.java struts/flow/trunk/src/java/org/apache/struts/flow/core/Interpreter.java struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_Flow.java struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_JavaScriptInterpreter.java struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/fom_system.js Added: struts/flow/trunk/src/examples/WEB-INF/classes/commons-logging.properties URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/classes/commons-logging.properties?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/classes/commons-logging.properties (added) +++ struts/flow/trunk/src/examples/WEB-INF/classes/commons-logging.properties Sat Jan 21 14:00:28 2006 @@ -0,0 +1,2 @@ +org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog +org.apache.commons.logging.simplelog.defaultlog=debug Added: struts/flow/trunk/src/examples/WEB-INF/classes/simplelog.properties URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/classes/simplelog.properties?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/classes/simplelog.properties (added) +++ struts/flow/trunk/src/examples/WEB-INF/classes/simplelog.properties Sat Jan 21 14:00:28 2006 @@ -0,0 +1 @@ +org.apache.commons.logging.simplelog.defaultlog=debug Added: struts/flow/trunk/src/examples/WEB-INF/guess/flow/NumberGuess.js URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/guess/flow/NumberGuess.js?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/guess/flow/NumberGuess.js (added) +++ struts/flow/trunk/src/examples/WEB-INF/guess/flow/NumberGuess.js Sat Jan 21 14:00:28 2006 @@ -0,0 +1,39 @@ +NumberGuess = function() { + + this.play = function() { + + this.random = Math.round( Math.random() * 9 ) + 1; + this.hint = "No hint for you!" + this.guesses = 0; + + while (true) { + + // send guess page to user and wait for response + flow.wait(); + + // process user's guess + this.guess = parseInt( params.guess ); + this.guesses++; + if (this.guess) { + if (this.guess > this.random) { + this.hint = "Nope, lower!" + } + else if (this.guess < this.random) { + this.hint = "Nope, higher!" + } + else { + // correct guess + break; + } + } + } + + // send success page to user + flash.guesses = this.guesses; + flash.random = this.random; + + flow.redirect( { "action" : "endGame" } ); + } + + this.endGame = function() {} +} Propchange: struts/flow/trunk/src/examples/WEB-INF/guess/flow/NumberGuess.js ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/guess/jsp/endGame.jsp URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/guess/jsp/endGame.jsp?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/guess/jsp/endGame.jsp (added) +++ struts/flow/trunk/src/examples/WEB-INF/guess/jsp/endGame.jsp Sat Jan 21 14:00:28 2006 @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<html> +<head> + <title>Struts Flow number guessing game</title> +</head> +<body> + + <h1>Success!</h1> + + <h2>The number was: <%= request.getAttribute("random") %></h2> + + <h3>It took you <%= request.getAttribute("guesses") %> tries.</h3> + + <p><a href="play.do">Play again</a></p> + + <a href="../../index.html">Return to index</a> +</body> +</html> Propchange: struts/flow/trunk/src/examples/WEB-INF/guess/jsp/endGame.jsp ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/guess/jsp/play.jsp URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/guess/jsp/play.jsp?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/guess/jsp/play.jsp (added) +++ struts/flow/trunk/src/examples/WEB-INF/guess/jsp/play.jsp Sat Jan 21 14:00:28 2006 @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<html> +<head> + <title>Struts Flow number guessing game</title> +</head> +<body> + + <h1>Guess the Number Between 1 and 10</h1> + + <h2><%= request.getAttribute("hint") %></h2> + + <h3>You've guessed <%= request.getAttribute("guesses") %> times.</h3> + + <form method="post" action="play.do"> + <input type="hidden" name="contid" value='<%= request.getAttribute("contid") %>' /> + <input type="text" name="guess"/> + <input type="submit"/> + </form> + <a href="../../index.html">Return to index</a> +</body> +</html> Propchange: struts/flow/trunk/src/examples/WEB-INF/guess/jsp/play.jsp ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/remote/flow/NumberGuess.js URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/remote/flow/NumberGuess.js?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/remote/flow/NumberGuess.js (added) +++ struts/flow/trunk/src/examples/WEB-INF/remote/flow/NumberGuess.js Sat Jan 21 14:00:28 2006 @@ -0,0 +1,44 @@ +NumberGuess = function() { + + this.play = function() { + + this.random = Math.round( Math.random() * 9 ) + 1; + this.hint = "No hint for you!" + this.guesses = 0; + + while (true) { + + // send guess page to user and wait for response + flow.wait(); + + // process user's guess + this.guess = parseInt( params.guess ); + this.guesses++; + if (this.guess) { + if (this.guess > this.random) { + this.hint = "Nope, lower!" + } + else if (this.guess < this.random) { + this.hint = "Nope, higher!" + } + else { + // correct guess + break; + } + } + } + + // send success page to user + flash.guesses = this.guesses; + flash.random = this.random; + + flow.redirect( { "action" : "endGame" } ); + } + + this.endGame = function() {} + + this.cheat = function() { + this.guesses += 5; + return {"secret":this.random, "guesses":this.guesses}; + } +} Propchange: struts/flow/trunk/src/examples/WEB-INF/remote/flow/NumberGuess.js ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/remote/jsp/endGame.jsp URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/remote/jsp/endGame.jsp?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/remote/jsp/endGame.jsp (added) +++ struts/flow/trunk/src/examples/WEB-INF/remote/jsp/endGame.jsp Sat Jan 21 14:00:28 2006 @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<html> +<head> + <title>Struts Flow number guessing game - Remote edition</title> +</head> +<body> + + <h1>Success!</h1> + + <h2>The number was: <%= request.getAttribute("random") %></h2> + + <h3>It took you <%= request.getAttribute("guesses") %> tries.</h3> + + <p><a href="play.do">Play again</a></p> + + <a href="../../index.html">Return to index</a> +</body> +</html> Propchange: struts/flow/trunk/src/examples/WEB-INF/remote/jsp/endGame.jsp ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/remote/jsp/play.jsp URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/remote/jsp/play.jsp?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/remote/jsp/play.jsp (added) +++ struts/flow/trunk/src/examples/WEB-INF/remote/jsp/play.jsp Sat Jan 21 14:00:28 2006 @@ -0,0 +1,38 @@ +<?xml version="1.0"?> +<html> +<head> + <title>Struts Flow number guessing game - Remote edition</title> + <script type="text/javascript"> + <!-- +function cheat() { + dojo.io.bind({ + url: 'play.do?FlowCall=cheat&contid=<%= request.getAttribute("contid") %>', + type: "text/javascript", + load: function(type, data, evt) { + eval("data = "+data); + alert("The secret number is "+data.secret+". After applying a penalty, you have guessed "+data.guesses+" times"); + } + }); +} + --> + </script> + <script type="text/javascript" src="../dojo-io.js"></script> +</head> +<body> + + <h1>Guess the Number Between 1 and 10</h1> + + <h2><%= request.getAttribute("hint") %></h2> + + <h3>You've guessed <%= request.getAttribute("guesses") %> times.</h3> + + <form method="post" action="play.do"> + <input type="hidden" name="contid" value='<%= request.getAttribute("contid") %>' /> + <input type="text" name="guess"/> + <input type="submit"/> + <input type="button" onclick="cheat()" value="Cheat" /> + </form> + + <a href="../../index.html">Return to index</a> +</body> +</html> Propchange: struts/flow/trunk/src/examples/WEB-INF/remote/jsp/play.jsp ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/templates/flow/NumberGuess.js URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/templates/flow/NumberGuess.js?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/templates/flow/NumberGuess.js (added) +++ struts/flow/trunk/src/examples/WEB-INF/templates/flow/NumberGuess.js Sat Jan 21 14:00:28 2006 @@ -0,0 +1,71 @@ +NumberGuess = function() { + + this.play = function() { + + this.random = Math.round( Math.random() * 9 ) + 1; + this.hint = "No hint for you!" + this.guesses = 0; + + while (true) { + + // send guess page to user and wait for response + flow.wait("play", this); + + // process user's guess + this.guess = parseInt( params.guess ); + this.guesses++; + if (this.guess) { + if (this.guess > this.random) { + this.hint = "Nope, lower!" + } + else if (this.guess < this.random) { + this.hint = "Nope, higher!" + } + else { + // correct guess + break; + } + } + } + + // send success page to user + flash.guesses = this.guesses; + flash.random = this.random; + + flow.redirect( { "action" : "endGame" } ); + } + + this.endGame = function() { + renderTemplate("endGame", this); + } + + this.cheat = function() { + this.guesses += 5; + return {"secret":this.random, "guesses":this.guesses}; + } +} + + +// This function renders the content directly using Javascript Templates +function renderTemplateAndWait(page, bizdata, ttl) { + var cont = new FOM_WebContinuation(new Continuation(), flow.continuation, ttl); + bizdata.contid = cont.id; + renderTemplate(page, bizdata); + flow.forward(null, bizdata, cont); + FOM_Flow.suicide(); +} + +function renderTemplate(page, bizdata) { + var res = flow.context.response; + var stream = struts.servletContext.getResourceAsStream("/WEB-INF/templates/jt/"+page+".jt"); + if (stream != null) { + var text = new String(stream.getText()); + var html = text.process(bizdata); + res.writer.print(html); + res.writer.close(); + } else { + res.sendError(res.SC_INTERNAL_SERVER_ERROR, "Unable to find page "+page); + } +} + +FOM_Flow.prototype._wait=renderTemplateAndWait; Propchange: struts/flow/trunk/src/examples/WEB-INF/templates/flow/NumberGuess.js ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/templates/jt/endGame.jt URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/templates/jt/endGame.jt?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/templates/jt/endGame.jt (added) +++ struts/flow/trunk/src/examples/WEB-INF/templates/jt/endGame.jt Sat Jan 21 14:00:28 2006 @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<html> +<head> + <title>Struts 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.do">Play again</a></p> + + <a href="../index.html">Return to index</a> +</body> +</html> Propchange: struts/flow/trunk/src/examples/WEB-INF/templates/jt/endGame.jt ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/templates/jt/play.jt URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/templates/jt/play.jt?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/templates/jt/play.jt (added) +++ struts/flow/trunk/src/examples/WEB-INF/templates/jt/play.jt Sat Jan 21 14:00:28 2006 @@ -0,0 +1,48 @@ +<?xml version="1.0"?> +<html> +<head> + <title>Struts Flow number guessing game</title> + <script type="text/javascript"> + <!-- +function cheat() { + hint = document.getElementById("hint"); + + dojo.io.bind({ + url: 'play.do?FlowCall=cheat&contid=${contid}', + type: "text/javascript", + load: function(type, data, evt) { + eval("data = "+data); + dojo.io.bind({ + url: "../cheat.jt", + type: "text/plain", + load: function(type, temp, evt) { + hint.innerHTML = temp.process(data); + } + }); + } + }); +} + --> + </script> + <script type="text/javascript" src="../../remote/dojo-io.js"></script> + <script type="text/javascript" src="../template.js"></script> +</head> +<body> + + <h1>Guess the Number Between 1 and 10</h1> + + <h2 id="hint">${hint}</h2> + + <h3>You've guessed ${guesses} times.</h3> + + <form method="post" action="play.do"> + <input type="hidden" name="contid" value="${contid}" /> + <input type="text" name="guess"/> + <input type="submit"/> + <input type="button" onclick="cheat()" value="Cheat" /> + </form> + + <a href="../../index.html">Return to index</a> + +</body> +</html> Propchange: struts/flow/trunk/src/examples/WEB-INF/templates/jt/play.jt ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/wizard/flow/Registration.js URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/wizard/flow/Registration.js?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/wizard/flow/Registration.js (added) +++ struts/flow/trunk/src/examples/WEB-INF/wizard/flow/Registration.js Sat Jan 21 14:00:28 2006 @@ -0,0 +1,39 @@ +flow.load("/WEB-INF/wizard/flow/wizard.js"); + +Registration = function() { + + this.start = function() { + var model = new java.util.HashMap(); + + var wizard = new Wizard(model); + wizard.populate = populate; + wizard.validate = validate; + + wizard.showForm( { "action" : "name-form" }, { + "title" : "User Name Information" + }); + wizard.showForm( { "action" : "hobbies-form" }, { + "title" : "User Hobbies" + }); + wizard.showForm( { "action" : "summary-form" } , { + "title" : "User Summary" + }); + }; +} + +function populate() { + var m = struts.paramValues; + for (var i = m.keySet().iterator(); i.hasNext(); ) { + var key = i.next(); + this.model.put(key, m.get(key)[0]); + } + // Bug in commons-chain prevents this + //this.model.putAll(struts.paramValues); +} + +function validate() { + if (this.model.get("name").length() < 2) { + return "Name must be specified"; + } +} + Propchange: struts/flow/trunk/src/examples/WEB-INF/wizard/flow/Registration.js ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/wizard/flow/wizard.js URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/wizard/flow/wizard.js?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/wizard/flow/wizard.js (added) +++ struts/flow/trunk/src/examples/WEB-INF/wizard/flow/wizard.js Sat Jan 21 14:00:28 2006 @@ -0,0 +1,180 @@ +/* + * This file provides a Wizard object that can be used to easily implement + * multi-page workflows, commonly called wizards. The following features + * are built into the framework: + * + * - Pluggable validation + * - Pluggable data population and post-population processing + * - Automatic forward/backward navigation handling + * - Capable of handing any model (POJO, DynaBean, JDOM Element, etc) + * + * To insert your own logic, particularly validation and population logic, + * simply the desired methods with your own. + */ + + /** + * Constructor for the Wizard. + * + * @param model The data model object to store form data + */ +function Wizard(model) { + + // The data model, can be anything + this.model = model; + + // The time to live for forms, defaults to continuation manager settings + this.timeToLive = 0; + + // The key the model is placed under + this.modelKey = "form"; + + // The key the errors are placed under + this.errorsKey = "errors"; + + // The name of the request parameter signifying the "Next" action + this.nextId = "next"; +} + +/** + * Called to populate the model with the request + */ +Wizard.prototype.populate = function() {} + +/** + * Called to handle any post-processing after populate has been called + */ +Wizard.prototype.postPopulate = function() {} + +/** + * Called to validate the form + * + * @param frmName The name of the form to validate + * @return Any errors, null if none + */ +Wizard.prototype.validate = function(frmName) {} + +/** + * Called to prepare the model right before the form is sent. + * + * @return The model to include in the business data passed to the form + */ +Wizard.prototype.prepareModel = function() {return this.model;} + +/** + * Creates a continuation, saves the context, and sends the form. Shouldn't + * need to be called from outside the Wizard class. + * + * @param name The name of the form to send + * @param lastWebCont The parent web continuation + * @param bizdata A map of objects to pass to the form + */ +Wizard.prototype.sendFormAndWait = function(name, lastWebCont, bizdata, ttl) { + flow.forward(name, bizdata, new FOM_WebContinuation(new Continuation(), lastWebCont, ttl)); + flow.exit(); +} + +/** + * Shows the form, handling validation and navigation. + * + * @param doValidate Whether to validate or not (optional) + * @param exitIds An array of submit button names that allow "next" behavior + * @return The submit button name that was pressed + */ +Wizard.prototype.showForm = function(frm, bizdata, doValidate, exitIds) { + + // Default validation to true if not passed + var doValidate = (doValidate == null ? true : doValidate); + + // Default to the next id if none passed + var exitIds = (exitIds == null ? new Array(this.nextId) : exitIds); + + var lastWebCont = flow.continuation; + // create a continuation, the invocation of which will resend + // the page: this is used to implement the back button + var wk = new FOM_WebContinuation(new Continuation(), lastWebCont); + flow.log.debug("saving spot "+wk.id+" before form:"+frm); + + // Loop to keep showing form until validation passes and next button + // is pressed + var keepShowing = true; + var thisWebCont; + var tmpModel; + var exitId; + while (keepShowing) { + keepShowing = false; + + // Wraps the model before attaching to bizdata to allow any necessary + // cloning or ActionForm wrapping + tmpModel = this.prepareModel(this.model); + bizdata[this.modelKey] = tmpModel; + + // Send the form and wait + thisWebCont = this.sendFormAndWait(frm, wk, bizdata); + + // Populate the model with form submission + this.populate(); + this.postPopulate(); + + // If validation is enabled, validate and determine if should keep + // showing + if (doValidate) { + var errors = this.validate(frm); + if (errors == null || errors.length == 0) { + bizdata[this.errorsKey] = null; + } else { + bizdata[this.errorsKey] = errors; + keepShowing = true; + } + } + + // Determine if next button is pressed and should stop showing + if ((doValidate && !keepShowing) || !doValidate) { + keepShowing = true; + var params = struts.param; + for (var id in exitIds) { + if (params[exitIds[id]] != null || params[exitIds[id]+'.x'] != null) { + exitId = exitIds[id]; + keepShowing = false; + break; + } + } + } + } + flow.continuationn = thisWebCont; + return exitId; +} + + +/** + * This function is called to restart a previously saved continuation + * passed as argument. Overrides the default handleContinuation to + * add support for back buttons. + * + * @param kont The continuation to restart + */ +function handleContinuation(k, wk) { + + // This can be overridden by declaring a "prevId" variable outside the function + var prevId = (this.prevId != null ? this.prevId : "prev"); + + flow.log.debug("Previous Id:"+struts.param[prevId]+" cont:"+wk.id); + if (struts.param[prevId]) { + var cont = wk; + for (var x=0; x<2; x++) { + if (cont == null) { + flow.log.error("can't get parent continuation, back "+x); + break; + } else { + cont = cont.getParent(); + } + } + if (cont != null) { + cont.continuation(cont); + } else { + k(wk); + } + } else { + k(wk); + } +} +flow.handleContinuation = handleContinuation; Propchange: struts/flow/trunk/src/examples/WEB-INF/wizard/flow/wizard.js ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/hobbies-form.jsp URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/hobbies-form.jsp?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/hobbies-form.jsp (added) +++ struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/hobbies-form.jsp Sat Jan 21 14:00:28 2006 @@ -0,0 +1,37 @@ +<?xml version="1.0"?> +<html> +<head> + <title><%=request.getAttribute("title")%></title> +</head> +<body> + + <h1><%=request.getAttribute("title")%></h1> + <p> + Enter your hobbies: + </p> + + <center style="color:red"><%=(request.getAttribute("errors") != null ? request.getAttribute("errors") : "")%></center> + + <% java.util.Map form = (java.util.Map)request.getAttribute("form"); %> + <form action="registration.do" method="POST"> + <table> + <tr> + <th>Favorite Sport</th> + <td><input type="text" name="sport" value="<%=(form.get("sport") != null ? form.get("sport") : "")%>"/></td> + </tr> + + <tr> + <th>Favorite Book</th> + <td><input type="text" name="book" value="<%=(form.get("book") != null ? form.get("book") : "")%>"/></td> + </tr> + + </table> + + <input type="hidden" name="contid" value='<%= request.getAttribute("contid") %>' /> + <input type="submit" name="prev" value="Previous" /> + <input type="submit" name="next" value="Next" /> + </form> + + <a href="../../index.html">Return to index</a> +</body> +</html> Propchange: struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/hobbies-form.jsp ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/name-form.jsp URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/name-form.jsp?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/name-form.jsp (added) +++ struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/name-form.jsp Sat Jan 21 14:00:28 2006 @@ -0,0 +1,40 @@ +<?xml version="1.0"?> +<html> +<head> + <title><%=request.getAttribute("title")%></title> +</head> +<body> + + <h1><%=request.getAttribute("title")%></h1> + <p> + Enter your name information: + </p> + + <center style="color:red"><%=(request.getAttribute("errors") != null ? request.getAttribute("errors") : "")%></center> + <form action="registration.do" method="POST"> + + <% java.util.Map form = (java.util.Map)request.getAttribute("form"); %> + <table> + <tr> + <th>First Name</th> + <td><input type="text" name="name" value="<%=(form.get("name") != null ? form.get("name") : "")%>"/></td> + </tr> + + <tr> + <th>Last Name</th> + <td><input type="text" name="lastname" value="<%=(form.get("lastname") != null ? form.get("lastname") : "")%>"/></td> + </tr> + + <tr> + <th>Middle Name</th> + <td><input type="text" name="middlename" value="<%=(form.get("middlename") != null ? form.get("middlename") : "")%>"/></td> + </tr> + </table> + + <input type="hidden" name="contid" value='<%= request.getAttribute("contid") %>' /> + <input type="submit" name="next" value="Next" /> + </form> + + <a href="../../index.html">Return to index</a> +</body> +</html> Propchange: struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/name-form.jsp ------------------------------------------------------------------------------ svn:executable = * Added: struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/summary-form.jsp URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/summary-form.jsp?rev=371121&view=auto ============================================================================== --- struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/summary-form.jsp (added) +++ struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/summary-form.jsp Sat Jan 21 14:00:28 2006 @@ -0,0 +1,48 @@ +<?xml version="1.0"?> +<html> +<head> + <title><%=request.getAttribute("title")%></title> +</head> +<body> + + <h1><%=request.getAttribute("title")%></h1> + <p> + Congratulations! + </p> + + <% java.util.Map form = (java.util.Map)request.getAttribute("form"); %> + <table border="1"> + <tr> + <th>First Name</th> + <td><%=form.get("name")%></td> + </tr> + + <tr> + <th>Last Name</th> + <td><%=form.get("lastname")%></td> + </tr> + + <tr> + <th>Middle Name</th> + <td><%=form.get("middlename")%></td> + </tr> + + <tr> + <th>Favorite Sport</th> + <td><%=form.get("sport")%></td> + </tr> + + <tr> + <th>Favorite Book</th> + <td><%=form.get("book")%></td> + </tr> + </table> + + <form action="registration.do" method="POST"> + <input type="hidden" name="contid" value='<%= request.getAttribute("contid") %>' /> + <input type="submit" name="prev" value="Previous" /> + </form> + + <a href="../../index.html">Return to index</a> +</body> +</html> Propchange: struts/flow/trunk/src/examples/WEB-INF/wizard/jsp/summary-form.jsp ------------------------------------------------------------------------------ svn:executable = * Modified: struts/flow/trunk/src/examples/index.html URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/examples/index.html?rev=371121&r1=371120&r2=371121&view=diff ============================================================================== --- struts/flow/trunk/src/examples/index.html (original) +++ struts/flow/trunk/src/examples/index.html Sat Jan 21 14:00:28 2006 @@ -8,21 +8,18 @@ in Struts Flow: </p> <ul> - <li><a href="guess/guess.do">Number Guess Example</a> - Shows a simple + <li><a href="guess/NumberGuess/play.do">Number Guess Example</a> - Shows a simple number guessing game to demonstrate the use of continuations.</li> - <li><a href="remote/guess.do">Number Guess Example - Remote Edition</a> - + <li><a href="remote/NumberGuess/play.do">Number Guess Example - Remote Edition</a> - Shows the above example but adding a remote rpc or (Ajax) example by adding a "cheat" button that retrieves the number from the server without reloading the page.</li> - <li><a href="templates/guess.do">Number Guess Example - Template Edition</a> - + <li><a href="templates/NumberGuess/play.do">Number Guess Example - Template Edition</a> - Shows the remote example but using <a href="http://www.trimpath.com/project/wiki/JavaScriptTemplates">Javascript Templates</a> to render HTML on both the server instead of JSP and client instead of string contatenations.</li> - <li><a href="rails/NumberGuess/play.do">Number Guess Example - Rails Edition</a> - Shows the - game but written using <a href="http://www.rubyonrails.org">Ruby on Rails</a>-style - controllers with a zero-configuration layout.</li> - <li><a href="wizard/registration.do">Registration Wizard Example</a> - + <li><a href="wizard/Registration/start.do">Registration Wizard Example</a> - Shows a simple server-side wizard framework built on continuations with automatic back button support both from a form and browser button.</li> Modified: struts/flow/trunk/src/java/org/apache/struts/flow/FlowAction.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/FlowAction.java?rev=371121&r1=371120&r2=371121&view=diff ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/FlowAction.java (original) +++ struts/flow/trunk/src/java/org/apache/struts/flow/FlowAction.java Sat Jan 21 14:00:28 2006 @@ -113,13 +113,8 @@ // A FlowCall means the request came from client-side javascript that // expects the return type to be JSON boolean isFlowCall = (request.getParameter("FlowCall") != null); - String func = null, controller = null; - if (isFlowCall) { - func = request.getParameter("FlowCall"); - } else { - func = getProperty("function", request, mapping); - controller = getProperty("controller", request, mapping); - } + String func = getProperty("function", request, mapping); + String controller = getProperty("controller", request, mapping); if ("true".equals(FlowConfiguration.getInstance().getProperty("flow.devMode"))) { SqlMap.reloadConfig(); @@ -150,25 +145,6 @@ throw new ServletException("You must specify a function name to call"); } else { - // validate JSON in the body of a flowcall - if (isFlowCall) { - StringBuffer sb = new StringBuffer(); - char[] buffer = new char[1024]; - int len = 0; - BufferedReader reader = request.getReader(); - while ((len = reader.read(buffer)) > 0 ) { - sb.append(buffer, 0, len); - } - String json = sb.toString(); - if (log.isDebugEnabled()) { - log.debug("processing json:"+json); - } - if (isValidJSON(json)) { - context.put("json", json); - } - - } - String id = mapping.getProperty("id"); if (id != null) { args.add(new Interpreter.Argument("id", id)); @@ -176,32 +152,47 @@ // call control script function - Object ret = interp.callController(controller, func, args, context); - - if (isFlowCall) { - Map atts = ConversionHelper.jsobjectToMap((Scriptable) ret); - String json = new JSONSerializer().serialize(atts); - if (log.isDebugEnabled()) { - log.debug("returning json: "+json); - } - response.getWriter().write(json); - response.getWriter().flush(); - response.getWriter().close(); - return null; - } + interp.callController(controller, func, args, context); return dispatchToPage(request, response, mapping, forward); } } else { // --- continue an existing flow - // kick off continuation - context.put("id", "5"); + // validate JSON in the body of a flowcall + if (isFlowCall) { + StringBuffer sb = new StringBuffer(); + char[] buffer = new char[1024]; + int len = 0; + BufferedReader reader = request.getReader(); + while ((len = reader.read(buffer)) > 0 ) { + sb.append(buffer, 0, len); + } + String json = sb.toString(); + if (log.isDebugEnabled()) { + log.debug("processing json:"+json); + } + if (isValidJSON(json)) { + context.put("json", json); + } + + } interp.handleContinuation( request.getParameter("contid"), new LinkedList(), context); - return dispatchToPage(request, response, mapping, forward); + if (isFlowCall) { + String json = new JSONSerializer().serialize(forward.getBizData()); + if (log.isDebugEnabled()) { + log.debug("returning json: "+json); + } + response.getWriter().write(json); + response.getWriter().flush(); + response.getWriter().close(); + return null; + } else { + return dispatchToPage(request, response, mapping, forward); + } } } Modified: struts/flow/trunk/src/java/org/apache/struts/flow/FlowPlugIn.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/FlowPlugIn.java?rev=371121&r1=371120&r2=371121&view=diff ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/FlowPlugIn.java (original) +++ struts/flow/trunk/src/java/org/apache/struts/flow/FlowPlugIn.java Sat Jan 21 14:00:28 2006 @@ -239,6 +239,7 @@ classesToRegister.add(SqlMap.class); interp.initialize(classesToRegister); interp.register("/org/apache/struts/flow/core/javascript/fom/fom_system.js"); + interp.register("/org/apache/struts/flow/core/javascript/fom/template.js"); interp.addFlowVariable("struts", new DefaultFlowVariableFactory(Struts.class)); interp.addFlowVariable("params", new DefaultFlowVariableFactory(Params.class)); return interp; Modified: struts/flow/trunk/src/java/org/apache/struts/flow/Forward.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/Forward.java?rev=371121&r1=371120&r2=371121&view=diff ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/Forward.java (original) +++ struts/flow/trunk/src/java/org/apache/struts/flow/Forward.java Sat Jan 21 14:00:28 2006 @@ -46,7 +46,7 @@ this.action = (String) setIfNotNull(action, map.get("action")); this.params = (Map) setIfNotNull(params, map.get("params")); this.controller = (String) setIfNotNull(controller, map.get("controller")); - this.redirect = "true".equals(map.get("redirect")); + this.redirect = Boolean.TRUE.equals(map.get("redirect")); this.options = map; } Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/Interpreter.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/Interpreter.java?rev=371121&r1=371120&r2=371121&view=diff ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/core/Interpreter.java (original) +++ struts/flow/trunk/src/java/org/apache/struts/flow/core/Interpreter.java Sat Jan 21 14:00:28 2006 @@ -222,7 +222,7 @@ * @param redirector a <code>Redirector</code> used to call views * @exception Exception if an error occurs */ - void handleContinuation(String continuationId, List params, + Object handleContinuation(String continuationId, List params, WebContext chainCtx) throws Exception; } Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_Flow.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_Flow.java?rev=371121&r1=371120&r2=371121&view=diff ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_Flow.java (original) +++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_Flow.java Sat Jan 21 14:00:28 2006 @@ -212,7 +212,7 @@ } public FOM_WebContinuation jsFunction_forward(Object options, - Object obj, + Object bizdata, Object wk) throws Exception { @@ -231,14 +231,26 @@ forward.setUri((String) options); } else if (options instanceof Scriptable && options != Undefined.instance) { - forward.populate((Map)ConversionHelper.jsobjectToMap((Scriptable)options)); + Map vals = (Map)ConversionHelper.jsobjectToMap((Scriptable)options); + forward.populate(vals); } - if (obj != null && obj != Undefined.instance) { - forward.setBizData((Map)ConversionHelper.jsobjectToMap((Scriptable)obj)); + if (bizdata != null && bizdata != Undefined.instance) { + forward.setBizData((Map)ConversionHelper.jsobjectToMap((Scriptable)bizdata)); } ctx.put(Constants.FORWARD_KEY, forward); return fom_wk; + } + + public String jsFunction_calculateUri(Object fwd, Object options, String pattern) { + Forward forward = (Forward)fwd; + if (options instanceof String) { + forward.setUri((String) options); + } else if (options instanceof Scriptable + && options != Undefined.instance) { + forward.populate((Map)ConversionHelper.jsobjectToMap((Scriptable)options)); + } + return forward.toUri(pattern); } public Scriptable jsFunction_createPageLocal() { Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_JavaScriptInterpreter.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_JavaScriptInterpreter.java?rev=371121&r1=371120&r2=371121&view=diff ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_JavaScriptInterpreter.java (original) +++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_JavaScriptInterpreter.java Sat Jan 21 14:00:28 2006 @@ -878,9 +878,10 @@ return ret; } - public void handleContinuation(String id, List params, + public Object handleContinuation(String id, List params, WebContext webctx) throws Exception { + Object ret = null; WebContinuation wk = continuationsMgr.lookupWebContinuation(id, getInterpreterID(), webctx); if (wk == null) { @@ -940,7 +941,7 @@ initFlowVariables(kScope.getFlowVariables(), webctx); Object[] args = new Object[] {k, fom_wk}; try { - ScriptableObject.callMethod(flow, + ret = ScriptableObject.callMethod(flow, "handleContinuation", args); } catch (JavaScriptException ex) { throw locationTracker.getException("Error calling continuation", ex); @@ -966,6 +967,7 @@ Context.exit(); Thread.currentThread().setContextClassLoader(savedClassLoader); } + return ret; } } Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/fom_system.js URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/fom_system.js?rev=371121&r1=371120&r2=371121&view=diff ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/fom_system.js (original) +++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/fom_system.js Sat Jan 21 14:00:28 2006 @@ -30,10 +30,37 @@ } -FOM_Flow.prototype.wait = function(ttl) { - this.forward(null, null, +FOM_Flow.prototype.wait = function(uri, bizData, ttl, fun) { + this._wait(uri, bizData, ttl, fun); + var funcName = params.FlowCall; + if (funcName) { + var func = controller[funcName]; + if (func) { + var json; + eval("json = "+flow.context.json); + var ret = func.call(controller, json); + this.forward(null, ret); + FOM_Flow.suicide(); + } else { + flow.log.error("Unable to locate function "+funcName+ + " on controller "+typeof(controller)); + } + } else { + flow.log.debug("Not a flow call"); + } +} + +FOM_Flow.prototype._wait = function(uri, bizData, ttl, fun) { + this.forward(uri, bizData, new FOM_WebContinuation(new Continuation(), this.continuation, ttl)); + if (fun) { + if (!(fun instanceof Function)) { + throw "Expected a function instead of: " + fun; + } + fun(); + } + FOM_Flow.suicide(); } @@ -78,6 +105,30 @@ */ FOM_Flow.prototype.exit = function() { FOM_Flow.suicide(); +} + + +// This function renders the content directly using Javascript Templates +FOM_Flow.prototype.renderAndWait = function(page, bizdata, ttl) { + var cont = new FOM_WebContinuation(new Continuation(), + this.continuation, ttl) + bizdata.contid = cont.id; + render(page, bizdata); + this.forward(null, bizdata, cont); + FOM_Flow.suicide(); +} + +FOM_Flow.prototype.render = function(page, bizdata) { + var res = this.context.response; + var stream = struts.servletContext.getResourceAsStream("/WEB-INF/templates/"+page+".jt"); + if (stream != null) { + var text = new String(stream.getText()); + var html = text.process(bizdata); + res.writer.print(html); + res.writer.close(); + } else { + res.sendError(res.SC_INTERNAL_SERVER_ERROR, "Unable to find page "+page); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]