Sunday, June 12, 2011

z3c.jbot: magical with your skins resources

This article is the consequence of a small comment of David Glick at Stack Overflow.

If you never met before z3c.jbot, let simply say: this is a toy that commonly make happy the themer of your team. It simplify a lot the customization of a single template inside the Plone universe.
The use of z3c.jbot give you some little performance cost, and commonly you can do stuff without it, however it's use require less development time most of times.

What I learn from the David's comment, is what the official documentation of z3c.bot report in a simple sentence:
CMF objects
Any skin-object (e.g. images, templates) on the file system (directory views) can be overridden.
What is amazing there in the part that say "Any skin-object". Later we will show two great examples.

Complex skins layers subfolders
Maybe Plone 5 (or 6, or 7) won't use the CMF skins technology. However today the CMF skins is still a reality.
What's the problem of skins? Commonly no-one: customize an object in the skins layer is very simple, but only if the object itself isn't in a skin subfolder.
What's the problem with subfolders? Well, the problem is always the customization. To customize the object in the sublayer "/foo/object", you need to customize also the foo folder, putting all this in your personal skins layer. But in this way you also need to customize all other skins object in the foo folder.

So why a product developer sometimes register a single skins layer with subfolders instead of register multiple layers, or keep all resources in a flat simple layer?
Because sometimes you need to put into Plone external resources, that commonly are found as a folder tree structure.
One of the most simple example can be the need of include into Plone an advanced JavaScript product, that is released with static HTML file, images and CSS: all of those resources are already configured to be used keeping this structure. Change this product configuration can be painful.

I will show two main examples:
  • TinyMCE
  • Archetypes widgets
Both examples are available in a collective product there:
https://svn.plone.org/svn/collective/collective.examples.jbotforskins/trunk/

Customizing TinyMCE
Today customizing TinyMCE can be tricky. Maybe you want to change only a little part, maybe a single JavaScript, but the product register a simple skins layer named tinymce, that contain:
langs (dir)
plugins (dir)
resolveuid.py
themes (dir)
tiny_mce_init.js
tiny_mce.js
tiny_mce_plone3.css.dtml
tiny_mce_popup.js
tiny_mce_src.js
tinymce_wysiwyg_support.pt
utils (dir)
wysiwyg_support.pt
I had only a couple of experiences customizing TinyMCE and I was forced to develop a new plugin both the times. Why? Because commonly you need to change something not in the skins layer root (where customizing is easy), but in one of the plugins subsection.

A way can be inject you modification using JavaScript, but this can be really tricky, because TinyMCE WYSIWYG editor is generated using JavaScript and loading an IFRAME (sometimes more that a single IFRAME, if you need to change something in the plonelink or ploneimage plugin).

So, as I sayd, a way is to develop another plugin, that (for example) will replace the basic plonelink ones. You need copy and paste all the plugin code, then you change what you need.
More or less you have created a plugin branch... when another version of TinyMCE will be released, you are forced to check your code for find any changes you need to merge in your plugin...

Let now show how z3c.jbot helps. For example, we simply add an alert JavaScript message inside one of the TinyMCE file. In this way can be really simple to see if our changes are taken (because using TinyMCE we see an alert every time).

We will take only this file into consideration:
Products/TinyMCE/skins/tinymce/plugins/plonelink/editor_plugin.js
How to change only this file without replacing the whole plugin?

First of all we add a Plone product to our buildout. The product can be really simple so we need only a ZCML registration, a folder and out customized JavaScript source.

First of all, we register the z3c.jbot folder.

After that we simply put in the jbot_templates folder the customized JavaScript source. The magic of z3c.jbot is use the name of the customized file for know what to customize. This name must reflect the canonical name of the original file, so:
Products.TinyMCE.skins.tinymce.plugins.plonelink.editor_plugin.js
Very easy! We customized a single file without creating a clone-plugin!

Archetypes widget
Another evil task of the Plone universe is when you need to customize an archetype widget. Why? I bet you know the answer... because all widgets are stored in a skins subfolder:
skins/archetypes/widgets/...
Change the template used for a widget is simple. Create a new template for a widget is easy... however is not so easy to change the default template for all widget of a kind.

Let show an example: imagine you need to customize the file widget, that is all stored in the file.pt template:
Products/Archetypes/skins/archetypes/widgets/file.pt
As before, we can simply put our customized file in the jbot_templates folder. The file name will be:
Products.Archetypes.skins.archetypes.widgets.file.pt
What we can put in the new widget? For example we could like to replace the HTML file upload with a fantastic HTML 5 Drag&Drop Javascript widget. All this can be obtained providing a customized file.pt templates.

Again, this is simple, but only thanks to z3c.jbot!