Semantic Compare show annotations for the second document

Product: webviewer

Product Version: 10.0.1

Please give a brief summary of your issue:
Semantic Text Compare annotate on second document

Please describe your issue and provide steps to reproduce it:
Hello, I have 2 questions about the comparison feature:

  1. When comparing 2 documents using Semantic Text Compare, I would like to be see the annotations for the document that is selected. Currently, I am only seeing the annotations for the document that was originally loaded. I have coded my page to load and save annotations that are added to the second document, but since I can’t access them in the comments panel, I can’t comment, reply, etc.

  2. Is it possible to suppress the annotations that represent the differences in the comments panel? I was able to find the annotations that represent the differences and hide them using AnnotationManager.hideAnnotation(), but it also hid the annotations on the documents. I would like to still see the differences, but only on the document. (see screenshot - highlighted annotation is what I would like to hide).

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

1 Like

Hi,

Are you using the full-apis/ViewerPDFSemanticDiffTest sample ?

Wanbo

1 Like

I don’t know where to find that sample. The issue I am having is from with my application that I built. I do have webviewer.fullApi = true, and to start the comparison, I am using DocumentViewer.startSemanticDiff to begin the comparison.

I used this example to get started adding this feature to our existing implementation of webviewer in our product. Apryse Documentation | Documentation.

1 Like

I was able to hide the annotations in the comments panel and keep them in the document using:

this.wvInstance.UI.setCustomNoteFilter(function (annotation) {
      return annotation.getCustomData('TextDiffType') === '' && annotation.getCustomData('TextDiffID') === '';
 });

I am still not able to show the annotations for the second document in the comments panel.

1 Like

Sorry for the late reply. I have checked with our team, and we have an item in our backlog for this, and we’ll work on this soon. Will keep you updated.

1 Like

Thank you for the update.

1 Like

Any follow up on this issue? I am also having this issue but haven’t found any solution for it

1 Like

Support for showing annotations for the 2nd document in notes panel has been added, and will be available in the next release of WebViewer (v10.2). Thanks.

Wanbo

1 Like

Is there anything that I need to do to make this work besides using version 10.2.0? I have tried updating to 10.2.0 and I am still not seeing the annotations for the second document viewer appearing in the comments panel.
Note in the screenshot: the document on the right is selected, but the annotation for the left document is still showing in the comments panel.

1 Like

I heard that there was something wrong with the downloaded build for 10.2.0, could you try updating to 10.2.2 and see if works for you? Thanks!

Wanbo

1 Like

I have tried 10.2.1 and 10.2.2 with the same results.

1 Like

Hi,

I just tried modifying the viewing sample code as attached below, and it worked for me. Please try it out.

// @link WebViewerInstance: https://docs.apryse.com/api/web/WebViewerInstance.html
// @link UI.loadDocument: https://docs.apryse.com/api/web/UI.html#loadDocument__anchor

WebViewer(
  {
    path: '../../../lib',
    fullAPI: true,
    disableMultiViewerComparison: true, 
  },
  document.getElementById('viewer')
).then((instance) => {
  samplesSetup(instance);

  document.getElementById('select').onchange = (e) => {
    instance.UI.loadDocument(e.target.value);
  };

  document.getElementById('file-picker').onchange = (e) => {
    const file = e.target.files[0];
    if (file) {
      instance.UI.loadDocument(file);
    }
  };

  document.getElementById('url-form').onsubmit = (e) => {
    e.preventDefault();
    instance.UI.loadDocument(document.getElementById('url').value);
  };

  const { UI, Core } = instance;
  const { Annotations } = Core;
  const { Color } = Annotations;

  UI.addEventListener(UI.Events.MULTI_VIEWER_READY, () => {
    const [documentViewer1, documentViewer2] = Core.getDocumentViewers();
    const startCompare = async () => {
      const shouldCompare = documentViewer1.getDocument() && documentViewer2.getDocument();
      if (shouldCompare) { // Check if both documents loaded before comparing
        const beforeColor = new Color(21, 205, 131, 0.4);
        const afterColor = new Color(255, 73, 73, 0.4);
        const options = { beforeColor, afterColor };
        const { doc1Annotations, doc2Annotations, diffCount } = await documentViewer1.startSemanticDiff(documentViewer2, options);
      }
    }
    documentViewer1.addEventListener('documentLoaded', startCompare);
    documentViewer2.addEventListener('documentLoaded', startCompare);
    documentViewer1.loadDocument('https://pdftron.s3.amazonaws.com/downloads/pl/demo-annotated.pdf');
    documentViewer2.loadDocument('https://pdftron.s3.amazonaws.com/downloads/pl/demo-annotated.pdf');
  });
  UI.enableFeatures([UI.Feature.MultiViewerMode]);

});

Thanks.

Wanbo

1 Like

I tried using the sample Angular app and pasted in the code to do a comparison. I am getting the same results.

import { AfterViewInit, Component, ElementRef, EventEmitter, Output, ViewChild } from '@angular/core';
import WebViewer, { WebViewerInstance } from "@pdftron/webviewer";
import { Subject } from "rxjs";

@Component({
  selector: 'app-root',
  styleUrls: ['app.component.css'],
  templateUrl: 'app.component.html'
})
export class AppComponent implements AfterViewInit {
  wvInstance?: WebViewerInstance;

  @ViewChild('viewer') viewer!: ElementRef;

  @Output() coreControlsEvent: EventEmitter<string> = new EventEmitter();

  private documentLoaded$: Subject<void>;

  constructor() {
    this.documentLoaded$ = new Subject<void>();
  }

