Hi guys,

So, prepare yourselves. :) I'm going to try to break down the Bling and
KSS conundrum in a few different sections below. I think it's important
that we think through these issues, and that we get some debate going
fairly quickly. This is holding up other work, as you know.

First of all, I think we need to acknowledge that AJAX isn't something we can just take lightly. We're talking about putting a lot more logic into our front-end than what we've done so far, by making pages more reactive, but also more complex. I've come to accept that there will be a trade-off of features, flexibility and aesthetics.

1. Getting the bundles set up

I'd urge you to look at the code for yourself. Here's how to get it set up.

1.1. Bling

According to Limi, the new ZPT implementation in Zope 2.10 is causing
some problems with Bling. However, the bundle uses Plone 3.0 which
depends on Zope 2.10. I'm using 2.10 for now. I'm also using Firefox, no
luck with Bling in Safari.

svn co https://svn.plone.org/svn/plone/review/bling-plip-121-122-bundle

There are only Zope 2 products here. The non-standard bits are a custom
branch of Archetypes (for automatic validation and quick-edit mode) and
the Bling product, which provides various demos and the custom code.

The templates document_view, event_view, global_contentviews and
portlet_calendar are subject to skin customisations in Bling/skins.

You need to quick-install Bling.

Verify that bling.js is enabled in portal_javscripts - I had some
trouble with it.

