Text compare

Compare text in a PDF using this JavaScript sample (no servers or other external dependencies required). This sample identifies and shows users the exact area where text has changed in documents.This sample works on all browsers (including IE11) and mobile devices without using plug-ins. Learn more about our Web SDK.

1/* global Diff */
2
3const compareViewer = [
4 {
5 initialDoc: '../../files/text-compare_1.pdf',
6 domElement: 'leftPanel',
7 diffPanel: 'compareLeftPanel',
8 instance: null,
9 displayingWebViewer: true,
10 filenameBtn: document.querySelector('#toggleLeftBtn'),
11 pageTextSections: null,
12 highlightColor: '#e74c3c',
13 backgroundColor: '#f9e6f0',
14 textColor: '#f9e79f',
15 searchTerm: '',
16 searchResult: [],
17 searchResultIndex: 0,
18 },
19 {
20 initialDoc: '../../files/text-compare_2.pdf',
21 domElement: 'rightPanel',
22 diffPanel: 'compareRightPanel',
23 instance: null,
24 displayingWebViewer: false,
25 pageTextSections: null,
26 filenameBtn: document.querySelector('#toggleRightBtn'),
27 highlightColor: '#45b39d',
28 backgroundColor: '#b3f9c6',
29 textColor: '#ebf5fb',
30 searchTerm: '',
31 searchResult: [],
32 searchResultIndex: 0,
33 },
34];
35
36const leftPanelIndex = 0;
37const rightPanelIndex = 1;
38
39let maxPageCount = 1;
40let workerTransportPromise;
41let scrollTimeout;
42let pageChangeTimeout;
43
44Core.setWorkerPath('../../../lib/core');
45Core.getDefaultBackendType().then(async pdfType => {
46 workerTransportPromise = Core.initPDFWorkerTransports(pdfType, {});
47
48 await Promise.all([initializeWebViewer(compareViewer[leftPanelIndex]), initializeWebViewer(compareViewer[rightPanelIndex])]);
49
50 maxPageCount = Math.min(compareViewer[leftPanelIndex].instance.Core.documentViewer.getPageCount(), compareViewer[rightPanelIndex].instance.Core.documentViewer.getPageCount());
51 compareViewer[leftPanelIndex].instance.Core.documentViewer.setCurrentPage(1);
52 compareViewer[rightPanelIndex].instance.Core.documentViewer.setCurrentPage(1);
53
54 document.querySelector('#totalPage').textContent = maxPageCount;
55 document.querySelector('#currentPage').setAttribute('max', maxPageCount);
56 document.querySelector('#currentPage').value = 1;
57
58 compareViewer[leftPanelIndex].filenameBtn.value = compareViewer[leftPanelIndex].instance.Core.documentViewer.getDocument().filename;
59 compareViewer[rightPanelIndex].filenameBtn.value = compareViewer[rightPanelIndex].instance.Core.documentViewer.getDocument().filename;
60
61 compareText(1);
62});
63// eslint-disable-next-line no-undef
64const WebViewerConstructor = isWebComponent() ? WebViewer.WebComponent : WebViewer;
65const initializeWebViewer = viewer => {
66 return new Promise(resolve => {
67 WebViewerConstructor(
68 {
69 path: '../../../lib',
70 // since there are two instance of WebViewer, use "workerTransportPromise" so viewers can share resources
71 workerTransportPromise: {
72 pdf: workerTransportPromise,
73 },
74 initialDoc: viewer.initialDoc,
75 disabledElements: ['toggleNotesButton', 'pageNavOverlay', 'searchButton'],
76 },
77 document.getElementById(`${viewer.domElement}`)
78 ).then(instance => {
79 const { documentViewer } = instance.Core;
80 const Core = instance.Core;
81 const { Feature, FitMode } = instance.UI;
82 viewer.instance = instance;
83 // disable tools and editing annotations
84 instance.UI.disableTools();
85 instance.UI.disableFeatures(Feature.Annotations);
86
87 documentViewer.addEventListener('documentLoaded', async () => {
88 const displayModeManager = documentViewer.getDisplayModeManager();
89 const displayMode = displayModeManager.isVirtualDisplayEnabled()
90 ? new Core.VirtualDisplayMode(documentViewer, Core.DisplayModes.Single)
91 : new Core.DisplayMode(documentViewer, Core.DisplayModes.Single);
92 displayModeManager.setDisplayMode(displayMode);
93 instance.UI.setFitMode(FitMode.FitWidth);
94 resolve(instance);
95 });
96
97 documentViewer.addEventListener('pageNumberUpdated', pageNumber => {
98 if (pageNumber > maxPageCount) {
99 documentViewer.setCurrentPage(maxPageCount);
100 return;
101 }
102
103 document.querySelector('#currentPage').value = pageNumber;
104 // update compare when page change, use debouncing to limit the amount of processing being done
105 clearTimeout(pageChangeTimeout);
106 pageChangeTimeout = setTimeout(() => {
107 const otherViewer = compareViewer[leftPanelIndex].instance === instance ? compareViewer[rightPanelIndex].instance : compareViewer[leftPanelIndex].instance;
108 if (otherViewer.Core.documentViewer.getCurrentPage() !== pageNumber) {
109 otherViewer.Core.documentViewer.setCurrentPage(pageNumber);
110 }
111 compareText(pageNumber);
112 }, 1000);
113 });
114
115 const documentContainer = document
116 .getElementById(`${viewer.domElement}`)
117 .querySelector('iframe')
118 .contentDocument.querySelector('.DocumentContainer');
119 documentContainer.onscroll = () => {
120 syncScrolls(documentContainer.scrollLeft, documentContainer.scrollTop);
121 clearTimeout(scrollTimeout);
122 };
123
124 documentViewer.addEventListener('zoomUpdated', zoom => {
125 syncZoom(zoom, viewer.domElement);
126 });
127 });
128 });
129};
130
131const getPageText = (instance, pageNumber) => {
132 const doc = instance.Core.documentViewer.getDocument();
133
134 return new Promise(resolve => {
135 doc.loadPageText(pageNumber, text => {
136 resolve(text);
137 });
138 });
139};
140
141const compareText = async pageNumber => {
142 const text0 = await getPageText(compareViewer[leftPanelIndex].instance, pageNumber);
143 const text1 = await getPageText(compareViewer[rightPanelIndex].instance, pageNumber);
144
145 compareViewer[leftPanelIndex].pageTextSections = [];
146 compareViewer[rightPanelIndex].pageTextSections = [];
147
148 const leftPanel = document.querySelector(`#${compareViewer[leftPanelIndex].diffPanel}`);
149 const rightPanel = document.querySelector(`#${compareViewer[rightPanelIndex].diffPanel}`);
150 leftPanel.innerHTML = '';
151 rightPanel.innerHTML = '';
152
153 let sectionIndex = 0;
154
155 const diffLines = Diff.diffLines(text0, text1);
156 for (let i = 0; i < diffLines.length; i++) {
157 const diffLine = diffLines[i];
158 const sectionLeft = document.createElement('div');
159 const sectionRight = document.createElement('div');
160 sectionLeft.className = 'section';
161 sectionRight.className = 'section';
162
163 if (!diffLine.removed && !diffLine.added) {
164 // handle case when the text are the same
165 // add a toggleable element that displayed the same text when double clicked
166
167 compareViewer[leftPanelIndex].pageTextSections.push(diffLine.value);
168 compareViewer[rightPanelIndex].pageTextSections.push(diffLine.value);
169 sectionLeft.setAttribute('section', sectionIndex);
170 sectionRight.setAttribute('section', sectionIndex);
171
172 sectionLeft.className = 'section identical';
173 sectionRight.className = 'section identical';
174
175 const btnLeft = document.createElement('span');
176 const btnRight = document.createElement('span');
177 btnLeft.innerHTML = '(...)';
178 btnRight.innerHTML = '(...)';
179
180 const textRight = document.createElement('p');
181 const textLeft = document.createElement('p');
182 textRight.innerHTML = diffLine.value.replace(/\r?\n/g, '<br />');
183 textRight.className = 'hidden';
184
185 textLeft.innerHTML = diffLine.value.replace(/\r?\n/g, '<br />');
186 textLeft.className = 'hidden';
187
188 sectionRight.appendChild(textRight);
189 sectionLeft.appendChild(textLeft);
190
191 sectionLeft.appendChild(btnLeft);
192 sectionRight.appendChild(btnRight);
193
194 const toggleText = () => {
195 if (window.getSelection().toString()) {
196 // return if highlighting text
197 return;
198 }
199 const displayingText = !(textLeft.className !== 'hidden');
200
201 textLeft.className = displayingText ? '' : 'hidden';
202 textRight.className = displayingText ? '' : 'hidden';
203 btnRight.className = displayingText ? 'hidden' : '';
204 btnLeft.className = displayingText ? 'hidden' : '';
205 };
206
207 sectionRight.addEventListener('mouseup', toggleText);
208 sectionLeft.addEventListener('mouseup', toggleText);
209
210 leftPanel.appendChild(sectionLeft);
211 rightPanel.appendChild(sectionRight);
212 } else {
213 let updatedLine = '';
214
215 if (i + 1 < diffLines.length && (diffLines[i + 1].removed || diffLines[i + 1].added)) {
216 updatedLine = diffLines[i + 1].value;
217 sectionLeft.setAttribute('section', sectionIndex);
218 sectionRight.setAttribute('section', sectionIndex);
219 compareViewer[leftPanelIndex].pageTextSections.push(diffLines[i].value);
220 compareViewer[rightPanelIndex].pageTextSections.push(diffLines[i + 1].value);
221 i++;
222 }
223
224 // get difference for individual characters so they can be highlighted
225 const diffChars = Diff.diffChars(diffLine.value, updatedLine);
226 let oldText = '';
227 let newText = '';
228
229 const addStyle = `background-color: ${compareViewer[rightPanelIndex].highlightColor}; color: ${compareViewer[rightPanelIndex].textColor};`;
230 const removeStyle = `background-color:${compareViewer[leftPanelIndex].highlightColor}; color: ${compareViewer[leftPanelIndex].textColor};`;
231 diffChars.forEach(char => {
232 const value = char.value.replace(/\r?\n/g, ' <br />');
233
234 if (!char.removed && !char.added) {
235 oldText += `<span>${value}</span>`;
236 newText += `<span>${value}</span>`;
237 } else if (char.added) {
238 newText += value.replace(/\s/g, '').length ? `<span style="${addStyle}">${value}</span>` : value;
239 } else if (char.removed) {
240 oldText += value.replace(/\s/g, '').length ? `<span style="${removeStyle}">${value}</span>` : value;
241 }
242 });
243
244 sectionRight.style.backgroundColor = compareViewer[rightPanelIndex].backgroundColor;
245 sectionLeft.style.backgroundColor = compareViewer[leftPanelIndex].backgroundColor;
246
247 const textLeft = document.createElement('p');
248 textLeft.innerHTML = oldText;
249 sectionLeft.appendChild(textLeft);
250 leftPanel.appendChild(sectionLeft);
251
252 const textRight = document.createElement('p');
253 textRight.innerHTML = newText;
254 sectionRight.appendChild(textRight);
255 rightPanel.appendChild(sectionRight);
256
257 const maxHeight = Math.max(sectionRight.scrollHeight, sectionLeft.scrollHeight);
258 sectionRight.style.height = `${maxHeight}px`;
259 sectionLeft.style.height = `${maxHeight}px`;
260 }
261
262 sectionIndex++;
263 }
264};
265
266const syncZoom = (zoom, domElement) => {
267 compareViewer.forEach(viewer => {
268 const instance = viewer.instance;
269
270 if (instance.UI.getZoomLevel() !== zoom && domElement !== viewer.domElement) {
271 instance.UI.setZoomLevel(zoom);
272 }
273 });
274};
275
276const syncScrolls = (scrollLeft, scrollTop) => {
277 compareViewer.forEach(viewer => {
278 const documentContainer = document
279 .getElementById(`${viewer.domElement}`)
280 .querySelector('iframe')
281 .contentDocument.querySelector('.DocumentContainer');
282 if (!documentContainer) {
283 return;
284 }
285
286 if (documentContainer.scrollLeft !== scrollLeft) {
287 documentContainer.scrollLeft = scrollLeft;
288 }
289
290 if (documentContainer.scrollTop !== scrollTop) {
291 documentContainer.scrollTop = scrollTop;
292 }
293 });
294};
295
296let scrollDebounce = 0;
297const scrollDebounceTime = 10;
298
299// re render the top display when window resize
300window.onresize = () => {
301 if (compareViewer[leftPanelIndex].instance && compareViewer[leftPanelIndex].instance.Core.documentViewer) {
302 compareText(compareViewer[leftPanelIndex].instance.Core.documentViewer.getCurrentPage());
303 }
304};
305
306document.querySelector('#currentPage').onchange = e => {
307 const value = e.currentTarget.value;
308 if (value <= maxPageCount) {
309 compareViewer[leftPanelIndex].instance.Core.documentViewer.setCurrentPage(value);
310 compareViewer[rightPanelIndex].instance.Core.documentViewer.setCurrentPage(value);
311 }
312};
313
314// sync the top displays
315document.getElementById('compareLeftPanel').onscroll = e => {
316 clearTimeout(scrollDebounce);
317
318 scrollDebounce = setTimeout(() => {
319 document.getElementById('compareRightPanel').scrollTop = e.target.scrollTop;
320 }, scrollDebounceTime);
321};
322
323document.getElementById('compareRightPanel').onscroll = e => {
324 clearTimeout(scrollDebounce);
325
326 scrollDebounce = setTimeout(() => {
327 document.getElementById('compareLeftPanel').scrollTop = e.target.scrollTop;
328 }, scrollDebounceTime);
329};
330
331const toggleWebViewer = () => {
332 if (compareViewer[leftPanelIndex].displayingWebViewer) {
333 document.getElementById('toggleRightBtn').disabled = true;
334 document.getElementById('toggleLeftBtn').disabled = false;
335
336 document.getElementById('rightPanel').classList.remove('hidden');
337 document.getElementById('leftPanel').classList.add('hidden');
338
339 compareViewer[leftPanelIndex].displayingWebViewer = false;
340 compareViewer[rightPanelIndex].displayingWebViewer = true;
341 } else {
342 document.getElementById('toggleRightBtn').disabled = false;
343 document.getElementById('toggleLeftBtn').disabled = true;
344
345 document.getElementById('rightPanel').classList.add('hidden');
346 document.getElementById('leftPanel').classList.remove('hidden');
347
348 compareViewer[leftPanelIndex].displayingWebViewer = true;
349 compareViewer[rightPanelIndex].displayingWebViewer = false;
350 }
351};
352
353document.getElementById('expandTextBtn').onclick = () => {
354 document.getElementById('expandTextBtn').hidden = true;
355 document.getElementById('shirkTextBtn').hidden = false;
356
357 Array.from(document.querySelectorAll('#compareLeftPanel>.identical')).forEach(identicalSection => {
358 identicalSection.querySelector('p').classList.remove('hidden');
359 identicalSection.querySelector('span').classList.add('hidden');
360 });
361
362 Array.from(document.querySelectorAll('#compareRightPanel>.identical')).forEach(identicalSection => {
363 identicalSection.querySelector('p').classList.remove('hidden');
364 identicalSection.querySelector('span').classList.add('hidden');
365 });
366};
367
368document.getElementById('shirkTextBtn').onclick = () => {
369 document.getElementById('expandTextBtn').hidden = false;
370 document.getElementById('shirkTextBtn').hidden = true;
371
372 Array.from(document.querySelectorAll('#compareLeftPanel>.identical')).forEach(identicalSection => {
373 identicalSection.querySelector('p').classList.add('hidden');
374 identicalSection.querySelector('span').classList.remove('hidden');
375 });
376
377 Array.from(document.querySelectorAll('#compareRightPanel>.identical')).forEach(identicalSection => {
378 identicalSection.querySelector('p').classList.add('hidden');
379 identicalSection.querySelector('span').classList.remove('hidden');
380 });
381};
382
383document.getElementById('colorPopup').onclick = e => {
384 e.stopPropagation();
385 const popup = document.querySelector('#colorFormPopup');
386 popup.hidden = !popup.hidden;
387};
388
389document.getElementById('colorFormPopup').onclick = e => {
390 e.stopPropagation();
391};
392
393document.getElementById('compareContainer').onclick = () => {
394 document.querySelector('#colorFormPopup').hidden = true;
395};
396
397const colorInputs = [
398 {
399 element: document.getElementById('rightHighlightColor'),
400 viewer: compareViewer[0],
401 color: 'highlightColor',
402 },
403 {
404 element: document.getElementById('rightBackgroundColor'),
405 viewer: compareViewer[0],
406 color: 'backgroundColor',
407 },
408 {
409 element: document.getElementById('rightTextColor'),
410 viewer: compareViewer[0],
411 color: 'textColor',
412 },
413 {
414 element: document.getElementById('leftHighlightColor'),
415 viewer: compareViewer[1],
416 color: 'highlightColor',
417 },
418 {
419 element: document.getElementById('leftBackgroundColor'),
420 viewer: compareViewer[1],
421 color: 'backgroundColor',
422 },
423 {
424 element: document.getElementById('leftTextColor'),
425 viewer: compareViewer[1],
426 color: 'textColor',
427 },
428];
429
430colorInputs.forEach(colorInput => {
431 colorInput.element.onchange = e => {
432 colorInput.viewer[colorInput.color] = e.srcElement.value;
433 compareText(compareViewer[0].instance.Core.documentViewer.getCurrentPage());
434 };
435});
436
437document.getElementById('toggleLeftBtn').onclick = () => {
438 toggleWebViewer();
439};
440
441document.getElementById('toggleRightBtn').onclick = () => {
442 toggleWebViewer();
443};
444
445const loadDocuments = (leftDocument, rightDocument) => {
446 let leftLoadDocumentPromise = Promise.resolve();
447 let rightLoadDocumentPromise = Promise.resolve();
448
449 if (leftDocument) {
450 document.querySelector(`#${compareViewer[leftPanelIndex].diffPanel}`).innerHTML = '';
451 leftLoadDocumentPromise = new Promise(resolve => {
452 compareViewer[leftPanelIndex].instance.Core.documentViewer.addEventListener(
453 'documentLoaded',
454 () => {
455 resolve();
456 },
457 { once: true }
458 );
459 });
460 compareViewer[leftPanelIndex].instance.UI.loadDocument(leftDocument);
461 }
462
463 if (rightDocument) {
464 document.querySelector(`#${compareViewer[rightPanelIndex].diffPanel}`).innerHTML = '';
465 rightLoadDocumentPromise = new Promise(resolve => {
466 compareViewer[rightPanelIndex].instance.Core.documentViewer.addEventListener(
467 'documentLoaded',
468 () => {
469 resolve();
470 },
471 { once: true }
472 );
473 });
474 compareViewer[rightPanelIndex].instance.UI.loadDocument(rightDocument);
475 }
476
477 Promise.all([leftLoadDocumentPromise, rightLoadDocumentPromise]).then(() => {
478 // wait for both documents to finish loading before getting file information and comparing them
479 maxPageCount = Math.min(compareViewer[leftPanelIndex].instance.Core.documentViewer.getPageCount(), compareViewer[rightPanelIndex].instance.Core.documentViewer.getPageCount());
480 compareViewer[leftPanelIndex].instance.Core.documentViewer.setCurrentPage(1);
481 compareViewer[rightPanelIndex].instance.Core.documentViewer.setCurrentPage(1);
482
483 document.querySelector('#totalPage').textContent = maxPageCount;
484 document.querySelector('#currentPage').setAttribute('max', maxPageCount);
485 document.querySelector('#currentPage').value = 1;
486
487 compareViewer[leftPanelIndex].filenameBtn.value = compareViewer[leftPanelIndex].instance.Core.documentViewer.getDocument().filename;
488 compareViewer[rightPanelIndex].filenameBtn.value = compareViewer[rightPanelIndex].instance.Core.documentViewer.getDocument().filename;
489
490 compareText(1);
491 });
492};
493
494document.getElementById('dropdown-form').onsubmit = e => {
495 e.preventDefault();
496 loadDocuments(document.querySelector('#leftPanel-select').value, document.querySelector('#rightPanel-select').value);
497};
498
499document.getElementById('url-form').onsubmit = e => {
500 e.preventDefault();
501 loadDocuments(document.querySelector('#leftPanel-url').value, document.querySelector('#rightPanel-url').value);
502};
503
504document.getElementById('file-picker-form').onsubmit = e => {
505 e.preventDefault();
506 loadDocuments(document.querySelector('#leftPanel-file-picker').files[0], document.querySelector('#rightPanel-file-picker').files[0]);
507};
508
509document.getElementById('findSelectedBtn').onclick = () => {
510 // get the currently selected text. We need to replace new lines with spaces for matching later.
511 const selection = window.getSelection();
512 // in "compareText", it set new lines to be " <br />", this undo it if needed
513 const selectedText = selection.toString().replace(/\s*\n/gm, ' ');
514 if (!selectedText) {
515 alert('No text selected to find');
516 return;
517 }
518
519 const selectedTextSection = selection.baseNode.parentElement.closest('.section');
520 const selectionNumber = parseInt(selectedTextSection.getAttribute('section'), 10);
521
522 let currentViewer = null;
523
524 if (selection.baseNode.parentElement.closest('.viewer').id === 'compareRightPanel') {
525 currentViewer = compareViewer[rightPanelIndex];
526 } else {
527 currentViewer = compareViewer[leftPanelIndex];
528 }
529
530 if (!currentViewer.displayingWebViewer) {
531 // if we aren't displaying the current viewer toggle to show it
532 toggleWebViewer();
533 }
534
535 // since we are searching all the text on a page, we need to find the number of previous occurrences of the search term
536 const sectionElements = Array.from(selection.baseNode.parentNode.parentElement.children);
537 let currentPreviousText = '';
538
539 for (let i = 0; sectionElements.length > i; i++) {
540 if (sectionElements[i] === selection.baseNode.parentElement) {
541 currentPreviousText += sectionElements[i].textContent.substring(0, selection.anchorOffset);
542 break;
543 }
544 currentPreviousText += sectionElements[i].textContent;
545 }
546
547 const previousSectionText = currentViewer.pageTextSections
548 .filter((t, i) => i < selectionNumber)
549 .map(t => t.replace(/\s*\n/gm, ' '))
550 .join(' ');
551 const previousText = `${previousSectionText}${currentPreviousText}`;
552
553 const matches = previousText.match(new RegExp(`${selectedText.replace(/[-[\]{}()*+?.,\\^$|#]/g, '\\$&').trim()}`, 'g'));
554 const previousOccurrencesInSection = matches ? matches.length : 0;
555
556 let count = 0;
557 const mode =
558 currentViewer.instance.Core.documentViewer.SearchMode.e_highlight |
559 currentViewer.instance.Core.documentViewer.SearchMode.e_ambient_string |
560 currentViewer.instance.Core.documentViewer.SearchMode.e_case_sensitive;
561 const searchOptions = {
562 onResult: result => {
563 if (count === previousOccurrencesInSection) {
564 // skip all the previous occurrences of the search term till we get to the currently selected text
565 currentViewer.instance.Core.documentViewer.displaySearchResult(result);
566 }
567 count++;
568 },
569 fullSearch: true,
570 startPage: currentViewer.instance.Core.documentViewer.getCurrentPage(),
571 endPage: currentViewer.instance.Core.documentViewer.getCurrentPage(),
572 };
573
574 currentViewer.instance.Core.documentViewer.textSearchInit(selectedText.trim(), mode, searchOptions);
575};
576
577document.getElementById('searchForm').onsubmit = e => {
578 e.preventDefault();
579 const currentSearchTerm = document.getElementById('textSearch').value;
580 const viewer = compareViewer[leftPanelIndex].displayingWebViewer ? compareViewer[leftPanelIndex] : compareViewer[rightPanelIndex];
581
582 if (viewer.searchTerm === currentSearchTerm && viewer.searchResult.length) {
583 // cycle through existing results
584 viewer.searchResultIndex = viewer.searchResultIndex + 1 < viewer.searchResult.length ? viewer.searchResultIndex + 1 : 0;
585 viewer.instance.Core.documentViewer.displaySearchResult(viewer.searchResult[viewer.searchResultIndex]);
586 } else {
587 viewer.searchTerm = currentSearchTerm;
588 viewer.searchResult = [];
589
590 const mode =
591 viewer.instance.Core.documentViewer.SearchMode.e_highlight | viewer.instance.Core.documentViewer.SearchMode.e_ambient_string | viewer.instance.Core.documentViewer.SearchMode.e_case_sensitive;
592 const isFullSearch = true;
593 viewer.instance.Core.documentViewer.textSearchInit(currentSearchTerm, mode, isFullSearch, result => {
594 // this callback get called as search term are found till the final "Done" result is returned
595
596 if (result.resultCode === Core.Search.ResultCode.FOUND) {
597 if (viewer.searchResult.length === 0) {
598 // display the first result received
599 viewer.instance.Core.documentViewer.displaySearchResult(result);
600 }
601 // store results for cycling through search, check "resultCode" to not add the "done" result
602 viewer.searchResult.push(result);
603 } else if (result.resultCode === Core.Search.ResultCode.DONE && !viewer.searchResult.length) {
604 alert(`No results found for ${currentSearchTerm}`);
605 }
606 });
607 }
608};

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales