Getting error(viewer 2 undefined) will switching layover to side-by-side compare

Product: web viewer

Product Version: 10.12.0

Please give a brief summary of your issue: Getting error(viewer 2 undefined) will switching layover to side-by-side compare. I have add custom button to switch layover to side-by-side and side-by-side to layover. When user try to switch from layover to side-by-side getting error viewer2 is undefined.

Here is my implemented code: -
const setupSideBySideCompare = (instance, selectedFile) => {
isSideBySide = true;
Apryse.disableUIElements(instance);
UI.enableFeatures([UI.Feature.MultiViewerMode]);
const [documentViewer1, documentViewer2] = instance.Core.getDocumentViewers();
documentViewer2.loadDocument(selectedFile);
instance.UI.setHeaderItems((header) => {
const defaultHeader = header.headers?.default;
const updatedHeader = defaultHeader.filter(
(item) => ![ā€˜Compareā€™, ā€˜Saveā€™, ā€˜Side-by-Sideā€™].includes(item.title)
);
header.headers.default = updatedHeader;
});
const startCompare = async () => {
const doc1 = documentViewer1.getDocument();
const doc2 = documentViewer2.getDocument();
if (doc1 && doc2) {
const beforeColor = new Color(21, 205, 131, 0.4);
const afterColor = new Color(255, 73, 73, 0.4);
const options = { beforeColor, afterColor };
await documentViewer1.startSemanticDiff(documentViewer2, options);
}
};

    documentViewer1.addEventListener('documentLoaded', startCompare);
    documentViewer2.addEventListener('documentLoaded', startCompare);
};

const setupLayoverCompare = async (instance, selectedFile) => {
    isLayover = true;
    UI.enableFeatures([UI.Feature.MultiViewerMode]);
    Apryse.disableUIElements(instance);
    instance.UI.setHeaderItems((header) => {
        const defaultHeader = header.headers?.default;
        const updatedHeader = defaultHeader.filter(
            (item) => !['Compare', 'Save', 'Layover', 'View Setting'].includes(item.title)
        );
        header.headers.default = updatedHeader;
    });
    await PDFNet.initialize();
    const [documentViewer1, documentViewer2] = instance.Core.getDocumentViewers();
    const currentFileUrl = documentViewer1.getDocument().ca.Ac.url;
    url = currentFileUrl;
    documentViewer2.loadDocument(selectedFile);
    const getDocument = async (documentPath) => {
        const newDoc = await instance.Core.createDocument(documentPath);
        return newDoc.getPDFDoc();
    };
    const [doc1, doc2] = await Promise.all([
        getDocument(currentFileUrl),
        getDocument(selectedFile),
    ]);

    const getPageArray = async (doc) => {
        const arr = [];
        const itr = await doc.getPageIterator(1);

        for (itr; await itr.hasNext(); itr.next()) {
            const page = await itr.current();
            arr.push(page);
        }
        return arr;
    };

    const [doc1Pages, doc2Pages] = await Promise.all([
        getPageArray(doc1),
        getPageArray(doc2),
    ]);

    const newDoc = await PDFNet.PDFDoc.create();
    newDoc.lock();

    const biggestLength = Math.max(doc1Pages.length, doc2Pages.length);

    for (let i = 0; i < biggestLength; i++) {
        let page1 = doc1Pages[i];
        let page2 = doc2Pages[i];

        if (!page1) {
            page1 = await doc1.pageCreate();
        }
        if (!page2) {
            page2 = await doc2.pageCreate();
        }

        await newDoc.appendVisualDiff(page1, page2);
    }

    newDoc.unlock();
    instance.UI.loadDocument(newDoc);
    instance.UI.disableFeatures([UI.Feature.MultiViewerMode]);
};

