paint-brush
A Guide to Creating Custom Form Fields Using the Foxit PDF SDK for Webby@foxitsoftware
4,075 reads
4,075 reads

A Guide to Creating Custom Form Fields Using the Foxit PDF SDK for Web

by Foxit SoftwareNovember 17th, 2023
Read on Terminal Reader
Read this story w/o Javascript

Too Long; Didn't Read

This tutorial will teach you how to create custom form fields in your web browser PDF docs using Foxit PDF Library for Web.
featured image - A Guide to Creating Custom Form Fields Using the Foxit PDF SDK for Web
Foxit Software HackerNoon profile picture

The PDF format has become indispensable in modern software, serving as a versatile solution for diverse document types. For businesses seeking secure, editable, and user-friendly PDFs, Foxit emerges as a valuable choice. Foxit’s PDF SDK libraries boast a rich array of features catering to various industries.


Web browser-based PDFs, in particular, find myriad applications in document management. They play a pivotal role in numerous banking systems, facilitating tasks such as generating monthly statements. Additionally, the compliance industry relies on web-based PDFs for secure data collection and storage.


This tutorial guides you through leveraging the Foxit PDF SDK for Web to craft customized form fields within your web browser PDF documents. The accompanying GitHub repository allows you to follow along and implement the steps outlined in the tutorial.


What is Foxit PDF SDK for Web?

The Foxit PDF SDK for Web, among the diverse PDF SDKs offered by Foxit, stands out as an all-encompassing PDF library that leverages the advantages of Foxit’s rendering engine. This SDK empowers you to seamlessly integrate a comprehensive and fully customizable PDF viewer into your applications.


Web PDFs crafted with Foxit’s SDK enable users to effortlessly view, fill out, annotate, and sign documents in various languages directly from their mobile or desktop browsers using JavaScript. The SDK is compatible with all major browsers, including Firefox, Safari, Chrome, and Opera.


To illustrate the functionality, you will embark on creating a new PDF project from a template, employing the Foxit PDF SDK for Web to provide the necessary structure. This hands-on approach will offer a practical demonstration of how the SDK enhances PDF capabilities within your web-based projects.


Implementing Foxit PDF SDK for Web

Download Foxit PDF SDK for Web. The ZIP file should contain the SDK, documentation and examples.


You can preview these examples by running an HTTP server from the unzipped directory.


# NPX available with NPM v5.2 or newer
npx http-server


Setup the Project

This tutorial uses Vite for frontend tooling. It’s based on ES modules (ESM), fast, and comes with everything you need to use the SDK out of the box. To create a new project from a template and start the development server, make sure you’ve got Node.js version 12.2.0 or newer and run the following commands:


npm create vite@latest project -- --template vanilla
cd project
npm install
npm run dev


Move the SDK into the created directory. For the rest of this tutorial, the SDK is assumed to be available at ./FoxitPDFSDKForWeb, relative to the parent project directory.


Loading the PDF

You will need a PDF viewer with a document uploaded to begin experimenting. To initialize the PDF viewer, first create the HTML structure and load the SDK.


<!-- index.html -->
<!-- ... -->
<body>
<div class="container">
<div id="viewer"></div>
<div id="menu"></div>
</div>
<script src="./FoxitPDFSDKForWeb/lib/PDFViewCtrl.full.js"></script>
<script type="module" src="/main.js"></script>
</body>
<!-- ... -->


Additionally, instyle.css, add some CSS to style the elements:


/* style.css */
html {
height: 100%;
}b
ody {
height: 100%;
margin: 0;
}.
container {
width: 100%;
height: 100%;
display: flex;
}#
viewer {
height: 100%;
flex: 1;
overflow: auto;
}#
menu {
width: 10rem;
}.
menu-element {
background: #f1f5f9;
padding: 1rem;
display: flex;
justify-content: center;
align-items: center;font-family: monospace;
margin: 0.5rem;
}


Inside main.js, use the SDK to create an instance of the pdfViewer:


