I agree with all those points.  I'm reading through the new navigation  
code and it's much nicer.  I'm very happy to see the clean separation  
of tree manipulation and rendering.  Thanks for all that hard work Jan!

I have a long specification written up below; I think I've dealt with  
the major design issues except the specific encoding restrictions on  
parameter names and values and the nitty gritty of cross-browser  
fragment updating.

If anyone wants to take the time to read through and ask probing  
questions or suggest how to encode hash parameters, I'm all ears.

Thank you,
Ian

=====================

URL Parameter Protocol Spec:

Enabling parameter updating via a mixin class parameter-mixin.   
defwidget can add this to the superclass list of widgets when any slot  
contains :parameter-p name where name is the parameter string  
associated with the slot value.  The default methods for non  
parameterized widgets simply return nil or do nothing.

The reason for the mixin is that we add overhead to URL processing and  
generation when we use automatic parameterization.  Users wishing to  
customize this can simply override current-parameters and update- 
parameters for their specific widget, ignoring the metaclass machinery.


Incoming URLs:

(defgeneric update-widget-parameters (pwidget parameters)
   "Given an alist of parameters, widget updates its state
    appropriately.  The default method for plain widgets does
    nothing.  The default method for parameter-mixin uses a
    method (parameter-slot-map that is automatically defined by
    the macro to get the list slots to update and the associated
    parameter names.

    The default method presumes that parameters take the form of
    (format nil "~A-~A" (class-of widget) slotname). This method is  
called
    after the update-children call during widget updating."

Conflicts and multiple-instances of a widget:

This scheme falls down when you have multiple versions of a widget
class using parameters on the same page.  We leave resolution of these
problems to the programmer, suggesting that they bypass the automated
mechanism.

Generating the Current URL:

If you want to generate a link that encodes the link's side effect  
into the url parameter arguments, then we need a way to easily  
generate the current URL for the other widgets in the post-action,  
post-parameter processing state.  However, the contract is that the  
state of the hierarchy given a URI should mirror the semantics of that  
URI.  So given the current URI and parameters, all we need to do is  
merge the desired side effects into the current URI.  Let's just give  
the user a default helper function:

(defgeneric merge-with-current-uri (webapp new-params)
   "This is a webapp scope method that implements a simple policy for
    taking the union of all provided parameters, giving preference
    to changes.")

==================================

URL Fragment Protocol Spec:

To review, URL fragments are used for:
1) Supporting back button state changes without page loads
2) Recording client-side state changes w/o server side updates
3) Bookmarking ajax state

All of this amounts to synchronizing significant state (for user- 
driven recreation via backbutton or bookmarks) between the URL bar,  
the client state and the server state.  When any one area changes, the  
others are to be updated.  This is done via polling the URL variable  
for changes (there is no event, last I checked, that you can listen  
to).  We do not enable polling unless the server or client side sends  
a non-empty fragment or the client side registers a callback.

We need a server-side as well as a client-side protocol.  On the  
server side we simply need to serialize a subset of tree state into a  
fragment and be able to reproduce that state when it is passed back  
from the client.  Client-side we need to handle the back button, and  
on a fresh page load detect whether the server hash matches ours and  
if not, ask the server to sync up by processing the hash fragment.

We add a new field to the ajax protocol that contains the current URL  
fragment (simpler to debug than a script).  However, we may not get  
all the state on an ajax call because all dirty widgets are not  
touched so what we're getting is a diff which needs to be merged via a  
simple policy.

To keep this simple, I don't intended it to integrate it into the  
parameter-mixin protocol (for now).  Theoretically, we could merge  
these two mechanisms so we have a fallback for non-javascript  
browsers; but I feel that is overly restrictive and few of us are  
programming for a non-javascript audience.  Don't use identifiers if  
you want a fallback mode.

It is assumed that users will define their own space of parameters and  
ensure that they are disjoint.

(defgeneric render-widget-fragment (widget)
    "Simply returns an alist of key, value pairs representing the
     current dynamic state of that widget.  It is merged into the
     current request's parameter list and shipped to the client.
     This function is called during rendering and accumulates
     key-value pairs in a global variable, doing duplicate detection."

During normal requests, the result list is combined into a fragment  
and sent via a script.  During ajax requests, a subset of parameters  
are sent and the client merges them with the current fragment to  
update the history.

(defgeneric update-widget-fragment (widget alist)
    "The widget updates its state using the fragment and marks itself
     dirty iff anything has changed.  This is only called via ajax."

There is a new test in the request-handler for a special URL parameter  
'fragment' which, like 'action', is reserved and used for AJAX  
updates.  When this parameter is set, it contains the URL fragment and  
walk-widget-tree is used to update the current set of active widgets.

Client-side:

The client has to handle only two events:
- backbutton changes the fragment (send full fragment to server)
- ajax call resulted in a fragment change (update URI fragment, update  
history)

This is all hidden inside the weblocks.js code.  However, we export  
one function and support a callback for client-only fragment state  
(e.g. a visualization zoom level where we want to avoid server calls,  
but record state change).  This can be done via an :before-load script  
or from a widget js file.

function change-client-fragment (param-dict)

   Called to store parameters in the URL fragment.  We will separate  
the client and server parameter namespaces to simplify things.

function register-client-fragment-handler (fn)

   Called after load by the success handler for the server-side state  
update.  The client-side updates always happen in the configuration  
determined by the server URL path, URL parameters, and fragment  
parameters.  The function simply accepts a dictionary with the updated  
parameters.



On Mar 21, 2009, at 6:20 PM, Jan Rychter wrote:

>
> Ian Eslick <[email protected]> writes:
>> I think that's the idea; let's not overcommit until we see how people
>> use it.  Any other comments or feedback?  I think some basic support
>> could be provided fairly quickly with some careful surgery on the  
>> walk-
>> widget method so we can experiment.  A sprint if you will...
>
> Sounds good so far -- IMHO update-widget-tree (right after the
> update-children call) is the place to do it, but someone needs to  
> design
> an interface/protocol. By that I mean something similar to the
> update-children/get-widget-for-tokens/update-dependents trio used for
> handling URI tokens and selection within the tree.
>
> There is also the question of whether parameters can modify the tree
> structure. I would suggest avoiding this.
>
> --J.
>
>> On Mar 21, 2009, at 1:50 PM, Jan Rychter wrote:
>>
>>>
>>> Ian Eslick <[email protected]> writes:
>>> [...]
>>>> The first is pretty easy, I hope.  As we walk the widget tree
>>>> invoking
>>>> navigation functionality, we have a new method that is called on  
>>>> each
>>>> widget that can be specialized to extract URL parameters and update
>>>> widget state without messing with rendering - essentially a  
>>>> potential
>>>> action tied to each widget.  Perhaps this is already effectively
>>>> there?  Individual users can decide how to create hard links that
>>>> generate these parameters.
>>>
>>> Do we leave the naming of the parameters up to application  
>>> developers?
>>> E.g. it is up to each widget to decide what it wants to extract?
>>>
>>> I suppose so, because if we try to force any structure we basically
>>> end
>>> up with a duplicate of the uri-token selector scheme, only for URL
>>> parameters...
>>>
>>> --J.
>>>
>>>>
>>
>>
>>
>
> >


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"weblocks" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/weblocks?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to