Things to try:

 - Double-click the title, description or body text on a Page (e.g. the
front-page). You should get the inline editor. For the body text, you
should get a rich editor (tinyMCE not kupu, it's simpler).

 - Click the view, edit etc tabs - they *should* load without re-loading
the whole page. For me, this doesn't work, though. :-(

 - portlet_calendar I think is meant to have no-page-reload
next/previous month, but this doesn't work for me - I just get the
portlet rendered out-of-context when I click on it.

 - Edit an Archetypes field object, and get a validation error on a
field (e.g. leave title blank) after moving away from it. For me, at the moment, this is throwing a SiteError (which gets rendered *into* the validation error box).

 - Add here/portlet_tags/macros/portlet to right_slots or left_slots.
Add a tag in the text box and press Enter. However, this results in a
SiteError for me at the moment.

As you can tell some things don't work. This is probably because of the Zope 2.10 issue. Ben is rumoured to be working on fixes, though I'm not willing to wait any longer to get this review work started.

I will describe Bling's architecture in more detail later, however.

1.2. KSS

The KSS bundle works on Zope 2.10, I used 2.10 svn from two weeks ago. I've used both Safari and Firefox.

svn co https://svn.plone.org/svn/plone/review/kss-base-bundle

You will also need the Plone 3.0 bundle, as the KSS bundle does not
reference it directly in its Externals.

(if you get errors on startup about ChimeraAzax you probably have an older bundle. Just remove this product, it's not that useful for the review)

Again, these all go in Products. There are no branches of CMFPlone, AT
or anything else. Instead, there are some overrides.

ATAzax customises AT's 'widgets' directory. The livesearch product
re-registers livesearch.js to use a KSS version. PloneAzax overrides
global_statusmessage, portlet_recent and portlet_calendar.

You need to quick-install PloneAzax, ATAzax, livesearch and
KSSMasterSelectWidget to see all the demos.

Things to try:

 - Calendar next/previous buttons reload inline

 - Click a contentviews tab (the green ones) - it should load inline.
Note that there is no feedback that it's thinking and it will take a few
seconds, so on first attempt, it'll seem like it's not working. This is
obviously a weakness (Balazs has said he will add a generic "spinner" soon).

 - Edit a Page and try to leave the title blank, then tab away from it.
You should get a validation error message. Note that validation is only enabled for StringWidget at the moment. (I don't think it's hard to do the validation for other types, but it does require that the AT widget templates are touched to add a particular CSS class, see below. For now, the KSS guys only did StringWidget as a demo).

 - Add a KSS Master Select Widget Demo Type object to see the
master-select widget in action. Obviously, this is just something for
demo purposes, not really related to any PLIP or necessarily important
for Plone

 - Do a LiveSearch. It should work as before, but it should be using
the 'livesearch' product which is KSS backed.

 - Open one browser window showing Plone, then open another. In the
second window, add a new object to a folder. Go back to the first
window, and wait a while (about 1 minute). Eventually, the "recent" portlet will refresh showing the new object, without needing a page reload or indeed any other action.

- Add an AzaxDemo SimpleContent in the ZMI, and go to it. This contains various demos outside Plone that show off KSS in a simpler environment. You'll see things like dependent updates, Scriptaculous effects etc, as well as an ECMAUnit test runner for JS unit tests. These are quite instructive, because they aren't distracted by Plone's large templates etc.

 - Type javascript:void(createLoggingPane(true)); into your Address
bar. You should see the KSS debug pane.

2. Pieces of the puzzle

The high-level overview.

2.1. Bling

When thinking about Bling, I find it easiest to think: Bling == Prototype. Bling is based on the philosophy that Prototype and friends do what we need to do, we just need to make it less work for our developers to write the appropriate Prototype code.

The file Bling/skins/bling.js contains the JS code that enables the features Bling brings to the table. These are very much extensions of Prototype that either add functionality not present there (e.g. things specific to Zope), or higher-level components that group functionality together (e.g. an effect followed by some action followed by another effect, and an update to the portal status message).

The file Bling/ajax.py contains some python functions and helper functions that can construct Prototype JS code based on parameters passed in. These are meant to be called from TAL and mainly generate inline JS. See the next section for an example.

The approach is thus very much a pragmatic get-it-working one, with a thin layer of Python to make it easier to use Prototype in page templates. I'd argue that it still requires an understand of the Prototype development model to fully appreciate what's going on, since the Python functions are typically delegating directly to a particular Prototype component.

The second part of the Bling work is PJS, a python-to-JS bridge. Unfortunately, I've only seen this in its doctest, but the idea is that you can work on a proxy Python object, call methods and set properties, which then gets rendered to a series of JS statements (again based on Prototype primitives). See using_pjs.txt in the Bling bundle for an example.

2.2. KSS

Whereas Bling started with specific use cases and Prototype components that were nearly there but needed to be integrated in Plone, the KSS guys (back when it was just kukit... see below) started with a development model. They built up their framework around the way they wanted to work with JS, and have only recently really got to the real Plone use cases.

When we refer to KSS, we are really talking about a few different bits:

- kukit is a pure-JS, Zope/Plone-independent framework for decoupling JS code that performs some action from the location where it is performed, and to provide a generic communication channel between server-side and client-side elements. kukit is based on plugins, which may for example specify a client-side-only command (like a visual effect), or some client-side handler for a server-side command (see below)

- Azax is a Zope 2 and/or 3 library that can talk to kukit. It provides a view base class (AzaxView, which extends BrowserView) that makes it easier to construct kukit commands for sending back to the client, as well as handling things like the registration of appropriate browser resources.

- KSS (kukit style sheet) is a CSS-like syntax for binding specific client-side or server-side commands to a node on a page.

For an example of a client-side-only kukit plugin, look at Azax/plugins/effects. In its configure.zcml, you will see:




This is the work of Azax. The first two are Zope 3 directives for making ++resource++prototype.js and ++resource++effects.js available. The last directive registers a kukit action called 'effect', that is triggered based on a CSS selector (the registerAction bit also registers a server-side action reference, but don't worry about that for now).

Here is the kukit bit, from browser/plugin.js:

kukit.ar.actionRegistry.register("effect", function (oper) {
        oper.completeParms([], {'type': 'fade'}, 'scriptaculous effect');
        var node = oper.node;
        if (oper.parms.type == 'fade') {
        } else if (oper.parms.type == 'appear') {
        } else if (oper.parms.type == 'puff') {
        } else if (oper.parms.type == 'blinddown') {
        } else if (oper.parms.type == 'blindup') {

kukit.cr.commandRegistry.registerFromAction('effect', kukit.cr.makeSelectorCommand);

Now, you can add to your page a <style rel="kukit" ...> element referring to a file like this:

.myNode:click {
    action-client: effect;
    effect-type: fade;

When you click any class="myNode" it will fade away. The action-client bit invokes a client-side action. The effect-type bit sets the 'type' parameter for the effect plugin.

A server-side action is similar, but involves a server-side handler, usually a view.

Let's say you'd written:

.myNode:click {
    action-server: myHandler;
    myHandler-foo: nodeAttr('id');

Note the nodeAttr() "function" - this extracts the id attribute of the invoked node. The other commonly used "functions" that refer back to the client-side page are currentFormVar() (the value of a form field), currentForm() (the whole form that would've been submitted), and kssAttr() (a more general way of passing parameters either embedded in a node's "class" or in a kukit: namespace attribute).

In this case, kukit will try to invoke ${context/absolute_url}/myHandler, and pass it a parameter 'foo' set to myNode's id. myHandler is often registered as a Zope 3 view:

<browser:page for="*" name="myHandler" class=".myhandlers.MyHandlers", attribute="myNode" permission="zope.Public" />

It could contain something like:

class MyHandlers(AzaxView)

  def myNode(foo):
self.replaceInnerHtml('.someOtherNode', 'You clicked <b>%s</b>' % foo)
      return self.render()

What happens here is that we are calling the replaceInnerHtml() convenience function, which takes a CSS selector as a first parameter (most of them do) and the HTML to place inside the matched node as the second parameter (this could obviously come from a page template or some other source).

When calling these types of commands (which are built up from server-side plugins - you can register a particular adapter to add more, and for most cases a ZCML registration as shown for the 'effect' example above suffices), they are added to a sequence of commands.

The self.render() statement renders these to an XML string which gets sent back to kukit on the cilent side. It will parse the XML payload and determine which client-side plugins are responsible for each command. Here, that may be a 'replaceInnerHtml' handler. This is told which CSS selector to use to figure out what nodes to replace, and the string to replace them with. Other handlers can obviously take different parameters.

3. The we-don't-do-JavaScript argument

One of the fundamental arguments for needing an AJAX framework at all has been that we are quite bad at writing JavaScript. That is, we have traditionally not had very many people capable of maintaining JavaScript.

Both the Bling and the KSS people are using this argumentation, though in slightly different ways.

The Bling position is that it contains very little code (see above). There are about 1,000 lines in bling.js, mostly concerned with putting Plone-specific wrappers around Prototype and Scriptaculous components, to introduce consistent behaviour and desired visual effects.

The remainder of the product is mostly about shielding the developer from having to write JS, by providing a python-to-JS bridge (PJS) and convenience functions (ajax.py) which are able to spit out appropriate Prototype code.

The KSS position is that Javascript should be removed from the page as much as possible. At most, template developers are expected to take some care in applying certain CSS classes or keeping sensible ids on the page elements. The KSS stylesheet links these CSS classes/ids to client-side or server-side plugins, which in turn perform the logic. On the server-side, handlers may also refer to the commands abstractly (by name). The real JS is written as command handlers or client-side plugins. These need to be written generically, in that they take the node that was matched (e.g. the node of the object clicked), potentially some arguments (which can be supplied in the KSS stylesheet, inferred from the node, or send back by a server-side handler) and then perform an action. That potentially makes them harder to write, but also more isolated and re-usable.

As for maintenance, the parts of KSS (kukit, really) that handle the plugin architecture, the marshalling of commands to and from the server and so the standard set of plugins for basic DOM operations etc are about 4,000 lines of JS. The code does generally seem pretty well modularised, commented and laid out.

One point about the KSS side of things is that we have at least two quite enthusiastic developers (Balazs and Godefroid) who know the platform very well, and a few others (e.g. Florian Schulze) who probably know it well enough to be able to figure out what's going on. We may be growing more JS developers as a result of AJAX becoming more important. :)

4. The Prototype argument

One of the initial discussions was around whether to use Prototype, Mochikit or some other underlying framework. The general consensus was that Prototype was the most widely used, mostly by virtue of Ruby-on-Rails, and that going with it would give us the best re-use story, not only of the framework itself, but also of third party JS components that may be useful to us.

That said, some developers expressed a preference for Mochikit's coding style and general architecture, feeling that it was more Pythonic and better tested. Godefroid also pointed out that there has been more svn activity in Mochikit than in Prototype/Scriptaculous of late - I can't really comment on that.

Both KSS and Bling use Prototype and Scriptaculous effects. KSS also ships with Mochikit at the moment, because it uses it in the logging pane, but I believe this is a soft dependency, and no "real" code uses it.

Bling, by its very nature, is very Prototype-specific. The wrappers it introduces are modeled around Prototype's primitives. This is part of what makes it simpler than KSS.

KSS, for its part, is very generic In theory, it should be possible to switch out Prototype-based plugins with Mochikit-based ones in KSS with no difference to any KSS stylesheets or server-side code. Of course, no-one's actually done that on a real and complex system yet, so it's hard to tell whether it'll really be that smooth. The decoupling is there to make it possible, however.

Right now, the KSS demos show off Scriptaculous. Some work has been done on the integration with the parts of Prototype that overlap with KSS/kukit, e.g. the transportation layer to talk to a server-side script. I believe this is working, but I haven't seen a more complex demo yet, mainly because the functionality that's there in the KSS bundle now has been able to make do with simpler primitives.

5. The inline-JavaScript-is-bad-yo argument

One of the strong reactions people have had to Bling is that it produces inline <script> tags in many places. There are some references to Behaviour.js and event-selectors.js, which should allow us to do some of the application of JS behaviour in the <head> and a separate file rather than inline, although I'm not able to see this working in the current bundle.

The main reason for using inline JS in Bling is simplicity. At the point in the template where you are defining an element, you have the necessary TAL context to refer to its url, id, name etc. For things like the inline validation and in-place editor use cases, this is very useful, because you can code the information about the field id (for example) alongside a specific rendering of a field (which is being rendered dynamically based on the AT schema in base_edit, say).

Here is the relevant code for doing inline validation on a field, from field.pt:

                tal:define="ajax python:modules['Products.Bling.ajax']"
tal:replace="structure python:ajax.checkedField(here.absolute_url() + '/ajax_validate', field.getName(), withvalue=True, error='error-' + field.getName())"/>

Notice how we are able to construct a specific URL. ajax.checkedField() is in ajax.py and builds a string of JS using Prototype - the output in the HTML ends up looking like this:

<script type="text/javascript"><!--
    new Form.Element.EventObserver($('title'),
function(element, value) { new Ajax.Updater({success: $('error-title'),failure: $('error-title')}, 'http://localhost:8082/bling/front-page/ajax_validate', { onFailure: function(request){new Effect.Appear($('error-title'),{}); Element.addClassName($('error-title'), 'error');Field.activate('title');}, parameters: "'name=title&value=' + value", onSuccess: function(request){Element.removeClassName($('error-title'), 'error');new Effect.DropOut($('error-title'),{});}, asynchronous: true, insertion: null, method: 'post'} ) })


(it's compressed into a long string, so sorry that my mail client doesn't like it much). ajax_validate, by the way, is in BaseObject.py, and basically just returns an error message.

KSS basically doesn't let you do inline JS at all. The application of behaviour must happen in the KSS stylesheet, outside the page. This is attractive in that it makes it easier to ensure your page templates don't have specific JS dependencies (turn off the KSS stylesheet, or simply don't add it until the template is known to work). For things like the inline validation use case, however, you then need to pass more state around in the abstract.

For example, ATAzax adds 'class="kssValidateInput"' to the <input type="text"> in string.pt, and in field.pt, it applies a CSS class to the field div: 'kukit-atfieldname-${field/getName}' (note that this class="kukit-[name]-[value]" melarky is basically a way to retain XHTML strict compliance; another, equivalent, way is to add a kukit:name="value" attribute, but then you may fail W3C validation)

So, let's say you had a string widget on field 'foo', you'd get

<div class="field ... kukit-atfieldname-foo">
 <input type="text" class="kssValidateInput" ... />

It then has a KSS rule:

.kssValidateInput:blur {
    action-server:                kssValidateField;
    kssValidateField-fieldname:   kssAttr('atfieldname', true);
    kssValidateField-value:       currentFormVar();

This will match any class="kssValidateInput" field (the <input> in the stringfield) when it is blurred, and call the kssValidateField action on the server, extracting the name from the kukit-atfieldname-${name} CSS class applied to the parent <div class="field">. The server-side handler is now passed two parameters: 'fieldname' is 'foo' (as per the kssAttr() statement) and 'value' is the value entered by the user in that field (as per the currentFormVar() statement).

It can now look up the field name in the context's schema and perform validation, and it can use a CSS selector that references the fieldname to ensure the message goes back to the right field. Again, this is done abstractly.

    def kssValidateField(self, fieldname, value):
        instance = self.context.aq_inner
        field = instance.getField(fieldname)
        error = field.validate(value, instance, {})
        # replace the error on the page
        self.issueFieldError(fieldname, error)
        return self.render()

    def issueFieldError(self, fieldname, error):
selector = self.getCssSelector('div#archetypes-fieldname-%s div.fieldErrorBox' % fieldname)
        if error:
            self.replaceInnerHTML(selector, error)
            errorklass = ' error'
            errorklass = ''
klass ="field%s Archetypes%sfield kukit-atfieldname-%s kukit-widgetstate-edit" % \
                    (errorklass, fieldname, fieldname)
        # set the field style in the required way
            self.getHtmlIdSelector('archetypes-fieldname-%s' % fieldname),
            'class', klass)

This is in ATAzax/validation.py, and is a Zope 3 view. Notice how the main function returns self.render(), which renders the appropriate response string to the client-side handler in kukit to process the commands. The commands are built up with calls to self.replaceInnerHTML(), self.clearChildNodes() etc, which are convenience functions built into the AzaxView base class (which itself inherits from BrowserView). It is not much harder to reference the commands by name, however, and pass them whatever parameters they need, and there is an adapter-based mechanism for plugging in new command types.

Here, the complexity of the KSS solution is not that hard to map out - you just have to think in terms of a variable (the 'fieldname') that is passed to the server-side handler after being extracted from the page, and that some CSS selector is used to refer back to the page. In more complex cases, this state-passing may be more cumbersome. For example, if you had a composite page with two objects being validated, you may need to pass not only the name of a field being validated, but also the UID or URL of the exact object being validated (in the example above, the KSS validation view is being called with the same context as the page template, so it is able to just use self.context).

Note that both Bling and KSS in these examples have had to deal with the existing HTML structure of AT fields and their use of CSS classes, which makes them look a bit more messy than they would've been if they'd started from scratch.

6. The we-love-Zope3 argument

Bling has very little need for Zope 3 infrastructure, and there are no Zope 3 techniques in use in the bundle. It may be possible to refactor some of the ajax.py JS-generating functions into components, but the benefits may not be that great - these are very close to the page template. It may be desirable to use a view to call some of the ajax.py functions, however, and prepare a result string to be rendered into the page, to keep some of those long python: expressions out of the page template.

I have seen very few examples of PJS in action, but Ben did assure me that the basic PJS implementation is pure-python, so that it could be used in a view, for example. Beyond that, there isn't that many server-side handler code in Bling at the moment. ajax_validate() went straight into BaseObject, and the inline editing code relies more on client-side JS plus the standard AT field save handlers.

KSS/Azax is very Zope 3 friendly. In fact, I believe Azax (the Zope-specific, not Plone-specific parts) will run on Zope 3 on its own. The preferred way of doing server-side handlers is via a Zope 3 view, although you can use a Script (Python) instead if you want. Plugging in new commands and client-side handlers is done using a custom ZCML directive, which registers the appropriate adapters to make the command callable and renderable. The KSS examples also use Zope 3 resources (the ++resource++ namespace) to make its JS and KSS files available (again, this is recommended but optional) and it has a custom ZCML directive that can compose the main 'kukit' resource from several stylesheets to make it a single import (and a single entry in portal_javscripts) even if some bits are optional/soft dependencies.

7. Real world progress

In theory, Bling has covered the major use cases - inline validation, in-place editor (including the tricky cases such as WYSIWYG editing of rich text fields), inline loading of fieldsets, inline calendar cycling. However, the bundle is fairly broken at the moment, which is a shame.

Bling also feels like it needs a fair bit of cleanup. There are various files which are either not used, or contain simple demos, and some JS libraries registered which I don't think are used. This is understandable in that Bling has been a testing ground for a lot of new use cases and functionality, but I wouldn't feel very comfortable shipping it as-is without some cleanup of the codebase. I doubt that this is terribly difficult, although it may depend on Ben to have the time to go through it.

The KSS bundle also covers most of the real use cases, and at the time of writing feels more solid. It does lack a Plone implementation of inline editing, which could be tricky, although hopefully it could leverage some of the JS/Prototype code from Bling for this purpose. The inline validation use case is only covered for StringField, but it should be fairly trivial to extend it to all fields - it just needs to be tested. Another small issue is the lack of a "spinner" (or a "loading..." message), which sometimes makes it a bit hard to see what's going on.

The KSS/Azax/PloneAzax/ATAzax codebase is much larger than Bling's, although it generally seems to be fairly well organised, clean and has some test coverage (I can't really comment on how good it is). There is a fair amount of code there for backwards compatibility (I believe it supports Zope 2.8, 2.9, 2.10, 3.0, 3.2 and 3.3 - wow) and selection of available features depending on Zope version. Some of that could probably go away as far as Plone is concerned, simplifying things.

There is some documentation on http://azax.ree.hu, though KSS/Azax will always have higher documentation needs than Bling since it has more infrastructure. I didn't find it too hard to find out what was going on and play with a few KSS commands of my own, but less experienced developers will require some tutorial-style documentation. This is true for Bling as well, although I imagine that someone familiar with Prototype would find Bling easier to get to grips with (and my the same token I find some of its JS to be voodoo).

8. Community support

Bling has been developed more or less exclusively by Ben Saller, with Alex Limi pushing use cases and UI decisions (they live in the same city, it helps). I believe Kapil has been helping out a bit as well, though almost all the checkin messages are from bcsaller.

The current state of the bundle is a bit troubling as far as keeping the software up-to-date goes. I'm not really sure what the problem is. In theory, Bling should require less maintenance than KSS, however, since it's mostly a wrapper around Prototype patterns and fairly "shallow" in terms of layers of indirection and abstraction.

KSS was started by Godefroid Chapelle and Balazs Ree, and has seen quite determined and steady development. Florian Schulze has been involved in the development as well, as has Martin Heidegger. There is also a sprint next week which will feature the above plus Daniel Nouri, David Convent and Christian Klinger. Daniel and David have not used KSS before as far as I understand, but are hoping to learn its development approach.

9. Future plans

I haven't heard too much concrete from Ben about the future plans of Bling. I know he's working on making the bundle work again with Zope 2.10/Plone 3.0. I also imagine that PJS will be showed off more on the server side, although I have yet to see it used for a real-world feature.

Godefroid and Balazs have shown very strong commitment to the KSS philosophy (Balazs called me once and said so in ten different ways before I could get a word in... :-), and they are also counting a lot on the forthcoming sprint to tidy up use cases, expand the inline validation and get inplace editing to work. They are also hoping and pushing for KSS + Azax (the Zope integration) to become an Ajax platform of choice in the Zope 3 world, and for KSS + kukit (the client-side-only parts) to be able to live outside Zope altogether. Those are erstwhile goals and I don't see any reason why this couldn't happen, but obviously not reality at the moment.

10. Caveats and concerns

I won't state a preference here, mostly because I don't really have one. The ideal outcome in my mind, which is also in line with what we discussed at the Archipelago sprint, is that KSS show that they can adopt the various Prototype components in bling.js without too much re-writing so that we can leverage a the real use-case work that Ben has done, but using the KSS binding and delivery mechanism.

I do find it a bit easier to understand where the server-side parts fit into the picture with KSS, because the separation of concerns seems clearer. The more comprehensive documentation in KSS probably helps, too. I'm sure that someone who understood Prototype would find Bling much easier to grok, though.

The main issue for me is one of risk. There is quite a lot of framework code in Azax, and a lot of JS framework code in kukit. Some of that necessarily overlaps with things that Prototype could do on its own, because it is promoting a development model that is orthogonal to what Prototype tries to achieve. In particular, I'm talking about the way server-side asynchronous requests are made. That said, at the time of writing the KSS bundle feels more solid and better tested. The things it claims to do work, and work quite well, and the code is quite well organised.

Azax is pretty well documented and has some test coverage, but it could be improved. There's also a big question mark over the in-place editing use case, which is demonstrated in the azaxdemo product on a simple form, but could be harder to do for Plone, especially when it comes to the WYSIWYG editor.

Many hopes for completing features are being pinned on the upcoming sprint, which will hopefully also prove whether the development model can be taught to people who aren't already familiar with it. This relates to another important point - there seem to be (a few) more people with their weight behind the KSS side of things than the Bling side of things (for political or practical reasons I don't know). I think it's fair to say that Bling has much less code to maintain, but it still needs people to drive its development.

Finally, here is a summary of what I feel is outstanding:


 - Make the bundle work again
- Ensure calendar cycling, portlet refresh, inline loading of view/edit/etc tabs are actually there
 - Clean up examples and half-finished items
 - Ensure no more than the necessary JS libraries are installed
 - Show how PJS is used in practice


- Make in-place editing work on all field types, especially rich-text fields - Make a generic "spinner" and consider hooks for other common Plone UI behaviour (e.g. Bling "glows" a field that is in-place editable for a few seconds after a page is loaded - these things are probably best kept general)
 - Finish in-place validation enabling of Archetypes
- Merge the customisations that go in ATAzax and PloneAzax into the core products once they're proven to work.
 - Improve interface documentation and test coverage
- Produce more tutorial-style documentation, e.g. around producing new plug-ins

If you got this far, well done. Make sure to tell me, I'll buy you a beer at the conference.


Framework-Team mailing list

Reply via email to