Edit online

Best Practices for Plugin Developers

This document is meant to provide tips for those who develop custom plugins to extend the functionality of Oxygen XML Web Author.

Preserving Compatibility for Plugins Developed Prior to New Features Being Added in Web Author

It is possible that functionality added in a custom plugin relies on a certain behavior in Oxygen XML Web Author that could change in future releases. Although the API will still be compatible, some functions may not work properly if those specific functions were developed in the plugin based on a previous behavior.

Starting with version 21.1.1, functionality was added to open documents in the Web Author visual editor without reloading the entire webpage (for example, topics can be opened from the DITA Map view without refreshing the page). Some custom functionality added in plugins prior to this release might require a page reload to work properly. For example, custom toolbar actions may no longer work as expected, or a side view might display the wrong information.

More specifically, a plugin's JavaScript code is loaded only once (when the web page is loaded), while a framework's JavaScript code is loaded each time the visual editor is loaded. So, if the plugin extends functionality that is also defined in a framework, the code from the plugin will not be loaded if the entire webpage is not refreshed.

To preserve full compatibility (at the cost of not being able to take advantage of the benefits of not requiring a full refresh whenever a document is opened in the editor), there is an option called Change editors without page reload in the Administration Page. Disabling this option will force the page to be reloaded whenever a document is opened. This could be a temporary solution while your custom plugin is being updated to account for the new behavior.

Common Mistakes:
  • Plugins keep a singleton object to hold information about the current editor. Since it is now possible to have multiple editors opened at once, this approach is no longer possible.
  • Plugins fail to clean up memory and listeners associated with the current editor when it is closed. Prior to version 21.1.1, this approach worked fine because the browser tab was reloaded anyway.

Disposing AbstratAction Implementations

If a plugin implements the AbstractAction class, you should consider implementing the dispose method of this class. Typical things to do in the dispose method include:
  1. Dispose any dialog box that was created by the action.
  2. Reverse any changes to the page DOM outside the editor content.
  3. Remove any global listeners (i.e. on the window object).
  4. Clear timers started using setTimeout or setInterval.
  5. Abort or ignore the results of any HTTP request that is in-progress.

Making Custom Side Views React to Editor Changes

In Web Author, a sync.view.ViewRenderer class is informed when the current editor has changed using the editorChanged method. This method can be called multiple times and the view needs to be updated when a new editor becomes active.

The view should also reset its state when the current editor is disposed. This situation can be identified by listening on the sync.api.Editor.EventTypes.DISPOSE event.

Although not as popular, Web Author has special editors (or previews) for non-XML files (for example, Markdown documents, images, or plain text files). There is also an empty editor that simply displays an error message for files that fail to load (for example, files that cannot be found on the file server). A sync.view.ViewRenderer implementation is notified anytime a file is loaded in an editor that it supports. By default, the only one that is supported by the sync.view.ViewRenderer is an editor with the type sync.api.Editor.EditorTypes.AUTHOR (the XML visual editor). For other editor types, it is disabled. If you want a view to be displayed when a file is loaded in any other type of editor (other than the normal XML visual editor), you can override the supportsEditor method in the sync.view.ViewRenderer implementation.

Clearing Information Related to the Current Editor

If a plugin listens on sync.api.Workspace.EventType.BEFORE_EDITOR_LOADED or sync.api.Workspace.EventType.EDITOR_LOADED events to store some information regarding the current editor, you should make sure to reset this information when the editor is disposed.

Events such as sync.api.Workspace.EventType.BEFORE_EDITOR_DISPOSED or sync.api.Workspace.EventType.EDITOR_DISPOSED can be used to clear all information.