Last date modified: 2026-Jul-14
Viewer Events
This page covers two categories of events:
- Viewer collection events — events on
IViewerCollection(e.g.mainCollection), such as when a document loads or the active viewer type changes - Individual viewer events — events on a specific viewer instance (e.g. page change, zoom)
Viewer collection events
A viewer collection (e.g. api.viewer.mainCollection) emits events throughout the document loading lifecycle. These are the most commonly used events in extensions, since most extension behavior is driven by which document is currently loaded.
Where to register collection event handlers
Register collection event handlers in the apiready lifecycle hook. At that point api.viewer.mainCollection is guaranteed to exist, but the first document has not yet loaded — so attaching contentchanged here ensures you receive every event, including the first.
Do not register in ready — by the time ready fires, mainCollection has already bootstrapped and the first contentchanged has already fired, so you will have missed it.
export default function(parameters: IExtensionParameters) {
return {
lifecycle: {
apiready: (api: IReviewInterfaceApi) => {
api.viewer.mainCollection.on(ViewerCollectionEventType.ContentChanged, (e: IContentChangedEvent) => {
// fires for every document load, including the first
});
}
}
};
}
Registering collection event handlers
Use string literal event names to register handlers. reviewapi is a types-only package with no JavaScript exports — ViewerCollectionEventType is a declare enum and cannot be imported as a value. The string literal values (e.g. 'contentchanged') are what the API uses at runtime.
import type { IViewerCollection } from 'reviewapi';
const collection: IViewerCollection = api.viewer.mainCollection;
collection.on('contentchanged', (e) => { /* ... */ });
collection.off('contentchanged', handler);
collection.once('contentchanged', handler); // fires once then auto-unregisters
contentchanged
Fires when the collection has finished loading content — a new document, an error state, or an empty queue. This is the primary event for extensions that need to react to document navigation.
The event handler receives an IContentChangedEvent:
| Property | Type | Description |
|---|---|---|
contentType
|
ContentType
|
What is being displayed (see below) |
item
|
IQueueItem \| undefined
|
The loaded queue item. Undefined when contentType is emptyqueue. |
viewerType
|
string \| undefined
|
The active viewer type (e.g. "native", "image"). Undefined when contentType is emptyqueue. |
reloadRequired
|
boolean \| undefined
|
Whether the viewer was forced to reload even if the item didn't change. |
ContentType values:
| Value | Meaning |
|---|---|
"queueitem"
|
A document loaded successfully |
"viewererror"
|
The viewer failed to load the document |
"collectionerror"
|
The collection itself encountered an error |
"emptyqueue"
|
The queue has no items |
"unsupporteditem"
|
The item is not supported by any available viewer |
import type { IContentChangedEvent } from 'reviewapi';
api.viewer.mainCollection.on('contentchanged', (e: IContentChangedEvent) => {
if (e.contentType !== 'queueitem') return;
console.log('Document loaded:', e.item?.artifactId, 'in viewer:', e.viewerType);
});
contentchanging
Fires when the collection has begun loading new content but before it finishes. Useful for showing a loading state in your extension UI or cancelling pending async work from the previous document.
api.viewer.mainCollection.on('contentchanging', () => {
// cancel any pending requests for the previous document
});
contentchangeapproved
Fires just before the collection begins loading new content — after the change has been approved but before contentchanging. The event handler receives an IContentChangeApprovedEvent with currentType and targetType properties identifying the viewer types involved in the transition.
import type { IContentChangeApprovedEvent } from 'reviewapi';
api.viewer.mainCollection.on('contentchangeapproved', (e: IContentChangeApprovedEvent) => {
console.log('Transitioning from', e.currentType, 'to', e.targetType);
});
activeViewerChanged
Fires when the user switches the active viewer type (e.g. from Native to Image). The user may do this without navigating to a new document. The event handler receives an IActiveViewerChangedEvent with currentType and targetType.
import type { IActiveViewerChangedEvent } from 'reviewapi';
api.viewer.mainCollection.on('activeviewerchanged', (e: IActiveViewerChangedEvent) => {
console.log('Viewer switched from', e.currentType, 'to', e.targetType);
});
documentMetaDataChanged
Fires when document metadata is updated, for example after a Mass Edit operation changes field values on the currently loaded document.
api.viewer.mainCollection.on('documentmetadatachanged', () => {
// refresh any extension UI that displays document field values
});
Other collection events
| Event | When it fires |
|---|---|
bootstrapstarted
|
Collection begins initializing |
bootstrapcompleted
|
Collection has finished initializing |
vieweractivated
|
A viewer card instance becomes active |
viewerdeactivated
|
A viewer card instance is deactivated |
viewerloadeditem
|
The active viewer card instance loads a queue item |
toolbarcontrolsenabled
|
All toolbar controls are enabled |
reloadCompleted
|
The active viewer card instance finishes reloading |
queuepointerchanged
|
The collection has a new queue pointer |
skeletonshown
|
The collection displays its skeleton (loading placeholder) |
skeletonhidden
|
The collection hides its skeleton |
Individual viewer events
The core viewer types include the Native, Image, Text, and Production viewers. They support registering event handlers for certain viewer-specific events.
This page contains the following information:
Register viewer event handlers
The core viewer types support registering event handlers on the viewer instance object as follows:
const viewerCollection = reviewApi.viewer.mainCollection;
const nativeViewer = viewerCollection.getViewer("native");
const zoomEventHandler = (e) => console.log(e);
nativeViewer.on("zoom", zoomEventHandler);
The following code sample unregisters the previous event handler:
nativeViewer.off("zoom", zoomEventHandler);
Alternatively, you could register the previous event handler as a one-time event handler. It is then automatically unregistered after the first event is emitted:
nativeViewer.once("zoom", zoomEventHandler);
Common events
The core viewer types generally share a common set of events with a few exceptions, such as the Text Viewer.
See the following section for information about event types:
Page events
The Native, Image, and Production viewers all emit page-related events. These events indicate when the total page count for a document is changed or when the page currently displayed is changed. See Page Change event and Page Count Change event.
Note: The Text Viewer doesn't paginate document content, so it doesn't raise page-related events. Additionally, certain file types don't emit page-related events in the Native Viewer, including email, audio, video, and short-message files.
Page Change event
The Page Change event is emitted when a user successfully navigates to a new page in a specific document as follows:
- The user scrolls through the document with the mouse.
- The user navigates between pages via the Thumbnail Viewer Card.
- The user navigates with the page navigation buttons.
- The user zooms in or out.
- The Review API invokes a page navigation.
The following code sample illustrates how an event handler is passed a new 0-based page index:
const viewerCollection = reviewApi.viewer.mainCollection;
const imageViewer = viewerCollection.getViewer("image");
const pageChangeEventHandler = (newPageIndex) => console.log(newPageIndex + 1);
imageViewer.on("pageChange", pageChangeEventHandler);
Page Count Change event
The Page Count Change event is emitted when the total number of pages changes for a specific document. Conversion streaming causes this change by allowing the Review Interface to begin displaying content for a conversion that is in progress. During conversion streaming, the Review Interface loads new pages and increases the page count for a document until the conversion is complete.
The following code sample illustrates how the event handler is passed a new total page count:
const viewerCollection = reviewApi.viewer.mainCollection;
const nativeViewer = viewerCollection.getViewer("native");
const pageCountChangeEventHandler = (newPageCount) => console.log(newPageCount);
nativeViewer.on("pageCountChange", pageCountChangeEventHandler);
Zoom event
The zoom event is emitted when a user zooms in or out in a viewer.
The event handler is passed a IZoomEvent as an argument. The IZoomEvent includes the current zoom index and the current zoom mode as follows:
const viewerCollection = reviewApi.viewer.mainCollection;
const nativeViewer = viewerCollection.getViewer("native");
const zoomEventHandler = (e) => {
console.log(e.zoomIndex);
console.log(e.zoomMode);
};
nativeViewer.on("zoom", zoomEventHandler);
On this page