diff --git a/ng2-components/ng2-alfresco-core/index.ts b/ng2-components/ng2-alfresco-core/index.ts index 22bee76be9..373d4bd815 100644 --- a/ng2-components/ng2-alfresco-core/index.ts +++ b/ng2-components/ng2-alfresco-core/index.ts @@ -122,6 +122,7 @@ import { NodePermissionDirective } from './src/directives/node-permission.direct import { UploadDirective } from './src/directives/upload.directive'; import { FileSizePipe } from './src/pipes/file-size.pipe'; +import { MimeTypeIconPipe } from './src/pipes/mime-type-icon.pipe'; import { HighlightPipe } from './src/pipes/text-highlight.pipe'; import { TimeAgoPipe } from './src/pipes/time-ago.pipe'; @@ -193,7 +194,8 @@ export function providers() { SharedLinksApiService, SitesApiService, DiscoveryApiService, - HighlightTransformService + HighlightTransformService, + MomentDateAdapter ]; } @@ -212,6 +214,15 @@ export function obsoleteMdlDirectives() { ]; } +export function pipes() { + return [ + FileSizePipe, + HighlightPipe, + TimeAgoPipe, + MimeTypeIconPipe + ]; +} + export function createTranslateLoader(http: Http, logService: LogService) { return new AlfrescoTranslateLoader(http, logService); } @@ -240,6 +251,7 @@ export function createTranslateLoader(http: Http, logService: LogService) { ], declarations: [ ...obsoleteMdlDirectives(), + ...pipes(), UploadDirective, NodePermissionDirective, HighlightDirective, @@ -251,16 +263,12 @@ export function createTranslateLoader(http: Http, logService: LogService) { InfoDrawerTitleDirective, InfoDrawerButtonsDirective, InfoDrawerContentDirective, - FileSizePipe, - HighlightPipe, - TimeAgoPipe, CreateFolderDialogComponent, DownloadZipDialogComponent ], providers: [ ...providers(), ...deprecatedProviders(), - MomentDateAdapter, { provide: TRANSLATION_PROVIDER, multi: true, @@ -284,14 +292,12 @@ export function createTranslateLoader(http: Http, logService: LogService) { PaginationModule, ToolbarModule, ...obsoleteMdlDirectives(), + ...pipes(), UploadDirective, NodePermissionDirective, HighlightDirective, DataColumnComponent, DataColumnListComponent, - FileSizePipe, - HighlightPipe, - TimeAgoPipe, CreateFolderDialogComponent, DownloadZipDialogComponent, InfoDrawerComponent, diff --git a/ng2-components/ng2-alfresco-core/src/pipes/mime-type-icon.pipe.ts b/ng2-components/ng2-alfresco-core/src/pipes/mime-type-icon.pipe.ts new file mode 100644 index 0000000000..34455d5b59 --- /dev/null +++ b/ng2-components/ng2-alfresco-core/src/pipes/mime-type-icon.pipe.ts @@ -0,0 +1,31 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Pipe, PipeTransform } from '@angular/core'; +import { ThumbnailService } from '../services/thumbnail.service'; + +@Pipe({ + name: 'adfMimeTypeIcon' +}) +export class MimeTypeIconPipe implements PipeTransform { + + constructor(private thumbnailService: ThumbnailService) { } + + transform(text: string): string { + return this.thumbnailService.getMimeTypeIcon(text); + } +} diff --git a/ng2-components/ng2-alfresco-core/src/services/alfresco-api.service.ts b/ng2-components/ng2-alfresco-core/src/services/alfresco-api.service.ts index bcd8fb96c2..50facc0dde 100644 --- a/ng2-components/ng2-alfresco-core/src/services/alfresco-api.service.ts +++ b/ng2-components/ng2-alfresco-core/src/services/alfresco-api.service.ts @@ -16,7 +16,7 @@ */ import { Injectable } from '@angular/core'; -import { AlfrescoApi } from 'alfresco-js-api'; +import { AlfrescoApi, ContentApi, NodesApi, RenditionsApi } from 'alfresco-js-api'; import * as alfrescoApi from 'alfresco-js-api'; import { AppConfigService } from './app-config.service'; import { StorageService } from './storage.service'; @@ -26,10 +26,22 @@ export class AlfrescoApiService { private alfrescoApi: AlfrescoApi; - public getInstance(): AlfrescoApi { + getInstance(): AlfrescoApi { return this.alfrescoApi; } + get contentApi(): ContentApi { + return this.getInstance().content; + } + + get nodesApi(): NodesApi { + return this.getInstance().nodes; + } + + get renditionsApi(): RenditionsApi { + return this.getInstance().core.renditionsApi; + } + constructor(private appConfig: AppConfigService, private storage: StorageService) { diff --git a/ng2-components/ng2-alfresco-core/src/services/renditions.service.ts b/ng2-components/ng2-alfresco-core/src/services/renditions.service.ts index 58dfe6a955..cab768dd68 100644 --- a/ng2-components/ng2-alfresco-core/src/services/renditions.service.ts +++ b/ng2-components/ng2-alfresco-core/src/services/renditions.service.ts @@ -16,9 +16,9 @@ */ import { Injectable } from '@angular/core'; +import { RenditionEntry, RenditionPaging } from 'alfresco-js-api'; import { Observable } from 'rxjs/Rx'; import { AlfrescoApiService } from './alfresco-api.service'; -import { LogService } from './log.service'; /** * RenditionsService @@ -28,52 +28,57 @@ import { LogService } from './log.service'; @Injectable() export class RenditionsService { - constructor(private apiService: AlfrescoApiService, - private logService: LogService) { - + constructor(private apiService: AlfrescoApiService) { } - isRenditionAvailable(nodeId: string, encoding: string) { + isRenditionAvailable(nodeId: string, encoding: string): Observable { return Observable.create((observer) => { - this.getRendition(nodeId, encoding).subscribe((res) => { - let isAvailable = true; - if (res.entry.status === 'NOT_CREATED') { - isAvailable = false; + this.getRendition(nodeId, encoding).subscribe( + (res) => { + let isAvailable = true; + if (res.entry.status.toString() === 'NOT_CREATED') { + isAvailable = false; + } + observer.next(isAvailable); + observer.complete(); + }, + () => { + observer.next(false); + observer.complete(); } - observer.next(isAvailable); - observer.complete(); - }, () => { - observer.next(false); - observer.complete(); - }); + ); }); } - isConversionPossible(nodeId: string, encoding: string) { + isConversionPossible(nodeId: string, encoding: string): Observable { return Observable.create((observer) => { - this.getRendition(nodeId, encoding).subscribe(() => { - observer.next(true); - observer.complete(); - }, () => { - observer.next(false); - observer.complete(); - }); + this.getRendition(nodeId, encoding).subscribe( + () => { + observer.next(true); + observer.complete(); + }, + () => { + observer.next(false); + observer.complete(); + } + ); }); } - getRendition(nodeId: string, encoding: string) { - return Observable.fromPromise(this.apiService.getInstance().core.renditionsApi.getRendition(nodeId, encoding)) - .catch(err => this.handleError(err)); + getRenditionUrl(nodeId: string, encoding: string): string { + return this.apiService.contentApi.getRenditionUrl(nodeId, 'pdf'); } - getRenditionsListByNodeId(nodeId: string) { - return Observable.fromPromise(this.apiService.getInstance().core.renditionsApi.getRenditions(nodeId)) - .catch(err => this.handleError(err)); + getRendition(nodeId: string, encoding: string): Observable { + return Observable.fromPromise(this.apiService.renditionsApi.getRendition(nodeId, encoding)); } - createRendition(nodeId: string, encoding: string) { - return Observable.fromPromise(this.apiService.getInstance().core.renditionsApi.createRendition(nodeId, {id: encoding})) - .catch(err => this.handleError(err)); + getRenditionsListByNodeId(nodeId: string): Observable { + return Observable.fromPromise(this.apiService.renditionsApi.getRenditions(nodeId)); + } + + createRendition(nodeId: string, encoding: string): Observable<{}> { + return Observable.fromPromise(this.apiService.renditionsApi.createRendition(nodeId, {id: encoding})); } convert(nodeId: string, encoding: string, pollingInterval: number = 1000) { @@ -85,12 +90,7 @@ export class RenditionsService { return Observable.interval(interval) .switchMap(() => this.getRendition(nodeId, encoding)) .takeWhile((data) => { - return (data.entry.status !== 'CREATED'); + return (data.entry.status.toString() !== 'CREATED'); }); } - - private handleError(error: any): Observable { - this.logService.error(error); - return Observable.throw(error || 'Server error'); - } } diff --git a/ng2-components/ng2-alfresco-viewer/index.ts b/ng2-components/ng2-alfresco-viewer/index.ts index 0a2b39c845..8b46aa36ac 100644 --- a/ng2-components/ng2-alfresco-viewer/index.ts +++ b/ng2-components/ng2-alfresco-viewer/index.ts @@ -26,15 +26,16 @@ import { MediaPlayerComponent } from './src/components/mediaPlayer.component'; import { NotSupportedFormatComponent } from './src/components/notSupportedFormat.component'; import { PdfViewerComponent } from './src/components/pdfViewer.component'; import { TxtViewerComponent } from './src/components/txtViewer.component'; -import { ViewerDialogComponent } from './src/components/viewer-dialog.component'; +import { PdfViewComponent } from './src/components/viewer-dialog/pdf-view/pdf-view.component'; +import { ViewerDialogComponent } from './src/components/viewer-dialog/viewer-dialog.component'; import { ViewerComponent } from './src/components/viewer.component'; import { ExtensionViewerDirective } from './src/directives/extension-viewer.directive'; import { RenderingQueueServices } from './src/services/rendering-queue.services'; import { ViewerService } from './src/services/viewer.service'; -export { ViewerDialogComponent } from './src/components/viewer-dialog.component'; -export { ViewerDialogSettings } from './src/components/viewer-dialog.settings'; +export { ViewerDialogComponent } from './src/components/viewer-dialog/viewer-dialog.component'; +export { ViewerDialogSettings } from './src/components/viewer-dialog/viewer-dialog.settings'; export { ViewerService } from './src/services/viewer.service'; export const VIEWER_DIRECTIVES: any[] = [ @@ -45,7 +46,8 @@ export const VIEWER_DIRECTIVES: any[] = [ NotSupportedFormatComponent, PdfViewerComponent, ExtensionViewerDirective, - ViewerDialogComponent + ViewerDialogComponent, + PdfViewComponent ]; @NgModule({ diff --git a/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.ts b/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.ts index 178a92f176..0560f52d23 100644 --- a/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.ts +++ b/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.ts @@ -17,7 +17,6 @@ import { Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; import { ContentService, RenditionsService } from 'ng2-alfresco-core'; -import { AlfrescoApiService } from 'ng2-alfresco-core'; const DEFAULT_CONVERSION_ENCODING = 'pdf'; @@ -54,9 +53,7 @@ export class NotSupportedFormatComponent implements OnInit, OnDestroy { constructor( private contentService: ContentService, - private renditionsService: RenditionsService, - private apiService: AlfrescoApiService - ) {} + private renditionsService: RenditionsService) {} /** * Checks for available renditions if the nodeId is present @@ -86,11 +83,12 @@ export class NotSupportedFormatComponent implements OnInit, OnDestroy { checkRendition(encoding: string = DEFAULT_CONVERSION_ENCODING): void { this.renditionsService.getRendition(this.nodeId, encoding) .subscribe( - (response: any) => { - if (response.entry.status === 'NOT_CREATED') { + (response) => { + const status = response.entry.status.toString(); + if (status === 'NOT_CREATED') { this.convertible = true; this.displayable = false; - } else if (response.entry.status === 'CREATED') { + } else if (status === 'CREATED') { this.convertible = false; this.displayable = true; } @@ -119,7 +117,7 @@ export class NotSupportedFormatComponent implements OnInit, OnDestroy { * Show the PDF rendition of the node */ showPDF(): void { - this.renditionUrl = this.apiService.getInstance().content.getRenditionUrl(this.nodeId, DEFAULT_CONVERSION_ENCODING); + this.renditionUrl = this.renditionsService.getRenditionUrl(this.nodeId, DEFAULT_CONVERSION_ENCODING); this.isConversionStarted = false; this.isConversionFinished = true; } diff --git a/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/pdf-view/pdf-view.component.html b/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/pdf-view/pdf-view.component.html new file mode 100644 index 0000000000..ca8062b2e5 --- /dev/null +++ b/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/pdf-view/pdf-view.component.html @@ -0,0 +1,69 @@ +
+
+
+

