handling of Plone legacy code
suggestion to handle the existing javascript in Plone, and integrating it
Problem statement
This issue was first raised when we kss-ised the action menus. The issue can be best described this way:
Any javascript code, that Plone loads on the page load event, will not be utilized on dynamic kss loads, since we do not know which node the handler should belong to. For example, the action menus are bound by the legacy code when the page is loaded, but when we replace the part of the page dynamically and this part contains the action menus, the legacy code will not be trigered and the menus will not be set up.
The best way to provide the new setup is through kss itself, but it is also important that we want to keep legacy code working if kss is inactive. This fulfills the requirement that Plone should work without kss as before.
Kss has a "load" event that is boundable to nodes and is properly invoked on dynamic loads. It also can limit its effect to phase 1 (original pageload) or phase 2 (dynamic pageloads). This means that a phase=2 load can coexist with the legacy code.
We will strictly talk about the existing javascript load code in Plone, that we want to reuse right away. This approach does not want to be valid for entirely new developments.
Process of reaching kss conformity with legacy js
I suggest the following generic approach to be taken. The approach should be executed on all plone javascript code step by step. Depending on the case, Level 2 may be sufficient to be reached, but in certain cases it is desirable to reach Level 3.
Level 1: use registerPloneFunction
All code that is listening to the page load event, should use registerPloneFunction. No script tags are allowed. Example:
registerPloneFunction(ploneFormTabbing.initialize);
At this stage, the code does not work with dynamic page loads yet but it at least uses a standard solution.
Level 2: write kss for reload
A lightweight javascript wrapper around the existing handler code should be created. Example:kukit.ar.actionRegistry.register("plone-initFormTabs", function(oper) {
oper.completeParms([], {}, 'plone-initFormTabs action');
if (oper.node.tagName.toLowerCase() != 'form') {
throw 'The plone-initFormTabs action can only execute on a form node as a target.';
}
var form = oper.node;
ploneFormTabbing.initializeForm(form);
});
kukit.cr.commandRegistry.registerFromAction('plone-initFormTabs',
kukit.cr.makeSelectorCommand);
This mainly just registers it as a client action, makes it visible for kss and adds parameter checking. (The last line is needed if it can be called explicitely from the server, which can be handy.)
It also needs a piece of zcml to let the server know about it:
<kss:registerAction
name="plone-initFormTabs"
command_factory="selector"
jsfile="/notes/handling_of_plone_legacy_code/browser/plugin.js"
/>
Then we need the kss rule to activate it all:
form.enableFormTabbing:load {
evt-load-initial: false;
action-client: plone-initFormTabs;
}
When this is implemented, original payloads are handled by the legacy code, while dynamic loads are handled by kss.
Level 3: take over initial loading by kss
Next, we can take over the initial loading also to the kss procedure. We only need to remove the initial parameter from the event (or set it to True):
form.enableFormTabbing:load {After this, the registerPloneFunction should get a second boolean True parameter:
action-client: plone-initFormTabs;
}
registerPloneFunction(ploneFormTabbing.initialize, True);
Then we modify the registerPloneFunction code in a way that if the second parameter is present, and kss is active, it should entirely bypass the execution. (This also has the advantage that in javascript the excess function parameters are silently swallowed, so any new code that calles the unmodified registerPloneFunction, will function as supposed to.)
When this is implemented, the legacy code will not be run only when kss is inactive. If kss is active, the legacy code is skipped entirely and kss can do whatever it sets up.
Changes needed to the Plone core
The above procedure needs to be applied to legacy code components one by one. There is one change that needed to be changed in the core, to allow the entire procedure:
registerPloneFunction needs to be altered in a way that if it receives a second parameter and it is True, and kss is loaded, it should not do anything just log an info message to kss that the registration is skipped in favour of the kss load events. This only comes to play if Level 3 is implemented for any given legacy js component.