Section:

Searching documents in Salesforce

Getting Started

We recommend the Overview page to learn how to correctly use a config.js before getting started.

Open a document

To search a document, you need to open it in WebViewer. See more in docs on opening documents.

Searching an open document

Once your document is loaded in WebViewer it is ready for search. From your LWC component where the WebViewer iFrame is mounted (in our sample, it is pdftronWvInstance), you need to post a message to your iframeWindow like so:

JavaScript

1this.iframeWindow.postMessage({ type: 'SEARCH_DOCUMENT', searchTerm }, '*');

searchTerm is required and represents a string or regular expression you would like to search the document for. type is optional, but recommended for handling multiple messages in a readable fashion.

Note: You must set regex: true in your options parameter to enable searching for a regex string.

Processing search in your config.js

Since WebViewer is hosted in an iFrame, we need to use our config.js file to access our WebViewer instance. In a Salesforce deployment, the equivalent of instance is readerControl.

In your config.js file, you can you listen for messages posted to the iFrame by registering an event listener using window.addEventListener("message", receiveMessage, false);. In this case, receiveMessage is a function that handles these posted messages. You can review the snippet below for an example of how to deal with posted messages.

Searching the document for a single instance of search term

This snippet uses the searchText() function. It searches the document one by one for the text matching searchValue. To go to the next result this function must be called again. Once document end is reach it will jump back to the first found result. To search and highlight every occurrence of the search term, review the next section.

JavaScript (v8.0+)

1function receiveMessage(event) {
2 const annotManager = docViewer.getAnnotationManager();
3
4 //you can register a searchListener to use a callback for result handling
5 const searchListener = (searchTerm, options, results) => {
6 // add redaction annotation for each search result
7 const newAnnotations = results.map(result => {
8 const annotation = new Annotations.RedactionAnnotation();
9 annotation.PageNumber = result.pageNum;
10 annotation.Quads = result.quads.map(quad => quad.getPoints());
11 annotation.StrokeColor = new Annotations.Color(136, 39, 31);
12 return annotation;
13 });
14
15 annotManager.addAnnotations(newAnnotations);
16 annotManager.drawAnnotationsFromList(newAnnotations);
17 };
18
19 if (event.isTrusted && typeof event.data === 'object') {
20 switch (event.data.type) {
21 case 'SEARCH_DOCUMENT':
22 if (event.data.term) {
23 const searchOptions = {
24 caseSensitive: true, // match case
25 wholeWord: true, // match whole words only
26 wildcard: false, // allow using '*' as a wildcard value
27 regex: false, // string is treated as a regular expression
28 searchUp: false, // search from the end of the document upwards
29 ambientString: true, // return ambient string as part of the result
30 };
31 instance.addSearchListener(searchListener);
32 instance.searchText(event.data.term, searchOptions); //search full text for single occurence of searchTerm
33 }
34 break;
35 default:
36 break;
37 }
38 }
39}

JavaScript (v7.0+)

1function receiveMessage(event) {
2 const annotManager = docViewer.getAnnotationManager();
3
4 //you can register a searchListener to use a callback for result handling
5 const searchListener = (searchTerm, options, results) => {
6 // add redaction annotation for each search result
7 const newAnnotations = results.map(result => {
8 const annotation = new Annotations.RedactionAnnotation();
9 annotation.PageNumber = result.pageNum;
10 annotation.Quads = result.quads.map(quad => quad.getPoints());
11 annotation.StrokeColor = new Annotations.Color(136, 39, 31);
12 return annotation;
13 });
14
15 annotManager.addAnnotations(newAnnotations);
16 annotManager.drawAnnotationsFromList(newAnnotations);
17 };
18
19 if (event.isTrusted && typeof event.data === 'object') {
20 switch (event.data.type) {
21 case 'SEARCH_DOCUMENT':
22 if (event.data.term) {
23 const searchOptions = {
24 caseSensitive: true, // match case
25 wholeWord: true, // match whole words only
26 wildcard: false, // allow using '*' as a wildcard value
27 regex: false, // string is treated as a regular expression
28 searchUp: false, // search from the end of the document upwards
29 ambientString: true, // return ambient string as part of the result
30 };
31 readerControl.addSearchListener(searchListener);
32 readerControl.searchText(event.data.term, searchOptions); //search full text for single occurence of searchTerm
33 }
34 break;
35 default:
36 break;
37 }
38 }
39}

Searching the document for all instances of search term (multiple highlights)

The following snippet uses the searchTextFull() function:

JavaScript (v8.0+)

1function receiveMessage(event) {
2 const annotManager = docViewer.getAnnotationManager();
3
4 //you can register a searchListener to use a callback for result handling
5 const searchListener = (searchTerm, options, results) => {
6 // add redaction annotation for each search result
7 const newAnnotations = results.map(result => {
8 const annotation = new Annotations.RedactionAnnotation();
9 annotation.PageNumber = result.pageNum;
10 annotation.Quads = result.quads.map(quad => quad.getPoints());
11 annotation.StrokeColor = new Annotations.Color(136, 39, 31);
12 return annotation;
13 });
14
15 annotManager.addAnnotations(newAnnotations);
16 annotManager.drawAnnotationsFromList(newAnnotations);
17 };
18
19 if (event.isTrusted && typeof event.data === 'object') {
20 switch (event.data.type) {
21 case 'SEARCH_DOCUMENT':
22 if (event.data.term) {
23 const searchOptions = {
24 caseSensitive: true, // match case
25 wholeWord: true, // match whole words only
26 wildcard: false, // allow using '*' as a wildcard value
27 regex: false, // string is treated as a regular expression
28 searchUp: false, // search from the end of the document upwards
29 ambientString: true, // return ambient string as part of the result
30 };
31 instance.addSearchListener(searchListener);
32 instance.searchTextFull(event.data.term, searchOptions); //search full text for every occurence of searchTerm
33 }
34 break;
35 default:
36 break;
37 }
38 }
39}

JavaScript (v7.0+)

1function receiveMessage(event) {
2 const annotManager = docViewer.getAnnotationManager();
3
4 //you can register a searchListener to use a callback for result handling
5 const searchListener = (searchTerm, options, results) => {
6 // add redaction annotation for each search result
7 const newAnnotations = results.map(result => {
8 const annotation = new Annotations.RedactionAnnotation();
9 annotation.PageNumber = result.pageNum;
10 annotation.Quads = result.quads.map(quad => quad.getPoints());
11 annotation.StrokeColor = new Annotations.Color(136, 39, 31);
12 return annotation;
13 });
14
15 annotManager.addAnnotations(newAnnotations);
16 annotManager.drawAnnotationsFromList(newAnnotations);
17 };
18
19 if (event.isTrusted && typeof event.data === 'object') {
20 switch (event.data.type) {
21 case 'SEARCH_DOCUMENT':
22 if (event.data.term) {
23 const searchOptions = {
24 caseSensitive: true, // match case
25 wholeWord: true, // match whole words only
26 wildcard: false, // allow using '*' as a wildcard value
27 regex: false, // string is treated as a regular expression
28 searchUp: false, // search from the end of the document upwards
29 ambientString: true, // return ambient string as part of the result
30 };
31 readerControl.addSearchListener(searchListener);
32 readerControl.searchTextFull(event.data.term, searchOptions); //search full text for every occurence of searchTerm
33 }
34 break;
35 default:
36 break;
37 }
38 }
39}

Sample project

You can review the Salesforce PDF App to showcase an end-to-end example of search, and how you can leverage it for redaction and content replacing on our Github repository.

Live demo

Check out this live PDF Search Demo (hosted outside of Salesforce).

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales