Interactive forms: rewrite AcroForms example
This patch lets the AcroForms example make use of the built-in interactive forms functionality in PDF.js. This makes the example: - much easier to understand; - more feature-complete; - in sync with the core when new functionality is added; - similar to the other examples in terms of structure.
This commit is contained in:
parent
8d684b5b3f
commit
63fa26843b
11
examples/acroforms/README.md
Normal file
11
examples/acroforms/README.md
Normal file
@ -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.
|
44
examples/acroforms/acroforms.html
Normal file
44
examples/acroforms/acroforms.html
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<html dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<title>AcroForms example</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../../build/dist/web/pdf_viewer.css">
|
||||||
|
|
||||||
|
<script src="../../build/dist/build/pdf.js"></script>
|
||||||
|
<script src="../../build/dist/web/pdf_viewer.js"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.page {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="pageContainer"></div>
|
||||||
|
|
||||||
|
<script src="acroforms.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
49
examples/acroforms/acroforms.js
Normal file
49
examples/acroforms/acroforms.js
Normal file
@ -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));
|
||||||
|
}
|
||||||
|
});
|
@ -1,160 +0,0 @@
|
|||||||
|
|
||||||
//
|
|
||||||
// Basic AcroForms input controls rendering
|
|
||||||
//
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// Specify the PDF with AcroForm here
|
|
||||||
var pdfWithFormsPath = '../../test/pdfs/f1040.pdf';
|
|
||||||
|
|
||||||
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.fieldName;
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// In production, the bundled pdf.js shall be used instead of RequireJS.
|
|
||||||
require.config({paths: {'pdfjs': '../../src'}});
|
|
||||||
require(['pdfjs/display/api', 'pdfjs/display/global'], function (api, global) {
|
|
||||||
// In production, change this to point to the built `pdf.worker.js` file.
|
|
||||||
global.PDFJS.workerSrc = '../../src/worker_loader.js';
|
|
||||||
|
|
||||||
// Fetch the PDF document from the URL using promises.
|
|
||||||
api.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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,23 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<script src="../../node_modules/requirejs/require.js"></script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.pdfpage { position:relative; top: 0; left: 0; border: solid 1px black; margin: 10px; }
|
|
||||||
.pdfpage > canvas { position: absolute; top: 0; left: 0; }
|
|
||||||
.pdfpage > div { position: absolute; top: 0; left: 0; }
|
|
||||||
.inputControl { background: transparent; border: 0px none; position: absolute; margin: auto; }
|
|
||||||
.inputControl[type='checkbox'] { margin: 0px; }
|
|
||||||
.inputHint { opacity: 0.2; background: #ccc; position: absolute; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script src="forms.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="viewer"></div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
Loading…
x
Reference in New Issue
Block a user