diff --git a/example/index.html b/example/index.html
index 034e2837..25735dfb 100644
--- a/example/index.html
+++ b/example/index.html
@@ -2,10 +2,10 @@
-
+
-
+
ng-pdfviewer.js test
diff --git a/ng-pdfviewer.js b/ng-pdfviewer.js
index 098b2ee3..fd8c3c8e 100644
--- a/ng-pdfviewer.js
+++ b/ng-pdfviewer.js
@@ -1,154 +1,297 @@
/**
* @preserve AngularJS PDF viewer directive using pdf.js.
*
- * https://github.com/akrennmair/ng-pdfviewer
+ * https://github.com/akrennmair/ng-pdfviewer
*
* MIT license
*/
angular.module('ngPDFViewer', []).
-directive('pdfviewer', [ '$parse', function($parse) {
- var canvas = null;
- var instance_id = null;
-
- return {
- restrict: "E",
- template: '',
- scope: {
- onPageLoad: '&',
- loadProgress: '&',
- src: '@',
- id: '='
- },
- controller: [ '$scope', function($scope) {
- $scope.pageNum = 1;
- $scope.pdfDoc = null;
- $scope.scale = 1.0;
-
- $scope.documentProgress = function(progressData) {
- if ($scope.loadProgress) {
- $scope.loadProgress({state: "loading", loaded: progressData.loaded, total: progressData.total});
- }
- };
-
- $scope.loadPDF = function(path) {
- console.log('loadPDF ', path);
- PDFJS.getDocument(path, null, null, $scope.documentProgress).then(function(_pdfDoc) {
- $scope.pdfDoc = _pdfDoc;
- $scope.renderPage($scope.pageNum, function(success) {
- if ($scope.loadProgress) {
- $scope.loadProgress({state: "finished", loaded: 0, total: 0});
- }
- });
- }, function(message, exception) {
- console.log("PDF load error: " + message);
- if ($scope.loadProgress) {
- $scope.loadProgress({state: "error", loaded: 0, total: 0});
- }
- });
- };
-
- $scope.renderPage = function(num, callback) {
- console.log('renderPage ', num);
- $scope.pdfDoc.getPage(num).then(function(page) {
- var viewport = page.getViewport($scope.scale);
- var ctx = canvas.getContext('2d');
-
- canvas.height = viewport.height;
- canvas.width = viewport.width;
-
- page.render({ canvasContext: ctx, viewport: viewport }).promise.then(
- function() {
- if (callback) {
- callback(true);
- }
- $scope.$apply(function() {
- $scope.onPageLoad({ page: $scope.pageNum, total: $scope.pdfDoc.numPages });
- });
- },
- function() {
- if (callback) {
- callback(false);
- }
- console.log('page.render failed');
- }
- );
- });
- };
-
- $scope.$on('pdfviewer.nextPage', function(evt, id) {
- if (id !== instance_id) {
- return;
- }
-
- if ($scope.pageNum < $scope.pdfDoc.numPages) {
- $scope.pageNum++;
- $scope.renderPage($scope.pageNum);
- }
- });
-
- $scope.$on('pdfviewer.prevPage', function(evt, id) {
- if (id !== instance_id) {
- return;
- }
-
- if ($scope.pageNum > 1) {
- $scope.pageNum--;
- $scope.renderPage($scope.pageNum);
- }
- });
-
- $scope.$on('pdfviewer.gotoPage', function(evt, id, page) {
- if (id !== instance_id) {
- return;
- }
-
- if (page >= 1 && page <= $scope.pdfDoc.numPages) {
- $scope.pageNum = page;
- $scope.renderPage($scope.pageNum);
- }
- });
- } ],
- link: function(scope, iElement, iAttr) {
- canvas = iElement.find('canvas')[0];
- instance_id = iAttr.id;
-
- iAttr.$observe('src', function(v) {
- console.log('src attribute changed, new value is', v);
- if (v !== undefined && v !== null && v !== '') {
- scope.pageNum = 1;
- scope.loadPDF(scope.src);
- }
- });
- }
- };
+directive('pdfviewer', [ '$parse', '$timeout', function($parse, $timeout) {
+ var canvas = null;
+ var instance_id = null;
+ var width = null;
+ var height = null;
+ var renderPromise = null;
+ var pageFit = false;
+
+ return {
+ restrict: "E",
+ template: '',
+ scope: {
+ onPageLoad: '&',
+ loadProgress: '&',
+ src: '@',
+ id: '='
+ },
+ controller: [ '$scope', function($scope) {
+ $scope.pageNum = 1;
+ $scope.pdfDoc = null;
+ $scope.scale = 1.0;
+
+ $scope.documentProgress = function(progressData) {
+ if ($scope.loadProgress) {
+ $scope.loadProgress({state: "loading", loaded: progressData.loaded, total: progressData.total});
+ }
+ };
+
+ $scope.convertDataURIToBinary = function (dataURI) {
+ var BASE64_MARKER = ';base64,';
+ var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
+ var base64 = dataURI.substring(base64Index);
+ var raw = window.atob(base64);
+ var rawLength = raw.length;
+ var array = new Uint8Array(new ArrayBuffer(rawLength));
+
+ for(var i = 0; i < rawLength; i++) {
+ array[i] = raw.charCodeAt(i);
+ }
+ return array;
+ };
+
+ $scope.loadPDF = function(path) {
+ if(path !== undefined)
+ {
+ var param = path.substr(0,4) !== 'data' ? path : $scope.convertDataURIToBinary(path);
+ console.log('loadPDF ', path, param);
+ PDFJS.getDocument(param, null, null, $scope.documentProgress).then(function(_pdfDoc) {
+ $scope.pdfDoc = _pdfDoc;
+ $scope.renderPage($scope.pageNum, function(success) {
+ if ($scope.loadProgress) {
+ $scope.loadProgress({state: "finished", loaded: 0, total: 0});
+ }
+ });
+ }, function(message, exception) {
+ console.log("PDF load error: " + message);
+ if ($scope.loadProgress) {
+ $scope.loadProgress({state: "error", loaded: 0, total: 0});
+ }
+ });
+ }
+
+ };
+
+ var ratio = 1;
+ var lastImageData;
+
+ $scope.setCanvasSize = function()
+ {
+ var ctx = canvas.getContext('2d');
+ var imageData;
+
+ if(lastImageData) imageData = lastImageData;
+ else
+ {
+ imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
+ lastImageData = imageData;
+ }
+
+ var newCanvas = document.createElement('canvas');
+ $(newCanvas)
+ .attr("width", imageData.width)
+ .attr("height", imageData.height);
+
+ newCanvas.getContext("2d").putImageData(imageData, 0, 0);
+
+ var scale;
+
+ if (pageFit && height && width)
+ {
+ // First, set according to width
+ scale = width / canvas.width;
+
+ // Then, make sure height is not too much
+ if(scale * canvas.height > height)
+ {
+ scale = height / canvas.height;
+ }
+
+ canvas.width = canvas.width * scale;
+ canvas.height = canvas.height * scale;
+ }
+ else
+ {
+ if(height === null)
+ {
+ scale = width / canvas.width;
+ canvas.width = width;
+ canvas.height = width * ratio;
+ }
+ else
+ {
+ scale = height / canvas.height;
+ canvas.height = height;
+ canvas.width = height * ratio;
+ }
+ }
+
+
+ ctx.scale(scale, scale);
+ ctx.drawImage(newCanvas, 0, 0);
+ };
+
+
+ $scope.renderPage = function(num, callback) {
+ console.log('renderPage ', num);
+ lastImageData = null;
+ $scope.pdfDoc.getPage(num).then(function(page) {
+
+ var scaling = width / page.getViewport(1.0).width;
+ var viewport = page.getViewport(scaling);
+
+ if(pageFit && viewport.height > height)
+ {
+ scaling *= height / viewport.height;
+ viewport = page.getViewport(scaling);
+ }
+
+ ratio = viewport.height / viewport.width;
+ var ctx = canvas.getContext('2d');
+
+ canvas.height = viewport.height;
+ canvas.width = viewport.width;
+
+
+ if(renderPromise != null)
+ {
+ renderPromise.cancel()
+ }
+
+ renderPromise = page.render({ canvasContext: ctx, viewport: viewport });
+ renderPromise.promise.then(
+ function() {
+ if (callback) {
+ callback(true);
+ }
+ $scope.$apply(function() {
+ $scope.onPageLoad({ page: $scope.pageNum, total: $scope.pdfDoc.numPages });
+ });
+ },
+ function() {
+ if (callback) {
+ callback(false);
+ }
+ console.log('page.render failed');
+ }
+ );
+ });
+ };
+
+ $scope.$on('pdfviewer.nextPage', function(evt, id) {
+ if (id !== instance_id) {
+ return;
+ }
+
+ if ($scope.pageNum < $scope.pdfDoc.numPages) {
+ $scope.pageNum++;
+ $scope.renderPage($scope.pageNum);
+ }
+ });
+
+ $scope.$on('pdfviewer.prevPage', function(evt, id) {
+ if (id !== instance_id) {
+ return;
+ }
+
+ if ($scope.pageNum > 1) {
+ $scope.pageNum--;
+ $scope.renderPage($scope.pageNum);
+ }
+ });
+
+ $scope.$on('pdfviewer.gotoPage', function(evt, id, page) {
+ if (id !== instance_id) {
+ return;
+ }
+
+ if (page >= 1 && page <= $scope.pdfDoc.numPages) {
+ $scope.pageNum = page;
+ $scope.renderPage($scope.pageNum);
+ }
+ });
+ } ],
+ link: function(scope, iElement, iAttr) {
+ canvas = iElement.find('canvas')[0];
+ instance_id = iAttr.id;
+ pageFit = iAttr.scale === 'page-fit';
+
+ if(typeof iAttr.width !== 'undefined')
+ {
+ width = parseInt(iAttr.width);
+ } else if(typeof iAttr.height !== 'undefined')
+ {
+ height = parseInt(iAttr.height);
+ }
+
+ var loadPdfTimeout = null;
+
+ iAttr.$observe('width', function(v) {
+ console.log('width attribute changed, new value is', v);
+ if(typeof iAttr.width !== 'undefined')
+ {
+ var newWidth = parseInt(iAttr.width);
+ if(Math.abs(newWidth - width) < 1) // Only re-render if the difference is at least a pixel.
+ return;
+
+ width = newWidth;
+
+ scope.setCanvasSize();
+
+ var loadPdf = function() { scope.loadPDF(scope.src); };
+ $timeout.cancel(loadPdfTimeout);
+ loadPdfTimeout = $timeout(loadPdf, 50);
+ }
+ });
+ iAttr.$observe('height', function(v) {
+ console.log('height attribute changed, new value is', v);
+ if(typeof iAttr.height !== 'undefined')
+ {
+ height = parseInt(iAttr.height);
+
+ scope.setCanvasSize();
+
+ var loadPdf = function() { scope.loadPDF(scope.src); };
+ $timeout.cancel(loadPdfTimeout);
+ loadPdfTimeout = $timeout(loadPdf, 50);
+ }
+ });
+
+ iAttr.$observe('src', function(v) {
+ console.log('src attribute changed, new value is', v);
+ if (v !== undefined && v !== null && v !== '') {
+ scope.pageNum = 1;
+ scope.loadPDF(scope.src);
+ }
+ });
+ }
+ };
}]).
service("PDFViewerService", [ '$rootScope', function($rootScope) {
- var svc = { };
- svc.nextPage = function() {
- $rootScope.$broadcast('pdfviewer.nextPage');
- };
-
- svc.prevPage = function() {
- $rootScope.$broadcast('pdfviewer.prevPage');
- };
-
- svc.Instance = function(id) {
- var instance_id = id;
-
- return {
- prevPage: function() {
- $rootScope.$broadcast('pdfviewer.prevPage', instance_id);
- },
- nextPage: function() {
- $rootScope.$broadcast('pdfviewer.nextPage', instance_id);
- },
- gotoPage: function(page) {
- $rootScope.$broadcast('pdfviewer.gotoPage', instance_id, page);
- }
- };
- };
-
- return svc;
+ var svc = { };
+ svc.nextPage = function() {
+ $rootScope.$broadcast('pdfviewer.nextPage');
+ };
+
+ svc.prevPage = function() {
+ $rootScope.$broadcast('pdfviewer.prevPage');
+ };
+
+ svc.Instance = function(id) {
+ var instance_id = id;
+
+ return {
+ prevPage: function() {
+ $rootScope.$broadcast('pdfviewer.prevPage', instance_id);
+ },
+ nextPage: function() {
+ $rootScope.$broadcast('pdfviewer.nextPage', instance_id);
+ },
+ gotoPage: function(page) {
+ $rootScope.$broadcast('pdfviewer.gotoPage', instance_id, page);
+ }
+ };
+ };
+
+ return svc;
}]);