  ngAfterViewInit(): void {

    WebViewer({
      path: '../lib',
      fullAPI: true
    }, this.viewer.nativeElement).then(instance => {
      this.wvInstance = instance;

      const { documentViewer, Annotations, annotationManager } = instance.Core;

      instance.UI.openElements(['notesPanel']);

      documentViewer.addEventListener('annotationsLoaded', () => {
        console.log('annotations loaded');
      });

      const { UI, Core } = instance;
      const { Color } = Annotations;

      UI.addEventListener(UI.Events.MULTI_VIEWER_READY, () => {
        const [documentViewer1, documentViewer2] = Core.getDocumentViewers();
        const startCompare = async () => {
          const shouldCompare = documentViewer1.getDocument() && documentViewer2.getDocument();
          if (shouldCompare) { // Check if both documents loaded before comparing
            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);
        documentViewer1.loadDocument('http://localhost:4200/files/fluffy.pdf');
        documentViewer2.loadDocument('http://localhost:4200/files/scooby.pdf');
      });
      UI.enableFeatures([UI.Feature.MultiViewerMode]);
    })
  }
}

1 Like

Hi,

Could you attach the screenshot of the version info shown in the browser console? Also you can try open your app in an Incognito window, in case the old cache was being used.

Wanbo

1 Like

Sure. Here is a screenshot with the version information. This is running in an Incognito window. I also restarted Windows to try to rule out caching.

1 Like

Hi,

I talked to my colleague and he suggested you can try upgrading to latest nightly build of v10.2, please check this link - Apryse Documentation | Documentation

Please let me know how it goes.

Thanks

1 Like

I have tried this nightly build - https://nightly-pdftron-uploads.s3.us-west-1.amazonaws.com/stable/2023-06-26/webviewer/WebViewer-10.2.2_2023-06-26_stable.zip and it appears to be working correctly in my test application. Is there a timeline of when this will be available through npm?

annotations and compare working

1 Like

Hi,

I think in the guide I sent previously there’s a section about installing the nightly build through npm. Here is the link - https://docs.apryse.com/documentation/web/faq/webviewer-nightly-build/#npm

1 Like

That works. Thank you for your help.

1 Like

Now that I am able to annotate on both documents, I am seeing some issues. I am not sure if I am doing something wrong. The document on the left is working correctly. I can create, edit and delete annotations. The document on the right has some problems. I am using an annotation manager for each document. When working with the right document, adding, replying and deleting will use the annotation manager for the right document. Editing comments will use the annotation viewer for the left document. The right document also doesn’t include the xfdf content.
For my use case, I need the xfdf data to pass to our API.

Is there a different way that I should be doing this?

import { AfterViewInit, Component, ElementRef, EventEmitter, Output, ViewChild } from '@angular/core';
import WebViewer, { Core, WebViewerInstance } from "@pdftron/webviewer";
import { Subject } from "rxjs";

@Component({
  selector: 'app-root',
  styleUrls: ['app.component.css'],
  templateUrl: 'app.component.html'
})
export class AppComponent implements AfterViewInit {
  wvInstance?: WebViewerInstance;

  @ViewChild('viewer') viewer!: ElementRef;

  @Output() coreControlsEvent: EventEmitter<string> = new EventEmitter();

  private documentLoaded$: Subject<void>;

  constructor() {
    this.documentLoaded$ = new Subject<void>();
  }

  ngAfterViewInit(): void {

    WebViewer({
      path: '../lib',
      fullAPI: true
    }, this.viewer.nativeElement).then(instance => {
      this.wvInstance = instance;

      const { documentViewer, Annotations, annotationManager } = instance.Core;

      instance.UI.openElements(['notesPanel']);

      documentViewer.addEventListener('annotationsLoaded', () => {
        console.log('annotations loaded');
      });

      const { UI, Core } = instance;
      const { Color } = Annotations;

      UI.addEventListener(UI.Events.MULTI_VIEWER_READY, () => {
        const [documentViewer1, documentViewer2] = Core.getDocumentViewers();
        const startCompare = async () => {
          const shouldCompare = documentViewer1.getDocument() && documentViewer2.getDocument();
          if (shouldCompare) { // Check if both documents loaded before comparing
            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);
        documentViewer1.loadDocument('http://localhost:4200/files/fluffy.pdf');
        documentViewer2.loadDocument('http://localhost:4200/files/scooby.pdf');

        let document1AnnotationManager = documentViewer1.getAnnotationManager();
        document1AnnotationManager.addEventListener(
          'annotationChanged',
          (annotations: any, action: any, { imported }: any) => {
            console.log('document1AnnotationManager.annotationChanged');
            this.saveAnnotations(document1AnnotationManager, annotations, action);
          }
        );


        let document2AnnotationManager = documentViewer2.getAnnotationManager();
        document2AnnotationManager.addEventListener(
          'annotationChanged',
          (annotations: any, action: any, { imported }: any) => {
            console.log('document2AnnotationManager.annotationChanged');
            this.saveAnnotations(document1AnnotationManager, annotations, action);
          }
        );
      });
      UI.enableFeatures([UI.Feature.MultiViewerMode]);
    })
  }

  private saveAnnotations(annotationManager: Core.AnnotationManager,
    annotations: any,
    action: string) {

    annotations.forEach((annotation: Core.Annotations.Annotation) => {
      annotationManager.exportAnnotationCommand().then((xfdfData: any) => {
        console.log(`Saving... ${action}`);
        console.log(`XFDF data = ${xfdfData}`);
      });
    });
  }

}


This gif is a recording that shows what is happening using the above sample code.
example-with-saving-annotations

1 Like