<HTML><BODY style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space; "><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Thank you very much for your feedback. Please, anyone else on this list who is using or attempting to use LivePage, let me know what you are doing with it or plan on doing with it. I want to take it from long-running experiment to solid, deployable code before the next release, and need to know how much API stability/backwards compatibility I should provide. I also need to know how people want to use LivePage, and if it has any usability shortcomings with this new design which I describe below. If there are any, I'd like to fix them before the next release.</DIV><BR><DIV><DIV>On Jun 1, 2005, at 4:46 PM, Alexey Shamrin wrote:</DIV><BR class="Apple-interchange-newline"><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">On 5/31/05, Donovan Preston &lt;<A href="mailto:dp@ulaluma.com">dp@ulaluma.com</A>&gt; wrote:</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">In this branch, input handlers can also return javascript which will</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">be executed as the response to the input event.</DIV></BLOCKQUOTE><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">What do you mean? I don't understand...</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Are you talking about javascript that will be executed without</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">round-trip to server?</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV>When a client-side event generates a trip to the server over the input conduit, the server-side handler method which is invoked can now return javascript stan. This return result is written as the response to the HTTP request which dispatched the event to the server, and the browser evals it. Previously, the server would arrange for the handler method to be called in the next reactor iteration and close the input HTTP request, writing nothing to it. The handler method would then call methods on the client handle which would generate javascript and buffer it or write it directly to the output conduit.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>So yes, one (output conduit) round trip is eliminated, and it becomes easier to support normal AJaX style events (where the browser is the only thing initiating requests, and the server does no pushing), which I call input only mode.</DIV><DIV><DIV><BR class="khtml-block-placeholder"></DIV><BLOCKQUOTE type="cite"><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">I encourage anyone who is interested in livepage to take a look at</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">this branch to see where it is going. Take a look at the examples to</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">see what has changed, read the code, and experiment with it. Ask</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">questions if you have any. I'll be trying to merge this branch into</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">the mainline (after adding some backwards compatibility) in the next</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">week.</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">I'll also be adding some LivePage docs. I think the API will settle</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">down after this last round of changes.</DIV> <BR></BLOCKQUOTE><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">1. nevow_insertNode from liveglue.js (and livepage.insert) is broken.</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">And (as far as I can see) it is not used anywhere in Nevow (including</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">examples). Remove?</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>I think I might fix it rather than removing it. I'll also write a test for it, since livetest can now reliably test livepage apps.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">2. I think you should have "nevow_" prefix for all things in liveglue.js.</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>I agree, except I think I want the new "server" object to keep that name. It will be much easier for people to understand and use livepage if they know that calling server.handle('foo') in javascript invokes the handle_foo method on the server. Are there other things in there that aren't prefixed with nevow_?</DIV><DIV><BR class="khtml-block-placeholder"></DIV><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">3. What is the purpose of ClientHandle.transient?</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>ClientHandle.transient and LivePage.locateHandler (whose default implementation looks for handle_* methods) are the new, easier to understand and use replacements for the handler decorator. Previously, there was a problem with handler because it registered the callable you gave it in a dictionary which lived for as long as the LivePage instance it was associated with. This means if you had a really, really long lived LivePage (which LivePage is designed to allow) you would leak more and more closures that the client can't ever call again (because you replaced the client-side dom that referenced those server-side closures with something else)</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Now, if you provide a handle_foo method, the client can always call server.handle('foo') as many times as it wants. However, it is still useful to register closures on the server and give the client the capability to call it. To avoid the aforementioned garbage problem, transient allows you to do this, but only allows the client to call it once, then pops the registration.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>This avoids the garbage problem well; if the client closes the browser, LivePage guarantees that the ClientHandle will die no more than 90 seconds later, taking the transient closure registration dictionary with it. If you are, for example, putting an "ok/cancel" dialog on the user's screen, you can register a single transient which gets called by either the ok or cancel button, ensuring that the transient will be popped when the client no longer has the capability to call it (because the UI has gone away, by the user clicking either ok or cancel)</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">4. Are these two equivalent?</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">onsubmit=livepage.server.handle(livepage.js.onSubmit, getValue('inputline'))</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">onsubmit=livepage.server.handle('onSubmit', getValue('inputline'))</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>No, because the client-side javascript "handle" function takes a string. The first would render down to:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>server.handle(onSubmit, getValue('inputline'))</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>The second would render down to:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>server.handle('onSubmit', getValue('inputLine'))</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>The first would barf because the global name onSubmit doesn't exist.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>The livepage.js object is like a stan.Tag for javascript; it creates literal javascript. For example:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>livepage.js.foo -&gt; foo</DIV><DIV>livepage.js.foo('1') -&gt; foo('1')</DIV><DIV>livepage.js('any string') -&gt; any string</DIV><DIV>livepage.js['1'] -&gt; ['1']</DIV><DIV>livepage.js.foo['1'] -&gt; foo['1']</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>There are a bunch of other js objects in the module now, such as window, document, this, server, set, append, alert, etc. They are really convenient for making your python code much shorter.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>I have an incredible LivePage app I wrote recently I am calling "Pavel". I will be cleaning it up soon and I will create a new open source project for it (rather than including it as a nevow example). I think it really showcases the power of LivePage and I'm excited to show it to people, but for now it is somewhat of a secret :-)</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><FONT class="Apple-style-span" color="#000000"></FONT></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">P.S. At this time I have only read the code and checked new</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">examples... I will try to experiment with it soon. But I must say your</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">javascript "constructor" looks interesting (livepage.assign,</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">livepage.var etc.)</DIV></BLOCKQUOTE><BR></DIV><DIV>assign and var are two experiments to get around the fact that python has no assignment overloading. Here are examples of usage:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>var(js.x, 5) -&gt; var x = 5</DIV><DIV>assign(js.x, 10) -&gt; x = 10</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>One other thing while I am discussing stan for javascript. This is a pain once you start using it, but I don't think there is any way around it other than education. You need to terminate your statements, since the javascript flatteners have no idea where it is appropriate to put newlines in javascript. So if you were sending the following:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>client.send([</DIV><DIV>    livepage.alert('hello'),</DIV><DIV>    livepage.set('name', 'Donovan Preston')])</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>You would need to terminate each statement, otherwise the javascript won't be correct. The above example would render as:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>alert('hello')set('name', 'Donovan Preston')</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Right now, you need to do:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>client.send([</DIV><DIV>    livepage.alert('hello'), livepage.eol,</DIV><DIV>    livepage.set('name', 'Donovan Preston')])</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Which will render down to:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>alert('hello')</DIV><DIV>set('name', 'Donovan Preston')</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>It occurs to me that it may be possible for Nevow to just infer that a newline is required between each element of a list or a tuple while in JavascriptContext. I will have to experiment and see whether this causes any inadvertent problems. If not, the requirement to manually insert newline characters will go away (horray!)</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Donovan</DIV><DIV><BR class="khtml-block-placeholder"></DIV></BODY></HTML>