diff --git a/.jshintignore b/.eslintignore
similarity index 62%
rename from .jshintignore
rename to .eslintignore
index 55fba529..bc3e05a1 100644
--- a/.jshintignore
+++ b/.eslintignore
@@ -3,15 +3,14 @@ l10n/
docs/
node_modules/
examples/
+external/bcmaps/
external/webL10n/
-external/shelljs/
-external/jpgjs/
-external/jasmine/
external/cmapscompress/
-external/importL10n/
-shared/
+external/builder/fixtures/
+external/builder/fixtures_esprima/
test/tmp/
test/features/
+test/pdfs/
test/resources/
test/font/*_spec.js
*~/
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 00000000..d034a3ce
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,136 @@
+{
+ "parserOptions": {
+ "ecmaVersion": 5,
+ },
+
+ "env": {
+ "browser": true,
+ "es6": true,
+ "worker": true,
+ "amd": true,
+ },
+
+ globals: {
+ "PDFJSDev": false,
+ "exports": false,
+ "SystemJS": false,
+ },
+
+ "rules": {
+ // Possible errors
+ "no-cond-assign": ["error", "except-parens"],
+ "no-constant-condition": ["error", { "checkLoops": false, }],
+ "no-dupe-args": "error",
+ "no-dupe-keys": "error",
+ "no-duplicate-case": "error",
+ "no-empty": ["error", { "allowEmptyCatch": true, }],
+ "no-ex-assign": "error",
+ "no-extra-boolean-cast": "error",
+ "no-extra-semi": "error",
+ "no-func-assign": "error",
+ "no-inner-declarations": ["error", "functions"],
+ "no-invalid-regexp": "error",
+ "no-irregular-whitespace": "error",
+ "no-obj-calls": "error",
+ "no-regex-spaces": "error",
+ "no-sparse-arrays": "error",
+ "no-unexpected-multiline": "error",
+ "no-unreachable": "error",
+ "no-unsafe-finally": "error",
+ "no-unsafe-negation": "error",
+ "use-isnan": "error",
+ "valid-typeof": ["error", { "requireStringLiterals": true, }],
+
+ // Best Practices
+ "accessor-pairs": ["error", { "setWithoutGet": true, }],
+ "curly": ["error", "all"],
+ "eqeqeq": ["error", "always"],
+ "no-caller": "error",
+ "no-else-return": "error",
+ "no-empty-pattern": "error",
+ "no-eval": "error",
+ "no-extend-native": "error",
+ "no-extra-bind": "error",
+ "no-extra-label": "error",
+ "no-fallthrough": "error",
+ "no-floating-decimal": "error",
+ "no-global-assign": "error",
+ "no-implied-eval": "error",
+ "no-iterator": "error",
+ "no-lone-blocks": "error",
+ "no-multi-spaces": "error",
+ "no-multi-str": "error",
+ "no-new-func": "error",
+ "no-new-wrappers": "error",
+ "no-new": "error",
+ "no-octal-escape": "error",
+ "no-octal": "error",
+ "no-redeclare": "error",
+ "no-self-assign": "error",
+ "no-self-compare": "error",
+ "no-unused-expressions": "error",
+ "no-unused-labels": "error",
+ "no-useless-call": "error",
+ "no-useless-concat": "error",
+ "wrap-iife": ["error", "any"],
+ "yoda": ["error", "never", { "onlyEquality": true, }],
+
+ // Strict Mode
+ "strict": ["error", "global"],
+
+ // Variables
+ "no-catch-shadow": "error",
+ "no-delete-var": "error",
+ "no-label-var": "error",
+ "no-shadow-restricted-names": "error",
+ "no-undef-init": "error",
+ "no-undef": ["error", { "typeof": true, }],
+ "no-unused-vars": ["error", {
+ "vars": "local",
+ "args": "none",
+ }],
+
+ // Stylistic Issues
+ "array-bracket-spacing": ["error", "never"],
+ "block-spacing": ["error", "always"],
+ "brace-style": ["error", "1tbs", {
+ "allowSingleLine": false,
+ }],
+ "comma-spacing": ["error", { "before": false, "after": true, }],
+ "comma-style": ["error", "last"],
+ "eol-last": "error",
+ "func-call-spacing": ["error", "never"],
+ "key-spacing": ["error", { "beforeColon": false, "afterColon": true, "mode": "strict", }],
+ "keyword-spacing": ["error", { "before": true, "after": true, }],
+ "linebreak-style": ["error", "unix"],
+ "max-len": ["error", 80],
+ "new-cap": ["error", { "newIsCap": true, "capIsNew": false, }],
+ "new-parens": "error",
+ "no-array-constructor": "error",
+ "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 0, "maxBOF": 1, }],
+ "no-new-object": "error",
+ "no-tabs": "error",
+ "no-trailing-spaces": ["error", { "skipBlankLines": false, }],
+ "no-whitespace-before-property": "error",
+ "operator-linebreak": ["error", "after", { "overrides": { ":": "ignore", } }],
+ "quotes": ["error", "single"],
+ "semi-spacing": ["error", { "before": false, "after": true, }],
+ "semi": ["error", "always"],
+ "space-before-blocks": ["error", "always"],
+ "space-before-function-paren": ["error", { "anonymous": "ignore", "named": "never", }],
+ "space-in-parens": ["error", "never"],
+ "space-infix-ops": ["error", { "int32Hint": false }],
+ "space-unary-ops": ["error", { "words": true, "nonwords": false, }],
+ "spaced-comment": ["error", "always", {
+ "line": {
+ "exceptions": ["//", "#else", "#endif"],
+ "markers": ["#if", "#elif", "#include", "#expand", "#error"],
+ },
+ "block": {
+ "balanced": true,
+ }
+ }],
+
+ // ECMAScript 6
+ },
+}
diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md
similarity index 89%
rename from CONTRIBUTING.md
rename to .github/CONTRIBUTING.md
index e383650a..dcb4715c 100644
--- a/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -4,7 +4,7 @@ The issues are used to track both bugs filed by users and specific work items fo
If the issue is related to errors produced by a specific PDF, please always include the PDF by providing a URL where contributors can download it. Without a PDF for reproduction, such issues will be closed. We understand that many PDFs contain sensitive information, however having a PDF is essential to resolving the issue and building our regression testing suite. If possible, try creating a reduced example exhibiting the problem but not containing sensitive data. Also small PDFs are best suited for our regression testing. If an important issue only shows on sensitive PDFs, contributors might be willing to accept these PDFs via a secure exchange.
-The issue tracking system is designed to record a single technical problem. A bug report is something where a developer/contributor can work on. The GitHub issue tracker is not a good place for general, not well thought out or unworkable ideas. Most likely a discussion-type issue will not be addressed for a long time or closed as invalid. The best place is our dev-pdf-js@lists.mozilla.org mailing list. You can subscribe to it using http://lists.mozilla.org or Google Groups. This way you will reach not only developers. As an alternative, you can join our weekly engineering meeting to discuss new ideas for the project.
+The issue tracking system is designed to record a single technical problem. A bug report is something where a developer/contributor can work on. The GitHub issue tracker is not a good place for general, not well thought out or unworkable ideas. Most likely a discussion-type issue will not be addressed for a long time or closed as invalid. The best place for general discussions is our #pdfjs IRC channel on irc.mozilla.org.
If you are developing a custom solution, first check the examples at https://github.com/mozilla/pdf.js#learning and search existing issues. If this does not help, please prepare a short well-documented example that demonstrates the problem and make it accessible online on your website, JS Bin, GitHub, etc. before opening a new issue or contacting us on the IRC channel -- keep in mind that just code snippets won't help us troubleshoot the problem.
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 00000000..8b3f1abb
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,17 @@
+Link to PDF file (or attach file here):
+
+Configuration:
+- Web browser and its version:
+- Operating system and its version:
+- PDF.js version:
+- Is an extension:
+
+Steps to reproduce the problem:
+1.
+2.
+
+What is the expected behavior? (add screenshot)
+
+What went wrong? (add screenshot)
+
+Link to a viewer (if hosted on a site other than mozilla.github.io/pdf.js or as Firefox/Chrome extension):
diff --git a/.jshintrc b/.jshintrc
deleted file mode 100644
index b777537c..00000000
--- a/.jshintrc
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- // Environments
- "browser": true,
- "devel": true,
- "worker": true,
-
- // Enforcing
- "maxlen": 80,
- "quotmark": "single",
- "trailing": true,
- "curly": true,
- "undef": true,
- "noarg": true,
- "nonbsp": true,
- "eqeqeq": true,
-
- // Relaxing
- "boss": true,
- "funcscope": true,
- "globalstrict": true,
- "loopfunc": true,
- "maxerr": 1000,
- "nonstandard": true,
- "sub": true,
- "validthis": true
-}
diff --git a/.travis.yml b/.travis.yml
index 796d98f9..0c0c23f8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,11 @@
language: node_js
node_js:
- - "0.12"
+ - node
+cache:
+ directories:
+ - node_modules
+install:
+ - npm install -g npm@latest
+ - npm install -g gulp-cli
+ - npm install
+ - npm update
diff --git a/README.md b/README.md
index 792ac2b7..50283730 100644
--- a/README.md
+++ b/README.md
@@ -9,38 +9,39 @@ rendering PDFs.
## Contributing
PDF.js is an open source project and always looking for more contributors. To
-get involved checkout:
+get involved, visit:
-+ [Issue Reporting Guide](https://github.com/mozilla/pdf.js/blob/master/CONTRIBUTING.md)
++ [Issue Reporting Guide](https://github.com/mozilla/pdf.js/blob/master/.github/CONTRIBUTING.md)
+ [Code Contribution Guide](https://github.com/mozilla/pdf.js/wiki/Contributing)
+ [Frequently Asked Questions](https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions)
+ [Good Beginner Bugs](https://github.com/mozilla/pdf.js/issues?direction=desc&labels=5-good-beginner-bug&page=1&sort=created&state=open)
-+ [Priorities](https://github.com/mozilla/pdf.js/milestones)
-+ [Attend a Public Meeting](https://github.com/mozilla/pdf.js/wiki/Weekly-Public-Meetings)
++ [Projects](https://github.com/mozilla/pdf.js/projects)
-For further questions or guidance feel free to stop by #pdfjs on
-irc.mozilla.org.
+Feel free to stop by #pdfjs on irc.mozilla.org for questions or guidance.
## Getting Started
### Online demo
-+ http://mozilla.github.io/pdf.js/web/viewer.html
++ https://mozilla.github.io/pdf.js/web/viewer.html
### Browser Extensions
-#### Firefox and Seamonkey
+#### Firefox (and Seamonkey)
-PDF.js is built into version 19+ of Firefox, however the extension is still available:
+PDF.js is built into version 19+ of Firefox, however one extension is still available:
-+ [Development Version](http://mozilla.github.io/pdf.js/extensions/firefox/pdf.js.xpi) - This version is updated every time new code is merged into the PDF.js codebase. This should be quite stable but still might break from time to time. This version is also reported to work when installed as extension in Seamonkey 2.39.
++ [Development Version](http://mozilla.github.io/pdf.js/extensions/firefox/pdf.js.xpi) - This extension is mainly intended for developers/testers, and it is updated every time new code is merged into the PDF.js codebase. It should be quite stable, but might break from time to time.
-#### Chrome and Opera
+ + Please note that the extension is *not* guaranteed to be compatible with Firefox versions that are *older* than the current ESR version, see the [Release Calendar](https://wiki.mozilla.org/RapidRelease/Calendar#Past_branch_dates).
+
+ + The extension should also work in Seamonkey, provided that it is based on a Firefox version as above (see [Which version of Firefox does SeaMonkey 2.x correspond with?](https://wiki.mozilla.org/SeaMonkey/FAQ#General)), but we do *not* guarantee compatibility.
+
+#### Chrome
+ The official extension for Chrome can be installed from the [Chrome Web Store](https://chrome.google.com/webstore/detail/pdf-viewer/oemmndcbldboiebfnladdacbdfmadadm).
*This extension is maintained by [@Rob--W](https://github.com/Rob--W).*
-+ Opera has also published an extension for their browser at the [Opera add-ons catalog](https://addons.opera.com/en/extensions/details/pdf-viewer/).
-+ Build Your Own - Get the code as explained below and issue `node make chromium`. Then open
++ Build Your Own - Get the code as explained below and issue `gulp chromium`. Then open
Chrome, go to `Tools > Extension` and load the (unpackaged) extension from the
directory `build/chromium`.
@@ -52,16 +53,19 @@ To get a local copy of the current code, clone it using git:
$ cd pdf.js
Next, install Node.js via the [official package](http://nodejs.org) or via
-[nvm](https://github.com/creationix/nvm). If everything worked out, run
+[nvm](https://github.com/creationix/nvm). You need to install the gulp package
+globally (see also [gulp's getting started](https://github.com/gulpjs/gulp/blob/master/docs/getting-started.md#getting-started)):
+
+ $ npm install -g gulp-cli
+
+If everything worked out, install all dependencies for PDF.js:
$ npm install
-to install all dependencies for PDF.js.
-
Finally you need to start a local web server as some browsers do not allow opening
PDF files using a file:// URL. Run
- $ node make server
+ $ gulp server
and then you can open
@@ -73,10 +77,10 @@ It is also possible to view all test PDF files on the right side by opening
## Building PDF.js
-In order to bundle all `src/` files into two productions scripts and build the generic
-viewer, issue:
+In order to bundle all `src/` files into two production scripts and build the generic
+viewer, run:
- $ node make generic
+ $ gulp generic
This will generate `pdf.js` and `pdf.worker.js` in the `build/generic/build/` directory.
Both scripts are needed but only `pdf.js` needs to be included since `pdf.worker.js` will
@@ -84,15 +88,21 @@ be loaded by `pdf.js`. If you want to support more browsers than Firefox you'll
to include `compatibility.js` from `build/generic/web/`. The PDF.js files are large and
should be minified for production.
+## Using PDF.js in a web application
+
+To use PDF.js in a web application you can choose to use a pre-built version of the library
+or to build it from source. We supply pre-built versions for usage with NPM and Bower under
+the `pdfjs-dist` name. For more information and examples please refer to the
+[wiki page](https://github.com/mozilla/pdf.js/wiki/Setup-pdf.js-in-a-website) on this subject.
+
## Learning
-You can play with the PDF.js API directly from your browser through the live
+You can play with the PDF.js API directly from your browser using the live
demos below:
-+ [Hello world](http://mozilla.github.io/pdf.js/examples/learning/helloworld.html)
-+ [Simple reader with prev/next page controls](http://mozilla.github.io/pdf.js/examples/learning/prevnext.html)
++ [Interactive examples](http://mozilla.github.io/pdf.js/examples/index.html#interactive-examples)
-The repo contains a hello world example that you can run locally:
+The repository contains a hello world example that you can run locally:
+ [examples/helloworld/](https://github.com/mozilla/pdf.js/blob/master/examples/helloworld/)
@@ -101,12 +111,7 @@ contributor Julian Viereck:
+ http://www.youtube.com/watch?v=Iv15UY-4Fg8
-You can read more about PDF.js here:
-
-+ http://andreasgal.com/2011/06/15/pdf-js/
-+ http://blog.mozilla.com/cjones/2011/06/15/overview-of-pdf-js-guts/
-
-Even more learning resources can be found at:
+More learning resources can be found at:
+ https://github.com/mozilla/pdf.js/wiki/Additional-Learning-Resources
@@ -120,19 +125,10 @@ Talk to us on IRC:
+ #pdfjs on irc.mozilla.org
-Join our mailing list:
+File an issue:
-+ dev-pdf-js@lists.mozilla.org
-
-Subscribe either using lists.mozilla.org or Google Groups:
-
-+ https://lists.mozilla.org/listinfo/dev-pdf-js
-+ https://groups.google.com/group/mozilla.dev.pdf-js/topics
++ https://github.com/mozilla/pdf.js/issues/new
Follow us on twitter: @pdfjs
+ http://twitter.com/#!/pdfjs
-
-Weekly Public Meetings
-
-+ https://github.com/mozilla/pdf.js/wiki/Weekly-Public-Meetings
diff --git a/docs/contents/examples/index.md b/docs/contents/examples/index.md
index 418bc207..f50b69ea 100644
--- a/docs/contents/examples/index.md
+++ b/docs/contents/examples/index.md
@@ -61,3 +61,25 @@ var viewport = page.getViewport(1);
var scale = desiredWidth / viewport.width;
var scaledViewport = page.getViewport(scale);
```
+
+## Interactive examples
+
+### Hello World with document load error handling
+
+The example demonstrates how promises can be used to handle errors during loading.
+It also demonstrates how to wait until page loaded and rendered.
+
+
+
+### Hello World using base64 encoded PDF
+
+The PDF.js can accept any decoded base64 data as an array.
+
+
+
+### Previous/Next example
+
+The same canvas cannot be used to perform to draw two pages at the same time --
+the example demonstrate how to wait on previous operation to be complete.
+
+
diff --git a/docs/contents/getting_started/index.md b/docs/contents/getting_started/index.md
index 6ba9f36e..b01362ec 100644
--- a/docs/contents/getting_started/index.md
+++ b/docs/contents/getting_started/index.md
@@ -107,7 +107,7 @@ $ cd pdf.js
## Trying the Viewer
-With the prebuilt or source version open `web/viewer.html` in a browser and the test pdf should load. Note: the worker is not enabled for file:// urls, so use a server. If you're using the source build and have node, you can run `node make server`.
+With the prebuilt or source version open `web/viewer.html` in a browser and the test pdf should load. Note: the worker is not enabled for file:// urls, so use a server. If you're using the source build and have node, you can run `gulp server`.
## More Information
diff --git a/docs/contents/index.md b/docs/contents/index.md
index 7acd0436..aaabe1e9 100644
--- a/docs/contents/index.md
+++ b/docs/contents/index.md
@@ -10,5 +10,5 @@ template: layout.jade
Download
Demo
- Github Project
+ GitHub Project
diff --git a/examples/acroforms/README.md b/examples/acroforms/README.md
new file mode 100644
index 00000000..50bf5bcf
--- /dev/null
+++ b/examples/acroforms/README.md
@@ -0,0 +1,11 @@
+## Overview
+
+Example to demonstrate PDF.js library usage for rendering files with AcroForms.
+
+## Getting started
+
+Build PDF.js using `gulp dist` and run `gulp server` to start a web server.
+You can then work with the example at
+http://localhost:8888/examples/acroforms/acroforms.html.
+
+Refer to `acroforms.js` for the source code of the example.
diff --git a/examples/acroforms/acroforms.html b/examples/acroforms/acroforms.html
new file mode 100644
index 00000000..bba3a775
--- /dev/null
+++ b/examples/acroforms/acroforms.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+ AcroForms example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/acroforms/acroforms.js b/examples/acroforms/acroforms.js
new file mode 100644
index 00000000..ca17a61b
--- /dev/null
+++ b/examples/acroforms/acroforms.js
@@ -0,0 +1,49 @@
+/* Copyright 2017 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+PDFJS.workerSrc = '../../build/dist/build/pdf.worker.js';
+
+var DEFAULT_URL = '../../test/pdfs/f1040.pdf';
+var DEFAULT_SCALE = 1.0;
+
+var container = document.getElementById('pageContainer');
+
+// Fetch the PDF document from the URL using promises.
+PDFJS.getDocument(DEFAULT_URL).then(function (doc) {
+ // Use a promise to fetch and render the next page.
+ var promise = Promise.resolve();
+
+ for (var i = 1; i <= doc.numPages; i++) {
+ promise = promise.then(function (pageNum) {
+ return doc.getPage(pageNum).then(function (pdfPage) {
+ // Create the page view.
+ var pdfPageView = new PDFJS.PDFPageView({
+ container: container,
+ id: pageNum,
+ scale: DEFAULT_SCALE,
+ defaultViewport: pdfPage.getViewport(DEFAULT_SCALE),
+ annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory(),
+ renderInteractiveForms: true,
+ });
+
+ // Associate the actual page with the view and draw it.
+ pdfPageView.setPdfPage(pdfPage);
+ return pdfPageView.draw();
+ });
+ }.bind(null, i));
+ }
+});
diff --git a/examples/acroforms/forms.js b/examples/acroforms/forms.js
deleted file mode 100644
index eda30662..00000000
--- a/examples/acroforms/forms.js
+++ /dev/null
@@ -1,150 +0,0 @@
-
-//
-// Basic AcroForms input controls rendering
-//
-
-'use strict';
-
-var formFields = {};
-
-function setupForm(div, content, viewport) {
- function bindInputItem(input, item) {
- if (input.name in formFields) {
- var value = formFields[input.name];
- if (input.type == 'checkbox') {
- input.checked = value;
- } else if (!input.type || input.type == 'text') {
- input.value = value;
- }
- }
- input.onchange = function pageViewSetupInputOnBlur() {
- if (input.type == 'checkbox') {
- formFields[input.name] = input.checked;
- } else if (!input.type || input.type == 'text') {
- formFields[input.name] = input.value;
- }
- };
- }
- function createElementWithStyle(tagName, item) {
- var element = document.createElement(tagName);
- var rect = PDFJS.Util.normalizeRect(
- viewport.convertToViewportRectangle(item.rect));
- element.style.left = Math.floor(rect[0]) + 'px';
- element.style.top = Math.floor(rect[1]) + 'px';
- element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
- element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
- return element;
- }
- function assignFontStyle(element, item) {
- var fontStyles = '';
- if ('fontSize' in item) {
- fontStyles += 'font-size: ' + Math.round(item.fontSize *
- viewport.fontScale) + 'px;';
- }
- switch (item.textAlignment) {
- case 0:
- fontStyles += 'text-align: left;';
- break;
- case 1:
- fontStyles += 'text-align: center;';
- break;
- case 2:
- fontStyles += 'text-align: right;';
- break;
- }
- element.setAttribute('style', element.getAttribute('style') + fontStyles);
- }
-
- content.getAnnotations().then(function(items) {
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- switch (item.subtype) {
- case 'Widget':
- if (item.fieldType != 'Tx' && item.fieldType != 'Btn' &&
- item.fieldType != 'Ch') {
- break;
- }
- var inputDiv = createElementWithStyle('div', item);
- inputDiv.className = 'inputHint';
- div.appendChild(inputDiv);
- var input;
- if (item.fieldType == 'Tx') {
- input = createElementWithStyle('input', item);
- }
- if (item.fieldType == 'Btn') {
- input = createElementWithStyle('input', item);
- if (item.flags & 32768) {
- input.type = 'radio';
- // radio button is not supported
- } else if (item.flags & 65536) {
- input.type = 'button';
- // pushbutton is not supported
- } else {
- input.type = 'checkbox';
- }
- }
- if (item.fieldType == 'Ch') {
- input = createElementWithStyle('select', item);
- // select box is not supported
- }
- input.className = 'inputControl';
- input.name = item.fullName;
- input.title = item.alternativeText;
- assignFontStyle(input, item);
- bindInputItem(input, item);
- div.appendChild(input);
- break;
- }
- }
- });
-}
-
-function renderPage(div, pdf, pageNumber, callback) {
- pdf.getPage(pageNumber).then(function(page) {
- var scale = 1.5;
- var viewport = page.getViewport(scale);
-
- var pageDisplayWidth = viewport.width;
- var pageDisplayHeight = viewport.height;
-
- var pageDivHolder = document.createElement('div');
- pageDivHolder.className = 'pdfpage';
- pageDivHolder.style.width = pageDisplayWidth + 'px';
- pageDivHolder.style.height = pageDisplayHeight + 'px';
- div.appendChild(pageDivHolder);
-
- // Prepare canvas using PDF page dimensions
- var canvas = document.createElement('canvas');
- var context = canvas.getContext('2d');
- canvas.width = pageDisplayWidth;
- canvas.height = pageDisplayHeight;
- pageDivHolder.appendChild(canvas);
-
- // Render PDF page into canvas context
- var renderContext = {
- canvasContext: context,
- viewport: viewport
- };
- page.render(renderContext).promise.then(callback);
-
- // Prepare and populate form elements layer
- var formDiv = document.createElement('div');
- pageDivHolder.appendChild(formDiv);
-
- setupForm(formDiv, page, viewport);
- });
-}
-
-// Fetch the PDF document from the URL using promices
-PDFJS.getDocument(pdfWithFormsPath).then(function getPdfForm(pdf) {
- // Rendering all pages starting from first
- var viewer = document.getElementById('viewer');
- var pageNumber = 1;
- renderPage(viewer, pdf, pageNumber++, function pageRenderingComplete() {
- if (pageNumber > pdf.numPages) {
- return; // All pages rendered
- }
- // Continue rendering of the next page
- renderPage(viewer, pdf, pageNumber++, pageRenderingComplete);
- });
-});
diff --git a/examples/acroforms/index.html b/examples/acroforms/index.html
deleted file mode 100644
index a54ba704..00000000
--- a/examples/acroforms/index.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/browserify/.gitignore b/examples/browserify/.gitignore
new file mode 100644
index 00000000..c2658d7d
--- /dev/null
+++ b/examples/browserify/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/examples/browserify/README.md b/examples/browserify/README.md
new file mode 100644
index 00000000..dd838f0b
--- /dev/null
+++ b/examples/browserify/README.md
@@ -0,0 +1,26 @@
+## Overview
+
+Example to demonstrate PDF.js library usage with Browserify.
+
+## Getting started
+
+Build project and install the example dependencies:
+
+ $ gulp dist
+ $ cd examples/browserify
+ $ npm install
+
+To build Browserify bundles, run `gulp build`. If you are running
+a web server, you can observe the build results at
+http://localhost:8888/examples/browserify/index.html
+
+See main.js, worker.js and gulpfile.js files. Please notice that PDF.js
+packaging requires packaging of the main application and PDF.js worker code,
+and the `workerSrc` path shall be set to the latter file. The pdf.worker.js file
+shall be excluded from the main bundle.
+
+Alternatives to the gulp commands (without compression) are:
+
+ $ mkdir -p ../../build/browserify
+ $ node_modules/.bin/browserify main.js -u ./node_modules/pdfjs-dist/build/pdf.worker.js -o ../../build/browserify/main.bundle.js
+ $ node_modules/.bin/browserify worker.js -o ../../build/browserify/pdf.worker.bundle.js
diff --git a/examples/browserify/gulpfile.js b/examples/browserify/gulpfile.js
new file mode 100644
index 00000000..b8d9ca00
--- /dev/null
+++ b/examples/browserify/gulpfile.js
@@ -0,0 +1,34 @@
+var gulp = require('gulp');
+var browserify = require('browserify');
+var streamify = require('gulp-streamify');
+var rename = require('gulp-rename');
+var uglify = require('gulp-uglify');
+var source = require('vinyl-source-stream');
+
+var OUTPUT_PATH = '../../build/browserify';
+var TMP_FILE_PREFIX = '../../build/browserify_';
+
+gulp.task('build-bundle', function() {
+ return browserify('main.js', {output: TMP_FILE_PREFIX + 'main.tmp'})
+ .ignore(require.resolve('pdfjs-dist/build/pdf.worker')) // Reducing size
+ .bundle()
+ .pipe(source(TMP_FILE_PREFIX + 'main.tmp'))
+ .pipe(streamify(uglify()))
+ .pipe(rename('main.bundle.js'))
+ .pipe(gulp.dest(OUTPUT_PATH));
+});
+
+gulp.task('build-worker', function() {
+ // We can create our own viewer (see worker.js) or use already defined one.
+ var workerSrc = require.resolve('pdfjs-dist/build/pdf.worker.entry');
+ return browserify(workerSrc, {output: TMP_FILE_PREFIX + 'worker.tmp'})
+ .bundle()
+ .pipe(source(TMP_FILE_PREFIX + 'worker.tmp'))
+ .pipe(streamify(uglify({compress:{
+ sequences: false // Chrome has issue with the generated code if true
+ }})))
+ .pipe(rename('pdf.worker.bundle.js'))
+ .pipe(gulp.dest(OUTPUT_PATH));
+});
+
+gulp.task('build', ['build-bundle', 'build-worker']);
diff --git a/examples/browserify/index.html b/examples/browserify/index.html
new file mode 100644
index 00000000..8bd4644d
--- /dev/null
+++ b/examples/browserify/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+ browserify example
+
+
+
+
+
+
diff --git a/examples/browserify/main.js b/examples/browserify/main.js
new file mode 100644
index 00000000..46a921a5
--- /dev/null
+++ b/examples/browserify/main.js
@@ -0,0 +1,35 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+// Hello world example for browserify.
+
+require('pdfjs-dist');
+
+var pdfPath = '../helloworld/helloworld.pdf';
+
+// Setting worker path to worker bundle.
+PDFJS.workerSrc = '../../build/browserify/pdf.worker.bundle.js';
+
+// It is also possible to disable workers via `PDFJS.disableWorker = true`,
+// however that might degrade the UI performance in web browsers.
+
+// Loading a document.
+var loadingTask = PDFJS.getDocument(pdfPath);
+loadingTask.promise.then(function (pdfDocument) {
+ // Request a first page
+ return pdfDocument.getPage(1).then(function (pdfPage) {
+ // Display page on the existing canvas with 100% scale.
+ var viewport = pdfPage.getViewport(1.0);
+ var canvas = document.getElementById('theCanvas');
+ canvas.width = viewport.width;
+ canvas.height = viewport.height;
+ var ctx = canvas.getContext('2d');
+ var renderTask = pdfPage.render({
+ canvasContext: ctx,
+ viewport: viewport
+ });
+ return renderTask.promise;
+ });
+}).catch(function (reason) {
+ console.error('Error: ' + reason);
+});
diff --git a/examples/browserify/package.json b/examples/browserify/package.json
new file mode 100644
index 00000000..aaca35ed
--- /dev/null
+++ b/examples/browserify/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "browserify-pdf.js-example",
+ "version": "0.1.0",
+ "devDependencies": {
+ "browserify": "^13.0.0",
+ "gulp": "^3.9.1",
+ "gulp-rename": "^1.2.2",
+ "gulp-streamify": "^1.0.2",
+ "gulp-uglify": "^1.5.3",
+ "pdfjs-dist": "../../build/dist",
+ "vinyl-source-stream": "^1.1.0"
+ },
+ "scripts": {
+ "build": "gulp build"
+ }
+}
diff --git a/examples/browserify/worker.js b/examples/browserify/worker.js
new file mode 100644
index 00000000..9745f5a5
--- /dev/null
+++ b/examples/browserify/worker.js
@@ -0,0 +1,7 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+// Hello world example for browserify: worker bundle.
+
+(typeof window !== 'undefined' ? window : {}).pdfjsDistBuildPdfWorker =
+ require('pdfjs-dist/build/pdf.worker');
diff --git a/examples/components/pageviewer.html b/examples/components/pageviewer.html
index 8794c353..6e57aa39 100644
--- a/examples/components/pageviewer.html
+++ b/examples/components/pageviewer.html
@@ -29,16 +29,14 @@ limitations under the License.
}
-
+
-
-
-
-
+
+
-
+
diff --git a/examples/components/pageviewer.js b/examples/components/pageviewer.js
index c36e3754..54e1dceb 100644
--- a/examples/components/pageviewer.js
+++ b/examples/components/pageviewer.js
@@ -16,17 +16,17 @@
'use strict';
if (!PDFJS.PDFViewer || !PDFJS.getDocument) {
- alert('Please build the library and components using\n' +
- ' `node make generic components`');
+ alert('Please build the pdfjs-dist library using\n' +
+ ' `gulp dist`');
}
// The workerSrc property shall be specified.
//
-PDFJS.workerSrc = '../../build/pdf.worker.js';
+PDFJS.workerSrc = '../../build/dist/build/pdf.worker.js';
// Some PDFs need external cmaps.
//
-// PDFJS.cMapUrl = '../../external/bcmaps/';
+// PDFJS.cMapUrl = '../../build/dist/cmaps/';
// PDFJS.cMapPacked = true;
var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
@@ -47,7 +47,7 @@ PDFJS.getDocument(DEFAULT_URL).then(function (pdfDocument) {
defaultViewport: pdfPage.getViewport(SCALE),
// We can enable text/annotations layers, if needed
textLayerFactory: new PDFJS.DefaultTextLayerFactory(),
- annotationsLayerFactory: new PDFJS.DefaultAnnotationsLayerFactory()
+ annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory()
});
// Associates the actual page with the view, and drawing it
pdfPageView.setPdfPage(pdfPage);
diff --git a/examples/components/simpleviewer.html b/examples/components/simpleviewer.html
index 65b01dbe..692d1ee0 100644
--- a/examples/components/simpleviewer.html
+++ b/examples/components/simpleviewer.html
@@ -35,12 +35,10 @@ limitations under the License.
}
-
+
-
-
-
-
+
+
diff --git a/examples/components/simpleviewer.js b/examples/components/simpleviewer.js
index fe2276fa..60438a46 100644
--- a/examples/components/simpleviewer.js
+++ b/examples/components/simpleviewer.js
@@ -16,20 +16,21 @@
'use strict';
if (!PDFJS.PDFViewer || !PDFJS.getDocument) {
- alert('Please build the library and components using\n' +
- ' `node make generic components`');
+ alert('Please build the pdfjs-dist library using\n' +
+ ' `gulp dist`');
}
// The workerSrc property shall be specified.
//
-PDFJS.workerSrc = '../../build/pdf.worker.js';
+PDFJS.workerSrc = '../../build/dist/build/pdf.worker.js';
// Some PDFs need external cmaps.
//
-// PDFJS.cMapUrl = '../../external/bcmaps/';
+// PDFJS.cMapUrl = '../../build/dist/cmaps/';
// PDFJS.cMapPacked = true;
var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
+var SEARCH_FOR = ''; // try 'Mozilla';
var container = document.getElementById('viewerContainer');
@@ -42,9 +43,19 @@ var pdfViewer = new PDFJS.PDFViewer({
});
pdfLinkService.setViewer(pdfViewer);
+// (Optionally) enable find controller.
+var pdfFindController = new PDFJS.PDFFindController({
+ pdfViewer: pdfViewer
+});
+pdfViewer.setFindController(pdfFindController);
+
container.addEventListener('pagesinit', function () {
// We can use pdfViewer now, e.g. let's change default scale.
pdfViewer.currentScaleValue = 'page-width';
+
+ if (SEARCH_FOR) { // We can try search for things
+ pdfFindController.executeCommand('find', {query: SEARCH_FOR});
+ }
});
// Loading document.
diff --git a/examples/helloworld/README.md b/examples/helloworld/README.md
index 7096b145..bc979fbb 100644
--- a/examples/helloworld/README.md
+++ b/examples/helloworld/README.md
@@ -8,7 +8,7 @@ simple and human-readable PDF.
Instead of simply opening `index.html` in a browser, you must serve the page
using a web server. This can be done on your local machine without an internet
-connection. In the root directory of PDF.js, run `node make server` in a
+connection. In the root directory of PDF.js, run `gulp server` in a
terminal. The example can then be viewed using the following URL:
`http://localhost:8888/examples/helloworld/index.html`
diff --git a/examples/helloworld/hello.js b/examples/helloworld/hello.js
index 9cd8295f..b4421b6d 100644
--- a/examples/helloworld/hello.js
+++ b/examples/helloworld/hello.js
@@ -1,34 +1,32 @@
-
-//
-// See README for overview
-//
-
'use strict';
-//
-// Fetch the PDF document from the URL using promises
-//
-PDFJS.getDocument('helloworld.pdf').then(function(pdf) {
- // Using promise to fetch the page
- pdf.getPage(1).then(function(page) {
- var scale = 1.5;
- var viewport = page.getViewport(scale);
+// In production, the bundled pdf.js shall be used instead of SystemJS.
+Promise.all([SystemJS.import('pdfjs/display/api'),
+ SystemJS.import('pdfjs/display/global')])
+ .then(function (modules) {
+ var api = modules[0], global = modules[1];
+ // In production, change this to point to the built `pdf.worker.js` file.
+ global.PDFJS.workerSrc = '../../src/worker_loader.js';
- //
- // Prepare canvas using PDF page dimensions
- //
- var canvas = document.getElementById('the-canvas');
- var context = canvas.getContext('2d');
- canvas.height = viewport.height;
- canvas.width = viewport.width;
+ // Fetch the PDF document from the URL using promises.
+ api.getDocument('helloworld.pdf').then(function (pdf) {
+ // Fetch the page.
+ pdf.getPage(1).then(function (page) {
+ var scale = 1.5;
+ var viewport = page.getViewport(scale);
- //
- // Render PDF page into canvas context
- //
- var renderContext = {
- canvasContext: context,
- viewport: viewport
- };
- page.render(renderContext);
+ // Prepare canvas using PDF page dimensions.
+ var canvas = document.getElementById('the-canvas');
+ var context = canvas.getContext('2d');
+ canvas.height = viewport.height;
+ canvas.width = viewport.width;
+
+ // Render PDF page into canvas context.
+ var renderContext = {
+ canvasContext: context,
+ viewport: viewport
+ };
+ page.render(renderContext);
+ });
});
});
diff --git a/examples/helloworld/index.html b/examples/helloworld/index.html
index 02947cf9..e27316ea 100644
--- a/examples/helloworld/index.html
+++ b/examples/helloworld/index.html
@@ -2,25 +2,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/examples/learning/helloworld.html b/examples/learning/helloworld.html
index 564c2ce1..685cccd7 100644
--- a/examples/learning/helloworld.html
+++ b/examples/learning/helloworld.html
@@ -13,7 +13,7 @@
-
+
-
-
+
-->
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ More Information
+
+
+ Less Information
+
+
+
+
+ Close
+
+
+
+
+
+
+
+
+
diff --git a/extensions/b2g/viewer.js b/examples/mobile-viewer/viewer.js
similarity index 79%
rename from extensions/b2g/viewer.js
rename to examples/mobile-viewer/viewer.js
index 94bb77ca..2c6cbb21 100644
--- a/extensions/b2g/viewer.js
+++ b/examples/mobile-viewer/viewer.js
@@ -1,4 +1,4 @@
-/* Copyright 2014 Mozilla Foundation
+/* Copyright 2016 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,49 +12,71 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/* globals PDFJS, Promise */
+/* globals PDFJS */
'use strict';
+if (!PDFJS.PDFViewer || !PDFJS.getDocument) {
+ alert('Please build the pdfjs-dist library using\n' +
+ ' `gulp dist`');
+}
+
PDFJS.useOnlyCssZoom = true;
PDFJS.disableTextLayer = true;
PDFJS.maxImageSize = 1024 * 1024;
-PDFJS.workerSrc = '../pdfjs-components/build/pdf.worker.js';
-PDFJS.cMapUrl = '../pdfjs-components/cmaps/';
+PDFJS.workerSrc = '../../build/dist/build/pdf.worker.js';
+PDFJS.cMapUrl = '../../build/dist/cmaps/';
PDFJS.cMapPacked = true;
+var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
var DEFAULT_SCALE_DELTA = 1.1;
var MIN_SCALE = 0.25;
var MAX_SCALE = 10.0;
var DEFAULT_SCALE_VALUE = 'auto';
var PDFViewerApplication = {
+ pdfLoadingTask: null,
pdfDocument: null,
pdfViewer: null,
pdfHistory: null,
pdfLinkService: null,
+ /**
+ * Opens PDF document specified by URL.
+ * @returns {Promise} - Returns the promise, which is resolved when document
+ * is opened.
+ */
open: function (params) {
- var url = params.url, originalUrl = params.originalUrl;
+ if (this.pdfLoadingTask) {
+ // We need to destroy already opened document
+ return this.close().then(function () {
+ // ... and repeat the open() call.
+ return this.open(params);
+ }.bind(this));
+ }
+
+ var url = params.url;
var self = this;
- this.setTitleUsingUrl(originalUrl);
+ this.setTitleUsingUrl(url);
// Loading document.
var loadingTask = PDFJS.getDocument(url);
+ this.pdfLoadingTask = loadingTask;
+
loadingTask.onProgress = function (progressData) {
self.progress(progressData.loaded / progressData.total);
};
- loadingTask.then(function (pdfDocument) {
- // Document loaded, specifying document for the viewer.
- this.pdfDocument = pdfDocument;
- this.pdfViewer.setDocument(pdfDocument);
- this.pdfLinkService.setDocument(pdfDocument);
- this.pdfHistory.initialize(pdfDocument.fingerprint);
- this.loadingBar.hide();
- this.setTitleUsingMetadata(pdfDocument);
- }.bind(this), function (exception) {
+ return loadingTask.promise.then(function (pdfDocument) {
+ // Document loaded, specifying document for the viewer.
+ self.pdfDocument = pdfDocument;
+ self.pdfViewer.setDocument(pdfDocument);
+ self.pdfLinkService.setDocument(pdfDocument);
+ self.pdfHistory.initialize(pdfDocument.fingerprint);
+
+ self.loadingBar.hide();
+ self.setTitleUsingMetadata(pdfDocument);
+ }, function (exception) {
var message = exception && exception.message;
var loadingErrorMessage = mozL10n.get('loading_error', null,
'An error occurred while loading the PDF.');
@@ -80,6 +102,32 @@ var PDFViewerApplication = {
});
},
+ /**
+ * Closes opened PDF document.
+ * @returns {Promise} - Returns the promise, which is resolved when all
+ * destruction is completed.
+ */
+ close: function () {
+ var errorWrapper = document.getElementById('errorWrapper');
+ errorWrapper.setAttribute('hidden', 'true');
+
+ if (!this.pdfLoadingTask) {
+ return Promise.resolve();
+ }
+
+ var promise = this.pdfLoadingTask.destroy();
+ this.pdfLoadingTask = null;
+
+ if (this.pdfDocument) {
+ this.pdfDocument = null;
+
+ this.pdfViewer.setDocument(null);
+ this.pdfLinkService.setDocument(null, null);
+ }
+
+ return promise;
+ },
+
get loadingBar() {
var bar = new PDFJS.ProgressBar('#loadingBar', {});
@@ -88,7 +136,7 @@ var PDFViewerApplication = {
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
this.url = url;
- var title = PDFJS.getFileName(url) || url;
+ var title = PDFJS.getFilenameFromUrl(url) || url;
try {
title = decodeURIComponent(title);
} catch (e) {
@@ -134,7 +182,7 @@ var PDFViewerApplication = {
setTitle: function pdfViewSetTitle(title) {
document.title = title;
- document.getElementById('activityTitle').textContent = title;
+ document.getElementById('title').textContent = title;
},
error: function pdfViewError(message, moreInfo) {
@@ -273,10 +321,11 @@ var PDFViewerApplication = {
document.getElementById('pageNumber').addEventListener('change',
function() {
- // Handle the user inputting a floating point number.
PDFViewerApplication.page = (this.value | 0);
- if (this.value !== (this.value | 0).toString()) {
+ // Ensure that the page number input displays the correct value, even if the
+ // value entered by the user was invalid (e.g. a floating point number).
+ if (this.value !== PDFViewerApplication.page.toString()) {
this.value = PDFViewerApplication.page;
}
});
@@ -288,11 +337,9 @@ var PDFViewerApplication = {
container.addEventListener('pagechange', function (evt) {
var page = evt.pageNumber;
- if (evt.previousPageNumber !== page) {
- document.getElementById('pageNumber').value = page;
- }
var numPages = PDFViewerApplication.pagesCount;
+ document.getElementById('pageNumber').value = page;
document.getElementById('previous').disabled = (page <= 1);
document.getElementById('next').disabled = (page >= numPages);
}, true);
@@ -312,38 +359,9 @@ document.addEventListener('DOMContentLoaded', function () {
});
})();
-// Support of the new version of navigator.mozL10n -- in PDF.js older/custom
-// version is used.
-var mozL10n = {
- get: function (id, args, fallback) {
- var s = (navigator.mozL10n && navigator.mozL10n.get(id)) || fallback;
- s = s.replace(/\{\{\s*(\w+)\s*\}\}/g, function (all, key) {
- return args[key] || '';
- });
- return s;
- },
-
- translate: function (fragment) {
- if (navigator.mozL10n) {
- navigator.mozL10n.translateFragment(fragment);
- }
- }
-};
-
-window.navigator.mozSetMessageHandler('activity', function(activity) {
- var blob = activity.source.data.blob;
- var fileURL = activity.source.data.url ||
- activity.source.data.filename ||
- ' '; // if no url or filename, use a non-empty string
-
- var url = URL.createObjectURL(blob);
- // We need to delay opening until all HTML is loaded.
- PDFViewerApplication.animationStartedPromise.then(function () {
- PDFViewerApplication.open({url: url, originalUrl: fileURL});
-
- var header = document.getElementById('header');
- header.addEventListener('action', function() {
- activity.postResult('close');
- });
+// We need to delay opening until all HTML is loaded.
+PDFViewerApplication.animationStartedPromise.then(function () {
+ PDFViewerApplication.open({
+ url: DEFAULT_URL
});
});
diff --git a/examples/node/domstubs.js b/examples/node/domstubs.js
index 5eb186b8..b654d607 100644
--- a/examples/node/domstubs.js
+++ b/examples/node/domstubs.js
@@ -123,6 +123,10 @@ DOMElement.prototype = {
global.document = {
childNodes : [],
+ get currentScript() {
+ return { src: '' };
+ },
+
get documentElement() {
return this;
},
diff --git a/examples/node/getinfo.js b/examples/node/getinfo.js
index 9c2faff6..3bed3929 100644
--- a/examples/node/getinfo.js
+++ b/examples/node/getinfo.js
@@ -4,18 +4,16 @@
//
// Basic node example that prints document metadata and text content.
// Requires single file built version of PDF.js -- please run
-// `node make singlefile` before running the example.
+// `gulp singlefile` before running the example.
//
var fs = require('fs');
-// HACK few hacks to let PDF.js be loaded not as a module in global space.
-global.window = global;
-global.navigator = { userAgent: "node" };
-global.PDFJS = {};
+// HACK adding DOMParser to read XMP metadata.
global.DOMParser = require('./domparsermock.js').DOMParserMock;
-require('../../build/singlefile/build/pdf.combined.js');
+// Run `gulp dist` to generate 'pdfjs-dist' npm package files.
+var pdfjsLib = require('../../build/dist');
// Loading file from file system into typed array
var pdfPath = process.argv[2] || '../../web/compressed.tracemonkey-pldi-09.pdf';
@@ -23,7 +21,7 @@ var data = new Uint8Array(fs.readFileSync(pdfPath));
// Will be using promises to load document, pages and misc data instead of
// callback.
-PDFJS.getDocument(data).then(function (doc) {
+pdfjsLib.getDocument(data).then(function (doc) {
var numPages = doc.numPages;
console.log('# Document Loaded');
console.log('Number of Pages: ' + numPages);
diff --git a/examples/node/pdf2svg.js b/examples/node/pdf2svg.js
index d4defb41..00d41216 100644
--- a/examples/node/pdf2svg.js
+++ b/examples/node/pdf2svg.js
@@ -8,14 +8,10 @@
var fs = require('fs');
// HACK few hacks to let PDF.js be loaded not as a module in global space.
-global.window = global;
-global.navigator = { userAgent: 'node' };
-global.PDFJS = {};
-
require('./domstubs.js');
-PDFJS.workerSrc = true;
-require('../../build/singlefile/build/pdf.combined.js');
+// Run `gulp dist` to generate 'pdfjs-dist' npm package files.
+var pdfjsLib = require('../../build/dist');
// Loading file from file system into typed array
var pdfPath = process.argv[2] || '../../web/compressed.tracemonkey-pldi-09.pdf';
@@ -48,7 +44,7 @@ function getFileNameFromPath(path) {
// Will be using promises to load document, pages and misc data instead of
// callback.
-PDFJS.getDocument(data).then(function (doc) {
+pdfjsLib.getDocument(data).then(function (doc) {
var numPages = doc.numPages;
console.log('# Document Loaded');
console.log('Number of Pages: ' + numPages);
@@ -63,7 +59,7 @@ PDFJS.getDocument(data).then(function (doc) {
console.log();
return page.getOperatorList().then(function (opList) {
- var svgGfx = new PDFJS.SVGGraphics(page.commonObjs, page.objs);
+ var svgGfx = new pdfjsLib.SVGGraphics(page.commonObjs, page.objs);
svgGfx.embedFonts = true;
return svgGfx.getSVG(opList, viewport).then(function (svg) {
var svgDump = svg.toString();
diff --git a/examples/svgviewer/index.html b/examples/svgviewer/index.html
index 2fb5ce8a..2b19c29f 100644
--- a/examples/svgviewer/index.html
+++ b/examples/svgviewer/index.html
@@ -2,35 +2,25 @@
-
-
-
-
-
-
-
-
+
-
+ PDF.js SVG viewer example
+
+
+
+
-
- SVG Viewer Example
+
diff --git a/examples/svgviewer/viewer.js b/examples/svgviewer/viewer.js
index 344315e7..3a5a831b 100644
--- a/examples/svgviewer/viewer.js
+++ b/examples/svgviewer/viewer.js
@@ -1,56 +1,55 @@
-
-//
-// See README for overview
-//
-
'use strict';
+var DEFAULT_SCALE = 1.5;
+
// Parse query string to extract some parameters (it can fail for some input)
var query = document.location.href.replace(/^[^?]*(\?([^#]*))?(#.*)?/, '$2');
var queryParams = query ? JSON.parse('{' + query.split('&').map(function (a) {
return a.split('=').map(decodeURIComponent).map(JSON.stringify).join(': ');
}).join(',') + '}') : {};
-var url = queryParams.file || '../../test/pdfs/liveprogramming.pdf';
-var scale = +queryParams.scale || 1.5;
-
-//
-// Fetch the PDF document from the URL using promises
-//
-PDFJS.getDocument(url).then(function(pdf) {
- var numPages = pdf.numPages;
- // Using promise to fetch the page
-
- // For testing only.
- var MAX_NUM_PAGES = 50;
- var ii = Math.min(MAX_NUM_PAGES, numPages);
+var url = queryParams.file || '../../web/compressed.tracemonkey-pldi-09.pdf';
+function renderDocument(pdf, svgLib) {
var promise = Promise.resolve();
- for (var i = 1; i <= ii; i++) {
- var anchor = document.createElement('a');
- anchor.setAttribute('name', 'page=' + i);
- anchor.setAttribute('title', 'Page ' + i);
- document.body.appendChild(anchor);
-
+ for (var i = 1; i <= pdf.numPages; i++) {
// Using promise to fetch and render the next page
- promise = promise.then(function (pageNum, anchor) {
+ promise = promise.then(function (pageNum) {
return pdf.getPage(pageNum).then(function (page) {
- var viewport = page.getViewport(scale);
+ var viewport = page.getViewport(DEFAULT_SCALE);
var container = document.createElement('div');
container.id = 'pageContainer' + pageNum;
container.className = 'pageContainer';
container.style.width = viewport.width + 'px';
container.style.height = viewport.height + 'px';
- anchor.appendChild(container);
+ document.body.appendChild(container);
return page.getOperatorList().then(function (opList) {
- var svgGfx = new PDFJS.SVGGraphics(page.commonObjs, page.objs);
+ var svgGfx = new svgLib.SVGGraphics(page.commonObjs, page.objs);
return svgGfx.getSVG(opList, viewport).then(function (svg) {
container.appendChild(svg);
});
});
});
- }.bind(null, i, anchor));
+ }.bind(null, i));
}
+}
+
+Promise.all([SystemJS.import('pdfjs/display/api'),
+ SystemJS.import('pdfjs/display/svg'),
+ SystemJS.import('pdfjs/display/global')])
+ .then(function (modules) {
+ var api = modules[0], svg = modules[1], global = modules[2];
+ // In production, change this to point to the built `pdf.worker.js` file.
+ global.PDFJS.workerSrc = '../../src/worker_loader.js';
+
+ // In production, change this to point to where the cMaps are placed.
+ global.PDFJS.cMapUrl = '../../external/bcmaps/';
+ global.PDFJS.cMapPacked = true;
+
+ // Fetch the PDF document from the URL using promises.
+ api.getDocument(url).then(function (doc) {
+ renderDocument(doc, svg);
+ });
});
diff --git a/examples/text-only/index.html b/examples/text-only/index.html
index 97a38bfa..df1d607d 100644
--- a/examples/text-only/index.html
+++ b/examples/text-only/index.html
@@ -1,6 +1,7 @@
+
Text-only PDF.js example
diff --git a/examples/text-only/pdf2svg.js b/examples/text-only/pdf2svg.js
index effaf2d5..c808db44 100644
--- a/examples/text-only/pdf2svg.js
+++ b/examples/text-only/pdf2svg.js
@@ -18,7 +18,7 @@ var PAGE_NUMBER = 1;
var PAGE_SCALE = 1.5;
var SVG_NS = 'http://www.w3.org/2000/svg';
-PDFJS.workerSrc = '../../build/pdf.worker.js';
+PDFJS.workerSrc = '../../build/generic/build/pdf.worker.js';
function buildSVG(viewport, textContent) {
// Building SVG with size of the viewport (for simplicity)
@@ -30,7 +30,7 @@ function buildSVG(viewport, textContent) {
// processing all items
textContent.items.forEach(function (textItem) {
- // we have to take in account viewport transform, which incudes scale,
+ // we have to take in account viewport transform, which includes scale,
// rotation and Y-axis flip, and not forgetting to flip text.
var tx = PDFJS.Util.transform(
PDFJS.Util.transform(viewport.transform, textItem.transform),
@@ -63,7 +63,7 @@ function pageLoaded() {
document.addEventListener('DOMContentLoaded', function () {
if (typeof PDFJS === 'undefined') {
alert('Built version of PDF.js was not found.\n' +
- 'Please run `node make generic`.');
+ 'Please run `gulp generic`.');
return;
}
pageLoaded();
diff --git a/examples/webpack/.gitignore b/examples/webpack/.gitignore
new file mode 100644
index 00000000..c2658d7d
--- /dev/null
+++ b/examples/webpack/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/examples/webpack/README.md b/examples/webpack/README.md
new file mode 100644
index 00000000..3a7ce9eb
--- /dev/null
+++ b/examples/webpack/README.md
@@ -0,0 +1,19 @@
+## Overview
+
+Example to demonstrate PDF.js library usage with Webpack.
+
+## Getting started
+
+Build project and install the example dependencies:
+
+ $ gulp dist
+ $ cd examples/webpack
+ $ npm install
+
+To build Webpack bundles, run `node_modules/.bin/webpack`. If you are running
+a web server, you can observe the build results at
+http://localhost:8888/examples/webpack/index.html
+
+See main.js and webpack.config.js files. Please notice that PDF.js
+packaging requires packaging of the main application and PDF.js worker code,
+and the `workerSrc` path shall be set to the latter file.
diff --git a/examples/webpack/index.html b/examples/webpack/index.html
new file mode 100644
index 00000000..ed25387f
--- /dev/null
+++ b/examples/webpack/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+ webpack example
+
+
+
+
+
+
diff --git a/examples/webpack/main.js b/examples/webpack/main.js
new file mode 100644
index 00000000..d0466b86
--- /dev/null
+++ b/examples/webpack/main.js
@@ -0,0 +1,35 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+// Hello world example for webpack.
+
+var pdfjsLib = require('pdfjs-dist');
+
+var pdfPath = '../helloworld/helloworld.pdf';
+
+// Setting worker path to worker bundle.
+pdfjsLib.PDFJS.workerSrc = '../../build/webpack/pdf.worker.bundle.js';
+
+// It is also possible to disable workers via `PDFJS.disableWorker = true`,
+// however that might degrade the UI performance in web browsers.
+
+// Loading a document.
+var loadingTask = pdfjsLib.getDocument(pdfPath);
+loadingTask.promise.then(function (pdfDocument) {
+ // Request a first page
+ return pdfDocument.getPage(1).then(function (pdfPage) {
+ // Display page on the existing canvas with 100% scale.
+ var viewport = pdfPage.getViewport(1.0);
+ var canvas = document.getElementById('theCanvas');
+ canvas.width = viewport.width;
+ canvas.height = viewport.height;
+ var ctx = canvas.getContext('2d');
+ var renderTask = pdfPage.render({
+ canvasContext: ctx,
+ viewport: viewport
+ });
+ return renderTask.promise;
+ });
+}).catch(function (reason) {
+ console.error('Error: ' + reason);
+});
diff --git a/examples/webpack/package.json b/examples/webpack/package.json
new file mode 100644
index 00000000..085fcd26
--- /dev/null
+++ b/examples/webpack/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "webpack-pdf.js-example",
+ "version": "0.1.0",
+ "devDependencies": {
+ "webpack": "~1.12.9",
+ "pdfjs-dist": "../../build/dist"
+ }
+}
diff --git a/examples/webpack/webpack.config.js b/examples/webpack/webpack.config.js
new file mode 100644
index 00000000..78ccf382
--- /dev/null
+++ b/examples/webpack/webpack.config.js
@@ -0,0 +1,23 @@
+var webpack = require('webpack');
+var path = require('path');
+
+module.exports = {
+ context: __dirname,
+ entry: {
+ 'main': './main.js',
+ 'pdf.worker': 'pdfjs-dist/build/pdf.worker.entry'
+ },
+ output: {
+ path: path.join(__dirname, '../../build/webpack'),
+ publicPath: '../../build/webpack/',
+ filename: '[name].bundle.js'
+ },
+ plugins: [
+ new webpack.optimize.UglifyJsPlugin({
+ compressor: {
+ screw_ie8: true,
+ warnings: false
+ }
+ })
+ ]
+};
diff --git a/extensions/b2g/images/div_line_left.png b/extensions/b2g/images/div_line_left.png
deleted file mode 100644
index db01f7b9..00000000
Binary files a/extensions/b2g/images/div_line_left.png and /dev/null differ
diff --git a/extensions/b2g/images/div_line_left@1.5x.png b/extensions/b2g/images/div_line_left@1.5x.png
deleted file mode 100644
index 07308a76..00000000
Binary files a/extensions/b2g/images/div_line_left@1.5x.png and /dev/null differ
diff --git a/extensions/b2g/images/div_line_left@2x.png b/extensions/b2g/images/div_line_left@2x.png
deleted file mode 100644
index 1747d886..00000000
Binary files a/extensions/b2g/images/div_line_left@2x.png and /dev/null differ
diff --git a/extensions/b2g/images/div_line_right.png b/extensions/b2g/images/div_line_right.png
deleted file mode 100644
index b917e423..00000000
Binary files a/extensions/b2g/images/div_line_right.png and /dev/null differ
diff --git a/extensions/b2g/images/div_line_right@1.5x.png b/extensions/b2g/images/div_line_right@1.5x.png
deleted file mode 100644
index d7ef1ca8..00000000
Binary files a/extensions/b2g/images/div_line_right@1.5x.png and /dev/null differ
diff --git a/extensions/b2g/images/div_line_right@2x.png b/extensions/b2g/images/div_line_right@2x.png
deleted file mode 100644
index e54b337e..00000000
Binary files a/extensions/b2g/images/div_line_right@2x.png and /dev/null differ
diff --git a/extensions/b2g/images/document_bg.png b/extensions/b2g/images/document_bg.png
deleted file mode 100644
index 2435f1c3..00000000
Binary files a/extensions/b2g/images/document_bg.png and /dev/null differ
diff --git a/extensions/b2g/images/icon_next_page.png b/extensions/b2g/images/icon_next_page.png
deleted file mode 100644
index d937c137..00000000
Binary files a/extensions/b2g/images/icon_next_page.png and /dev/null differ
diff --git a/extensions/b2g/images/icon_next_page@1.5x.png b/extensions/b2g/images/icon_next_page@1.5x.png
deleted file mode 100644
index 61119dff..00000000
Binary files a/extensions/b2g/images/icon_next_page@1.5x.png and /dev/null differ
diff --git a/extensions/b2g/images/icon_previous_page.png b/extensions/b2g/images/icon_previous_page.png
deleted file mode 100644
index cfbf730e..00000000
Binary files a/extensions/b2g/images/icon_previous_page.png and /dev/null differ
diff --git a/extensions/b2g/images/icon_previous_page@1.5x.png b/extensions/b2g/images/icon_previous_page@1.5x.png
deleted file mode 100644
index 110232b4..00000000
Binary files a/extensions/b2g/images/icon_previous_page@1.5x.png and /dev/null differ
diff --git a/extensions/b2g/images/icon_zoom_in@1.5x.png b/extensions/b2g/images/icon_zoom_in@1.5x.png
deleted file mode 100644
index 96e461ba..00000000
Binary files a/extensions/b2g/images/icon_zoom_in@1.5x.png and /dev/null differ
diff --git a/extensions/b2g/images/icon_zoom_out@1.5x.png b/extensions/b2g/images/icon_zoom_out@1.5x.png
deleted file mode 100644
index 93ef2dd5..00000000
Binary files a/extensions/b2g/images/icon_zoom_out@1.5x.png and /dev/null differ
diff --git a/extensions/b2g/images/spinner.png b/extensions/b2g/images/spinner.png
deleted file mode 100644
index b68e0fdb..00000000
Binary files a/extensions/b2g/images/spinner.png and /dev/null differ
diff --git a/extensions/b2g/images/toolbar_background.png b/extensions/b2g/images/toolbar_background.png
deleted file mode 100644
index 0af2b38d..00000000
Binary files a/extensions/b2g/images/toolbar_background.png and /dev/null differ
diff --git a/extensions/b2g/viewer.html b/extensions/b2g/viewer.html
deleted file mode 100644
index 7baa1f7f..00000000
--- a/extensions/b2g/viewer.html
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
-
- PDF.js viewer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- More Information
-
-
- Less Information
-
-
-
-
- Close
-
-
-
-
-
-
-
diff --git a/extensions/chromium/chrome.tabs.executeScriptInFrame.js b/extensions/chromium/chrome.tabs.executeScriptInFrame.js
deleted file mode 100644
index c36c951c..00000000
--- a/extensions/chromium/chrome.tabs.executeScriptInFrame.js
+++ /dev/null
@@ -1,283 +0,0 @@
-/**
- * (c) 2013 Rob Wu
- * Released under the MIT license
- * https://github.com/Rob--W/chrome-api/chrome.tabs.executeScriptInFrame
- *
- * Implements the chrome.tabs.executeScriptInFrame API.
- * This API is similar to the chrome.tabs.executeScript method, except
- * that it also recognizes the "frameId" property.
- * This frameId can be obtained through the webNavigation or webRequest API.
- *
- * When an error occurs, chrome.runtime.lastError is set.
- *
- * Required permissions:
- * webRequest
- * webRequestBlocking
- * Host permissions for the tab
- *
- * In addition, the following field must also be set in manifest.json:
- * "web_accessible_resources": ["getFrameId"]
- */
-/* globals chrome, console */
-
-(function() {
- /* jshint browser:true, maxlen:100 */
- 'use strict';
-
- chrome.tabs.executeScriptInFrame = executeScript;
-
- // This URL is used to communicate the frameId. The resource is never
- // visited, so it should be a non-existent location. Do not use *, ", '
- // or line breaks in the file name.
- var URL_WHAT_IS_MY_FRAME_ID = chrome.extension.getURL('getFrameId');
- // The callback will be called within ... ms:
- // Don't set a too low value.
- var MAXIMUM_RESPONSE_TIME_MS = 1000;
-
- // Callbacks are stored here until they're invoked.
- // Key = dummyUrl, value = callback function
- var callbacks = {};
-
- chrome.webRequest.onBeforeRequest.addListener(function showFrameId(details) {
- // Positive integer frameId >= 0
- // Since an image is used as a data transport, we add 1 to get a
- // non-zero width.
- var frameId = details.frameId + 1;
- // Assume that the frameId fits in three bytes - which is a very
- // reasonable assumption.
- var width = String.fromCharCode(frameId & 0xFF, (frameId >> 8) & 0xFF);
- // When frameId > 0xFFFF, use the height to convey the additional
- // information. Again, add 1 to make sure that the height is non-zero.
- var height = String.fromCharCode((frameId >> 16) + 1, 0);
- // Convert data to base64 to avoid loss of bytes
- var image = 'data:image/gif;base64,' + btoa(
- // 4749 4638 3961 (GIF header)
- 'GIF89a' +
- // Logical Screen Width (LSB)
- width +
- // Logical Screen Height (LSB)
- height +
- // "No Global Color Table follows"
- '\x00' +
- // Background color
- '\xff' +
- // No aspect information is given
- '\x00' +
- // (image descriptor)
- // Image Separator
- '\x2c' +
- // Image Position (Left & Top)
- '\x00\x00\x00\x00' +
- // Image Width (LSB)
- width +
- // Image Height (LSB)
- height +
- // Local Color Table is not present
- '\x00' +
- // (End of image descriptor)
- // Image data
- '\x02\x02\x44\x01\x00' +
- // GIF trailer
- '\x3b'
- );
- return {redirectUrl: image};
- }, {
- urls: [URL_WHAT_IS_MY_FRAME_ID + '*'],
- types: ['image']
- }, ['blocking']);
-
- chrome.runtime.onMessage.addListener(function(message, sender,
- sendResponse) {
- if (message && message.executeScriptCallback) {
- var callback = callbacks[message.identifier];
- if (callback) {
- if (message.hello) {
- clearTimeout(callback.timer);
- return;
- }
- delete callbacks[message.identifier];
- // Result within an array to be consistent with the
- // chrome.tabs.executeScript API.
- callback([message.evalResult]);
- } else {
- console.warn('Callback not found for response in tab ' +
- sender.tab.id);
- }
- }
- });
-
- /**
- * Execute content script in a specific frame.
- *
- * @param tabId {integer} required
- * @param details.frameId {integer} required
- * @param details.code {string} Code or file is required (not both)
- * @param details.file {string} Code or file is required (not both)
- * @param details.runAt {optional string} One of "document_start",
- * "document_end", "document_idle"
- * @param callback {optional function(optional result array)} When an error
- * occurs, result
- * is not set.
- */
- function executeScript(tabId, details, callback) {
- console.assert(typeof details === 'object',
- 'details must be an object (argument 0)');
- var frameId = details.frameId;
- console.assert(typeof tabId === 'number',
- 'details.tabId must be a number');
- console.assert(typeof frameId === 'number',
- 'details.frameId must be a number');
- var sourceType = ('code' in details ? 'code' : 'file');
- console.assert(sourceType in details, 'No source code or file specified');
- var sourceValue = details[sourceType];
- console.assert(typeof sourceValue === 'string',
- 'details.' + sourceType + ' must be a string');
- var runAt = details.runAt;
- if (!callback) {
- callback = function() {/* no-op*/};
- }
- console.assert(typeof callback === 'function',
- 'callback must be a function');
-
- if (frameId === 0) {
- // No need for heavy lifting if we want to inject the script
- // in the main frame
- var injectDetails = {
- allFrames: false,
- runAt: runAt
- };
- injectDetails[sourceType] = sourceValue;
- chrome.tabs.executeScript(tabId, injectDetails, callback);
- return;
- }
-
- var identifier = Math.random().toString(36);
-
- if (sourceType === 'code') {
- executeScriptInFrame();
- } else { // sourceType === 'file'
- (function() {
- var x = new XMLHttpRequest();
- x.open('GET', chrome.extension.getURL(sourceValue), true);
- x.onload = function() {
- sourceValue = x.responseText;
- executeScriptInFrame();
- };
- x.onerror = function executeScriptResourceFetchError() {
- var message = 'Failed to load file: "' + sourceValue + '".';
- console.error('executeScript: ' + message);
- chrome.runtime.lastError = chrome.extension.lastError =
- { message: message };
- try {
- callback();
- } finally {
- chrome.runtime.lastError = chrome.extension.lastError = undefined;
- }
- };
- x.send();
- })();
- }
-
- function executeScriptInFrame() {
- callbacks[identifier] = callback;
- chrome.tabs.executeScript(tabId, {
- code: '(' + DETECT_FRAME + ')(' +
- 'window,' +
- JSON.stringify(identifier) + ',' +
- frameId + ',' +
- JSON.stringify(sourceValue) + ')',
- allFrames: true,
- runAt: 'document_start'
- }, function(results) {
- if (results) {
- callback.timer = setTimeout(executeScriptTimedOut,
- MAXIMUM_RESPONSE_TIME_MS);
- } else {
- // Failed :(
- delete callbacks[identifier];
- callback();
- }
- });
- }
-
- function executeScriptTimedOut() {
- var callback = callbacks[identifier];
- if (!callback) {
- return;
- }
- delete callbacks[identifier];
- var message = 'Failed to execute script: Frame ' + frameId +
- ' not found in tab ' + tabId;
- console.error('executeScript: ' + message);
- chrome.runtime.lastError = chrome.extension.lastError =
- { message: message };
- try {
- callback();
- } finally {
- chrome.runtime.lastError = chrome.extension.lastError = undefined;
- }
- }
- }
-
- /**
- * Code executed as a content script.
- */
- var DETECT_FRAME = '' + function checkFrame(window, identifier, frameId,
- code) {
- var i;
- if ('__executeScript_frameId__' in window) {
- evalAsContentScript();
- } else {
- // Do NOT use new Image() because of http://crbug.com/245296
- // in Chrome 27-29
- i = window.document.createElement('img');
- i.onload = function() {
- window.__executeScript_frameId__ = (this.naturalWidth - 1) +
- (this.naturalHeight - 1 << 16);
- evalAsContentScript();
- };
- // Trigger webRequest event to get frameId
- // (append extra characters to bust the cache)
- i.src = 'URL_WHAT_IS_MY_FRAME_ID?' +
- Math.random().toString(36).slice(-6);
- }
-
- for (i = 0 ; i < window.frames.length; ++i) {
- try {
- var frame = window.frames[i];
- var scheme = frame.location.protocol;
- if (scheme !== 'https:' && scheme !== 'http:' && scheme !== 'file:') {
- checkFrame(frame, identifier, frameId, code);
- }
- } catch (e) {
- // blocked by same origin policy, so it's not a javascript:/about:blank
- // URL. chrome.tabs.executeScript will run the script for the frame.
- }
- }
-
- function evalAsContentScript() {
- if (window.__executeScript_frameId__ !== frameId) {
- return;
- }
- // Send an early message to make sure that any blocking code
- // in the evaluated code does not cause the time-out in the background
- // page to be triggered
- chrome.runtime.sendMessage({
- executeScriptCallback: true,
- hello: true,
- identifier: identifier
- });
- var result = null;
- try {
- // jshint evil:true
- result = window.eval(code);
- } finally {
- chrome.runtime.sendMessage({
- executeScriptCallback: true,
- evalResult: result,
- identifier: identifier
- });
- }
- }
- }.toString().replace('URL_WHAT_IS_MY_FRAME_ID', URL_WHAT_IS_MY_FRAME_ID);
-})();
diff --git a/extensions/chromium/contentscript.js b/extensions/chromium/contentscript.js
index c78cf4ad..18675091 100644
--- a/extensions/chromium/contentscript.js
+++ b/extensions/chromium/contentscript.js
@@ -23,31 +23,10 @@ function getViewerURL(pdf_url) {
return VIEWER_URL + '?file=' + encodeURIComponent(pdf_url);
}
-// (un)prefixed property names
-var createShadowRoot, shadowRoot;
-if (typeof Element.prototype.createShadowRoot !== 'undefined') {
- // Chrome 35+
- createShadowRoot = 'createShadowRoot';
- shadowRoot = 'shadowRoot';
-} else if (typeof Element.prototype.webkitCreateShadowRoot !== 'undefined') {
- // Chrome 25 - 34
- createShadowRoot = 'webkitCreateShadowRoot';
- shadowRoot = 'webkitShadowRoot';
- try {
- document.createElement('embed').webkitCreateShadowRoot();
- } catch (e) {
- // Only supported since Chrome 33.
- createShadowRoot = shadowRoot = '';
- }
-}
-
-// Only observe the document if we can make use of Shadow DOM.
-if (createShadowRoot) {
- if (CSS.supports('animation', '0s')) {
- document.addEventListener('animationstart', onAnimationStart, true);
- } else {
- document.addEventListener('webkitAnimationStart', onAnimationStart, true);
- }
+if (CSS.supports('animation', '0s')) {
+ document.addEventListener('animationstart', onAnimationStart, true);
+} else {
+ document.addEventListener('webkitAnimationStart', onAnimationStart, true);
}
function onAnimationStart(event) {
@@ -57,10 +36,9 @@ function onAnimationStart(event) {
}
// Called for every or element in the page.
-// It does not trigger any Mutation observers, but it may modify the
-// shadow DOM rooted under the given element.
-// Calling this function multiple times for the same element is safe, i.e.
-// it has no side effects.
+// This may change the type, src/data attributes and/or the child nodes of the
+// element. This function only affects elements for the first call. Subsequent
+// invocations have no effect.
function watchObjectOrEmbed(elem) {
var mimeType = elem.type;
if (mimeType && 'application/pdf' !== mimeType.toLowerCase()) {
@@ -86,33 +64,35 @@ function watchObjectOrEmbed(elem) {
return;
}
- if (elem[shadowRoot]) {
- // If the element already has a shadow root, assume that we've already
- // seen this element.
+ if (elem.__I_saw_this_element) {
return;
}
- elem[createShadowRoot]();
+ elem.__I_saw_this_element = true;
+
+ var tagName = elem.tagName.toUpperCase();
+ var updateEmbedOrObject;
+ if (tagName === 'EMBED') {
+ updateEmbedOrObject = updateEmbedElement;
+ } else if (tagName === 'OBJECT') {
+ updateEmbedOrObject = updateObjectElement;
+ } else {
+ return;
+ }
+
+ var lastSrc;
+ var isUpdating = false;
function updateViewerFrame() {
- var path = elem[srcAttribute];
- if (!path) {
- elem[shadowRoot].textContent = '';
- } else {
- elem[shadowRoot].innerHTML =
- // Set display: inline-block; to the host element (/) to
- // ensure that the dimensions defined on the host element are applied to
- // the iframe (http://crbug.com/358648).
- // The styles are declared in the shadow DOM to allow page authors to
- // override these styles (e.g. .style.display = 'none';).
- '' +
- '';
- elem[shadowRoot].lastChild.src = getEmbeddedViewerURL(path);
+ if (!isUpdating) {
+ isUpdating = true;
+ try {
+ if (lastSrc !== elem[srcAttribute]) {
+ updateEmbedOrObject(elem);
+ lastSrc = elem[srcAttribute];
+ }
+ } finally {
+ isUpdating = false;
+ }
}
}
@@ -128,6 +108,97 @@ function watchObjectOrEmbed(elem) {
});
}
+// Display the PDF Viewer in an .
+function updateEmbedElement(elem) {
+ if (elem.type === 'text/html' && elem.src.lastIndexOf(VIEWER_URL, 0) === 0) {
+ // The viewer is already shown.
+ return;
+ }
+ // The tag needs to be removed and re-inserted before any src changes
+ // are effective.
+ var parentNode = elem.parentNode;
+ var nextSibling = elem.nextSibling;
+ if (parentNode) {
+ parentNode.removeChild(elem);
+ }
+ elem.type = 'text/html';
+ elem.src = getEmbeddedViewerURL(elem.src);
+ if (parentNode) {
+ parentNode.insertBefore(elem, nextSibling);
+ }
+}
+
+// Display the PDF Viewer in an .
+function updateObjectElement(elem) {
+ // elements are terrible. Experiments (in49.0.2623.75) show that the
+ // following happens:
+ // - When fallback content is shown (e.g. because the built-in PDF Viewer is
+ // disabled), updating the "data" attribute has no effect. Not surprising
+ // considering that HTMLObjectElement::m_useFallbackContent is not reset
+ // once it is set to true. Source:
+ // WebKit/Source/core/html/HTMLObjectElement.cpp#378 (rev 749fe30d676b6c14).
+ // - When the built-in PDF Viewer plugin is enabled, updating the "data"
+ // attribute reloads the content (provided that the type was correctly set).
+ // - When is used
+ // (tested with a data-URL, data:text/html,, the extension's
+ // origin whitelist is not set up, so the viewer can't load the PDF file.
+ // - The content of the tag may be affected by tags.
+ //
+ // To make sure that our solution works for all cases, we will insert a frame
+ // as fallback content and force the tag to render its fallback
+ // content.
+ var iframe = elem.firstElementChild;
+ if (!iframe || !iframe.__inserted_by_pdfjs) {
+ iframe = createFullSizeIframe();
+ elem.textContent = '';
+ elem.appendChild(iframe);
+ iframe.__inserted_by_pdfjs = true;
+ }
+ iframe.src = getEmbeddedViewerURL(elem.data);
+
+ // Some bogus content type that is not handled by any plugin.
+ elem.type = 'application/not-a-pee-dee-eff-type';
+ // Force the to reload and render its fallback content.
+ elem.data += '';
+
+ // Usually the browser renders plugin content in this tag, which is completely
+ // oblivious of styles such as padding, but we insert and render child nodes,
+ // so force padding to be zero to avoid undesired dimension changes.
+ elem.style.padding = '0';
+
+ // and elements have a "display:inline" style by default.
+ // Despite this property, when a plugin is loaded in the tag, the tag is
+ // treated like "display:inline-block". However, when the browser does not
+ // render plugin content, the tag does not behave like that, and as
+ // a result the width and height is ignored.
+ // Force "display:inline-block" to make sure that the width/height as set by
+ // web pages is respected.
+ // ( behaves as expected with the default display value, but setting it
+ // to display:inline-block doesn't hurt).
+ elem.style.display = 'inline-block';
+}
+
+// Create an