Creating form fields like annotations

162 views
Skip to first unread message

André Rieussec

unread,
Apr 2, 2018, 1:34:15 PM4/2/18
to PDFTron WebViewer
Hi,

I'm currently evaluating PDFNet for a client. I need to allow users to dynamically add form fields to a PDF document by "drawing" them, just like annotations can be drawn.

I've been able to create form fields and save the updated PDF by following the documentation. But I don't know how to place the fields with the mouse.

I've also followed the doc on how to create a triangle annotation. But I'm not sure how to use that to create a field.

Is there an example somewhere of how I can put the two together?

Thanks!

Matt Parizeau

unread,
Apr 3, 2018, 4:25:08 PM4/3/18
to PDFTron WebViewer

To summarize you may want to take the approach of extending from the RectangleCreateTool and then on mouse up (i.e. user is finished dragging) you could delete the rectangle annotation that was created by the tool and add a TextWidgetAnnotation at the same location. If you get stuck on this just post some of the code that you've been working on and we could help you get it working.

Matt Parizeau
Software Developer
PDFTron Systems Inc.

André Rieussec

unread,
Apr 5, 2018, 12:51:48 PM4/5/18
to PDFTron WebViewer
Thanks for the help. I've got the CreateTool going with the mouse events, but I don't think the mouse coordinates in the event are what I can use to place the field on the page... either that or I'm missing something else in my code. Here's the TypeScript code I have, maybe you can suggest something?

let startPoint: Point;

export const FormFieldCreateTool = function(docViewer: any) {
Tools.RectangleCreateTool.apply(this, arguments);
// Tools.RectangleCreateTool.call(this, docViewer, FormFieldAnnotation);
} as any as { new(docViewer: any): any; };

FormFieldCreateTool.prototype = $.extend(new Tools.RectangleCreateTool(), {

mouseLeftDown: function(e: any) {
startPoint = {
x: e.originalEvent.layerX,
y: e.originalEvent.layerY
};
console.log('mouse left down', arguments);

Tools.RectangleCreateTool.prototype.mouseLeftDown.apply(this, arguments);
},

mouseLeftUp: async function(e: any) {
console.log('mouse left up', arguments);

const docViewer = this.getDocumentViewer();
const pageNumber = docViewer.getCurrentPage();
const doc = docViewer.getDocument();
const pdfDoc = await doc.getPDFDoc();
pdfDoc.initSecurityHandler();
pdfDoc.lock();
const field = await pdfDoc.fieldCreateFromStrings('bar', FieldType.e_text, 'Bar', '');
console.log('field', field);
const annot = await PDFNet.WidgetAnnot.create(
pdfDoc,
await PDFNet.Rect.init(startPoint.x, startPoint.y, e.originalEvent.layerX, e.originalEvent.layerY),
field
);
const page = await pdfDoc.getPage(pageNumber);
console.log(page);
page.annotPushBack(annot);
pdfDoc.refreshFieldAppearances();

Tools.RectangleCreateTool.prototype.mouseLeftUp.apply(this, arguments);
}
});

Matt Parizeau

unread,
Apr 5, 2018, 5:47:09 PM4/5/18
to PDFTron WebViewer
Instead of looking at the mouse coordinates yourself you could look at the X and Y values of the rectangle annotation that the tool creates. These coordinates will already be in viewer page coordinates and then you'll need to convert them to PDF page coordinates since it looks like you're using the PDFNetJS full version APIs.

For example in your mouseLeftUp:
var doc = docViewer.getDocument();
var pageIndex = this.annotation.PageNumber - 1;

var startPoint = doc.getPDFCoordinates(pageIndex, this.annotation.X, this.annotation.Y);
var endPoint = doc.getPDFCoordinates(pageIndex, this.annotation.X + this.annotation.Width, this.annotation.Y + this.annotation.Height);

Let me know if that gets you on the right track or if you have any other questions.

Matt Parizeau
Software Developer
PDFTron Systems Inc.

André Rieussec

unread,
Apr 10, 2018, 1:19:57 PM4/10/18
to PDFTron WebViewer
Thanks for the help Matt! I was able to create a TextWidgetAnnotation and then upon saving the document I create a PDF field. Now I'm wondering how I could show the resize handles around the TextWidgetAnnotation. Is there a way to do that?

Here is my mouseLeftUp so far:

mouseLeftUp: async function(e: any) {
const pageNumber = this.annotation.PageNumber;
const annotManager = readerControl.docViewer.getAnnotationManager();
const fieldManager = annotManager.getFieldManager();

const field = new Annotations.Forms.Field('myfield', {
type: 'Tx'
});
const inputAnnot = new Annotations.TextWidgetAnnotation(field, {
backgroundColor: new Annotations.Color(255, 255, 255)
});
inputAnnot.PageNumber = pageNumber;
inputAnnot.X = this.annotation.X;
inputAnnot.Y = this.annotation.Y;
inputAnnot.Width = this.annotation.Width;
inputAnnot.Height = this.annotation.Height;

annotManager.addAnnotation(inputAnnot);
fieldManager.addField(field);
annotManager.drawAnnotations(pageNumber, null, true);

fieldAnnots.push(inputAnnot);

Tools. GenericAnnotationCreateTool.prototype.mouseLeftUp.apply(this, arguments);
}

Matt Parizeau

unread,
Apr 11, 2018, 2:26:44 PM4/11/18
to PDFTron WebViewer
At what point do you want to show the resize handles, immediately after creating it? HTML based annotations aren't currently setup to show resize handles so maybe you could keep around the rectangle annotation that the tool creates and select it to show the handles. To select an annotation you can call annotManager.selectAnnotation(annot);

From the rectangle annotation you could keep a reference to the widget annotation so that when it's resized you would update the dimensions and location of the widget. To do this you could listen to AnnotationManager's annotationChanged event and check if the changed annot has a reference to a widget and if so to resize. For example:
annotManager.on('annotationChanged', function(e, annots) {
  annots
.forEach(function(annot) {
   
if (annot.Custom && annot.Custom.widget) {
      annot
.Custom.widget.X = annot.X;
     
...
     
...
   
}
 
});
});

If you want to have it so that when the field is focused that the selection handles appear then at creation time you could add a focus listener on inputAnnot.innerElement and select the rectangle annotation.

Matt Parizeau
Software Developer
PDFTron Systems Inc.

André Rieussec

unread,
Apr 30, 2018, 12:58:20 PM4/30/18
to PDFTron WebViewer
I'm making good progress with this. Now my next question is: is there a way to delete a PDF form field that's already in the file? I'm able to delete the corresponding annotation with:
annotManager.deleteAnnotation(annot)
And it appears to delete the field as well. But when I save the PDF back to the server and reload it, the fields are still in there.
Reply all
Reply to author
Forward
0 new messages