Personal tools

Jun 01, 2010

Sorrento Amberjack Sprint: can you please make my Javascript simpler?!

The Javascript source of collective.amberjack need some love. Not a simple task, but something has been done (and something more will be in future).

First of all: the inherited problems

Version 1.0 of collective.amberjack.core is a simple Plone 4 compatibility version of the old 0.9 released.

When we released this we already know that the Javascript code inside was a mess, but before beginning some kind of refactoring procedure we need to know how the project will be changed in future.

The product has a core got from the Amberjack library, in last years many different programmers take part to the develop, meanwhile the product itself (and also Plone) was changing.

Amberjack original library is framework independent while Plone (that is a smart guy) rely on jQuery. Also we must not forget that Amberjack has not exactly the same target of collective.amberjack...

Wow... how many problems!

Not all those problems will be fixed in the 1.1 version, but I managed to simplify a little the code of two of the main method of amberjackPlone.js source.

How the old amberjackPlone.js was done

Saying "the code is ugly but works" is not a valid excuse... amberjackPlone.js contains two important methods:

  • highlightStep is the method that highlight all the clickable/usable elements in the page for all steps.
  • doStep is the method called to reproduce the user action on the page

What a user can do in a Plone site is a long list of different actions... list that become something like this for highlightStep:

if(type_obj=="checkbox" || type_obj=="radio"){
else if (type_obj=="select"){
	var highlightThis = jq(obj + " option[value="+ AjSteps[num].getValue() +"]");
else if (type_obj=="multiple_select") {
...going on and on...

...and like this for doStep:

if (type_obj == 'link') {
	location.href = obj.attr('href');
else if (type_obj == 'button');
else if (type_obj == 'collapsible') {
...going on and on and on and on...

Ugly enough? Do you think that the AntiIfCampaign hate us? Yes... probably...

So the first step is to remove this mess and try to port in Javascript the concept of adapter (unluckily not so flexible as Zope ones).

Even worst: many of the if statement in both doStep and highlightStep was testing the same expressions (like the "select")!

All this code has been removed.

Now both doStep and highlightStep are simply calling a sort of adapter built in the stepAdapters.js file:

AmberjackPlone.stepAdapters = {
	link: {
		highlight: null,
		checkStep: null,
		step: function(obj, type_obj, jq_obj, value) {
			location.href = obj.attr('href');
	button: {
		highlight: null,
		checkStep: null,
		step: function(obj, type_obj, jq_obj, value) {;
	collapsible: {
... going on and on, but more readable!

For every possible action know, highlightStep and doStep will check if an handler is present in this structure (in this example the code is from the doStep):

if (AmberjackPlone.stepAdapters[type_obj] && AmberjackPlone.stepAdapters[type_obj].step)
	AmberjackPlone.stepAdapters[type_obj].step(obj, type_obj, jq_obj, value);

The highlightStep will check for highlight function.

If not if found, perform the old final else statement.

What is the checkStep section? In this sprint another group (Mirco and Simone Orsi) take a look to the feature that test if a user has completed all the steps before can go to the next page. Again, for some possible action the tour can try to test if you have finished your work.

In the old approach this will lead us to a new big and monolithic function. Now is only a new tiny method that call an handler.

What's next?

Adding some documentation, for sure...

Also other part of the code can be changed to become more clear... be continued!

Problem with documentcontext in Java Agent

Filed Under:

In a Java agent, If you are accessing your document via agentContext.getDocumentContext(), I've found a problem in managing attachment with extractFile method

Error found is "a database handle to a remote database cannot be used by more than one thread"

This is my workaround.

Instead of doing:

AgentContext agentContext = session.getAgentContext();
lotus.domino.Document inDoc = agentContext.getDocumentContext();
Database db = agentContext.getCurrentDatabase();

 try doing this : 

AgentContext agentContext = session.getAgentContext();
lotus.domino.Document inDoc = agentContext.getDocumentContext();
String unid = inDoc.getUniversalID();
Database db = agentContext.getCurrentDatabase();
lotus.domino.Document inDoc2 = db.getDocumentByUNID( unid );

Now works!

Sorrento Sprint Summary - collective.amberjack progress report

RedTurtle is participating each year in Sorrento's Plone sprints. We were there also last week. It was an amazing time of brainstorming and coding. I will try to make a summary of what we have archived.


We have started collective.amberjack presence in Sorrento with Massimo's presentation at the European Plone Symposium



Then we had two sprinting days. We have started day one with brainstorming. We had three objectives/questions:

  • collective.amberjack sandbox
  • refactoring the code - how to simplify collective.amberjack tour definition and registration
  • translations - how to manage tour/steps translations

thanks to a fruitful discussion (garbas, dukebody, gborelli, miziodel, shywolf9982, sorry if I forgot your name ;-) we have right now answers to all of our dilemmas.


First idea of having a sandbox for collective.amberjack came up at last Plone Conference in Budapest. We have collected a lot of ideas for different use cases. We have had also some internal brainstorms in RedTurtle about it. Finally after confronting all the concepts - during Sorrento brainstorming - we will have a simple solution which should satisfy most of the users:

  • simple Plone site deployment (like
  • open registration for all users
  • collective.amberjack preinstalled and ready to use
  • user will try-out Plone using amberjack in his member folder
  • nightly restart with fresh Data.fs

Code refactoring

We have started refactoring collective.amberjack. There are 3 areas of interests: javascript, tour definition and tour registration. Luca was doing a great job trying to simplify javascript part. He also prepare a good startup for future enhancements. I was refactoring tour part. We have decided to use a 

configuration baseD tour definition,

which looks like that:

steps = 
title = Add and publish a Folder

blueprint = collective.amberjack.blueprints.step
title = Create a new folder
url = /
text = Folders are one of ....
validators = 
        python: isManager
        python: isNotFolderCreated
microsteps = 

blueprint = collective.amberjack.blueprints.microstep
description = If you don't want to perform the ...
automatically done by your browser.

blueprint = collective.amberjack.blueprints.microstep
idstep = menu_add-new
description = Click the [Add new...] drop-down menu.

blueprint = collective.amberjack.blueprints.microstep
idstep = new_folder
description = Select [Folder] from the menu.

This concept is well known across the community. I hope it will be also more human readable comparing to python dictionary ;-). We have a working version in the trunk. For new tours we have also 

new tour registration 

- comparing to old approach (registration only using ZCML) you can now use also TTW registration. Other important change is that tour doesn't need to be a python package any more. Because it's a simple .cfg file right now you can simply zip it into an archive (zip, tar) and register it. We have a working implementation for web source and local file system registration (which you can find in the trunk). Archive file can be shipped with multiple tours and with


which right now are still just a concept that need to be implemented. We would like to make a use of i18ndude tool but because it was designed for ZPT this could be a wrong approach. Overall idea is to keep all the files (tour and the translations) together, something like:

  |- tour1.cfg
  |- tour1_en.po
  |- tour1_it.po
  |- tour1.pot
  |- tour2.cfg
  |- tour2_en.po


Fixing bugs

Mirco and Federica were working together and did an enormous job fixing most of the 1.1a release bugs. Thanks to Rob we have solved also some TinyMCE problems that we have had. We have still some open issues, like 'new portlet creation' tour that need some attention so we still need your help!

What's next?

The current development focus is on 1.1 release, which includes:

  • new tour definition (python dictionary based tour will still work until 1.2)
  • new tour registration (old registration will still work until 1.2)
  • finish translation implementation
  • fix last bugs
  • deploy sandbox probably on
  • collective.amberjack.windmill - which should become default interface for creating and editing tours; we have right now something more then just proof of concept: