How to synchronize the scroll behavior while comparing two different pdf version documents in Angular 4+?

88 Views Asked by At

I have loaded two different pdf versions documents side by side using ng2-pdf-viewer in my angular application. two version documents have different content for some paragraphs.

My Task is: while scrolling up/down the left document I have to show the same content in the right document and vice versa.

Problem: while scrolling left pdf right pdf is scrolling(using event listeners) , inside right pdf scroll listener i have added code to scroll left pdf. so without any user interaction both pdf files scrolling to end of the document How to fix this problem?

below is my component.html

<section style = "display: flex; border:1px groove">
<section style="width: 40.5%;background: #EFEFEF;">
    <section style="background: #DFE6EE;margin-bottom: 5px;height:25px;">
       <span><app-toolbar></app-toolbar></span> 
        </section>
    <pdf-viewer
    [src]="oldDocSrc"
    [render-text]="renderText"
    [rotation]="0"
    [original-size]="false"
    [show-all]="true"
    [show-borders]="false"
    [fit-to-page]="false"
    [zoom]="zoom_to"
    [zoom-scale]="'page-width'"
    [stick-to-page]="false"
    [render-text]="true"
    [external-link-target]="'blank'"
    [autoresize]="true"
    #viewer1
    (after-load-complete)="loadCompleteL($event)"
    (pageChange)="onPageChangeL($event)"
    class="viewer" id="final-pdfViewer1">
    </pdf-viewer>
</section>
<section id="virscrSec" style="width: 0.25%;background:#BECDE0;">
    <!-- <div id="virscr" style="border-radius: 0px;height: 20px;width: 10px;" class="virit-scr"></div> -->
</section>
<section  style="width: 40.5%;background: #EFEFEF;">
    <section style="background: #DFE6EE;margin-bottom: 5px;height:25px;">
       <span> <app-toolbar></app-toolbar></span>
        </section>
    <pdf-viewer
    [src]="latestDocSrc"
    [render-text]="renderText"
    [rotation]="0"
    [original-size]="false"
    [show-all]="true"
    [show-borders]="false"
    [fit-to-page]="false"
    [zoom]="zoom_to"
    [zoom-scale]="'page-width'"
    [stick-to-page]="false"
    [render-text]="true"
    [external-link-target]="'blank'"
    [autoresize]="true"
    #viewer2
    (after-load-complete)="loadCompleteR($event)"
    class="viewer" id="final-pdfViewer">
    </pdf-viewer>
</section>
<section id="virscrSec" style="width: 0.25%;background:#BECDE0;">
</section>
<section style="width: 18.5%;">
        <section style="font-weight: bold;font-size: 15px;color:#727375;
         height:25px;align-items: center;background: #DFE6EE;display: flex;">Change List</section>
            <section id="changes-data" style="border: 1px solid #DFE6EE; padding: 2px; margin: 2px;max-height: 586px; overflow: scroll;">
                <section *ngFor="let change of changesData; let j = index;" style="display: flex;flex-direction: row;padding:5px;">
                    <div class="change-data" style="width: 100%" (click)="scrollToChangeN(change, j)">
                        <div style="background: #F2F7FD; border: 1px solid #DFE6EE;padding: 5px;">
                            {{change?.currentPage || change?.sourcePage}}.{{change?.operation}}
                        </div>
                        <div style="border: 1px solid #DFE6EE; padding: 7px;">
                            <div style="background: #FCC5CB;padding: 5px;margin-bottom: 7px;line-height: 25px;display: inline;" *ngIf="change?.sourceText">{{change?.sourceText}}</div>
                            <div *ngIf="change?.sourceText" style="margin-bottom: 5px;"></div>
                            <div style="background: #C4EEE2;padding: 5px;line-height: 25px;display: inline;" *ngIf="change?.currentText">{{change?.currentText}}</div>
                        </div>
                    </div>
                </section>
            </section>
</section>

