Wednesday, December 07, 2005

Bling!

Dynamic this and that... Everyone wants it, why doesn't Plone have it? There are alot of people and groups working on the AJAXification of Zope technologies with varying degrees of success. Here are the main trends I see people pointing at:
  • Don't invent a new Javascript library
  • Don't force the developer to learn Javascript
I am sure there are others. Right now the flavors of the day are MochiKit and the Prototype family of products. I would say that both of them are great, they both provide OO abstractions around writing JS, making it more fun. MochiKit borrows ideas from Python and Twisted and is quite nice to program with. Prototype, Scripaculous and OpenRico excel in the library of existing visual effects and widgets. They also have great mindshare around them in the form that they are included with and used in Rails.

Don't invent something new, don't code Javascript
I've been experimenting with both in the context of Plone. Here is how it breaks down. Mochikit might be better if you are writing alot of Javascript. This is not however the goal of my experimentation. I like auto generated forms and widgets and I'd rather just make those come alive than. Prototype and family are already used in this capacity in Rails so there is experience in what makes a logical binding between the server side and the client.

If we are not writing Javascript then what do we write? Well, Plone UI people know TAL and a bit of Python so I thought I'd aim for that. Introduce Bling, some helper code than can be used in TAL to spit out the Javascript you need.
I only wrote this yesterday so its a little halfed backed but here is how it might work. This will create a "checkedField", something that validates server-side on change using AJAX and then writes to or clears an error div on the client.


<label for="foo">FOO</label> <input type="text" id="foo"
name="foo"\/>
<div tal:replace="structure python:ajax.checkedField(
here.portal_url() + '/dval',
'foo', error='error')"/>


which might generate something like




<label for="foo">FOO</label> <input id="foo" name="foo" type="text">
<script type="text/javascript">
new Form.Element.EventObserver($('foo'),
function(element, value) { new Ajax.Updater({success:
$('error'),failure:
$('error')},
'http://site/bling/dval', {
onFailure:function(request){
new Effect.Appear($('error'),{}); Fie\ld.activate('foo');},
parameters:Form.Element.serialize($('foo')),
onSuccess:function(request){new Effect.DropOut($('error'),{})},
asynchronous:true,insertion:null,method:'post\'} ) })




Fun Prototype callouts you didn't have to write or think about. Most of the kinds of tags you'd expect in rails are here already and I've added a few more to show how something like Plone could carry a standard array of reuable behaviors and visual effects.

Next we change something like Archetypes that already has per-field validation logic and vocabulary support and allow for things like auto-completion and validition from the widget layer with out change.

To show how simple this is I've written it into a product already. This will install the proper scripts into the resource registries in Plone. Just create a new site, install this product and play with the test.pt template in its skin path. The methods of interest are in Bling/ajax.py

To get the bundle you need darcs:


darcs get http://darcs.objectrealms.net/repos/Bling

or you can just look at the repo at
http://darcs.objectrealms.net/darcsweb.cgi/bling

3 comments:

Jonah said...

Hey Ben,

Cool demo.

Out of curiousity, have you contrasted this approach with the combination of microformats + some good, mochikit-based, unobstrusive javascript?

This is an approach Anders and the webstandards folks have been promoting. You can begin to see this in action on PloneStickies
and we are having great success with this approach with a tagging service/js client implementation.

This amounts to adding behavioral aspects to xhtml by the introduction of magical styles, which the included javascript can then operate on. Real similar to the way tables become sortable now.

I thinnk this approach more closely captures one of the original goals of zpts, namely roundtripping with designers and html folks.
It is important to expose the html (and even the javascript), and be cautious about autogenerating code - it becomes much harder to debug, control, and change.

Even in the case of widgets, which are used within autogenerated at forms, it sounds like it would be tricky and indirect to swap out behaviors. Or maybe not, just less obvious where they are coming from.

/jsb

Benjamin Saller said...

Jonah,

Thanks for the questions. Here is my thinking. Most of what you're talking about we already have. The behavious.js library bling includes does CSS style tag -> js function mapping. Thats in there. The reason you don't see it in the examples is that I am talking about triggering behavior on fields needing custom binding points to the server. Its not /ajax?object_id=xxx&myfield=yyy&value=zzz . We retain the object publishling notion and so the object will handle the message from the client. This means that we must encode this information into the page rather than rely on generic css selectors.

Mochikit is excellent if you are writing JS. With Bling you write none, its a collection of reusable behavior you trigger in the language you already know, TAL. If you use Archetypes (which all the major types in Plone do) then their widgets will include the proper TAL tags out of the box. This means you write neither TAL or JS, but that the object is handling requests with the same logic it would normally do on the server side. As an example things like validation is hooked to the validate_field style processing AT already has and auto-completed can be offered for anything with a vocabulary.

Inplace editing is also offered on views, but this requires that each field is somehow delimited in the HTML and bound back to a handler on the server, again not something totally generic.

It might be possible to encode some information in know places into pages that behaviors could look for an consume so that the existance of a generic style would be meaningful but in general this isn't what people are looking for. Given a project like stickies it makes sense that you'd want some drag and drop behavior on anything with a given style and thats fine, but I see also that you'd either pass that information to a tool or keep it in a cookie.

I suppose if the ajax handle were assumed to always be current_page+/fixed_method for a given behavior I could move to generic styles for everything, but it doesn't really help anyway. The consumer of bling isn't writing any javascript to being with, they shouldn't have to care.

Anonymous said...

Is it normal that on /test_bling when I click on "Submit Form", I only get the following :

[("Form.serialize($('myForm'))", ''), ('_', '')]

and not something like :

FOO=XXX & BAR=YYY & Tags=zzz ?

I would expect the ajax to be executed so that when I get to my python script I can use the existing data in my form.

Followers