WebApp 1.3 API changes

February 12, 2013 by Monomon   Comments (0)

, , , , ,

'About' text

Perhaps the most visible change for plug-in developers is that each plug-in now has its own 'about' text.

This text appears in the 'about' section of Settings. For widgets, it can also be seen separately when a user clicks on the 'about' button in the widget's header. This button only appears if the widget registered the 'about' text.

In order to add about text to a plug-in, an 'about' property needs to be passed in its configuration:

Ext.applyIf( config, { about : 'plugin about text' });

Recommended is that the plugin will also initialize the new configuration option 'displayName', which will be the displayed name of the plugin in places in the UI where the plugin is referenced.

If the plugin wishes to register additional blocks of text for the about text, or doesn't want to use the 'about' configuration option, the Plugin/Widget class has been extended with the function 'registerAboutText()' which will be used to register the about text as well.

For better separation of the about text from code, Zarafa recommends creating an ABOUT.js file in the js source folder of the plugin (e.g. plugins/browsercompatibility/js). Inside it, add an ABOUT member to the plug-in's namespace:

Zarafa.plugins.browsercompatibility.ABOUT = "about text";

This is then assigned to an 'about' property of the plug-in config during initialization. This way several plug-ins in the same namespace may share 'about' information:

Ext.applyIf(config, {
name : 'browsercompatibility',
displayName : _('Browser Compatibility Plugin'),
about : Zarafa.plugins.browsercompatibiltiy.ABOUT

Error handling

There have been several changes related to error handling.

Store and proxy exceptions

Store and data proxy exception handling has been centralized in Zarafa.js. It listens to the 'exception' event of Ext.data.DataProxy.

In the handler, Zarafa.onException, depending on the type of error, a message is constructed and then displayed in a notifier (see section Notification system).

This means that now a PHP module does not have to worry about setting up its own exception handlers. As long as it sends a proper message back to the client, the core system will pick it up and show a notification.

Plugins can still listen to the exception event of their proxy or store in the same way they used to:

this.store.on('exception', this.onException, this);

Connection timeout handling

There is now a dedicated mechanism for checking the WebApp's connection to the server - Zarafa.core.PingService. It regularly sends a request to the server in order to determine whether it is reachable. When a ping request fails, the service displays a notification and retries with an exponentially growing timeout.

When the server becomes unavailable, queued requests will be suspended. If the connection is restored, these requests will be re-added to the queue.

Login errors

The behaviour of WebApp has been improved in the case when a user's session expires or another user logs in in the same browser.

When this occurs the user is notified that they need to reauthenticate. They could choose to continue working, but would be unable to retrieve from or send anything to the server.

Notification system

A significant improvement in WebApp 1.3 is the overhaul of the WebApp notification system.

There is a global Zarafa.core.ui.notifier.Notifier object created in Zarafa.core.Container, which takes care of registering and selecting notifier plug-ins, and displaying messages through them.

The notifier plugins are:

  • Zarafa.core.ui.notifier.SliderNotifierPlugin - a box that slides into the window; may be timed or persistent, e.g. waiting for a click
    • Zarafa.core.ui.notifier.DropdownBoxPlugin - a box that slides from centre top
    • Zarafa.core.ui.notifier.PopupBoxPlugin - a sliding box in the bottom right corner
  • Zarafa.core.ui.notifier.MessageBoxPlugin - notification is displayed in a regular Ext.MessageBox
  • Zarafa.core.ui.notifier.ConsolePlugin - prints to the browser console

Zarafa.core.ui.notifier.Notifier identifies the above listed plug-ins by short names, such as 'dropdown' and 'messagebox'.

Plugins register themselves to Notifier by calling the following method:

container.getNotifier().registerPlugin('dropdown', new Zarafa.core.ui.notifier.DropdownBoxPlugin());

Then, in order to show a notification, a component may call the notifier plugin's notify method.

The notify method takes four arguments:

  • notification type - error, warning, info
    • a subtype is optional, but recommended; it is separated from the type with a dot - e.g. error.proxy
  • title
  • message
  • config - an optional configuration that can contain the following:
    • container - container to which the notifier will be restricted
    • persistent - true to make the message persistent, not timed; it can be hidden later by using the 'destroy' option
    • destroy - don't create a new message, but destroy the previous
    • update - don't create a new message, but update the previous
    • reference - original message which must be updated by this action
    • listeners - event handlers which must be registered on the element

Persistent notifiers obtain the DOM element containing the notification in order to remove or update it.

Here is an example of creating a persistent notification, updating it, and then destroying it.

// notify() returns the DOM element
var notifyEl = container.getNotifier().notify('error.connection', 'title', 'your message', {
container : this.getEl(),
persistent : false

// update notification with another title and message
container.getNotifier().notify('error.connection', 'new title', 'new message', {
container : this.getEl(),
update : true,
reference : notifyEl

// use this element to tell the notifier which message to destroy
container.getNotifier().notify('error.connection', null, null, {
container : this.getEl(),
destroy : true,
reference : notifyEl

getNotifier() initializes the notifier if it hasn't been already. The type of notifier is selected by matching the message type against a setting. For example, by default "error" is shown in a messagebox notifier; "info.newmail" is shown in a popup notifier.

Selecting the type of notifier for your own component would simply require you to place a mapping of a custom notification subtype to a notifier type in settings, and then use this notification subtype when calling notify().


Attachment handling has become a lot easier and more intuitive for users, leveraging some HTML5 APIs such as File and FileList.

Gone is the WebApp attachment dialog. Instead, when a user clicks on the 'attachment' button, they immediately get a file selection dialog. In addition, files can be dragged directly from the desktop/file browser to WebApp.

The above-mentioned APIs are not supported by IE9, which falls back to the previous method.

Added attachments appear as interactive boxes, which indicate the upload progress of the file, can be easily removed, etc.

Since the latest changes plug-ins do not have to use their own dialogs and a special recordType to make instances of attachments -  the IPMAttachmentStore will use the IPMAttachmentStore::reader::recordType. One only needs to configure the recordType in the reader.

RecipientField drag&drop

The Zarafa.common.recipientfield.ui.RecipientField now supports drag&drop by default; it has a drag zone and a drop zone installed on it. Now a user can drag recipients between the various recipient fields in WebApp - TO, CC, etc.

In RecipientField the configuration options enableDrag, enableDrop, and enableDragDrop are set to true by default, so the drag and drop zones are installed in RecipientField.initEvents.

Its parent class, Zarafa.common.ui.BoxField, has BoxFieldDragZone and BoxFieldDropZone defined, but not instantiated. A developer can easily create a BoxField with draggable boxes by following RecipientField.initEvents.

// this class extends BoxField
myCustomClass = Ext.extend(Zarafa.common.ui.BoxField, {
// This method is called during rendering; another method could be used, but should be in a suitable place
initEvents : function()
// do not forget to call the superclass method
myCustomClass.superclass.initEvents.apply(this, arguments);

// enable dragging from this field
this.dragZone = new Zarafa.common.ui.BoxFieldDragZone(this.container, {
ddGroup : 'dd.mapiitem', // drag and drop group determines the fields this component cooperates with
field : this // pass a reference to this field to the DragZone

// enable dropping in this field
this.dropZone = new Zarafa.common.ui.BoxFieldDropZone(this.container, {
ddGroup : 'dd.mapiitem',
field : this


In order for the different fields to cooperate, one should also override some methods of the Zarafa.common.ui.BoxFieldDropZone - e.g. onNodeDrop, isValidDropPoint, etc. Check the documentation for more details.

Callback queue now available

There is a new class Zarafa.core.data.CallbackQueue. It allows the sequential execution of tasks - for example multiple validation steps to be added and executed in order.

Currently it is used to validate messages before they are sent from a Zarafa.core.ui.MessageContentPanel.

Here is an excerpt from MessageContentPanel showing how to use the CallbackQueue:

first create the queue

this.sendValidationQueue = new Zarafa.core.data.CallbackQueue();

add a task to it

this.sendValidationQueue.add(this.validateEmptyRecipients, this);

when we are ready, run it

this.sendValidationQueue.run(this.onCompleteValidateSendRecord, this);

this.onCompleteValidateSendRecord is the callback that will be invoked once the queue has finished.

Plug-in namespacing

Plug-in namespacing has been tidied up. All plug-ins have been moved under Zarafa.plugins, and widgets under Zarafa.widgets.

For instance, the Twidget now resides in Zarafa.widgets.twidget. All Quick item widgets have been moved to Zarafa.widgets.quickitems.

The pdfbox plugin is namespaced under Zarafa.plugins.pdfbox.

It is desirable that all plugins and widgets keep to this structure.


See WebApp 1.3 Release notes for more general information