UI.setHeaderItems((header) => {
header.length = 0;
header.push({
type: ā€˜actionButtonā€™,
title: ā€˜Compareā€™,
img: ā€˜ā€™,
onClick: async () => {
if (isComparePopupOpen) return;
isComparePopupOpen = true;
Apryse.GetFileVersionList();
const onCompare = async () => {
const fileInput = document.getElementById(ā€˜comparisonOptionsā€™);
const selectedFile = fileInput.value;

              document.body.removeChild(popup);
              isComparePopupOpen = false;
              if (Apryse.compareDefaultLayout) {
                  if (Apryse.compareDefaultLayout === 'SideBySide') {
                      setupSideBySideCompare(instance, selectedFile);
                  }
                  else if (Apryse.compareDefaultLayout === 'OverLay') {
                      setupLayoverCompare(instance, selectedFile);
                  }
              }
              else {
                  setupSideBySideCompare(instance, selectedFile);
              }

              instance.UI.setHeaderItems((compareHeader) => {
                  compareHeader.length = 0;

                  compareHeader.push({
                      type: 'actionButton',
                      title: 'Side-by-Side',
                      img: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 3h9v18H3V3zm11 0h7v18h-7V3z"/></svg>',
                      onClick: () => setupSideBySideCompare(instance, selectedFile),
                  });

                  compareHeader.push({
                      type: 'actionButton',
                      title: 'Layover',
                      img: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 3h18v7H3V3zm0 11h18v7H3v-7z"/></svg>',
                      onClick: () => setupLayoverCompare(instance, selectedFile),
                  });

                  compareHeader.push({
                      type: 'actionButton',
                      title: 'Back',
                      img: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.5 4.5l-1.4 1.4 6.1 6.1H3v2h17.2l-6.1 6.1 1.4 1.4L21.9 12z"/></svg>',
                      onClick: async () => {
                          UI.disableFeatures([UI.Feature.MultiViewerMode]);
                          Apryse.enableUIElements(instance);
                          instance.UI.setHeaderItems((backHeader) => {
                              const defaultHeader = backHeader.headers?.default;
                              const updatedHeader = defaultHeader.filter(
                                  (item) => !['Side-by-Side', 'Layover', 'Back', 'View Setting'].includes(item.title)
                              );
                              backHeader.headers.default = updatedHeader;
                          });

                          if (isLayover) {
                              await loadDocumentWithCleanup(instance, url);
                          }
                          window.location.reload();
                      },
                  });
                  if (isSideBySide) {
                      instance.UI.setHeaderItems((sideBySideheader) => {
                          const defaultHeader = sideBySideheader.headers?.default;
                          const updatedHeader = defaultHeader.filter(
                              (item) => !['Side-by-Side'].includes(item.title)
                          );
                          sideBySideheader.headers.default = updatedHeader;
                      });
                  }
              });
          };

          const onCancel = () => {
              document.body.removeChild(popup);
              isComparePopupOpen = false;
          };

          const popup = createPopup(onCompare, onCancel);
      },
  });

});
(Think of this as an email subject)

Please describe your issue and provide steps to reproduce it:
(The more descriptive your answer, the faster we are able to help you)

Please provide a link to a minimal sample where the issue is reproducible:

1 Like

Hello, Iā€™m AiRon, an automated tech support bot :robot: While you wait for one of our customer support representatives, I can help you with your question.

It looks like youā€™re encountering an error message stating ā€œviewer 2 undefinedā€ when trying to switch from layover to side-by-side comparison in WebViewer. This error typically occurs when the code attempts to access the second viewer before it has been properly initialized or loaded.

Some things you can try:

  • Ensure that the MultiViewerMode feature is enabled before attempting to access the second viewer. This mode allows you to work with multiple document viewers simultaneously.

  • Check that getDocumentViewers() is returning two viewers. If not, verify that the MultiViewerMode is correctly set up.

  • Ensure that documents are loaded into both viewers before attempting operations that involve them. You can achieve this by waiting for the documentLoaded event on both viewers.

  • Verify that the selectedFile variable is correctly defined and passed to loadDocument() when switching modes. This ensures that the correct document is being loaded into the second viewer.

  • Review the lifecycle of your custom button logic to ensure it correctly initializes and cleans up resources when switching between comparison modes.



Here are some resources that might help you:

  • MultiViewerMode Guide - This guide provides instructions on setting up and using multiple viewers in WebViewer.

  • Document Loading Guide - Learn about the document loading process and how to handle events like documentLoaded.

  • Annotations Guide - This guide covers working with annotations, which might be relevant if your comparison involves annotation differences.

  • UI Customization Guide - Explore how to customize the WebViewer UI, which can help in setting up custom buttons and interactions.



Hopefully, this helps you solve your problem while you wait for a human to get back to you.

1 Like

Hello Rishu,

Thank you for contacting WebViewer Forums.

You may have to wait for the document viewers to be ready before doing any operations on them to ensure they are available. In the following guide, we recommend using the MULTI_VIEWER_READY event: Enabling and using multiple DocumentViewers in the UI | Apryse documentation

For example:

instance.UI.addEventListener(UI.Events.MULTI_VIEWER_READY, () => {
      const [documentViewerOne, documentViewerTwo] = getDocumentViewers();

Regards,
Luke

1 Like