Some test text!

Search
Hamburger Icon

Search & highlight text in documents using JavaScript

This JavaScript sample lets you search and highlight text in PDF, DOCX, PPTX and XLSX documents by extracting text position (no servers or other external dependencies required). Users can search through a PDF for a whole word or look for case sensitive words. If a word is located in the document it is highlighted and the user can jump to the position of the word in the document. This sample works on all browsers (including IE11) and mobile devices without using plug-ins. To view an example visit our Text Search & Highlight demo. Learn more about our JavaScript PDF Library.

Get Started Samples Download

To run this sample, get started with a free trial of Apryse SDK.

JavaScript

HTML

const viewerElement = document.getElementById('viewer');
// eslint-disable-next-line no-undef
const { WebViewerConstructor, uiOption } = getSampleOptions();

WebViewerConstructor(
  {
    path: '../../../lib',
    initialDoc: 'https://pdftron.s3.amazonaws.com/downloads/pl/legal-contract.pdf',
    ui: uiOption,
  },
  viewerElement
).then(instance => {
  samplesSetup(instance);
  const { documentViewer, annotationManager, Annotations } = instance.Core;

  const renderCheckBoxes = pageCount => {
    const pagesDiv = document.getElementById('pages');
    let pageNumber;
    const checkboxes = [];

    for (pageNumber = 1; pageNumber <= pageCount; pageNumber++) {
      const input = document.createElement('input');
      /* eslint-disable prefer-template */
      input.id = `page-${pageNumber}`;
      input.type = 'checkbox';
      input.checked = false;
      input.value = pageNumber;

      checkboxes.push(input);

      const label = document.createElement('label');
      label.htmlFor = `page-${pageNumber}`;
      label.innerHTML = `Page ${pageNumber}`;

      const lineBreak = document.createElement('br');

      pagesDiv.appendChild(input);
      pagesDiv.appendChild(label);
      pagesDiv.appendChild(lineBreak);
    }

    return checkboxes;
  };

  const highlightText = (searchText, pageNumber) => {
    const doc = documentViewer.getDocument();

    // gets all text on the requested page
    // see https://docs.apryse.com/api/web/Core.Document.html#loadPageText__anchor
    doc.loadPageText(pageNumber).then(text => {
      let textStartIndex = 0;
      let textIndex;
      const annotationPromises = [];

      // find the position of the searched text and add text highlight annotation at that location
      while ((textIndex = text.indexOf(searchText, textStartIndex)) > -1) {
        textStartIndex = textIndex + searchText.length;
        // gets quads for each of the characters from start to end index. Then,
        // resolve the annotation and return.
        // see https://docs.apryse.com/api/web/Core.Document.html#getTextPosition__anchor
        const annotationPromise = doc.getTextPosition(pageNumber, textIndex, textIndex + searchText.length).then(quads => {
          const annotation = new Annotations.TextHighlightAnnotation();
          annotation.Author = annotationManager.getCurrentUser();
          annotation.PageNumber = pageNumber;
          annotation.Quads = quads;
          annotation.StrokeColor = new Annotations.Color(0, 255, 255);
          return annotation;
        });
        annotationPromises.push(annotationPromise);
      }

      // Wait for all annotations to be resolved.
      Promise.all(annotationPromises).then(annotations => {
        annotationManager.addAnnotations(annotations);
        annotationManager.selectAnnotations(annotations);
      });
    });
  };

  const removeHighlightedText = pageNumber => {
    const annotations = annotationManager.getAnnotationsList().filter(annotation => {
      return annotation.PageNumber === pageNumber;
    });
    annotationManager.deleteAnnotations(annotations);
  };

  documentViewer.addEventListener('documentLoaded', () => {
    const textInput = document.getElementById('text');
    const checkboxes = renderCheckBoxes(documentViewer.getPageCount());

    checkboxes.forEach(checkbox => {
      checkbox.addEventListener('change', () => {
        const pageNumber = Number(checkbox.value);

        if (checkbox.checked && textInput.value) {
          highlightText(textInput.value, pageNumber);
        } else {
          removeHighlightedText(pageNumber);
        }
      });
    });

    textInput.addEventListener(
      'input',
      // debounce loaded elsewhere
      // eslint-disable-next-line
      debounce(() => {
        checkboxes.forEach(checkbox => {
          const pageNumber = Number(checkbox.value);

          if (checkbox.checked) {
            removeHighlightedText(pageNumber);

            if (textInput.value) {
              highlightText(textInput.value, pageNumber);
            }
          }
        });
      }, 200)
    );

    // highlight search text in the first page by default
    checkboxes[0].checked = true;
    highlightText(textInput.value, 1);
  });
});