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.
- 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
AbstractAction
class, you should consider
implementing the dispose
method of this class. Typical things to do in the
dispose
method include:- Dispose any dialog box that was created by the action.
- Reverse any changes to the page DOM outside the editor content.
- Remove any global listeners (i.e. on the
window
object). - Clear timers started using
setTimeout
orsetInterval
. - 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.