Customize annotation context menu ​
This section covers:
- Customize context menus for SDK-supported annotations
- Customize context menus for unsupported annotations
- Hide the context menu or menu items
- Show a custom context menu
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);
}
})()
}
});