Skip to content

Customize annotation context menu ​

This section covers:

Customize context menus for SDK-supported annotations ​

The SDK supports most standard annotation types. Each type has its own context menu. The table below lists supported annotations and their XML element names.

json
{
  "line": "fv--line-contextmenu",
  "linearrow": "fv--linearrow-contextmenu",
  "linedimension": "fv--linedimension-contextmenu",
  "polylinedimension": "fv--polylinedimension-contextmenu",
  "polygondimension": "fv--polygondimension-contextmenu",
  "circle": "fv--circle-contextmenu",
  "square": "fv--square-contextmenu",
  "polyline": "fv--polyline-contextmenu",
  "polygon": "fv--polygon-contextmenu",
  "polygoncloud": "fv--polygoncloud-contextmenu",
  "fileattachment": "fv--fileattachment-contextmenu",
  "freetexttypewriter": "fv--freetexttypewriter-contextmenu",
  "typewriter": "fv--typewriter-contextmenu",
  "freetextcallout": "fv--freetextcallout-contextmenu",
  "callout": "fv--callout-contextmenu",
  "freetexttextbox": "fv--freetexttextbox-contextmenu",
  "textbox": "fv--textbox-contextmenu",
  "freetext": "fv--freetext-contextmenu",
  "ink": "fv--ink-contextmenu",
  "stamp": "fv--stamp-contextmenu",
  "text": "fv--text-contextmenu",
  "areahighlight": "fv--areahighlight-contextmenu",
  "highlight": "fv--highlight-contextmenu",
  "caret": "fv--caret-contextmenu",
  "replace": "fv--replace-contextmenu",
  "squiggly": "fv--squiggly-contextmenu",
  "strikeout": "fv--strikeout-contextmenu",
  "redact": "fv--redact-contextmenu",
  "underline": "fv--underline-contextmenu",
  "media": "fv--media-contextmenu",
  "image": "fv--image-contextmenu",
  "link": "fv--link-contextmenu",
  "sound": "fv--sound-contextmenu"
}

You can obtain annotation element names with super.getAnnotsContextMenuName(owner) on UIExtension.XViewerUI. See the viewerUI customization examples in the hide-menu and show-custom-context-menu sections below.

For supported annotations, use fragment configuration with UIExtension.UIConsts.FRAGMENT_ACTION.REPLACE, UIExtension.UIConsts.FRAGMENT_ACTION.APPEND, and UIExtension.UIConsts.FRAGMENT_ACTION.REMOVE to replace, add, or remove menu items.

Replace menu items ​

javascript
new UIExtension.PDFUI({
    appearance: UIExtension.appearances.AdaptiveAppearance.extend({
        getDefaultFragments: function () {
            return [{
                target: 'fv--highlight-contextmenu',
                action: UIExtension.UIConsts.FRAGMENT_ACTION.REPLACE,
                template: `
                    <contextmenu name="fv--highlight-contextmenu">
                        <contextmenu-item-reply></contextmenu-item-reply>
                        <contextmenu-item-delete-annot></contextmenu-item-delete-annot>
                        <contextmenu-item-properties></contextmenu-item-properties>
                        <contextmenu-item name="x-user-custom-contextmenu-item">Custom </contextmenu-item>
                    </contextmenu>`,
                config: [{
                    target: 'x-user-custom-contextmenu-item',
                    callback: function () {
                        alert('custom contextmenu item clicked!');
                    }
                }]
            }];
        }
    })
})

Insert menu items ​

javascript
new UIExtension.PDFUI({
    appearance: UIExtension.appearances.AdaptiveAppearance.extend({
        getDefaultFragments: function () {
            return [{
                target: 'fv--textbox-contextmenu',
                action: UIExtension.UIConsts.FRAGMENT_ACTION.APPEND,
                template: `
                    <contextmenu-item name="x-user-custom-contextmenu-item">Custom</contextmenu-item>
                `,
                config: [{
                    target: 'x-user-custom-contextmenu-item',
                    callback: function () {
                        alert('custom contextmenu item clicked!');
                    }
                }]
            }];
        }
    })
});

Remove menu items ​

javascript
new UIExtension.PDFUI({
    appearance: UIExtension.appearances.AdaptiveAppearance.extend({
        getDefaultFragments: function () {
            return [{
                target: 'fv--media-contextmenu>fv--contextmenu-item-media-download',
                action: UIExtension.UIConsts.FRAGMENT_ACTION.REMOVE
            }]
        }
    })
})

Customize context menus for unsupported annotations ​

Unsupported annotations are types defined in the PDF specification but not listed above. To customize their context menus, override getAnnotsContextMenuName in XViewerUI, create a new context menu, and add it to the template.

To check whether an annotation is supported, inspect its element name. Supported annotations are typically tagged as "fv--default-annot-contextmenu".

The example below assumes the document contains a trapnet annotation, which the SDK does not support. It shows how to customize that context menu.

javascript
new UIExtension.PDFUI({
    viewerOptions: {
        viewerUI: new class extends UIExtension.XViewerUI {
            createContextMenu(owner, anchor, config) {
                if (owner instanceof PDFViewCtrl.AnnotComponent) {
                    if (owner.annot.getType() === 'trapnet') {
                        return 'custom-trapnet-contextmenu-name';
                    }
                }
                return super.createContextMenu(owner, anchor, config);
            }
        }()
    },
    appearance: UIExtension.appearances.AdaptiveAppearance.extend({
        getDefaultFragments: function () {
            return [{
                target: 'template-container',
                action: UIExtension.UIConsts.FRAGMENT_ACTION.APPEND,
                template: `
                    <contextmenu name="custom-trapnet-contextmenu-name">
                        <contextmenu-item-reply></contextmenu-item-reply>
                        <contextmenu-item-delete-annot></contextmenu-item-delete-annot>
                        <contextmenu-item-properties></contextmenu-item-properties>
                        <contextmenu-item name="x-user-custom-contextmenu-item">Custom </contextmenu-item>
                    </contextmenu>
                `,
                config: [{
                    target: 'x-user-custom-contextmenu-item',
                    callback: function () {
                        alert('custom contextmenu item clicked!');
                    }
                }]
            }]
        }
    })
})

Hide the context menu or menu items ​

Use one of the following approaches.

1. Force-hide via a class in fragments ​

javascript
new UIExtension.PDFUI({
    appearance: UIExtension.appearances.AdaptiveAppearance.extend({
        getDefaultFragments: function () {
            // the other options ...
            return [{
                target: 'fv--underline-contextmenu',
                config: {
                    cls: 'fv__ui-force-hide'
                }
            }]
        }
    })
})

This forces the underline annotation context menu to stay hidden, so right-clicking an underline annotation has no effect.

2. Customize viewerUI ​

javascript
new UIExtension.PDFUI({
    viewerOptions: {
        viewerUI: new class extends UIExtension.XViewerUI {
            createContextMenu(owner, anchor, config) {
                if (owner instanceof PDFViewCtrl.AnnotComponent) {
                    const contextMenuName = super.getAnnotsContextMenuName(owner)
                    if (contextMenuName === 'fv--underline-contextmenu') {
                        return;
                    }
                }
                return super.createContextMenu(owner, anchor, config);
            }
        }()
    }
});

This hides the built-in menu on right-click and shows the browser default menu instead.

3. Override AnnotComponent.showContextMenu ​

javascript
const pdfui = new UIExtension.PDFUI({
    // ....
});
pdfui.initializePromise.then(function () {
    var annotMap = {};
    pdfui.registerMatchRule(function (annot, AnnotComponentClass) {
        let type = annot.getType();
        var intent = annot.getIntent && annot.getIntent() || "default";
        // You can add more annotation types
        if (type === 'underline') {
            return AnnotComponentClass;
        }
        if (annotMap[type] && annotMap[type][intent]) {
            return annotMap[type][intent];
        }
        annotMap[type] = annotMap[type] || {};
        return annotMap[type][intent] = (class extends AnnotComponentClass {
            showContextMenu() {
                // Do nothing
            }
        });
    });
});

This also hides the built-in menu on right-click and shows the browser default menu.

Show a custom context menu ​

Override viewerUI to show your own context menu.

javascript
new UIExtension.PDFUI({
    viewerOptions: {
        viewerUI: new (class extends UIExtension.XViewerUI {
            createContextMenu(owner, anchor, config) {
                if (owner instanceof PDFViewCtrl.AnnotComponent) {
                    const contextMenuName = super.getAnnotsContextMenuName(owner);
                    if (contextMenuName === "fv--underline-contextmenu") {
                        return new (class extends PDFViewCtrl.IContextMenu {
                            constructor() {
                                super();
                                this.initContextmenu();
                            }

                            destroy() {
                                $(anchor).contextMenu("destroy");
                            }

                            showAt(x, y) {
                                $(anchor).contextMenu();
                            }

                            disable() {
                                super.disable();
                                $(anchor).contextMenu("destroy");
                            }

                            enable() {
                                super.enable();
                                this.initContextmenu();
                            }

                            initContextmenu() {
                                // The code example below requires referencing Jquery libraries including contextMenu.min.css, contextMenu.min.js and min.js.
                                $(anchor).contextMenu({
                                    selector: config.selector,
                                    items: [
                                        {
                                            name: 'show "Hello World"',
                                            callback: function () {
                                                alert("hello world");
                                            }
                                        },
                                        {
                                            name: 'show "Bye!"',
                                            callback: function () {
                                                alert("Bye!");
                                            }
                                        }
                                    ]
                                });
                            }
                        })();
                    }
                }
                return super.createContextMenu(owner, anchor, config);
            }
        })()
    }
});