below is my component.ts file

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { PdfViewerComponent } from 'ng2-pdf-viewer';
import { SESSION_STORAGE, StorageService } from 'ngx-webstorage-service';
import { Subscription } from 'rxjs';
import { DocumentService } from 'src/app/services/document.service';
@Component({
  selector: 'doc-version-compare',
  templateUrl: './csr-compare.component.html',
  styleUrls: ['./csr-compare.component.scss']
})
export class CsrCompareComponent implements OnInit {

  zoom_to = 1;
  renderText = true;
  leftPDF;
  rightPDF;

  // virscrEle;
  scrollData;
  actualChangesData;
  changesData;

  versionInfo: any;
  oldDocSrc;
  latestDocSrc;
  subscriptionList: Subscription[] = [];

  @ViewChild("viewer1") viewer1: PdfViewerComponent;
  @ViewChild("viewer2") viewer2: PdfViewerComponent;
  currentPageL: number = 1;
  currentPageR: number = 1;
  scaleL;
  scaleR;
  constructor(private router: Router, @Inject(SESSION_STORAGE) private storage: StorageService,
    private http: HttpClient,
    private docService: DocumentService) {
    this.versionInfo = this.storage.get('versionInfo');
  }

  ngOnInit(): void {
    let reqObj = {
      "studyId": this.versionInfo.latest.studyId,
      "sourceWorkflowId": this.versionInfo.old.wfId,
      "currentWorkflowId": this.versionInfo.latest.wfId,
      "sourceFileName": this.versionInfo.old.fileName,
      "currentFileName": this.versionInfo.latest.fileName
    }
    let sub = this.docService.getCompareId(reqObj).subscribe(compId => {
      // this.oldDocSrc = environment.onlyofficeEndPoint + '/compare-service/document/' + compId + '/' + 'source';
      // this.latestDocSrc = environment.onlyofficeEndPoint + '/compare-service/document/' + compId + '/' + 'current';
      let subO = this.docService.getDocumentData(compId, 'source').subscribe((res: any) => {
        let srcUrl = res.url;
        const headers = new HttpHeaders().set('Authorization', (this.storage.get('accesstoken')))
        const options = { headers: headers, responseType: 'blob' as 'json' };
        this.http.get(srcUrl, options).subscribe((response: any) => {
          const blob = new Blob([response], { type: 'application/pdf' });
          const blobUrl = URL.createObjectURL(blob);
          this.oldDocSrc = blobUrl;
        })
      });
      this.subscriptionList.push(subO);

      let subN = this.docService.getDocumentData(compId, 'current').subscribe((res: any) => {
        let srcUrl = res.url;
        const headers = new HttpHeaders().set('Authorization', (this.storage.get('accesstoken')))
        const options = { headers: headers, responseType: 'blob' as 'json' };
        this.http.get(srcUrl, options).subscribe((response: any) => {
          const blob = new Blob([response], { type: 'application/pdf' });
          const blobUrl = URL.createObjectURL(blob);
          this.latestDocSrc = blobUrl;
        })
      });
      this.subscriptionList.push(subN);
      // this.getChangesData(compId);
      this.getScrollData(compId);
    });
    this.subscriptionList.push(sub);
  }

  sourcePagesHeight:[{pageNo: string, pageHeight: string}];
  currentPagesHeight:[{pageNo: string, pageHeight: string}];
  
    // console.log(document.querySelectorAll('[aria-label ="Page 1"]'));

  getChangesData(compId) {
    let subc = this.docService.getChangesData(compId).subscribe((changes:any) => {
      this.actualChangesData = changes;
      this.changesData = changes.filter(x => x.operation != 'EQUAL');
      console.log(this.changesData);
    })
    this.subscriptionList.push(subc);
  }

  getScrollData(compId) {
    let subc = this.docService.getScrollData(compId).subscribe(scrollD => {
      // console.log({ scrollD });
      this.scrollData = scrollD;
    })
    this.subscriptionList.push(subc);
  }
  backToCsr(routeStr) {
    this.router.navigate(['user/' + this.storage.get('userRole').toLowerCase() + '/' + routeStr],
      { queryParamsHandling: 'preserve' });
  }