import "./style.css";
const licenseSN = "...";
const licenseKey = "...";
const viewerContainer = document.getElementById("viewer");
const pdfViewer = new PDFViewCtrl.PDFViewer({
libPath: "./FoxitPDFSDKForWeb/lib",
jr: {
licenseSN,
licenseKey,
},
customs: {
ScrollWrap: PDFViewCtrl.CustomScrollWrap.create(viewerContainer),
},
});


You can find your values for licenseSN and licenseKey inside the ./FoxitPDFSDKForWeb/examples/license-key.js file.

The pdfViewer is created by providing the constructor with a configuration object containing:


  • libPath: The relative path to the lib folder of the unzipped SDK package

  • jr: Config options for the JR engine that include, most importantly, licensing information

  • customs.ScrollWrap: A custom component that controls PDF sizing and scrolling, where setting it adjusts the viewer to the container


With pdfViewer created, all you have to do is initialize it and load the document:


// ...
const loadPDF = async (url) => {
const response = await fetch(url);
const blob = await response.blob();return pdfViewer.openPDFByFile(blob);
};
pdfViewer.init(viewerContainer);
loadPDF("./FoxitPDFSDKForWeb/docs/FoxitPDFSDKforWeb_DemoGuide.pdf");


The above snippet fetches the PDF file as a blob and opens it in the viewer using its openPDFByFile() method. The PDF document used is a demo guide from the SDK’s included documentation.


Included documentation


The additional space on the right will serve as a menu for draggable form fields.

Creating Custom Form Fields

All you need to create a form field with the Foxit SDK is a viewer, the form field’s metadata (such as field type or select options), and the form field position. For this example, you’ll create a set of predefined form fields with ready metadata that the user can drag and drop into the viewer.


Defining Metadata

Start by defining the metadata for allowed fields, as well as additional helpers:

// ...
const menuContainer = document.getElementById("menu");
const randomId = () => `_${Math.random().toString(36).substring(2, 9)}`;
const FieldTypes = PDFViewCtrl.PDF.form.constant.Field_Type;
const formFields = [
{
label: "Push Button",
name: "push-button",
type: FieldTypes.PushButton,
width: 50,
height: 30,
},
{
label: "Checkbox",
name: "checkbox",
type: FieldTypes.CheckBox,
width: 50,height: 30,
},
{
label: "Radio Button",
name: "radio-button",
type: FieldTypes.RadioButton,
width: 80,
height: 30,
},
{
label: "Combo Box",
name: "combo-box",
type: FieldTypes.ComboBox,
width: 60,
height: 30,
},
{
label: "List Box",
name: "list-box",
type: FieldTypes.ListBox,
width: 60,
height: 100,
},
{
label: "Text",
name: "text",
type: FieldTypes.Text,
width: 60,
height: 30,
},
];
const comboBoxOptions = [
{ label: "10", value: "10", selected: true, defaultSelected: true },
{ label: "20", value: "20", selected: false, defaultSelected: false },
{ label: "30", value: "30", selected: false, defaultSelected: false },
{ label: "40", value: "40", selected: false, defaultSelected: false },
];
const listBoxOptions = comboBoxOptions;


The randomId() function will generate IDs to identify form fields within the document. FieldTypes is a shortcut for faster reference of predefined field types available in the SDK. Each form field entry contains:


  • A label to inform the user about its use
  • A name for matching dragged elements to the metadata entries
  • A type to indicate the field’s type
  • A width and height for calculating the position rectangle within the PDF

Lastly, comboBoxOptions and listBoxOptions contain sample options for fields that require users to select one.

Creating Drag and Drop Elements

With the metadata ready, you can create a function for handling the logic of drag and drop, as well as the form field placement:


// ...
const loadFormFieldsMenu = async (PDFDoc) => {
const PDFForm = await PDFDoc.loadPDFForm();
formFields.forEach((formField) => {
const element = document.createElement("div");
element.draggable = true;
element.id = formField.name;
element.classList.add("menu-element");
element.textContent = formField.label;
element.addEventListener("dragstart", (event) => {
event.dataTransfer.setData("text/plain", event.target.id);
});
menuContainer.append(element);
});
};


