Customize the context menu in PDF Viewer
16 Feb 202624 minutes to read
The PDF Viewer supports adding custom options to the context menu using the addCustomMenu() method. Define actions for custom items with the customContextMenuSelect() method.
Add a custom option
The following example adds custom options to the context menu.
let viewer: PdfViewer = new PdfViewer();
viewer.documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf";
viewer.resourceUrl = "https://cdn.syncfusion.com/ej2/31.1.23/dist/ej2-pdfviewer-lib";
var menuItems: MenuItemModel[] = [
{
text: 'Search In Google',
id: 'search_in_google',
iconCss: 'e-icons e-search'
},
{
text: 'Lock Annotation',
iconCss: 'e-icons e-lock',
id: 'lock_annotation'
},
{
text: 'Unlock Annotation',
iconCss: 'e-icons e-unlock',
id: 'unlock_annotation'
},
{
text: 'Lock Form Field',
iconCss: 'e-icons e-lock',
id: 'read_only_true'
},
{
text: 'Unlock Form Field',
iconCss: 'e-icons e-unlock',
id: 'read_only_false'
},
];
viewer.documentLoad = function (args) {
viewer.addCustomMenu(menuItems, true);
}
viewer.customContextMenuSelect = function (args) {
switch (args.id) {
case 'search_in_google':
for (var i = 0; i < viewer.textSelectionModule.selectionRangeArray.length; i++) {
var content = viewer.textSelectionModule.selectionRangeArray[i].textContent;
if ((viewer.textSelectionModule.isTextSelection) && (/\S/.test(content))) {
window.open('http://google.com/search?q=' + content);
}
}
break;
case 'lock_annotation':
lockAnnotations(args);
break;
case 'unlock_annotation':
unlockAnnotations(args);
break;
case 'read_only_true':
setReadOnlyTrue(args);
break;
case 'read_only_false':
setReadOnlyFalse(args);
break;
case 'formfield properties':
break;
default:
break;
}
};Customize the default vs custom menu
Toggle the display of the default context menu. When the addCustomMenu parameter is true, the default menu is hidden; when false, default menu items are displayed alongside custom items.
let viewer: PdfViewer = new PdfViewer();
viewer.documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf";
viewer.resourceUrl = "https://cdn.syncfusion.com/ej2/31.1.23/dist/ej2-pdfviewer-lib";
var menuItems: MenuItemModel[] = [
{
text: 'Search In Google',
id: 'search_in_google',
iconCss: 'e-icons e-search'
},
{
text: 'Lock Annotation',
iconCss: 'e-icons e-lock',
id: 'lock_annotation'
},
{
text: 'Unlock Annotation',
iconCss: 'e-icons e-unlock',
id: 'unlock_annotation'
},
{
text: 'Lock Form Field',
iconCss: 'e-icons e-lock',
id: 'read_only_true'
},
{
text: 'Unlock Form Field',
iconCss: 'e-icons e-unlock',
id: 'read_only_false'
},
];
viewer.documentLoad = function (args) {
viewer.addCustomMenu(menuItems, true);
}Show or hide custom items before opening
Use customContextMenuBeforeOpen() to hide or show custom options dynamically.
let viewer: PdfViewer = new PdfViewer();
viewer.documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf";
viewer.resourceUrl = "https://cdn.syncfusion.com/ej2/31.1.23/dist/ej2-pdfviewer-lib";
var menuItems: MenuItemModel[] = [
{
text: 'Search In Google',
id: 'search_in_google',
iconCss: 'e-icons e-search'
},
{
text: 'Lock Annotation',
iconCss: 'e-icons e-lock',
id: 'lock_annotation'
},
{
text: 'Unlock Annotation',
iconCss: 'e-icons e-unlock',
id: 'unlock_annotation'
},
{
text: 'Lock Form Field',
iconCss: 'e-icons e-lock',
id: 'read_only_true'
},
{
text: 'Unlock Form Field',
iconCss: 'e-icons e-unlock',
id: 'read_only_false'
},
];
viewer.documentLoad = function (args) {
viewer.addCustomMenu(menuItems, false, false);
}
viewer.customContextMenuSelect = function (args) {
switch (args.id) {
case 'search_in_google':
for (var i = 0; i < viewer.textSelectionModule.selectionRangeArray.length; i++) {
var content = viewer.textSelectionModule.selectionRangeArray[i].textContent;
if ((viewer.textSelectionModule.isTextSelection) && (\/\S\/.test(content))) {
window.open('http://google.com/search?q=' + content);
}
}
break;
case 'lock_annotation':
lockAnnotations(args);
break;
case 'unlock_annotation':
unlockAnnotations(args);
break;
case 'read_only_true':
setReadOnlyTrue(args);
break;
case 'read_only_false':
setReadOnlyFalse(args);
break;
case 'formfield properties':
break;
default:
break;
}
};
viewer.customContextMenuBeforeOpen = function (args) {
for (var i = 0; i < args.ids.length; i++) {
var search = document.getElementById(args.ids[i]);
if (search) {
search.style.display = 'none';
if (args.ids[i] === 'search_in_google' && (viewer.textSelectionModule) && viewer.textSelectionModule.isTextSelection) {
search.style.display = 'block';
} else if (args.ids[i] === "lock_annotation" || args.ids[i] === "unlock_annotation") {
var isLockOption = args.ids[i] === "lock_annotation";
for (var j = 0; j < viewer.selectedItems.annotations.length; j++) {
var selectedAnnotation = viewer.selectedItems.annotations[j];
if (selectedAnnotation && selectedAnnotation.annotationSettings) {
var shouldDisplay = (isLockOption && !selectedAnnotation.annotationSettings.isLock) ||
(!isLockOption && selectedAnnotation.annotationSettings.isLock);
search.style.display = shouldDisplay ? 'block' : 'none';
}
}
} else if ((args.ids[i] === "read_only_true" || args.ids[i] === "read_only_false") && viewer.selectedItems.formFields.length !== 0) {
var isReadOnlyOption = args.ids[i] === "read_only_true";
for (var k = 0; k < viewer.selectedItems.formFields.length; k++) {
var selectedFormFields = viewer.selectedItems.formFields[k];
if (selectedFormFields) {
var selectedFormField = viewer.selectedItems.formFields[k].isReadonly;
var displayMenu = (isReadOnlyOption && !selectedFormField) || (!isReadOnlyOption && selectedFormField);
search.style.display = displayMenu ? 'block' : 'none';
}
}
} else if (args.ids[i] === 'formfield properties' && viewer.selectedItems.formFields.length !== 0) {
search.style.display = 'block';
}
}
}
};
function lockAnnotations(args) {
for (var i = 0; i < viewer.annotationCollection.length; i++) {
if (viewer.annotationCollection[i].uniqueKey === viewer.selectedItems.annotations[0].id) {
viewer.annotationCollection[i].annotationSettings.isLock = true;
viewer.annotationCollection[i].isCommentLock = true;
viewer.annotation.editAnnotation(viewer.annotationCollection[i]);
}
args.cancel = false;
}
}
function unlockAnnotations(args) {
for (var i = 0; i < viewer.annotationCollection.length; i++) {
if (viewer.annotationCollection[i].uniqueKey === viewer.selectedItems.annotations[0].id) {
viewer.annotationCollection[i].annotationSettings.isLock = false;
viewer.annotationCollection[i].isCommentLock = false;
viewer.annotation.editAnnotation(viewer.annotationCollection[i]);
}
args.cancel = false;
}
}
function setReadOnlyTrue(args) {
var selectedFormFields = viewer.selectedItems.formFields;
for (var i = 0; i < selectedFormFields.length; i++) {
var selectFormFields = selectedFormFields[i];
if (selectFormFields) {
viewer.formDesignerModule.updateFormField(selectFormFields, {
isReadOnly: true,
});
}
args.cancel = false;
}
}
function setReadOnlyFalse(args) {
var selectedFormFields = viewer.selectedItems.formFields;
for (var i = 0; i < selectedFormFields.length; i++) {
var selectFormFields = selectedFormFields[i];
if (selectFormFields) {
viewer.formDesignerModule.updateFormField(selectFormFields, {
isReadOnly: false,
});
}
args.cancel = false;
}
}The following is the output of the custom context menu with customization.
import { PdfViewer, Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer} from '@syncfusion/ej2-pdfviewer';
import { MenuItemModel } from '@syncfusion/ej2-navigations';
import { CheckBox, ChangeEventArgs } from '@syncfusion/ej2-buttons';
PdfViewer.Inject(Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer);
let pdfviewer: PdfViewer = new PdfViewer();
pdfviewer.documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf";
pdfviewer.resourceUrl = "https://cdn.syncfusion.com/ej2/25.1.35/dist/ej2-pdfviewer-lib";
var menuItems: MenuItemModel[] = [
{
text: 'Search In Google',
id: 'search_in_google',
iconCss: 'e-icons e-search'
},
{
text: 'Lock Annotation',
iconCss: 'e-icons e-lock',
id: 'lock_annotation'
},
{
text: 'Unlock Annotation',
iconCss: 'e-icons e-unlock',
id: 'unlock_annotation'
},
{
text: 'Lock Form Fields',
iconCss: 'e-icons e-lock',
id: 'read_only_true'
},
{
text: 'Unlock Form Fields',
iconCss: 'e-icons e-unlock',
id: 'read_only_false'
},
];
pdfviewer.appendTo('#PdfViewer');
pdfviewer.documentLoad = function (args: any) {
pdfviewer.addCustomMenu(menuItems, false, false);
}
pdfviewer.customContextMenuSelect = function (args: any) {
switch (args.id) {
case 'search_in_google':
for (var i = 0; i < pdfviewer.textSelectionModule.selectionRangeArray.length; i++) {
var content = pdfviewer.textSelectionModule.selectionRangeArray[i].textContent;
if ((pdfviewer.textSelectionModule.isTextSelection) && (/\S/.test(content))) {
window.open('http://google.com/search?q=' + content);
}
}
break;
case 'lock_annotation':
lockAnnotations(args);
break;
case 'unlock_annotation':
unlockAnnotations(args);
break;
case 'read_only_true':
setReadOnlyTrue(args);
break;
case 'read_only_false':
setReadOnlyFalse(args);
break;
case 'formfield properties':
break;
default:
break;
}
};
pdfviewer.customContextMenuBeforeOpen = function (args: any) {
for (var i = 0; i < args.ids.length; i++) {
var search = document.getElementById(args.ids[i]);
if (search) {
search.style.display = 'none';
if (args.ids[i] === 'search_in_google' && (pdfviewer.textSelectionModule) && pdfviewer.textSelectionModule.isTextSelection) {
search.style.display = 'block';
} else if (args.ids[i] === "lock_annotation" || args.ids[i] === "unlock_annotation") {
var isLockOption = args.ids[i] === "lock_annotation";
for (var j = 0; j < pdfviewer.selectedItems.annotations.length; j++) {
var selectedAnnotation: any = pdfviewer.selectedItems.annotations[j];
if (selectedAnnotation && selectedAnnotation.annotationSettings) {
var shouldDisplay = (isLockOption && !selectedAnnotation.annotationSettings.isLock) ||
(!isLockOption && selectedAnnotation.annotationSettings.isLock);
search.style.display = shouldDisplay ? 'block' : 'none';
}
}
} else if ((args.ids[i] === "read_only_true" || args.ids[i] === "read_only_false") && pdfviewer.selectedItems.formFields.length !== 0) {
var isReadOnlyOption = args.ids[i] === "read_only_true";
for (var k = 0; k < pdfviewer.selectedItems.formFields.length; k++) {
var selectedFormFields = pdfviewer.selectedItems.formFields[k];
if (selectedFormFields) {
var selectedFormField = pdfviewer.selectedItems.formFields[k].isReadonly;
var displayMenu = (isReadOnlyOption && !selectedFormField) || (!isReadOnlyOption && selectedFormField);
search.style.display = displayMenu ? 'block' : 'none';
}
}
} else if (args.ids[i] === 'formfield properties' && pdfviewer.selectedItems.formFields.length !== 0) {
search.style.display = 'block';
}
}
}
};
function lockAnnotations(args: any) {
for (var i = 0; i < pdfviewer.annotationCollection.length; i++) {
if (pdfviewer.annotationCollection[i].uniqueKey === pdfviewer.selectedItems.annotations[0].id) {
pdfviewer.annotationCollection[i].annotationSettings.isLock = true;
pdfviewer.annotationCollection[i].isCommentLock = true;
pdfviewer.annotation.editAnnotation(pdfviewer.annotationCollection[i]);
}
args.cancel = false;
}
}
function unlockAnnotations(args: any) {
for (var i = 0; i < pdfviewer.annotationCollection.length; i++) {
if (pdfviewer.annotationCollection[i].uniqueKey === pdfviewer.selectedItems.annotations[0].id) {
pdfviewer.annotationCollection[i].annotationSettings.isLock = false;
pdfviewer.annotationCollection[i].isCommentLock = false;
pdfviewer.annotation.editAnnotation(pdfviewer.annotationCollection[i]);
}
args.cancel = false;
}
}
function setReadOnlyTrue(args: any) {
var selectedFormFields = pdfviewer.selectedItems.formFields;
for (var i = 0; i < selectedFormFields.length; i++) {
var selectedFormField = selectedFormFields[i];
if (selectedFormField) {
pdfviewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: true,
} as any);
}
args.cancel = false;
}
}
function setReadOnlyFalse(args: any) {
var selectedFormFields = pdfviewer.selectedItems.formFields;
for (var i = 0; i < selectedFormFields.length; i++) {
var selectedFormField = selectedFormFields[i];
if (selectedFormField) {
pdfviewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: false,
} as any);
}
args.cancel = false;
}
}
let defaultCheckBoxObj: CheckBox = new CheckBox({
change: contextmenuHelper,
label: "Hide Default Context Menu"
});
defaultCheckBoxObj.appendTo('#hide');
let positionCheckBoxObj: CheckBox = new CheckBox({
change: contextmenuHelper,
label: "Add Custom option at bottom"
});
positionCheckBoxObj.appendTo('#toolbar');
function contextmenuHelper(args: ChangeEventArgs): void {
pdfviewer.addCustomMenu(menuItems, defaultCheckBoxObj.checked, positionCheckBoxObj.checked);
}<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 PDF Viewer</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript PDF Viewer Control" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-base/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-pdfviewer/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-navigations/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-dropdowns/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-lists/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-inputs/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-notifications/styles/material.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div>
<input type="checkbox" id="hide">
</div>
<div>
<input type="checkbox" id="toolbar">
</div>
<div id='PdfViewer' style="height:500px;width:100%;"></div>
</div>
</body>
</html>NOTE
To set up the server-backed PDF Viewer, add the following
serviceUrlin theindex.tsfile: