Customize the context menu in PDF Viewer
28 Feb 202624 minutes to read
The PDF Viewer supports adding custom options to the context menu using the addCustomMenu() method; define custom actions with customContextMenuSelect(). See the addCustomMenu and customContextMenuSelect() API.
Add a custom option
The following example adds custom options to the context menu.
import { PdfViewerComponent, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print,
TextSelection, TextSearch, Annotation, FormFields, FormDesigner,PageOrganizer } from "@syncfusion/ej2-vue-pdfviewer";
import { MenuComponent } from "@syncfusion/ej2-vue-navigations";
import { CheckBoxComponent } from "@syncfusion/ej2-vue-buttons";
export default {
components: {
'ejs-pdfviewer': PdfViewerComponent,
'ejs-menu': MenuComponent,
'ejs-checkbox': CheckBoxComponent
},
data: function() {
return {
documentPath:'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf',
resourceUrl: 'https://cdn.syncfusion.com/ej2/31.2.2/dist/ej2-pdfviewer-lib',
menuItems : [
{
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'
},
]
}
},
provide: {
PdfViewer: [Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner,PageOrganizer]
},
methods: {
documentLoad: function (args) {
var viewer = this.$refs.pdfviewer.ej2Instances;
viewer.addCustomMenu(this.menuItems, false, false);
},
}
}import {
PdfViewerComponent as EjsPdfviewer, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print,
TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer
} from "@syncfusion/ej2-vue-pdfviewer";
import { MenuComponent as EjsMenu } from "@syncfusion/ej2-vue-navigations";
import { CheckBoxComponent as EjsCheckbox } from "@syncfusion/ej2-vue-buttons";
import { provide, ref } from "vue";
const pdfviewer = ref(null);
const documentPath = 'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf';
const resourceUrl = 'https://cdn.syncfusion.com/ej2/31.2.2/dist/ej2-pdfviewer-lib';
const menuItems = [
{
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'
},
]
provide('PdfViewer', [Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer])
const documentLoad = function (args) {
const viewer = pdfviewer.value.ej2Instances;
viewer.addCustomMenu(this.menuItems, false, false);
}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.
import {
PdfViewerComponent as EjsPdfviewer, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print,
TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer
} from "@syncfusion/ej2-vue-pdfviewer";
import { MenuComponent as EjsMenu } from "@syncfusion/ej2-vue-navigations";
import { CheckBoxComponent as EjsCheckbox, SwitchComponent as EjsSwitch } from "@syncfusion/ej2-vue-buttons";
import { provide, ref } from "vue";
const pdfviewer = ref(null);
const documentPath = 'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf';
const resourceUrl = 'https://cdn.syncfusion.com/ej2/31.2.2/dist/ej2-pdfviewer-lib';
const menuItems = [
{
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'
},
]
provide('PdfViewer', [Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView,
Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer])
const documentLoad = function (args) {
const viewer = pdfviewer.value.ej2Instances;
viewer.addCustomMenu(this.menuItems, true);
}import { PdfViewerComponent, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print,
TextSelection, TextSearch, Annotation, FormFields, FormDesigner,PageOrganizer } from "@syncfusion/ej2-vue-pdfviewer";
import { MenuComponent } from "@syncfusion/ej2-vue-navigations";
import { CheckBoxComponent, SwitchComponent } from "@syncfusion/ej2-vue-buttons";
export default {
components: {
'ejs-pdfviewer': PdfViewerComponent,
'ejs-switch': SwitchComponent,
'ejs-menu': MenuComponent,
'ejs-checkbox': CheckBoxComponent
},
data: function() {
return {
documentPath:'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf',
resourceUrl: 'https://cdn.syncfusion.com/ej2/31.2.2/dist/ej2-pdfviewer-lib',
menuItems : [
{
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'
},
]
}
},
provide: {
PdfViewer: [ Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView,
Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner,PageOrganizer]
},
methods: {
documentLoad: function (args) {
var viewer = this.$refs.pdfviewer.ej2Instances;
viewer.addCustomMenu(this.menuItems, true);
},
}
}Show or hide custom items before opening
Use customContextMenuBeforeOpen() to hide or show custom options dynamically.
<template>
<div id="app">
<ul>
<ejs-checkbox label='Hide Default Context Menu' id="enable" @change="contextmenuHelper"
checked="false"></ejs-checkbox>
<ejs-checkbox label='Add Custom option at bottom' id="position" @change="contextmenuHelper"
checked="false"></ejs-checkbox>
</ul>
<ejs-pdfviewer id="pdfViewer" ref="pdfviewer" :resourceUrl="resourceUrl" :documentPath="documentPath"
:documentLoad="documentLoad" :customContextMenuBeforeOpen="customContextMenuBeforeOpen"
:customContextMenuSelect="customContextMenuSelect">
</ejs-pdfviewer>
</div>
</template>
<script>
import { PdfViewerComponent, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer } from "@syncfusion/ej2-vue-pdfviewer";
import { MenuComponent } from "@syncfusion/ej2-vue-navigations";
import { CheckBoxComponent } from "@syncfusion/ej2-vue-buttons";
export default {
name: "App",
components: {
'ejs-pdfviewer': PdfViewerComponent,
'ejs-menu': MenuComponent,
'ejs-checkbox': CheckBoxComponent
},
data: function () {
return {
documentPath: 'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf',
resourceUrl: 'https://cdn.syncfusion.com/ej2/31.2.2/dist/ej2-pdfviewer-lib',
menuItems: [
{
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'
},
]
}
},
provide: {
PdfViewer: [Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print,
TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer]
},
methods: {
documentLoad: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
viewer.addCustomMenu(this.menuItems, false, false);
},
customContextMenuSelect: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
switch (args.id) {
case 'search_in_google':
for (let i = 0; i < viewer.textSelectionModule.selectionRangeArray.length; i++) {
let 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':
this.lockAnnotations(args);
break;
case 'unlock_annotation':
this.unlockAnnotations(args);
break;
case 'read_only_true':
this.setReadOnlyTrue(args);
break;
case 'read_only_false':
this.setReadOnlyFalse(args);
break;
default:
break;
}
},
customContextMenuBeforeOpen: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
for (let i = 0; i < args.ids.length; i++) {
let 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") {
let isLockOption = args.ids[i] === "lock_annotation";
for (let j = 0; j < viewer.selectedItems.annotations.length; j++) {
let selectedAnnotation = viewer.selectedItems.annotations[j];
if (selectedAnnotation && selectedAnnotation.annotationSettings) {
let 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) {
let isReadOnlyOption = args.ids[i] === "read_only_true";
for (let j = 0; j < viewer.selectedItems.formFields.length; j++) {
let selectedFormFields = viewer.selectedItems.formFields[j];
if (selectedFormFields) {
let selectedFormField = viewer.selectedItems.formFields[j].isReadonly;
let 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';
}
}
}
},
lockAnnotations: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
for (let 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;
}
},
unlockAnnotations: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
for (let 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;
}
},
setReadOnlyTrue: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
let selectedFormFields = viewer.selectedItems.formFields;
for (let i = 0; i < selectedFormFields.length; i++) {
let selectedFormField = selectedFormFields[i];
if (selectedFormField) {
viewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: true,
});
}
args.cancel = false;
}
},
setReadOnlyFalse: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
let selectedFormFields = viewer.selectedItems.formFields;
for (let i = 0; i < selectedFormFields.length; i++) {
let selectedFormField = selectedFormFields[i];
if (selectedFormField) {
viewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: false,
});
}
args.cancel = false;
}
},
contextmenuHelper: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
viewer.addCustomMenu(this.menuItems, enable.checked, position.checked);
},
}
};
</script><template>
<div id="app">
<ul>
<ejs-checkbox label='Hide Default Context Menu' id="enable" @change="contextmenuHelper"
checked="false"></ejs-checkbox>
<ejs-checkbox label='Add Custom option at bottom' id="position" @change="contextmenuHelper"
checked="false"></ejs-checkbox>
</ul>
<ejs-pdfviewer id="pdfViewer" ref="pdfviewer" :serviceUrl="serviceUrl" :documentPath="documentPath"
:documentLoad="documentLoad" :customContextMenuBeforeOpen="customContextMenuBeforeOpen"
:customContextMenuSelect="customContextMenuSelect">
</ejs-pdfviewer>
</div>
</template>
<script setup>
import {
PdfViewerComponent as EjsPdfviewer, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print,
TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer
} from "@syncfusion/ej2-vue-pdfviewer";
import { MenuComponent as EjsMenu } from "@syncfusion/ej2-vue-navigations";
import { CheckBoxComponent as EjsCheckbox } from "@syncfusion/ej2-vue-buttons";
import { provide, ref } from "vue";
const pdfviewer = ref(null);
const documentPath = 'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf';
const serviceUrl = "https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer";
const menuItems = [
{
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'
},
]
provide('PdfViewer', [Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print,
TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer])
const documentLoad = function (args) {
let viewer = pdfviewer.value.ej2Instances;
viewer.addCustomMenu(menuItems, false, false);
}
const customContextMenuSelect = function (args) {
let viewer = pdfviewer.value.ej2Instances;
switch (args.id) {
case 'search_in_google':
for (let i = 0; i < viewer.textSelectionModule.selectionRangeArray.length; i++) {
let 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;
default:
break;
}
}
const customContextMenuBeforeOpen = function (args) {
let viewer = pdfviewer.value.ej2Instances;
for (let i = 0; i < args.ids.length; i++) {
let 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") {
let isLockOption = args.ids[i] === "lock_annotation";
for (let j = 0; j < viewer.selectedItems.annotations.length; j++) {
let selectedAnnotation = viewer.selectedItems.annotations[j];
if (selectedAnnotation && selectedAnnotation.annotationSettings) {
let 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) {
let isReadOnlyOption = args.ids[i] === "read_only_true";
for (let j = 0; j < viewer.selectedItems.formFields.length; j++) {
let selectedFormFields = viewer.selectedItems.formFields[j];
if (selectedFormFields) {
let selectedFormField = viewer.selectedItems.formFields[j].isReadonly;
let 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';
}
}
}
}
const lockAnnotations = function (args) {
let viewer = pdfviewer.value.ej2Instances;
for (let 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;
}
}
const unlockAnnotations = function (args) {
let viewer = pdfviewer.value.ej2Instances;
for (let 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;
}
}
const setReadOnlyTrue = function (args) {
let viewer = pdfviewer.value.ej2Instances;
let selectedFormFields = viewer.selectedItems.formFields;
for (let i = 0; i < selectedFormFields.length; i++) {
let selectedFormField = selectedFormFields[i];
if (selectedFormField) {
viewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: true,
});
}
args.cancel = false;
}
}
const setReadOnlyFalse = function (args) {
let viewer = pdfviewer.value.ej2Instances;
let selectedFormFields = viewer.selectedItems.formFields;
for (let i = 0; i < selectedFormFields.length; i++) {
let selectedFormField = selectedFormFields[i];
if (selectedFormField) {
viewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: false,
});
}
args.cancel = false;
}
}
const contextmenuHelper = function (args) {
let viewer = pdfviewer.value.ej2Instances;
viewer.addCustomMenu(menuItems, enable.checked, position.checked);
}
</script><template>
<div id="app">
<ul>
<ejs-checkbox label='Hide Default Context Menu' id="enable" @change="contextmenuHelper"
checked="false"></ejs-checkbox>
<ejs-checkbox label='Add Custom option at bottom' id="position" @change="contextmenuHelper"
checked="false"></ejs-checkbox>
</ul>
<ejs-pdfviewer id="pdfViewer" ref="pdfviewer" :serviceUrl="serviceUrl" :documentPath="documentPath"
:documentLoad="documentLoad" :customContextMenuBeforeOpen="customContextMenuBeforeOpen"
:customContextMenuSelect="customContextMenuSelect">
</ejs-pdfviewer>
</div>
</template>
<script>
import {
PdfViewerComponent, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print,
TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer
} from "@syncfusion/ej2-vue-pdfviewer";
import { MenuComponent } from "@syncfusion/ej2-vue-navigations";
import { CheckBoxComponent } from "@syncfusion/ej2-vue-buttons";
export default {
name: "App",
components: {
'ejs-pdfviewer': PdfViewerComponent,
'ejs-menu': MenuComponent,
'ejs-checkbox': CheckBoxComponent
},
data: function () {
return {
documentPath: 'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf',
serviceUrl: "https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer",
menuItems: [
{
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'
},
]
}
},
provide: {
PdfViewer: [Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print,
TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer]
},
methods: {
documentLoad: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
viewer.addCustomMenu(this.menuItems, false, false);
},
customContextMenuSelect: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
switch (args.id) {
case 'search_in_google':
for (let i = 0; i < viewer.textSelectionModule.selectionRangeArray.length; i++) {
let 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':
this.lockAnnotations(args);
break;
case 'unlock_annotation':
this.unlockAnnotations(args);
break;
case 'read_only_true':
this.setReadOnlyTrue(args);
break;
case 'read_only_false':
this.setReadOnlyFalse(args);
break;
default:
break;
}
},
customContextMenuBeforeOpen: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
for (let i = 0; i < args.ids.length; i++) {
let 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") {
let isLockOption = args.ids[i] === "lock_annotation";
for (let j = 0; j < viewer.selectedItems.annotations.length; j++) {
let selectedAnnotation = viewer.selectedItems.annotations[j];
if (selectedAnnotation && selectedAnnotation.annotationSettings) {
let 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) {
let isReadOnlyOption = args.ids[i] === "read_only_true";
for (let j = 0; j < viewer.selectedItems.formFields.length; j++) {
let selectedFormFields = viewer.selectedItems.formFields[j];
if (selectedFormFields) {
let selectedFormField = viewer.selectedItems.formFields[j].isReadonly;
let 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';
}
}
}
},
lockAnnotations: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
for (let 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;
}
},
unlockAnnotations: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
for (let 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;
}
},
setReadOnlyTrue: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
let selectedFormFields = viewer.selectedItems.formFields;
for (let i = 0; i < selectedFormFields.length; i++) {
let selectedFormField = selectedFormFields[i];
if (selectedFormField) {
viewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: true,
});
}
args.cancel = false;
}
},
setReadOnlyFalse: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
let selectedFormFields = viewer.selectedItems.formFields;
for (let i = 0; i < selectedFormFields.length; i++) {
let selectedFormField = selectedFormFields[i];
if (selectedFormField) {
viewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: false,
});
}
args.cancel = false;
}
},
contextmenuHelper: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
viewer.addCustomMenu(this.menuItems, enable.checked, position.checked);
},
}
};
</script>The following is the output of custom context menu with customization.
<template>
<div id="app">
<ul>
<ejs-checkbox label='Hide Default Context Menu' id="enable" @change="contextmenuHelper"
checked="false"></ejs-checkbox>
<ejs-checkbox label='Add Custom option at bottom' id="position" @change="contextmenuHelper"
checked="false"></ejs-checkbox>
</ul>
<ejs-pdfviewer id="pdfViewer" ref="pdfViewer" :resourceUrl="resourceUrl" :documentPath="documentPath"
:documentLoad="documentLoad" :customContextMenuBeforeOpen="customContextMenuBeforeOpen"
:customContextMenuSelect="customContextMenuSelect">
</ejs-pdfviewer>
</div>
</template>
<script setup>
import { provide, ref } from "vue";
import {
PdfViewerComponent as EjsPdfviewer, Toolbar, Magnification, Navigation, LinkAnnotation,
BookmarkView, ThumbnailView, Print, TextSelection, TextSearch,
Annotation, FormDesigner, FormFields, PageOrganizer
} from '@syncfusion/ej2-vue-pdfviewer';
import { CheckBoxComponent as EjsCheckbox } from "@syncfusion/ej2-vue-buttons";
const pdfViewer = ref(null);
const documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf";
const resourceUrl = "https://cdn.syncfusion.com/ej2/25.1.35/dist/ej2-pdfviewer-lib";
const menuItems = ref([{
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'
},
]);
provide('PdfViewer', [Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView,
Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer]);
const documentLoad = function () {
const viewer = pdfViewer.value.ej2Instances;
viewer.addCustomMenu(menuItems.value, false, false);
}
const customContextMenuSelect = function (args) {
const viewer = pdfViewer.value.ej2Instances;
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;
default:
break;
}
}
const customContextMenuBeforeOpen = function (args) {
const viewer = pdfViewer.value.ej2Instances;
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 j = 0; j < viewer.selectedItems.formFields.length; j++) {
var selectedFormFields = viewer.selectedItems.formFields[j];
if (selectedFormFields) {
var selectedFormField = viewer.selectedItems.formFields[j].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';
}
}
}
}
const lockAnnotations = function (args) {
const viewer = pdfViewer.value.ej2Instances;
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;
}
}
const unlockAnnotations = function (args) {
const viewer = pdfViewer.value.ej2Instances;
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;
}
}
const setReadOnlyTrue = function (args) {
const viewer = pdfViewer.value.ej2Instances;
var selectedFormFields = viewer.selectedItems.formFields;
for (var i = 0; i < selectedFormFields.length; i++) {
var selectedFormField = selectedFormFields[i];
if (selectedFormField) {
viewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: true,
});
}
args.cancel = false;
}
}
const setReadOnlyFalse = function (args) {
const viewer = pdfViewer.value.ej2Instances;
var selectedFormFields = viewer.selectedItems.formFields;
for (var i = 0; i < selectedFormFields.length; i++) {
var selectedFormField = selectedFormFields[i];
if (selectedFormField) {
viewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: false,
});
}
args.cancel = false;
}
}
const contextmenuHelper = function () {
const viewer = pdfViewer.value.ej2Instances;
viewer.addCustomMenu(menuItems.value, enable.checked, position.checked);
}
</script>
<style>
@import '../node_modules/@syncfusion/ej2-base/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-lists/styles/material.css';
@import '../node_modules/@syncfusion/ej2-vue-pdfviewer/styles/material.css';
#pdfViewer {
height: 640px;
}
</style><template>
<div id="app">
<ul>
<ejs-checkbox label='Hide Default Context Menu' id="enable" @change="contextmenuHelper"
checked="false"></ejs-checkbox>
<ejs-checkbox label='Add Custom option at bottom' id="position" @change="contextmenuHelper"
checked="false"></ejs-checkbox>
</ul>
<ejs-pdfviewer id="pdfViewer" ref="pdfviewer":resourceUrl="resourceUrl" :documentPath="documentPath" :documentLoad="documentLoad"
:customContextMenuBeforeOpen="customContextMenuBeforeOpen" :customContextMenuSelect="customContextMenuSelect">
</ejs-pdfviewer>
</div>
</template>
<script>
import {
PdfViewerComponent, Toolbar, Magnification, Navigation, LinkAnnotation,
BookmarkView, ThumbnailView, Print, TextSelection, TextSearch,
Annotation, FormDesigner, FormFields, PageOrganizer
} from '@syncfusion/ej2-vue-pdfviewer';
import { CheckBoxComponent } from "@syncfusion/ej2-vue-buttons";
export default {
name: "App",
components: {
'ejs-pdfviewer': PdfViewerComponent,
'ejs-checkbox': CheckBoxComponent
},
name: 'app',
data() {
return {
documentPath: "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf",
resourceUrl: "https://cdn.syncfusion.com/ej2/25.1.35/dist/ej2-pdfviewer-lib",
menuItems: [{
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'
},
]
};
},
provide: {
PdfViewer: [Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView,
Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer]
},
methods: {
documentLoad: function () {
let viewer = this.$refs.pdfviewer.ej2Instances;
viewer.addCustomMenu(this.menuItems, false, false);
},
customContextMenuSelect: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
switch (args.id) {
case 'search_in_google':
for (let i = 0; i < viewer.textSelectionModule.selectionRangeArray.length; i++) {
let 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':
this.lockAnnotations(args);
break;
case 'unlock_annotation':
this.unlockAnnotations(args);
break;
case 'read_only_true':
this.setReadOnlyTrue(args);
break;
case 'read_only_false':
this.setReadOnlyFalse(args);
break;
default:
break;
}
},
customContextMenuBeforeOpen: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
for (let i = 0; i < args.ids.length; i++) {
let 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") {
let isLockOption = args.ids[i] === "lock_annotation";
for (let j = 0; j < viewer.selectedItems.annotations.length; j++) {
let selectedAnnotation = viewer.selectedItems.annotations[j];
if (selectedAnnotation && selectedAnnotation.annotationSettings) {
let 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) {
let isReadOnlyOption = args.ids[i] === "read_only_true";
for (let j = 0; j < viewer.selectedItems.formFields.length; j++) {
let selectedFormFields = viewer.selectedItems.formFields[j];
if (selectedFormFields) {
let selectedFormField = viewer.selectedItems.formFields[j].isReadonly;
let 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';
}
}
}
},
lockAnnotations: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
for (let 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;
}
},
unlockAnnotations: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
for (let 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;
}
},
setReadOnlyTrue: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
let selectedFormFields = viewer.selectedItems.formFields;
for (let i = 0; i < selectedFormFields.length; i++) {
let selectedFormField = selectedFormFields[i];
if (selectedFormField) {
viewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: true,
});
}
args.cancel = false;
}
},
setReadOnlyFalse: function (args) {
let viewer = this.$refs.pdfviewer.ej2Instances;
let selectedFormFields = viewer.selectedItems.formFields;
for (let i = 0; i < selectedFormFields.length; i++) {
let selectedFormField = selectedFormFields[i];
if (selectedFormField) {
viewer.formDesignerModule.updateFormField(selectedFormField, {
isReadOnly: false,
});
}
args.cancel = false;
}
},
contextmenuHelper: function () {
let viewer = this.$refs.pdfviewer.ej2Instances;
viewer.addCustomMenu(this.menuItems, enable.checked, position.checked);
},
}
}
</script>
<style>
@import '../node_modules/@syncfusion/ej2-base/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-lists/styles/material.css';
@import '../node_modules/@syncfusion/ej2-vue-pdfviewer/styles/material.css';
#pdfViewer {
height: 640px;
}
</style>NOTE
To set up the server-backed PDF Viewer, add the following service URL in
App.vue:
serviceUrl: 'https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer'
Then configure the PDF Viewer template with the:serviceUrl='service'attribute on the viewer container.