Loading

+
+ +
+
+
+
+ + +
+
+ keyboard_arrow_left +
+ +
+ +
/ {{ totalPages }}
+
+ +
+ keyboard_arrow_right +
+
+ +
+
+ zoom_out_map +
+
+ zoom_in +
+
+ zoom_out +
+
+
diff --git a/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/pdf-view/pdf-view.component.scss b/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/pdf-view/pdf-view.component.scss new file mode 100644 index 0000000000..86e500a6ac --- /dev/null +++ b/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/pdf-view/pdf-view.component.scss @@ -0,0 +1,339 @@ +.adf-pdf-view { + + &__loading-screen { + + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + height: 85vh; + + .md-spinner { + margin: 0 auto; + } + } + + .left { + float: left; + } + + .viewer-toolbar-pagination{ + padding-top: 4px; + top: 80px; + right:35px; + width:auto; + position:absolute; + border-radius: 10px; + background: #3E3E3E; + color: white; + } + + .viewer-toolbar-command{ + height: 30px; + padding-top: 4px; + top: 80px; + left:35px; + width:auto; + position:absolute; + border-radius: 10px; + background: #3E3E3E; + color: white; + } + + .viewer-pagenumber-input { + border: none; + display: block; + font-size: 16px; + padding: 4px 0; + background: 0 0; + text-align: right; + color: inherit; + width: 33px; + margin-right: 4px; + height: 20px; + } + + .viewer-total-pages { + border: medium none; + display: flex; + font-size: 16px; + padding: 4px 0px; + background: transparent none repeat scroll 0px 0px; + text-align: right; + color: inherit; + margin-right: 4px; + height: 20px; + align-items: center; + justify-content: center; + } + + .viewer-page-counter { + margin-right: 20px; + } + + .button-page { + margin-right: 4px; + height: 24px; + width: 24px; + margin-left: 4px; + cursor: pointer; + } + + .button-page:hover { + cursor: pointer; + background: grey; + border-radius: 24px; + } +} + + +.adf-pdf-view { + .textLayer { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + overflow: hidden; + opacity: 0.2; + line-height: 1.0; + + & > div { + color: transparent; + position: absolute; + white-space: pre; + cursor: text; + -webkit-transform-origin: 0% 0%; + -moz-transform-origin: 0% 0%; + -o-transform-origin: 0% 0%; + -ms-transform-origin: 0% 0%; + transform-origin: 0% 0%; + } + + .highlight { + margin: -1px; + padding: 1px; + + background-color: rgb(180, 0, 170); + border-radius: 4px; + + &.begin { + border-radius: 4px 0px 0px 4px; + } + + &.end { + border-radius: 0px 4px 4px 0px; + } + + &.middle { + border-radius: 0px; + } + + &.selected { + background-color: rgb(0, 100, 0); + } + } + + &::selection { background: rgb(0,0,255); } + &::-moz-selection { background: rgb(0,0,255); } + + .endOfContent { + display: block; + position: absolute; + left: 0px; + top: 100%; + right: 0px; + bottom: 0px; + z-index: -1; + cursor: default; + user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + -moz-user-select: none; + + &.active { + top: 0px; + } + } + } + + .annotationLayer { + section { + position: absolute; + } + + .linkAnnotation { + & > a { + position: absolute; + font-size: 1em; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7") 0 0 repeat; + + &:hover { + opacity: 0.2; + background: #ff0; + box-shadow: 0px 2px 10px #ff0; + } + } + } + + .textAnnotation { + img { + position: absolute; + cursor: pointer; + } + } + + .popupWrapper { + position: absolute; + width: 20em; + } + + .popup { + position: absolute; + z-index: 200; + max-width: 20em; + background-color: #FFFF99; + box-shadow: 0px 2px 5px #333; + border-radius: 2px; + padding: 0.6em; + margin-left: 5px; + cursor: pointer; + word-wrap: break-word; + + h1 { + font-size: 1em; + border-bottom: 1px solid #000000; + padding-bottom: 0.2em; + } + + p { + padding-top: 0.2em; + } + } + + .highlightAnnotation, + .underlineAnnotation, + .squigglyAnnotation, + .strikeoutAnnotation, + .fileAttachmentAnnotation { + cursor: pointer; + } + } + + .pdfViewer { + canvasWrapper { + overflow: hidden; + } + + .page { + direction: ltr; + width: 816px; + height: 1056px; + margin: 1px auto -8px auto; + position: relative; + overflow: visible; + border: 9px solid transparent; + background-clip: content-box; + background-color: white; + + canvas { + margin: 0; + display: block; + } + + .loadingIcon { + position: absolute; + display: block; + left: 0; + top: 0; + right: 0; + bottom: 0; + } + } + + &.removePageBorders { + .page { + margin: 0px auto 10px auto; + border: none; + } + } + + .loadingIcon { + width: 100px; + height: 100px; + left: 50% !important; + top: 50% !important; + + margin-top: -50px; + margin-left: -50px; + + font-size: 5px; + text-indent: -9999em; + border-top: 1.1em solid rgba(3,0,2, 0.2); + border-right: 1.1em solid rgba(3,0,2, 0.2); + border-bottom: 1.1em solid rgba(3,0,2, 0.2); + border-left: 1.1em solid #030002; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; + + border-radius: 50%; + &:after { + border-radius: 50%; + } + } + } + + * { + padding: 0; + margin: 0; + } + + .hidden, [hidden] { + display: none !important; + } +} + +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +.viewer-pdf-container { + overflow: auto; + -webkit-overflow-scrolling: touch; + position: absolute; + top: 32px; + right: 0; + bottom: 0; + left: 0; + outline: none; +} +html[dir='ltr'] .viewer-pdf-container { + box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05); +} +html[dir='rtl'] .viewer-pdf-container { + box-shadow: inset -1px 0 0 hsla(0,0%,100%,.05); +} diff --git a/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/pdf-view/pdf-view.component.ts b/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/pdf-view/pdf-view.component.ts new file mode 100644 index 0000000000..2ea4c62618 --- /dev/null +++ b/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/pdf-view/pdf-view.component.ts @@ -0,0 +1,386 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component, HostListener, Input, OnInit, ViewEncapsulation } from '@angular/core'; +import { LogService } from 'ng2-alfresco-core'; +import { RenderingQueueServices } from '../../../services/rendering-queue.services'; + +declare let PDFJS: any; + +@Component({ + selector: 'adf-pdf-view', + templateUrl: 'pdf-view.component.html', + styleUrls: [ 'pdf-view.component.scss' ], + providers: [ RenderingQueueServices ], + host: { 'class': 'adf-pdf-view' }, + encapsulation: ViewEncapsulation.None +}) +export class PdfViewComponent implements OnInit { + + @Input() + fileUrl: string; + + page: number; + displayPage: number; + totalPages: number; + loadingPercent: number; + showToolbar = false; + isLoading = false; + + private currentPdfDocument: any; + private pdfViewer: any; + private currentScaleMode: string = 'auto'; + private currentScale: number; + + private MAX_AUTO_SCALE: number = 1.25; + private DEFAULT_SCALE_DELTA: number = 1.1; + private MIN_SCALE: number = 0.25; + private MAX_SCALE: number = 10.0; + + constructor(private renderingQueueServices: RenderingQueueServices, + private logService: LogService) { + } + + ngOnInit() { + if (this.fileUrl) { + this.render(this.fileUrl); + } + } + + private render(src) { + return new Promise((resolve, reject) => { + this.isLoading = true; + const loadingTask = this.getPDFJS().getDocument(src); + + loadingTask.onProgress = (progressData) => { + let level = progressData.loaded / progressData.total; + this.loadingPercent = Math.round(level * 100); + }; + + loadingTask.then( + (pdfDocument) => { + this.currentPdfDocument = pdfDocument; + this.totalPages = pdfDocument.numPages; + this.page = 1; + this.displayPage = 1; + this.initPDFViewer(this.currentPdfDocument); + + this.currentPdfDocument.getPage(1).then( + () => { + this.scalePage('auto'); + this.showToolbar = true; + this.isLoading = false; + resolve(); + }, + (error) => { + this.isLoading = false; + reject(error); + } + ); + }, + (error) => { + this.isLoading = false; + reject(error); + } + ); + }); + } + + /** + * return the PDFJS global object (exist to facilitate the mock of PDFJS in the test) + * + * @returns {PDFJS} + */ + getPDFJS() { + return PDFJS; + } + + initPDFViewer(pdfDocument: any) { + let documentContainer = document.getElementById('viewer-pdf-container'); + let viewer: any = document.getElementById('viewer-viewerPdf'); + + window.document.addEventListener('scroll', (event) => { + this.watchScroll(event.target); + }, true); + + this.pdfViewer = new PDFJS.PDFViewer({ + container: documentContainer, + viewer: viewer, + renderingQueue: this.renderingQueueServices + }); + + this.renderingQueueServices.setViewer(this.pdfViewer); + + this.pdfViewer.setDocument(pdfDocument); + } + + /** + * Method to scale the page current support implementation + * + * @param {string} scaleMode - new scale mode + */ + scalePage(scaleMode) { + this.currentScaleMode = scaleMode; + + if (this.pdfViewer) { + + let viewerContainer = document.getElementById('viewer-main-container'); + let documentContainer = document.getElementById('viewer-pdf-container'); + + let widthContainer; + let heigthContainer; + + if (viewerContainer && viewerContainer.clientWidth <= documentContainer.clientWidth) { + widthContainer = viewerContainer.clientWidth; + heigthContainer = viewerContainer.clientHeight; + } else { + widthContainer = documentContainer.clientWidth; + heigthContainer = documentContainer.clientHeight; + } + + let currentPage = this.pdfViewer._pages[this.pdfViewer._currentPageNumber - 1]; + + let padding = 20; + let pageWidthScale = (widthContainer - padding) / currentPage.width * currentPage.scale; + let pageHeightScale = (heigthContainer - padding) / currentPage.width * currentPage.scale; + + let scale; + + switch (this.currentScaleMode) { + case 'page-actual': + scale = 1; + break; + case 'page-width': + scale = pageWidthScale; + break; + case 'page-height': + scale = pageHeightScale; + break; + case 'page-fit': + scale = Math.min(pageWidthScale, pageHeightScale); + break; + case 'auto': + let horizontalScale; + if (this.isLandscape) { + horizontalScale = Math.min(pageHeightScale, pageWidthScale); + } else { + horizontalScale = pageWidthScale; + } + scale = Math.min(this.MAX_AUTO_SCALE, horizontalScale); + + break; + default: + this.logService.error('pdfViewSetScale: \'' + scaleMode + '\' is an unknown zoom value.'); + return; + } + + this.setScaleUpdatePages(scale); + } + } + + /** + * Update all the pages with the newScale scale + * + * @param {number} newScale - new scale page + */ + setScaleUpdatePages(newScale: number) { + if (!this.isSameScale(this.currentScale, newScale)) { + this.currentScale = newScale; + + this.pdfViewer._pages.forEach(function (currentPage) { + currentPage.update(newScale); + }); + + this.pdfViewer.update(); + } + } + + /** + * method to check if the request scale of the page is the same for avoid unuseful re-rendering + * + * @param {number} oldScale - old scale page + * @param {number} newScale - new scale page + * + * @returns {boolean} + */ + isSameScale(oldScale: number, newScale: number) { + return (newScale === oldScale); + } + + /** + * method to check if is a land scape view + * + * @param {number} width + * @param {number} height + * + * @returns {boolean} + */ + isLandscape(width: number, height: number) { + return (width > height); + } + + /** + * Method triggered when the page is resized + */ + onResize() { + this.scalePage(this.currentScaleMode); + } + + /** + * toggle the fit page pdf + */ + pageFit() { + if (this.currentScaleMode !== 'page-fit') { + this.scalePage('page-fit'); + } else { + this.scalePage('auto'); + } + } + + /** + * zoom in page pdf + * + * @param {number} ticks + */ + zoomIn(ticks: number) { + let newScale: any = this.currentScale; + do { + newScale = (newScale * this.DEFAULT_SCALE_DELTA).toFixed(2); + newScale = Math.ceil(newScale * 10) / 10; + newScale = Math.min(this.MAX_SCALE, newScale); + } while (--ticks > 0 && newScale < this.MAX_SCALE); + this.currentScaleMode = 'auto'; + this.setScaleUpdatePages(newScale); + } + + /** + * zoom out page pdf + * + * @param {number} ticks + */ + zoomOut(ticks: number) { + let newScale: any = this.currentScale; + do { + newScale = (newScale / this.DEFAULT_SCALE_DELTA).toFixed(2); + newScale = Math.floor(newScale * 10) / 10; + newScale = Math.max(this.MIN_SCALE, newScale); + } while (--ticks > 0 && newScale > this.MIN_SCALE); + this.currentScaleMode = 'auto'; + this.setScaleUpdatePages(newScale); + } + + /** + * load the previous page + */ + previousPage() { + if (this.pdfViewer && this.page > 1) { + this.page--; + this.displayPage = this.page; + + this.pdfViewer.currentPageNumber = this.page; + } + } + + /** + * load the next page + */ + nextPage() { + if (this.pdfViewer && this.page < this.totalPages) { + this.page++; + this.displayPage = this.page; + + this.pdfViewer.currentPageNumber = this.page; + } + } + + /** + * load the page in input + * + * @param {string} page - page to load + */ + inputPage(page: string) { + let pageInput = parseInt(page, 10); + + if (!isNaN(pageInput) && pageInput > 0 && pageInput <= this.totalPages) { + this.page = pageInput; + this.displayPage = this.page; + this.pdfViewer.currentPageNumber = this.page; + } else { + this.displayPage = this.page; + } + } + + /** + * Litener Scroll Event + * + * @param {any} target + */ + watchScroll(target) { + let outputPage = this.getVisibleElement(target); + + if (outputPage) { + this.page = outputPage.id; + this.displayPage = this.page; + } + } + + /** + * find out what elements are visible within a scroll pane + * + * @param {any} target + * + * @returns {Object} page + */ + getVisibleElement(target) { + return this.pdfViewer._pages.find((page) => { + return this.isOnScreen(page, target); + }); + } + + /** + * check if a page is visible + * + * @param {any} page + * @param {any} target + * + * @returns {boolean} + */ + isOnScreen(page: any, target: any) { + let viewport: any = {}; + viewport.top = target.scrollTop; + viewport.bottom = viewport.top + target.scrollHeight; + let bounds: any = {}; + bounds.top = page.div.offsetTop; + bounds.bottom = bounds.top + page.viewport.height; + return ((bounds.top <= viewport.bottom) && (bounds.bottom >= viewport.top)); + } + + /** + * Litener Keyboard Event + * @param {KeyboardEvent} event + */ + @HostListener('document:keydown', ['$event']) + handleKeyboardEvent(event: KeyboardEvent) { + let key = event.keyCode; + if (key === 39) { // right arrow + this.nextPage(); + } else if (key === 37) {// left arrow + this.previousPage(); + } + } + +} diff --git a/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog.component.html b/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/viewer-dialog.component.html similarity index 86% rename from ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog.component.html rename to ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/viewer-dialog.component.html index 0bc07ff470..ed43a620e1 100644 --- a/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog.component.html +++ b/ng2-components/ng2-alfresco-viewer/src/components/viewer-dialog/viewer-dialog.component.html @@ -3,7 +3,10 @@ - {{ fileName }} + + + {{ fileName }} +