Skip to content

Commit ea9cf28

Browse files
authored
Merge pull request legalthings#6 from legalthings/upgrade-instructions
Upgrade instructions
2 parents f8024d4 + 942b571 commit ea9cf28

File tree

4 files changed

+456
-109
lines changed

4 files changed

+456
-109
lines changed

README.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,233 @@ Include `viewer.html` using [SSI](http://httpd.apache.org/docs/2.4/howto/ssi.htm
4141
</html>
4242
```
4343

44+
## Upgrading the source
45+
46+
Normally mozilla's PDF js viewer, will only run as standalone. This version is patched so you can include it within a
47+
page.
48+
49+
To update this version, get the pdf.js source code and build the project
50+
51+
git clone https://github.com/mozilla/pdf.js.git
52+
cd pdf.js
53+
npm install
54+
node make generic
55+
cd ..
56+
57+
And update the files from source and patch them
58+
59+
cd pdf.js-viewer
60+
npm install
61+
./build.sh ../pdf.js/build/generic/
62+
63+
### Manual patching
64+
65+
When updating to a new minor (or major) version, it's likely than one or more of the chunks can't be applied. This
66+
means you need to do these modifications manually.
67+
68+
69+
#### function getL10nData()
70+
71+
The viewer uses `l10n.js` with a `<link rel="resource" type="application/l10n">` header for internationalization. This
72+
chunk makes using that optional.
73+
74+
function getL10nData(key, args, fallback) {
75+
var data = gL10nData[key];
76+
if (!data) {
77+
- console.warn('#' + key + ' is undefined.');
78+
+ if (Object.keys(gL10nData).length > 0) {
79+
+ console.warn('#' + key + ' is undefined.');
80+
+ }
81+
if (!fallback) {
82+
return null;
83+
}
84+
85+
#### Dynamic paths
86+
87+
The viewer uses relative paths to JavaScript files. This doesn't work when the viewer is embedded on a web page.
88+
Instead the paths are determined based on the path of the current JavaScript file.
89+
90+
-PDFJS.imageResourcesPath = './images/';
91+
- PDFJS.workerSrc = '../build/pdf.worker.js';
92+
- PDFJS.cMapUrl = '../web/cmaps/';
93+
- PDFJS.cMapPacked = true;
94+
+var scriptTagContainer = document.body ||
95+
+ document.getElementsByTagName('head')[0];
96+
+var pdfjsSrc = scriptTagContainer.lastChild.src;
97+
+
98+
+if (pdfjsSrc) {
99+
+ PDFJS.imageResourcesPath = pdfjsSrc.replace(/pdf\.js$/i, 'images/');
100+
+ PDFJS.workerSrc = pdfjsSrc.replace(/pdf\.js$/i, 'pdf.worker.js');
101+
+ PDFJS.cMapUrl = pdfjsSrc.replace(/pdf\.js$/i, 'cmaps/');
102+
+}
103+
+
104+
+PDFJS.cMapPacked = true;
105+
106+
#### Explicitly load a PDF document
107+
108+
The viewer shouldn't start loading a (default) document when it's loaded. Instead we want to expose the initialization,
109+
so it can be called in JavaScript with `PDFJS.webViewerLoad()`.
110+
111+
-document.addEventListener('DOMContentLoaded', webViewerLoad, true);
112+
+// document.addEventListener('DOMContentLoaded', webViewerLoad, true);
113+
+PDFJS.webViewerLoad = function (src) {
114+
+ if (src) DEFAULT_URL = src;
115+
+
116+
+ webViewerLoad();
117+
+}
118+
119+
On several places the code assumes that a PDF is loaded, which (because of the explicit load) might not be the case. We
120+
need to check if `pdfDocument` is set before using it.
121+
122+
##### PDFViewerApplication.pagesCount() and PDFLinkService.pagesCount()
123+
124+
get pagesCount() {
125+
- return this.pdfDocument.numPages;
126+
+ return this.pdfDocument ? this.pdfDocument.numPages : 0;
127+
},
128+
129+
_The pagesCount method for both `PDFViewerApplication` and `PDFLinkService`. Both need to be patched._
130+
131+
##### PDFViewerApplication.cleanup()
132+
133+
cleanup: function pdfViewCleanup() {
134+
this.pdfViewer.cleanup();
135+
this.pdfThumbnailViewer.cleanup();
136+
- this.pdfDocument.cleanup();
137+
+ if (this.pdfDocument) {
138+
+ this.pdfDocument.cleanup();
139+
+ }
140+
},
141+
142+
#### overlayManagerRegister
143+
144+
The overlay is registered when the viewer is loaded. The original code will only do this once and give an error on each
145+
subsequent call. Escpecially with single-page applications (eg an Angular app), the viewer may be loaded multiple times.
146+
This patch causes pdf.js to unregister an unusued (closed) overlay.
147+
148+
register: function overlayManagerRegister(name, callerCloseMethod, canForceClose) {
149+
return new Promise(function (resolve) {
150+
var element, container;
151+
if (!name || !(element = document.getElementById(name)) ||
152+
!(container = element.parentNode)) {
153+
throw new Error('Not enough parameters.');
154+
} else if (this.overlays[name]) {
155+
- throw new Error('The overlay is already registered.');
156+
+ if (this.active !== name) {
157+
+ this.unregister(name);
158+
+ } else {
159+
+ throw new Error('The overlay is already registered and active.');
160+
+ }
161+
}
162+
163+
#### webViewerChange trigger on file upload dialog
164+
165+
Whenever a file dialog is used (so with any `<input type="file">` on the page), the file is loaded into the pdf.js
166+
viewer. We don't want this behaviour, so comment it out.
167+
168+
-window.addEventListener('change', function webViewerChange(evt) {
169+
+/*window.addEventListener('change', function webViewerChange(evt) {
170+
var files = evt.target.files;
171+
if (!files || files.length === 0) {
172+
return;
173+
@@ -17627,7 +17647,7 @@
174+
setAttribute('hidden', 'true');
175+
document.getElementById('download').setAttribute('hidden', 'true');
176+
document.getElementById('secondaryDownload').setAttribute('hidden', 'true');
177+
-}, true);
178+
+}, true);*/
179+
180+
#### handleMouseWheel()
181+
182+
The JavaScript pdf.js file might be loaded while the viewer isn't being displayed. This causes an error on mouse move.
183+
We need to check if the viewer is initialized, before handling the event.
184+
185+
function handleMouseWheel(evt) {
186+
+ // Ignore mousewheel event if pdfViewer isn't loaded
187+
+ if (!PDFViewerApplication.pdfViewer) return;
188+
189+
#### Load code for worker using AJAX if needed
190+
191+
A [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) can't use code from
192+
a same-origin domain. The CORS headers don't apply.
193+
194+
he patch will cause pdf.js to first try to create the Worker the regular way, with a URL to the JavaScript source. If
195+
this fails, the source if fetched using AJAX and used to create an
196+
[object url](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL). If this also fails, pdf.js will go
197+
onto it's last resort by calling `setupFakeWorker()`.
198+
199+
+ /**
200+
+ * Needed because workers cannot load scripts outside of the current origin (as of firefox v45).
201+
+ * This patch does require the worker script to be served with a (Access-Control-Allow-Origin: *) header
202+
+ * @patch
203+
+ */
204+
+ var loadWorkerXHR = function(){
205+
+ var url = PDFJS.workerSrc;
206+
+ var jsdfd = PDFJS.createPromiseCapability();
207+
+
208+
+ if (url.match(/^blob:/) || typeof URL.createObjectURL === 'undefined') {
209+
+ jsdfd.reject(); // Failed loading using blob
210+
+ }
211+
+
212+
+ var xmlhttp;
213+
+ xmlhttp = new XMLHttpRequest();
214+
+
215+
+ xmlhttp.onreadystatechange = function(){
216+
+ if (xmlhttp.readyState != 4) return;
217+
+
218+
+ if (xmlhttp.status == 200) {
219+
+ info('Loaded worker source through XHR.');
220+
+ var workerJSBlob = new Blob([xmlhttp.responseText], { type: 'text/javascript' });
221+
+ jsdfd.resolve(window.URL.createObjectURL(workerJSBlob));
222+
+ } else {
223+
+ jsdfd.reject();
224+
+ }
225+
+ };
226+
+
227+
+ xmlhttp.open('GET', url, true);
228+
+ xmlhttp.send();
229+
+ return jsdfd.promise;
230+
+ }
231+
+
232+
+ var workerError = function() {
233+
+ loadWorkerXHR().then(function(blob) {
234+
+ PDFJS.workerSrc = blob;
235+
+ loadWorker();
236+
+ }, function() {
237+
+ this.setupFakeWorker();
238+
+ }.bind(this));
239+
+ }.bind(this);
240+
+
241+
242+
- if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
243+
+ var loadWorker = function() {
244+
var workerSrc = PDFJS.workerSrc;
245+
if (!workerSrc) {
246+
error('No PDFJS.workerSrc specified');
247+
@@ -3559,6 +3603,8 @@
248+
// Some versions of FF can't create a worker on localhost, see:
249+
// https://bugzilla.mozilla.org/show_bug.cgi?id=683280
250+
var worker = new Worker(workerSrc);
251+
+ worker.onerror = workerError;
252+
+
253+
var messageHandler = new MessageHandler('main', worker);
254+
this.messageHandler = messageHandler;
255+
256+
@@ -3589,11 +3635,16 @@
257+
return;
258+
} catch (e) {
259+
info('The worker has been disabled.');
260+
+ workerError();
261+
}
262+
- }
263+
+ }.bind(this);
264+
// Either workers are disabled, not supported or have thrown an exception.
265+
// Thus, we fallback to a faked worker.
266+
- this.setupFakeWorker();
267+
+ if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
268+
+ loadWorker();
269+
+ } else {
270+
+ this.setupFakeWorker();
271+
+ }
272+
}
273+

build.sh

100644100755
Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,28 @@
1-
cat source/web/l10n.js source/build/pdf.js source/web/compatibility.js source/web/debugger.js source/web/viewer.js > pdf.js
1+
#!/bin/bash
2+
3+
if [[ $# < 1 ]]; then
4+
echo USAGE $0 SOURCE_PATH 1>&2
5+
exit 1
6+
fi
7+
8+
source="$1"
9+
10+
if [[ ! -f "$source/build/pdf.js" ]]; then
11+
echo "$source/build/pdf.js" not found 1>&2
12+
exit 1
13+
fi
14+
15+
cat "$source/web/l10n.js" "$source/build/pdf.js" "$source/web/compatibility.js" "$source/web/debugger.js" "$source/web/viewer.js" > pdf.js
216
patch pdf.js < pdf.js.patch
317

4-
cp source/build/pdf.worker.js .
18+
cp "$source/build/pdf.worker.js" .
519
patch pdf.worker.js < pdf.worker.js.patch
620

7-
uglifycss source/web/viewer.css > viewer.css
21+
uglifycss "$source/web/viewer.css" > viewer.css
822
node grunt/css-prefix.js viewer.css viewer.css pdfjs
923

10-
sed -r 's/url\((")?images\//url\(\1@pdfjsImagePath\//g' < source/web/viewer.css | uglifycss > viewer.less
24+
sed -r 's/url\((")?images\//url\(\1@pdfjsImagePath\//g' < "$source/web/viewer.css" | uglifycss > viewer.less
1125
node grunt/css-prefix.js viewer.less viewer.less pdfjs
1226

13-
cp source/web/cmaps/ source/web/images/ source/web/locale/ . -a
27+
cp "$source/web/cmaps/" "$source/web/images/" "$source/web/locale/" . -a
1428

0 commit comments

Comments
 (0)