diff --git a/README.md b/README.md index 11222f5..3fe7586 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,27 @@ # PDF.js viewer Angular directive -Embed [PDF.js](https://mozilla.github.io/pdf.js/) viewer into your angular application, maintaining that look and feel +Embed Mozilla's [PDF.js](https://mozilla.github.io/pdf.js/) viewer into your angular application, maintaining that look and feel of pdf's we all love. The directive embeds the [full viewer](https://mozilla.github.io/pdf.js/web/viewer.html), which allows you to scroll through the pdf. -## Installation +![viewer-example](https://cloud.githubusercontent.com/assets/5793511/24605022/6dd5abee-1867-11e7-881a-0d68dc7c77f3.png) + + +## Installation bower install angular-pdfjs-viewer --save ## Usage +Below you will find a basic example of how the directive can be used. +Note that the order of the scripts matters. Stick to the order of dependencies as shown in the example below. +Also note that images, translations and such are being loaded from the `web` folder. -Note that the order of the scripts matters. Stick to the order of dependencies as shown in the example below. Also note -that images, translations and such are being loaded from the `web` folder. - -**View** +### View ```html - + - Angular PDF.js demo - - @@ -30,43 +30,19 @@ that images, translations and such are being loaded from the `web` folder. -
- - +
+
``` -The `scale` attribute can be used to obtain the current scale (zoom level) of the PDF. This is read only. - -The directive takes the following optional attributes to modify the toolbar - - download="false" print="false" open="false" - -Omitting these attributes will by default show the options in the toolbar. - -The `on-init` function is called when PDF.JS is fully loaded. The `on-page-load` function is each time a page is -loaded and will pass the page number. When the scale changes all pages are unloaded, so `on-page-load` will be called -again for each page. - -**Controller** +### Controller ```js angular.module('app', ['pdfjsViewer']); @@ -74,28 +50,100 @@ angular.module('app').controller('AppCtrl', function($scope) { $scope.pdf = { src: 'example.pdf', }; - - $scope.$watch('scale', function() { - ... - }); - - $scope.onInit = function() { - ... - }; - - $scope.onPageLoad = function(page) { - ... - }; }); ``` -_If `onPageLoad()` returns `false`, the page will not be marked as loaded and `onPageLoad` will be called again for -that page on the next (200ms) interval._ +## Directive options +The `` directive takes the following attributes. -## Demo -You can test out a demo of this directive. You must run the node server first due to CORS. First make sure - the dependencies are installed. +#### `src` +The source should point to the URL of a publicly available pdf. +Note that the `src` must be passed in as an interpolation string. + +```html + +``` + +```javascript +$scope.src = "http://example.com/file.pdf"; +``` +--- + +#### `data` +In the case that you cannot simply use the URL of the pdf, you can pass in raw data as +a [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) object. +The `data` attribute takes a scope variable as its argument. + +```html + +``` + +```javascript +$scope.data = null; // this is loaded async + +$http.get("http://example.com/file.pdf", { + responseType: 'arraybuffer' +}).then(function (response) { + $scope.data = new Uint8Array(response.data); +}); +``` +--- + +#### `scale` +The `scale` attribute can be used to obtain the current scale (zoom level) of the PDF. +The value will be stored in the variable specified. **This is read only**. + +```html + +``` +--- + +#### `download, print, open` +These buttons are by default all visible in the toolbar and can be hidden. + +```html + +``` +--- + +#### `on-init` +The `on-init` function is called when PDF.JS is fully loaded. + +```html + +``` + +```javascript +$scope.onInit = function () { + // pdf.js is initialized +} +``` +--- + +#### `on-page-load` +The `on-page-load` function is each time a page is loaded and will pass the page number. +When the scale changes all pages are unloaded, so `on-page-load` will be called again for each page. +_If `onPageLoad()` returns `false`, the page will not be marked as loaded and `onPageLoad` will be called again for that page on the next (200ms) interval._ + +```html + +``` + +```javascript +$scope.onPageLoad = function (page) { + // page is loaded +}; +``` +--- + +## Styling +The `` directive automatically expands to the height and width of its first immediate parent, in the case of the example `.some-pdf-container`. +If no parent container is given the html `body` will be used. Height and width are required to properly display the contents of the pdf. + +## Demo +You can test out a [demo](https://github.com/legalthings/angular-pdfjs-viewer/tree/master/demo) of this directive. +You must run the node server first due to CORS. First make sure the dependencies are installed. cd demo npm install @@ -108,7 +156,6 @@ Afterwards run the server like so. The server will be running on localhost:8080 ## Advanced configuration - By default the location of PDF.js assets are automatically determined. However if you place them on alternative locations they may not be found. If so, you can configure these locations. @@ -129,4 +176,3 @@ Note that a number of images used in the PDF.js viewer are loaded by the `viewer through JavaScript. Instead you need to compile the `viewer.less` file as lessc --global-var='pdfjsImagePath=/assets/pdf.js-viewer/images' viewer.less viewer.css - diff --git a/bower.json b/bower.json index 051c975..634c192 100644 --- a/bower.json +++ b/bower.json @@ -15,7 +15,7 @@ }, "dependencies": { "angular": "^1.5.8", - "pdf.js-viewer": "~1.6.210" + "pdf.js-viewer": "~1.6.211" }, "ignore": [ "**/.*", diff --git a/demo/app.js b/demo/app.js index 761cc20..3638aeb 100644 --- a/demo/app.js +++ b/demo/app.js @@ -1,7 +1,25 @@ angular.module('app', ['pdfjsViewer']); -angular.module('app').controller('AppCtrl', function($scope) { +angular.module('app').controller('AppCtrl', function ($scope, $http, $timeout) { + var url = 'example.pdf'; + $scope.pdf = { - src: 'example.pdf' + src: url, // get pdf source from a URL that points to a pdf + data: null // get pdf source from raw data of a pdf }; + + getPdfAsArrayBuffer(url).then(function (response) { + $scope.pdf.data = new Uint8Array(response.data); + }, function (err) { + console.log('failed to get pdf as binary:', err); + }); + + function getPdfAsArrayBuffer (url) { + return $http.get(url, { + responseType: 'arraybuffer', + headers: { + 'foo': 'bar' + } + }); + } }); diff --git a/demo/bower.json b/demo/bower.json index 2d95c56..ffafe14 100644 --- a/demo/bower.json +++ b/demo/bower.json @@ -5,6 +5,6 @@ "private": "true", "dependencies": { "angular": "^1.5.8", - "pdf.js-viewer": "~1.6.210" + "pdf.js-viewer": "~1.6.211" } } diff --git a/demo/index.html b/demo/index.html index bab0a92..50b4530 100644 --- a/demo/index.html +++ b/demo/index.html @@ -28,7 +28,14 @@
+ + + +
diff --git a/dist/angular-pdfjs-viewer.js b/dist/angular-pdfjs-viewer.js index 21557bd..390fa55 100644 --- a/dist/angular-pdfjs-viewer.js +++ b/dist/angular-pdfjs-viewer.js @@ -379,6 +379,8 @@ onInit: '&', onPageLoad: '&', scale: '=?', + src: '@?', + data: '=?' }, link: function ($scope, $element, $attrs) { $element.children().wrap('
'); @@ -387,6 +389,13 @@ var loaded = {}; var numLoaded = 0; + if (!window.PDFJS) { + return console.warn("PDFJS is not set! Make sure that pdf.js is loaded before angular-pdfjs-viewer.js is loaded."); + } + + // initialize the pdf viewer with (with empty source) + window.PDFJS.webViewerLoad(); + function onPdfInit() { initialised = true; @@ -403,7 +412,11 @@ } var poller = $interval(function () { - var pdfViewer = PDFViewerApplication.pdfViewer; + if (!window.PDFViewerApplication) { + return; + } + + var pdfViewer = window.PDFViewerApplication.pdfViewer; if (pdfViewer) { if ($scope.scale !== pdfViewer.currentScale) { @@ -414,7 +427,7 @@ } else { console.warn("PDFViewerApplication.pdfViewer is not set"); } - + var pages = document.querySelectorAll('.page'); angular.forEach(pages, function (page) { var element = angular.element(page); @@ -442,11 +455,25 @@ $interval.cancel(poller); }); + // watch pdf source + $scope.$watchGroup([ + function () { return $scope.src; }, + function () { return $scope.data; } + ], function (values) { + var src = values[0]; + var data = values[1]; + + if (!src && !data) { + return; + } + + window.PDFViewerApplication.open(src || data); + }); + + // watch other attributes $scope.$watch(function () { - return $attrs.src; + return $attrs; }, function () { - if (!$attrs.src) return; - if ($attrs.open === 'false') { document.getElementById('openFile').setAttribute('hidden', 'true'); document.getElementById('secondaryOpenFile').setAttribute('hidden', 'true'); @@ -469,12 +496,8 @@ if ($attrs.height) { document.getElementById('outerContainer').style.height = $attrs.height; } - - PDFJS.webViewerLoad($attrs.src); }); } }; }]); - - // }(); diff --git a/src/angular-pdfjs-viewer.js b/src/angular-pdfjs-viewer.js index 030e048..2060533 100644 --- a/src/angular-pdfjs-viewer.js +++ b/src/angular-pdfjs-viewer.js @@ -76,6 +76,8 @@ onInit: '&', onPageLoad: '&', scale: '=?', + src: '@?', + data: '=?' }, link: function ($scope, $element, $attrs) { $element.children().wrap('
'); @@ -84,6 +86,13 @@ var loaded = {}; var numLoaded = 0; + if (!window.PDFJS) { + return console.warn("PDFJS is not set! Make sure that pdf.js is loaded before angular-pdfjs-viewer.js is loaded."); + } + + // initialize the pdf viewer with (with empty source) + window.PDFJS.webViewerLoad(); + function onPdfInit() { initialised = true; @@ -100,7 +109,11 @@ } var poller = $interval(function () { - var pdfViewer = PDFViewerApplication.pdfViewer; + if (!window.PDFViewerApplication) { + return; + } + + var pdfViewer = window.PDFViewerApplication.pdfViewer; if (pdfViewer) { if ($scope.scale !== pdfViewer.currentScale) { @@ -111,7 +124,7 @@ } else { console.warn("PDFViewerApplication.pdfViewer is not set"); } - + var pages = document.querySelectorAll('.page'); angular.forEach(pages, function (page) { var element = angular.element(page); @@ -139,11 +152,25 @@ $interval.cancel(poller); }); + // watch pdf source + $scope.$watchGroup([ + function () { return $scope.src; }, + function () { return $scope.data; } + ], function (values) { + var src = values[0]; + var data = values[1]; + + if (!src && !data) { + return; + } + + window.PDFViewerApplication.open(src || data); + }); + + // watch other attributes $scope.$watch(function () { - return $attrs.src; + return $attrs; }, function () { - if (!$attrs.src) return; - if ($attrs.open === 'false') { document.getElementById('openFile').setAttribute('hidden', 'true'); document.getElementById('secondaryOpenFile').setAttribute('hidden', 'true'); @@ -166,8 +193,6 @@ if ($attrs.height) { document.getElementById('outerContainer').style.height = $attrs.height; } - - PDFJS.webViewerLoad($attrs.src); }); } };