diff --git a/example/index.html b/example/index.html index a98ac58..70cf85a 100644 --- a/example/index.html +++ b/example/index.html @@ -10,7 +10,13 @@

{{pdfName}}

- + + +
Fork me on GitHub diff --git a/example/js/controllers/docCtrl.js b/example/js/controllers/docCtrl.js index 4e2df4c..a6fba77 100644 --- a/example/js/controllers/docCtrl.js +++ b/example/js/controllers/docCtrl.js @@ -1,34 +1,50 @@ -app.controller('DocCtrl', function($scope) { +app.controller('DocCtrl', function($scope, NgPdfFactory) { $scope.pdfName = 'Relativity: The Special and General Theory by Albert Einstein'; - $scope.pdfUrl = 'pdf/relativity.pdf'; - $scope.pdfPassword = 'test'; $scope.scroll = 0; $scope.loading = 'loading'; + $scope.changePdfPage = 1; + + $scope.pdfConfig = new NgPdfFactory('pdf/relativity.pdf', { fitToPage: true }); + $scope.protectedPdfConfig = new NgPdfFactory('pdf/relativity.protected.pdf', { fitToPage: true, useCredentials: true, password: 'test' }); + + $scope.$watch('pdfUrl', (newVal, oldVal) => { + if (newVal !== '' && newVal !== oldVal) { + $scope.pdfConfig = new NgPdfFactory(newVal, { fitToPage: true }); + } + }); + + $scope.$watch('changePdfPage', (newVal, oldVal) => { + if (newVal !== '' && newVal !== oldVal) { + $scope.pdfConfig.goToPage(newVal) + } + }); + + $scope.$watch(() => { return $scope.pdfConfig.currentPage }, (newVal, oldVal) => { + if (newVal !== '' && newVal !== oldVal) { + $scope.changePdfPage = newVal; + } + }); $scope.getNavStyle = function(scroll) { if(scroll > 100) return 'pdf-controls fixed'; else return 'pdf-controls'; } - $scope.onError = function(error) { - console.log(error); - } + $scope.onPdfLoadingSuccess = function() { + console.log('pdf loaded') + }; - $scope.onLoad = function() { - $scope.loading = ''; - } + $scope.onPdfLoadingProgress = function (progressData) { + console.log('pdf loading on progress', progressData); + }; - $scope.onProgress = function (progressData) { - console.log(progressData); + $scope.onPdfLoadingError = function(error) { + console.log('pdf loading error', error); }; - $scope.onPassword = function (updatePasswordFn, passwordResponse) { - if (passwordResponse === PDFJS.PasswordResponses.NEED_PASSWORD) { - updatePasswordFn($scope.pdfPassword); - } else if (passwordResponse === PDFJS.PasswordResponses.INCORRECT_PASSWORD) { - console.log('Incorrect password') - } + $scope.onIncorrectPdfPassword = function () { + console.error('password is wrong!'); }; }); diff --git a/example/partials/viewer.html b/example/partials/viewer.html index d28859a..e0617aa 100644 --- a/example/partials/viewer.html +++ b/example/partials/viewer.html @@ -1,20 +1,20 @@
diff --git a/src/angular-pdf.directive.js b/src/angular-pdf.directive.js index 077266c..1f8683f 100644 --- a/src/angular-pdf.directive.js +++ b/src/angular-pdf.directive.js @@ -22,31 +22,44 @@ export const NgPdf = ($window, $document, $log) => { canvas.getContext('2d').setTransform(ratio, 0, 0, ratio, 0, 0); return canvas; }; - + const initCanvas = (element, canvas) => { angular.element(canvas).addClass('rotate0'); element.append(canvas); }; + const onPassword = function (password, incorrectPasswordCallback) { + return function (updatePasswordFn, passwordResponse) { + switch (passwordResponse) { + case PDFJS.PasswordResponses.NEED_PASSWORD: + updatePasswordFn(password); + break; + case PDFJS.PasswordResponses.INCORRECT_PASSWORD: + incorrectPasswordCallback(); + break; + } + }; + }; + return { restrict: 'E', - templateUrl(element, attr) { - return attr.templateUrl ? attr.templateUrl : 'partials/viewer.html'; + scope: { + pdf: '=', + onError: '&', + onProgress: '&', + onSuccess: '&', + onIncorrectPassword: '&' }, link(scope, element, attrs) { let renderTask = null; let pdfLoaderTask = null; let debug = false; - let url = scope.pdfUrl; - let httpHeaders = scope.httpHeaders; - let pdfDoc = null; - let pageToDisplay = isFinite(attrs.page) ? parseInt(attrs.page) : 1; - let pageFit = attrs.scale === 'page-fit'; + let httpHeaders = scope.pdf.httpHeaders; let limitHeight = attrs.limitcanvasheight === '1'; - let scale = attrs.scale > 0 ? attrs.scale : 1; + let pdfDoc = null; + let pageToDisplay = scope.pdf.currentPage; let canvas = $document[0].createElement('canvas'); initCanvas(element, canvas); - let creds = attrs.usecredentials; debug = attrs.hasOwnProperty('debug') ? attrs.debug : false; let ctx = canvas.getContext('2d'); @@ -61,9 +74,19 @@ export const NgPdf = ($window, $document, $log) => { }); PDFJS.disableWorker = true; - scope.pageNum = pageToDisplay; - scope.renderPage = num => { + renderPDF() + scope.$watch(() => scope.pdf, (newVal, oldVal) => { + if (newVal !== oldVal) { + renderPDF(); + } + }); + + const renderPage = num => { + if (pdfDoc === null) { + console.warn("pdfDoc is null") + return; + } if (renderTask) { renderTask._internalRenderTask.cancel(); } @@ -73,16 +96,16 @@ export const NgPdf = ($window, $document, $log) => { let pageWidthScale; let renderContext; - if (pageFit) { + if (scope.pdf.fitToPage) { viewport = page.getViewport(1); const clientRect = element[0].getBoundingClientRect(); pageWidthScale = clientRect.width / viewport.width; if (limitHeight) { pageWidthScale = Math.min(pageWidthScale, clientRect.height / viewport.height); } - scale = pageWidthScale; + scope.pdf.scale = pageWidthScale; } - viewport = page.getViewport(scale); + viewport = page.getViewport(scope.pdf.scale); setCanvasDimensions(canvas, viewport.width, viewport.height); @@ -102,57 +125,6 @@ export const NgPdf = ($window, $document, $log) => { }); }; - scope.goPrevious = () => { - if (scope.pageToDisplay <= 1) { - return; - } - scope.pageToDisplay = parseInt(scope.pageToDisplay) - 1; - scope.pageNum = scope.pageToDisplay; - }; - - scope.goNext = () => { - if (scope.pageToDisplay >= pdfDoc.numPages) { - return; - } - scope.pageToDisplay = parseInt(scope.pageToDisplay) + 1; - scope.pageNum = scope.pageToDisplay; - }; - - scope.zoomIn = () => { - pageFit = false; - scale = parseFloat(scale) + 0.2; - scope.renderPage(scope.pageToDisplay); - return scale; - }; - - scope.zoomOut = () => { - pageFit = false; - scale = parseFloat(scale) - 0.2; - scope.renderPage(scope.pageToDisplay); - return scale; - }; - - scope.fit = () => { - pageFit = true; - scope.renderPage(scope.pageToDisplay); - } - - scope.changePage = () => { - scope.renderPage(scope.pageToDisplay); - }; - - scope.rotate = () => { - if (canvas.getAttribute('class') === 'rotate0') { - canvas.setAttribute('class', 'rotate90'); - } else if (canvas.getAttribute('class') === 'rotate90') { - canvas.setAttribute('class', 'rotate180'); - } else if (canvas.getAttribute('class') === 'rotate180') { - canvas.setAttribute('class', 'rotate270'); - } else { - canvas.setAttribute('class', 'rotate0'); - } - }; - function clearCanvas() { if (ctx) { ctx.clearRect(0, 0, canvas.width, canvas.height); @@ -163,64 +135,64 @@ export const NgPdf = ($window, $document, $log) => { clearCanvas(); let params = { - 'url': url, - 'withCredentials': creds + 'url': scope.pdf.url, + 'withCredentials': scope.pdf.useCredentials }; - if (httpHeaders) { - params.httpHeaders = httpHeaders; - } + // if (httpHeaders) { + // params.httpHeaders = httpHeaders; + // } - if (url && url.length) { + if (scope.pdf.url && scope.pdf.url.length) { pdfLoaderTask = PDFJS.getDocument(params); pdfLoaderTask.onProgress = scope.onProgress; - pdfLoaderTask.onPassword = scope.onPassword; + pdfLoaderTask.onPassword = onPassword(scope.pdf.password, scope.onIncorrectPassword); pdfLoaderTask.then( _pdfDoc => { - if (angular.isFunction(scope.onLoad)) { - scope.onLoad(); - } + run_success_hook() pdfDoc = _pdfDoc; - scope.renderPage(scope.pageToDisplay); + renderPage(scope.pdf.currentPage); scope.$apply(() => { - scope.pageCount = _pdfDoc.numPages; + scope.pdf.pageCount = _pdfDoc.numPages; }); }, error => { - if (error) { - if (angular.isFunction(scope.onError)) { - scope.onError(error); - } - } + run_error_hook(error) } ); } } - scope.$watch('pageNum', newVal => { - scope.pageToDisplay = parseInt(newVal); - if (pdfDoc !== null) { - scope.renderPage(scope.pageToDisplay); - } + scope.$watch(() => { return scope.pdf.currentPage }, () => { + renderPage(scope.pdf.currentPage); }); - scope.$watch('pdfUrl', newVal => { - if (newVal !== '') { - if (debug) { - $log.log('pdfUrl value change detected: ', scope.pdfUrl); - } - url = newVal; - scope.pageNum = scope.pageToDisplay = pageToDisplay; - if (pdfLoaderTask) { - pdfLoaderTask.destroy().then(() => { - renderPDF(); - }); - } else { - renderPDF(); - } + scope.$watch(() => { return scope.pdf.scale }, () => { + renderPage(scope.pdf.currentPage); + }); + + scope.$watch(() => { return scope.pdf.fitToPage }, (newVal) => { + if (newVal === true) { + renderPage(scope.pdf.currentPage); } }); + + scope.$watch(() => { return scope.pdf.rotation }, (newVal) => { + canvas.setAttribute('class', 'rotate'+parseInt(newVal)); + }) + + const run_success_hook = () => { + if (angular.isFunction(scope.onSuccess)) { + scope.onSuccess(); + } + }; + + const run_error_hook = (error) => { + if (angular.isFunction(scope.onError)) { + scope.onError(error); + } + }; } } } diff --git a/src/angular-pdf.factory.js b/src/angular-pdf.factory.js new file mode 100644 index 0000000..7ebcfef --- /dev/null +++ b/src/angular-pdf.factory.js @@ -0,0 +1,80 @@ +export const NgPdfFactory = function () { + 'ngInject'; + + const defaultOptions = { + currentPage: 1, + fitToPage: false, + httpHeaders: null, + scale: 1, + useCredentials: false, + password: null, + rotation: 0, + pageCount: null, + }; + + return function (url, opts) { + let self = this + + let options = Object.assign({}, defaultOptions, opts) + + Object.defineProperty(this, 'url', { + enumerable: true, + writable: false, + value: url + }); + + // defined all properties in defaultOptions and opts as property of this object + Object.keys(options).forEach((e) => { + Object.defineProperty(self, e, { + enumerable: true, + set: (value) => { options[e] = value }, + get: () => { return options[e] } + }); + }) + + this.goPrevious = () => { + if (options.currentPage <= 1) { + return false; + } + options.currentPage -= 1; + }; + + this.goNext = () => { + if (options.currentPage >= options.pageCount) { + return false; + } + options.currentPage += 1; + }; + + this.zoomIn = () => { + options.fitToPage = false; + options.scale = parseFloat(options.scale) + 0.2 + }; + + this.zoomOut = () => { + options.fitToPage = false; + options.scale = parseFloat(options.scale) - 0.2 + }; + + this.fit = () => { + options.fitToPage = true; + } + + this.rotateLeft = () => { + options.rotation = ((options.rotation === 0 ? 360 : options.rotation) - 90); + }; + + this.rotateRight = () => { + options.rotation = (options.rotation + 90) % 360; + }; + + this.goToPage = (pageNum) => { + pageNum = parseInt(pageNum); + if (pageNum !== NaN && pageNum > 0 && pageNum < options.pageCount) { + options.currentPage = pageNum; + } else { + return false; + } + }; + }; +} diff --git a/src/angular-pdf.module.js b/src/angular-pdf.module.js index 3932137..3a8d1ad 100644 --- a/src/angular-pdf.module.js +++ b/src/angular-pdf.module.js @@ -1,9 +1,11 @@ import angular from 'angular'; import { NgPdf } from './angular-pdf.directive' +import { NgPdfFactory } from './angular-pdf.factory' export const Pdf = angular .module('pdf', []) .directive('ngPdf', NgPdf) + .factory('NgPdfFactory', NgPdfFactory) .name; export default Pdf;