The function accepts PDFDoc—an SDK object representing a PDF document—as an argument. It’s used to retrieve a PDFForm object, which will be used to add and configure the form fields, after those fields are processed into draggable elements and added to the side menu.


Each element has a draggable attribute set to true to allow for dragging, as well as an id corresponding to each form field’s unique name to match them with the underlying metadata. This id is later used inside the dragstart event listener to transfer it during the drag and drop action.


To get the PDFDoc parameter required for the loadFormFieldsMenu() function, you’ll have to get the resulting promise of the loadPDF() function by modifying it as below:


// ...
loadPDF("./FoxitPDFSDKForWeb/docs/FoxitPDFSDKforWeb_DemoGuide.pdf").then(
(PDFDoc) => {
loadFormFieldsMenu(PDFDoc);
}
);


With the menu items created, the app now looks like this:


App preview


Implementing Drag & Drop Functionality

Having created the draggable elements, it’s time to fully implement the drag and drop functionality and allow for creating form fields in the viewer:


// ...
const loadFormFieldsMenu = async (PDFDoc) => {
// ...
viewerContainer.addEventListener("dragover", (event) => {
event.preventDefault();
});
viewerContainer.addEventListener("drop", async (event) => {
event.preventDefault();
const droppedFormFieldName = event.dataTransfer.getData("text/plain");
const formField = formFields.find(
({ name }) => name === droppedFormFieldName
);
const pos = await pdfViewer.convertClientCoordToPDFCoord({
clientX: event.clientX,
clientY: event.clientY,
});
const id = randomId();await PDFForm.addControl(pos.index, id, formField.type, {
left: pos.left - formField.width / 2,
right: pos.left + formField.width / 2,
top: pos.top + formField.height / 2,
bottom: pos.top - formField.height / 2,
});
const field = PDFForm.getField(id);
if (formField.type === FieldTypes.ComboBox) {
field.setOptions(comboBoxOptions);
} else if (formField.type === FieldTypes.ListBox) {
field.setOptions(listBoxOptions);
}
});
};
// ...


In the above code, thedragover event listener forwards the interaction to be handled in the drop event by calling preventDefault().


Inside the drop event handler, the matching metadata is first retrieved using the dragged element’s data. Then, the mouse position from the event is transformed into PDF coordinates using the convertClientCoordToPDFCoord() method available on the pdfViewer instance.


The position, metadata, and randomly generated ID are used in the addControl() method call from the PDFForm object created earlier in the function. The method accepts the following arguments:


  • The index of the page to place the form field at (retrieved from convertClientCoordToPDFCoord() call)
  • The randomly generated ID for the newly created form field
  • The type of the form field according to provided constants (retrieved from metadata)
  • The argument that defines the placement for the form field in the form of a rectangle, calculated using width and height to make the mouse coordinates the form field’s center


Finally, in case the field accepts a list of options, it’s first accessed by the getField() method of the PDFForm object using the ID. The options are set accordingly using the setOptions() method.

The final app, with a few form fields already placed, looks like this:


Final app


Conclusion

Adding functionality to your PDFs can indeed bring significant benefits to your organization and users. Electronic updates and signatures save time, money, and effort, while customized and secure documents enhance trust in your company.


As demonstrated earlier, Foxit’s multilingual PDF tool, coupled with the Foxit PDF SDK for Web, provides a robust solution. You can create custom form fields, implement drag-and-drop functionality, and unlock a range of capabilities. However, this is just the tip of the iceberg. The Foxit PDF SDK for Web offers a comprehensive set of features for further enhancing your PDF functionality.


To delve deeper into the possibilities, refer to the official documentation and additional resources provided by the SDK. The documentation will guide you through advanced features, customization options, and best practices.


If you want to review the tutorial or check your work, you can refer to the GitHub repository associated with the tutorial. The repository likely contains the source code, examples, and additional materials to help you understand and implement the concepts covered in the tutorial.


Also published here.