On 12 Nov 2003, at 20:20, Tim Olson wrote:
sorry i'm so late in commenting on this but please NO NO NO!
we are using javascript not as a flow engine but as a simple scripting
controller. we have one main pipeline which does auth, i18n, etc, and which
calls specific pipeline fragments for each page. typical subsitemap code
looks like
<map:match action="*/profile/edit"> <map:call function="dumpUserData"/> <map:generate src="cocoon://generate"/> <map:transform src="profileForm.xsl"/> <map:serialize/> </map:match>
function dumpUserData() { userID = util.getRequestParam("userID") - 0 userHome = util.lookupHome("User") user = userHome.findByPrimaryKey(userID) util.set( "user", user.getValueObject() ) }
our generator is generic and takes the values set by the utility object and
marshalls them into XML which is fed to the XSLT...
by enforcing the use of sendPage(), you would force us to break all of our
subsitemap blocks into two pieces
<map:match action="*/profile/edit"> <map:call function="dumpUserData"/> </map:match>
<map:match action="*/profile/edit2"> <map:generate src="cocoon://generate"/> <map:transform src="profileForm.xsl"/> <map:serialize/> </map:match>
(with the addition of sendPage("edit2") in our javascript)
this is heinous and unnecessarily complicates our nice structure.
also, we have cases where we call several javascript controller modules to
get various data needed by the xslt:
<map:match action="*/profile/edit"> <map:call function="dumpUserData"/> <map:call function="dumpOrderData"/> <map:call function="dumpNewsItems"/> <map:generate src="cocoon://generate"/> <map:transform src="homePage.xsl"/> <map:serialize/> </map:match>
currently, we can easily tack on a javascript module to add XML data to the
transformation pipeline, but how could this work if every js was required to
sendPage()? it makes our usage pattern seem impossible, but we find this
way of using javascript to be quite wonderful, and quite independent of flow
concerns.
The above was the original reason to introduce actions. Actions were just empty tags. Were later shaped to contain pipelines and do all sorts of things, but the above was the spirit.
Now, I understand that it appears shameful to have to force people to do
<map:match pattern="*/profile/edit"> <map:call function="dumpUserData"/> </map:match>
<map:match pattern="*/profile/edit2"> <map:generate src="cocoon://generate"/> <map:transform src="profileForm.xsl"/> <map:serialize/> </map:match>
instead of simply
<map:match action="*/profile/edit"> <map:call function="dumpUserData"/> <map:generate src="cocoon://generate"/> <map:transform src="profileForm.xsl"/> <map:serialize/> </map:match>
but you forget to look at a few thing:
1) what if the dumpUserData is later changed to call "sendPage()"? it would never return there and you'll find it really hard to understand why.
2) the first, while more verbose, forces you to separate clearly "controller logic" from the "presentation" logic. I wouldn't write it like the above but like
<pipeline internal-only="true"> <match pattern="screen/edit"> <generate src="cocoon://generate"/> <transform src="profileForm.xsl"/> <serialize/> </match> </pipeline>
<pipeline> <match pattern="*/profile/*"> <call function="main"> <param name="action" value="{2}"/> </call> </match> </pipeline>
function main(action) { func = this[action]; if (func != undefined) func.apply(this,args); cocoon.sendPage("screen/" + action); }
function edit() { userID = util.getRequestParam("userID") - 0; userHome = util.lookupHome("User"); user = userHome.findByPrimaryKey(userID); util.set( "user", user.getValueObject() ); }
which seems more verbose, but it's, IMO, much cleaner as the main() method acts as a dispatcher for screens and you can overload them if you need to.
this is the approach that I've used in all my flowscripts and it has been working quite nicely (that is, couldn't find out a cleaner way of doing the same).
HTH
-- Stefano.