Customizing WebViewer UI Popups

The popups in WebViewer UI are small floating menus.

In WebViewer UI, there are 4 types of popups:

Apryse Docs Image
  • text popup; appears on highlight of a text when using select tool

Apryse Docs Image

Apryse Docs Image

Apryse Docs Image

There are a number of ways you may want to customize Popups. To name a few:

The WebViewer UI provides API's to easily handle each of these cases and more.

Get items

The unique identifier of the items in the popup can be retrieved using the getItems API.
It returns an array of objects where each object contains a key that denotes the dataElement.

Adding items

Adding items can be done using the add API.
The type of items to add can be found in the list of items for Modular UI.

Add new items at beginning of the popup

To add new items at beginning of the popup, do not provide a second parameter to the add function.

1WebViewer(...)
2 .then(function(instance) {
3 instance.UI.contextMenuPopup.add({
4 type: 'actionButton',
5 label: 'some-label',
6 onClick: () => console.log('clicked'),
7 });
8 });

Add new items at a specific location in the popup

There are 2 ways to do this.

Option one:

  • If you know the specific element you want it to be after then you can provide a valid dataElement string as a second parameter. This will insert the new item(s) after the specified data element.

Option two:

  • If you know the index where you want to add it (for example as the last button) then you can get the list of data elements in the popup using the getItems API. Then retrieve the data element from the item at that index.
1WebViewer(...)
2 .then(function(instance) {
3 // insert after the last element in the popup
4 const contextMenuItems = instance.UI.contextMenuPopup.getItems();
5 const lastItem = contextMenuItems[contextMenuItems.length - 1];
6
7 instance.UI.contextMenuPopup.add({
8 type: 'actionButton',
9 label: 'Get selected text',
10 onClick: () => console.log(instance.Core.documentViewer.getSelectedText()),
11 },
12 lastItem.dataElement);
13 });

Modifying items

Existing items can be modified using updateElements.
The items in the popup can be replaced using update.

Update existing elements' properties

1WebViewer(...)
2 .then(function(instance) {
3 // Updating existing sticky tool button in context menu popup with new label and new on click handler
4 instance.UI.updateElement("stickyToolButton", {label: 'new-label', onClick: () => console.log('clicked')});
5 });

Replace existing elements

1WebViewer(...)
2 .then(function(instance) {
3 // replace existing items with a new array of items
4 instance.UI.contextMenuPopup.update([
5 {
6 type: 'actionButton',
7 label: '1',
8 onClick: () => console.log('clicked'),
9 },
10 {
11 type: 'actionButton',
12 label: '2',
13 onClick: () => console.log('clicked'),
14 },
15 ]);
16 });

Update ordering of elements in the popup

This can be done by:

  1. Get the list of data elements in the popup using the getItems API
  2. Modify ordering of the elements in the list retrieved from step 1.
  3. call update
1WebViewer(...)
2 .then(function(instance) {
3 const contextMenuItems = instance.UI.contextMenuPopup.getItems();
4 const newArray = contextMenuItems.reverse();
5 instance.UI.contextMenuPopup.update(newArray);
6 });

Deleting items

Items in the popup can be deleted using the using disableElements.

Adds a custom overlay to annotation on hover

1WebViewer(...)
2 .then(function(instance) {
3 instance.UI.setAnnotationContentOverlayHandler(annotation => {
4 const div = document.createElement('div');
5 div.appendChild(document.createTextNode(`Created by: ${annotation.Author}`));
6 div.appendChild(document.createElement('br'));
7 div.appendChild(document.createTextNode(`Created on ${annotation.DateCreated}`));
8 return div;
9 });
10 });

Customizing Popups with the Modular UI

When using the Modular UI, you can continue using existing Popup APIs. As of 11.8, you can also customize Popups using configuration files, making it easy to audit your current customizations at a glance or maintain different variants for different use cases.

To recap, there are three Popups you can customize using these APIs:

For example, you may want to add a ToolButton to the ContextMenuPopup, so users can quickly access commonly used tools:

JavaScript 11.8+

1WebViewer(...)
2 .then(function(instance) {
3 instance.UI.contextMenuPopup.add({
4 dataElement: 'rectangleToolButtonInContextMenu',
5 type: 'toolButton',
6 toolName: 'AnnotationCreateRectangle'
7 });
8
9 // Alternatively, you can use the constructor to create the new button.
10 const ellipseToolButton = new instance.UI.Components.ToolButton({
11 dataElement: 'ellipseToolButtonInContextMenu',
12 toolName: 'AnnotationCreateEllipse',
13 });
14
15 // And then add it
16 instance.UI.contextMenuPopup.add([ellipseToolButton]);
17 });

Notice that we used a ToolButton as defined in the items documentation. Popups in the Modular UI support the following item types:

Customizing via the configuration file

Starting in 11.8, when you call exportModularComponents, you will see a new key in the JSON for the three customizable Popups:

JSON

1// Other components removed for ease of readability.
2{
3 "modularComponents": {},
4 "modularHeaders": {},
5 "panels": {},
6 "flyouts": {},
7 "popups": {
8 "annotationPopup": [
9 {
10 "dataElement": "viewFileButton"
11 },
12 {
13 "dataElement": "annotationCommentButton"
14 },
15 {
16 "dataElement": "annotationStyleEditButton"
17 }
18 ],
19 "textPopup": [
20 {
21 "dataElement": "copyTextButton"
22 },
23 {
24 "dataElement": "textHighlightToolButton"
25 },
26 {
27 "dataElement": "textUnderlineToolButton"
28 },
29 {
30 "dataElement": "textSquigglyToolButton"
31 },
32 {
33 "dataElement": "textStrikeoutToolButton"
34 },
35 {
36 "dataElement": "textRedactToolButton"
37 },
38 {
39 "dataElement": "linkButton"
40 }
41 ],
42 "contextMenuPopup": [
43 {
44 "dataElement": "panToolButton"
45 },
46 {
47 "dataElement": "stickyToolButton"
48 },
49 {
50 "dataElement": "highlightToolButton"
51 },
52 {
53 "dataElement": "freeHandToolButton"
54 },
55 {
56 "dataElement": "freeHandHighlightToolButton"
57 },
58 {
59 "dataElement": "freeTextToolButton"
60 },
61 {
62 "dataElement": "markInsertTextToolButton"
63 },
64 {
65 "dataElement": "markReplaceTextToolButton"
66 }
67 ]
68 }
69}

Each Popup will be a key in the JSON, with a list of the buttons it contains. The dataElements point to buttons the UI ships by default, such as the annotationStyleEditButton which toggles the Style Panel.

Why are there more items for each Popup than I can see in the UI?

The items for each Popup may not match what you see in all circumstances in the UI. For example, the AnnotationPopup includes the annotationGroupButton that only renders when you select multiple annotations.

As with any custom component in the Modular UI, if you pass custom handlers or render functions, make sure those functions are added to the FunctionMap when importing your configuration. See the FunctionMap guide for more in-depth examples.

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales