Using Search API from Code

This example demonstrates how to programmatically utilize the Search API of a PDF viewer to search for the word "wetlands" in lowercase within a PDF document. The code retrieves the coordinates of the search results and highlights the found words using a custom highlight, which is implemented as stylized HTML elements positioned absolutely relative to the browser window.

// PDF Viewer instance let viewer; // Stores search results returned by the Search API let searchResults = []; // Overlay container for custom highlights let highlightLayer = null; // Entry point window.onload = async function () { // DsPdfViewer.LicenseKey = "***key***"; viewer = new DsPdfViewer('#viewer', { restoreViewStateOnLoad: false }); viewer.addDefaultPanels(); const pdfUrl = "/document-solutions/javascript-pdf-viewer/demos/product-bundles/assets/pdf/wetlands.pdf"; // Open document and fit width await viewer.open(pdfUrl); viewer.zoom = { mode: 1 }; createHighlightLayer(); updateLayerTransform(); await performSearch("wetlands"); renderHighlights(); // Re-render highlights when layout changes viewer.scrollView.addEventListener("scroll", renderHighlights); viewer.scrollView.addEventListener("pointerdown", renderHighlights); viewer.scrollView.addEventListener("pointerup", () => setTimeout(renderHighlights)); window.addEventListener("resize", () => { updateLayerTransform(); setTimeout(renderHighlights); }); }; /** * Performs text search and stores results. */ async function performSearch(text) { searchResults = []; const iterator = await viewer.searcher.search({ Text: text, MatchCase: true }); let result = await iterator.next(); while (!result.done) { searchResults.push(result.value); result = await iterator.next(); } } /** * Creates a dedicated overlay layer inside the document view. */ function createHighlightLayer() { if (highlightLayer) return; const documentView = viewer.hostElement.querySelector(".gcv-document-view"); highlightLayer = document.createElement("div"); highlightLayer.className = "highlight-layer"; documentView.appendChild(highlightLayer); } /** * Aligns overlay coordinate system with window coordinates. * convertPdfRectToWindowCoordinates() returns window-based values, * so we compensate by translating the entire layer. */ function updateLayerTransform() { const documentView = viewer.hostElement.querySelector(".gcv-document-view"); if (!documentView || !highlightLayer) return; const rect = documentView.getBoundingClientRect(); highlightLayer.style.transform = `translate(${-rect.left}px, ${-rect.top}px)`; } /** * Renders all highlight rectangles. */ function renderHighlights() { clearHighlights(); for (const item of searchResults) { const rect = viewer.convertPdfRectToWindowCoordinates( item.PageIndex, item.ItemArea ); addHighlight(rect, item.DisplayText); } } /** * Creates a single highlight rectangle. */ function addHighlight(rect, tooltipText) { const highlight = document.createElement("div"); highlight.className = "highlight-box"; highlight.title = `Match: ${tooltipText}`; const [x1, y1, x2, y2] = rect; highlight.style.left = `${x1}px`; highlight.style.top = `${y1}px`; highlight.style.width = `${x2 - x1}px`; highlight.style.height = `${y2 - y1}px`; highlightLayer.appendChild(highlight); } /** * Removes all highlights. */ function clearHighlights() { if (!highlightLayer) return; highlightLayer.innerHTML = ""; }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Using Search API from Code</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="./src/styles.css"> <script src="/document-solutions/javascript-pdf-viewer/demos/product-bundles/build/dspdfviewer.js"></script> <script src="/document-solutions/javascript-pdf-viewer/demos/product-bundles/build/wasmSupportApi.js"></script> <script src="/document-solutions/javascript-pdf-viewer/demos/resource/js/init.js"></script> <script src="./src/app.js"></script> <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> </head> <body> <div id="viewer"></div> </body> </html>
#viewer { height: 100%; } /* Overlay layer */ .highlight-layer { position: absolute; inset: 0; pointer-events: none; z-index: 5; transform: translate3d(0, 0, 0); } /* Highlight rectangle container with border */ .highlight-box { position: absolute; pointer-events: none; background-color: orange; /* fill */ border: 1px solid rgb(219, 127, 6); /* border */ opacity: 0.2; border-radius: 4px; overflow: hidden; cursor: pointer; } /* Animated wave inside highlight */ .highlight-box::after { content: ""; position: absolute; inset: 0; background: yellow; clip-path: inset(0 75% 0 0); animation: wave-animation 1s infinite ease-in-out; opacity: 0.7; z-index: 0; } /* Wave animation keyframes */ @keyframes wave-animation { 0% { clip-path: inset(0 75% 0 0); } 100% { clip-path: inset(0 0 0 75%); } } body { overflow: hidden; }