Skip to content

Commit

Permalink
Merge pull request #36 from legalthings/source-as-binary
Browse files Browse the repository at this point in the history
Added attribute to set raw data as the source of the pdf
  • Loading branch information
jasny committed Apr 6, 2017
2 parents cedb0e7 + a0fc098 commit ee7de57
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 78 deletions.
162 changes: 104 additions & 58 deletions 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
<!DOCTYPE html>
<html lang="en" data-ng-app="app" ng-controller="AppCtrl">
<html ng-app="app" ng-controller="AppCtrl">
<head>
<meta charset="utf-8"/>
<title>Angular PDF.js demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">

<script src="bower_components/pdf.js-viewer/pdf.js"></script>
<link rel="stylesheet" href="bower_components/pdf.js-viewer/viewer.css">

Expand All @@ -30,72 +30,120 @@ that images, translations and such are being loaded from the `web` folder.
<script src="app.js"></script>

<style>
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.some-pdf-container {
width: 100%;
height: 100%;
}
html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
.some-pdf-container { width: 100%; height: 100%; }
</style>
</head>
<body>
<div class='some-pdf-container'>
<pdfjs-viewer src="{{ pdf.src }}" scale="scale"
download="true" print="false" open="false"
on-init="onInit()" on-page-load="onPageLoad(page)">
</pdfjs-viewer>
<div class="some-pdf-container">
<pdfjs-viewer src="{{ pdf.src }}"></pdfjs-viewer>
</div>
</body>
</html>
```

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']);

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 `<pdfjs-viewer>` 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
<pdfjs-viewer src="{{ $ctrl.src }}"></pdfjs-viewer>
```

```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
<pdfjs-viewer data="$ctrl.data"></pdfjs-viewer>
```

```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
<pdfjs-viewer scale="$ctrl.scale"></pdfjs-viewer>
```
---

#### `download, print, open`
These buttons are by default all visible in the toolbar and can be hidden.

```html
<pdfjs-viewer download="false" print="false" ... ></pdfjs-viewer>
```
---

#### `on-init`
The `on-init` function is called when PDF.JS is fully loaded.

```html
<pdfjs-viewer on-init="$ctrl.onInit()"></pdfjs-viewer>
```

```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
<pdfjs-viewer on-init="$ctrl.onPageLoad()"></pdfjs-viewer>
```

```javascript
$scope.onPageLoad = function (page) {
// page is loaded
};
```
---

## Styling
The `<pdfjs-viewer>` 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
Expand All @@ -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.

Expand All @@ -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

2 changes: 1 addition & 1 deletion bower.json
Expand Up @@ -15,7 +15,7 @@
},
"dependencies": {
"angular": "^1.5.8",
"pdf.js-viewer": "~1.6.210"
"pdf.js-viewer": "~1.6.211"
},
"ignore": [
"**/.*",
Expand Down
22 changes: 20 additions & 2 deletions 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'
}
});
}
});
2 changes: 1 addition & 1 deletion demo/bower.json
Expand Up @@ -5,6 +5,6 @@
"private": "true",
"dependencies": {
"angular": "^1.5.8",
"pdf.js-viewer": "~1.6.210"
"pdf.js-viewer": "~1.6.211"
}
}
7 changes: 7 additions & 0 deletions demo/index.html
Expand Up @@ -28,7 +28,14 @@
</head>
<body>
<div class='some-pdf-container'>
<!-- Example of loading pdf from URL string. Note that this must be an interpolation string -->
<pdfjs-viewer src="{{ pdf.src }}"></pdfjs-viewer>

<!--
Example of loading pdf from raw binary data. Note that this must be a scope variable.
Comment upper viewer out if you use this viewer (because multi pdf viewers are currently not supported)
-->
<!-- <pdfjs-viewer data="pdf.data"></pdfjs-viewer> -->
</div>
</body>
</html>
41 changes: 32 additions & 9 deletions dist/angular-pdfjs-viewer.js
Expand Up @@ -379,6 +379,8 @@
onInit: '&',
onPageLoad: '&',
scale: '=?',
src: '@?',
data: '=?'
},
link: function ($scope, $element, $attrs) {
$element.children().wrap('<div class="pdfjs" style="width: 100%; height: 100%;"></div>');
Expand All @@ -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;

Expand All @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -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');
Expand All @@ -469,12 +496,8 @@
if ($attrs.height) {
document.getElementById('outerContainer').style.height = $attrs.height;
}

PDFJS.webViewerLoad($attrs.src);
});
}
};
}]);

//
}();

0 comments on commit ee7de57

Please sign in to comment.