[ADF-2388, ADF-2375] PDF Viewer - show buffer thumbnail on pagechange (#3011)

* disable thumbnails button until document is loaded

* show buffer thumbnail on page change

* correct value property

* correct test
This commit is contained in:
Cilibiu Bogdan
2018-03-06 09:00:52 +02:00
committed by Denys Vuika
parent 8f63af1fbd
commit 69ac38713f
8 changed files with 99 additions and 22 deletions

View File

@@ -9,16 +9,12 @@
position: relative; position: relative;
&__content { &__content {
top: 0; top: 5px;
left: 50%; left: 50%;
height: 0; height: 0;
position: absolute; position: absolute;
} }
&__thumb:first-child {
margin-top: 15px;
}
&__thumb { &__thumb {
cursor: pointer; cursor: pointer;
display: block; display: block;

View File

@@ -17,6 +17,7 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { PdfThumbListComponent } from './pdfViewer-thumbnails.component'; import { PdfThumbListComponent } from './pdfViewer-thumbnails.component';
import { PdfThumbComponent } from './pdfViewer-thumb.component'; import { PdfThumbComponent } from './pdfViewer-thumb.component';
@@ -55,6 +56,9 @@ describe('PdfThumbListComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [
NoopAnimationsModule
],
declarations: [ declarations: [
PdfThumbListComponent, PdfThumbListComponent,
PdfThumbComponent PdfThumbComponent
@@ -81,7 +85,7 @@ describe('PdfThumbListComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
const renderedIds = component.renderItems.map(item => item.id); const renderedIds = component.renderItems.map(item => item.id);
const rangeIds = viewerMock._pages.slice(0, 7).map(item => item.id); const rangeIds = viewerMock._pages.slice(0, 6).map(item => item.id);
expect(renderedIds).toEqual(rangeIds); expect(renderedIds).toEqual(rangeIds);
}); });
@@ -91,24 +95,23 @@ describe('PdfThumbListComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
const renderedIds = component.renderItems.map(item => item.id); const renderedIds = component.renderItems.map(item => item.id);
const rangeIds = viewerMock._pages.slice(6, 14).map(item => item.id); const rangeIds = viewerMock._pages.slice(5, 12).map(item => item.id);
expect(renderedIds).toEqual(rangeIds); expect(renderedIds).toEqual(rangeIds);
}); });
it('should render items containing current document page', () => { it('should render items containing current document page', () => {
fixture.nativeElement.scrollTop = 1700;
fixture.detectChanges(); fixture.detectChanges();
const renderedIds = component.renderItems.map(item => item.id); const renderedIds = component.renderItems.map(item => item.id);
expect(renderedIds).not.toContain(3); expect(renderedIds).not.toContain(10);
viewerMock.eventBus.dispatch('pagechange', { pageNumber: 3 }); component.scrollInto(10);
const newRenderedIds = component.renderItems.map(item => item.id); const newRenderedIds = component.renderItems.map(item => item.id);
expect(newRenderedIds).toContain(3); expect(newRenderedIds).toContain(10);
}); });
it('should not change items if range contains current document page', () => { it('should not change items if range contains current document page', () => {
@@ -126,6 +129,19 @@ describe('PdfThumbListComponent', () => {
expect(newRenderedIds).toContain(12); expect(newRenderedIds).toContain(12);
}); });
it('should scroll thumbnail height amount to buffer thumbnail onPageChange event', () => {
spyOn(component, 'scrollInto');
fixture.detectChanges();
expect(component.renderItems[component.renderItems.length - 1].id).toBe(6);
expect(fixture.debugElement.nativeElement.scrollTop).toBe(0);
viewerMock.currentPageNumber = 6;
expect(component.scrollInto).not.toHaveBeenCalled();
expect(fixture.debugElement.nativeElement.scrollTop).toBe(129);
});
it('should return current viewed page as selected', () => { it('should return current viewed page as selected', () => {
fixture.nativeElement.scrollTop = 0; fixture.nativeElement.scrollTop = 0;
fixture.detectChanges(); fixture.detectChanges();
@@ -136,17 +152,10 @@ describe('PdfThumbListComponent', () => {
}); });
it('should go to selected page', () => { it('should go to selected page', () => {
fixture.nativeElement.scrollTop = 0;
fixture.detectChanges(); fixture.detectChanges();
const renderedIds = component.renderItems.map(item => item.id);
expect(renderedIds).not.toContain(12);
component.goTo(12); component.goTo(12);
const newRenderedIds = component.renderItems.map(item => item.id); expect(viewerMock.currentPageNumber).toBe(12);
expect(newRenderedIds).toContain(12);
}); });
}); });

View File

@@ -35,7 +35,8 @@ export class PdfThumbListComponent implements OnInit, AfterViewInit, OnDestroy {
renderItems = []; renderItems = [];
private items = []; private items = [];
private itemHeight: number = 114; private margin: number = 15;
private itemHeight: number = 114 + this.margin;
@ContentChild(TemplateRef) @ContentChild(TemplateRef)
template: any; template: any;
@@ -87,7 +88,7 @@ export class PdfThumbListComponent implements OnInit, AfterViewInit, OnDestroy {
return; return;
} }
this.element.nativeElement.scrollTop = Math.floor(index - 1 ) * this.itemHeight; this.element.nativeElement.scrollTop = index * this.itemHeight;
this.calculateItems(); this.calculateItems();
} }
@@ -133,5 +134,9 @@ export class PdfThumbListComponent implements OnInit, AfterViewInit, OnDestroy {
if (index < 0) { if (index < 0) {
this.scrollInto(event.pageNumber); this.scrollInto(event.pageNumber);
} }
if (index >= this.renderItems.length - 1) {
this.element.nativeElement.scrollTop += this.itemHeight;
}
} }
} }

View File

@@ -37,6 +37,7 @@
<ng-container *ngIf="allowThumbnails"> <ng-container *ngIf="allowThumbnails">
<button mat-icon-button <button mat-icon-button
[disabled]="isPanelDisabled"
(click)="toggleThumbnails()"> (click)="toggleThumbnails()">
<mat-icon>dashboard</mat-icon> <mat-icon>dashboard</mat-icon>
</button> </button>

View File

@@ -40,6 +40,7 @@
justify-content: flex-end; justify-content: flex-end;
align-items: flex-end; align-items: flex-end;
display: flex; display: flex;
color: mat-color($foreground, text, 0.54);
} }
} }

View File

@@ -437,4 +437,56 @@ describe('Test PdfViewer component', () => {
}); });
}); });
}); });
describe('Viewer events', () => {
beforeEach(() => {
component.urlFile = require('../assets/fake-test-file.pdf');
fixture.detectChanges();
});
it('should emit pagechange event', (done) => {
component.ngOnChanges(null).then(() => {
fixture.detectChanges();
return fixture.whenStable().then(() => {
expect(component.displayPage).toBe(1);
const args = {
pageNumber: 6,
source: {
container: component.documentContainer
}
};
component.pdfViewer.eventBus.dispatch('pagechange', args);
fixture.detectChanges();
expect(component.displayPage).toBe(6);
expect(component.page).toBe(6);
done();
});
});
});
it('should emit pagesloaded event', (done) => {
component.ngOnChanges(null).then(() => {
fixture.detectChanges();
return fixture.whenStable().then(() => {
expect(component.isPanelDisabled).toBe(true);
const args = {
pagesCount: 10,
source: {
container: component.documentContainer
}
};
component.pdfViewer.eventBus.dispatch('pagesloaded', args);
fixture.detectChanges();
expect(component.isPanelDisabled).toBe(false);
done();
});
});
});
});
}); });

View File

@@ -67,6 +67,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
MIN_SCALE: number = 0.25; MIN_SCALE: number = 0.25;
MAX_SCALE: number = 10.0; MAX_SCALE: number = 10.0;
isPanelDisabled = true;
showThumbnails: boolean = false; showThumbnails: boolean = false;
pdfThumbnailsContext: { viewer: any } = { viewer: null }; pdfThumbnailsContext: { viewer: any } = { viewer: null };
@@ -78,6 +79,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
private logService: LogService) { private logService: LogService) {
// needed to preserve "this" context // needed to preserve "this" context
this.onPageChange = this.onPageChange.bind(this); this.onPageChange = this.onPageChange.bind(this);
this.onPagesLoaded = this.onPagesLoaded.bind(this);
} }
ngOnChanges(changes) { ngOnChanges(changes) {
@@ -142,6 +144,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
this.documentContainer = document.getElementById('viewer-pdf-viewer'); this.documentContainer = document.getElementById('viewer-pdf-viewer');
this.documentContainer.addEventListener('pagechange', this.onPageChange, true); this.documentContainer.addEventListener('pagechange', this.onPageChange, true);
this.documentContainer.addEventListener('pagesloaded', this.onPagesLoaded, true);
this.pdfViewer = new PDFJS.PDFViewer({ this.pdfViewer = new PDFJS.PDFViewer({
container: this.documentContainer, container: this.documentContainer,
@@ -159,6 +162,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
ngOnDestroy() { ngOnDestroy() {
if (this.documentContainer) { if (this.documentContainer) {
this.documentContainer.removeEventListener('pagechange', this.onPageChange, true); this.documentContainer.removeEventListener('pagechange', this.onPageChange, true);
this.documentContainer.removeEventListener('pagesloaded', this.onPagesLoaded, true);
} }
} }
@@ -369,6 +373,15 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
this.displayPage = event.pageNumber; this.displayPage = event.pageNumber;
} }
/**
* Pages Loaded Event
*
* @param event
*/
onPagesLoaded(event) {
this.isPanelDisabled = false;
}
/** /**
* Litener Keyboard Event * Litener Keyboard Event
* @param KeyboardEvent event * @param KeyboardEvent event

View File

@@ -11,7 +11,7 @@
.adf-viewer { .adf-viewer {
.mat-toolbar, .mat-icon { .mat-toolbar {
color: mat-color($foreground, text, 0.54); color: mat-color($foreground, text, 0.54);
} }