Last date modified: 2026-Jul-14

Viewer Events

This page covers two categories of events:


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.

Copy
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.

Copy
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
Copy
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.

Copy
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.

Copy
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.

Copy
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.

Copy
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:

Copy
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:

Copy
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:

Copy
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:

Copy
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:

Copy
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:

Copy
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);
Return to top of the page
Feedback