  newScrollData;
  loadCompleteL(event) {
    
    this.leftPDF = document.getElementsByClassName('ng2-pdf-viewer-container')[0];
    this.scaleL = this.viewer1.pdfViewer.currentScale;
    this.buildNewScrollData();
    this.scrollListenerL1();
    
  }

  loadCompleteR(event) {
    this.rightPDF = document.getElementsByClassName('ng2-pdf-viewer-container')[1];
    this.scaleR = this.viewer2.pdfViewer.currentScale;
    this.scrollListenerR();
    this.rightPDF.addEventListener('scroll', (event) => {
          this.leftPDF.removeEventListener('scroll')
          let scrollItem = this.scrollData.diffMap.find((item) => item.cpOffset > this.rightPDF.scrollTop);
          this.leftPDF.scrollTo({top:scrollItem.spOffset, behavior: 'smooth'});
    })
  }

  buildNewScrollData() {
    // if(!this.newScrollData) {
    //   this.newScrollData = 1;
      // console.log(this.scrollData);
      setTimeout(() => {
        this.scrollData.diffMap.forEach(x => {
          let spage = x.sourcePage;
          let cpage = x.currentPage;
          if(spage > 1 && cpage > 1) {
            x['spOffset'] = Math.floor((document.querySelectorAll('[aria-label ^= "Page "]')[spage-1].getBoundingClientRect().top) - (this.leftPDF.getBoundingClientRect().top));
            x['cpOffset'] = Math.floor((document.querySelectorAll('[aria-label ^= "Page "]')[cpage-1].getBoundingClientRect().top) - (this.rightPDF.getBoundingClientRect().top));
          } else {
            x['spOffset'] = x.sourcePageOffset;
            x['cpOffset'] = x.currentPageOffset
            ;            
          }
        });
        this.changesData = this.scrollData['diffMap'].filter(x => x.operation != 'EQUAL');
     
      },3000);
   
  }

  currentPageData:any= [];
  currentItem;

  oldLeftScrollTop:number = 1;
  isScrollL:boolean = false;
  scrollListenerL1() {
    this.leftPDF.addEventListener('scroll',
    (event) => {
        this.isScrollR = true;
        this.isScrollL = false;
        console.log(event.target.scrollTop ,'and' ,this.oldLeftScrollTop);
        // console.log(this.viewer1.pdfViewer);
        if(this.leftPDF.scrollTop - this.oldLeftScrollTop <= 100) {
          event.preventDefault();
          return false;
        }  else if(this.isScrollR) {
          this.oldLeftScrollTop = event.target.scrollTop;
          let scrollItem = this.scrollData.diffMap.find((item) => item.spOffset > this.leftPDF.scrollTop);
          this.rightPDF.scrollTo({top:scrollItem.cpOffset, behavior: 'smooth'});
        }
        });
  }

  oldRightScrollTop:number = 1;
  isScrollR:boolean = false;
  scrollListenerR() {
    
      this.rightPDF.addEventListener('scroll', (event) =>{
        this.isScrollL = true;
        this.isScrollR = false;
        if(this.rightPDF.scrollTop - this.oldRightScrollTop <= 100) {
          event.preventDefault();
          return false;
        } else if(this.isScrollL) {
          console.log('scrolling from right===============');
          this.oldRightScrollTop = this.rightPDF.scrollTop;
          let scrollItem = this.scrollData.diffMap.find((item) => item.cpOffset > this.rightPDF.scrollTop);
          this.leftPDF.scrollTo({top:scrollItem.spOffset, behavior: 'smooth'});
        }
        })
  }

  ngOnDestroy() {
    this.subscriptionList.forEach(subscription => subscription.unsubscribe());
  }
}
0

There are 0 best solutions below