ViewerFormFiller.cs
//
// This code is part of Document Solutions for PDF demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System.IO;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
namespace DsPdfWeb.Demos
{
//
// This sample demonstrates using the GcPdfViewer's Form Filler.
// It loads an example Commercial Rental Application Form.
// To make form input more convenient, we customize the appearance and
// behavior of the Form Filler dialog using the formFiller option.
// After loading the document - the Form Filler dialog is displayed
// using the client side showFormFiller method.
// This and other samples in this section demonstrate the features of GcPdfViewer
// (a JavaScript PDF viewer control included with DsPdf), mainly the ability
// to change PDF files (add or edit annotations and AcroForm fields, rotate pages etc.)
// when the JS viewer on the client is supported by DsPdf running on the server.
//
// To enable the editing features of the viewer, its supportApi property must be set
// to a URL on the server that implements all or some of the edit supporting APIs
// that are known to/expected by the viewer. This DsPdf demo site provides those APIs,
// which makes it possible to demonstrate the editing when you open the PDF viewer
// in this sample. When you download this sample, in addition to the .NET Core
// console app project that generates the sample PDF, an ASP.NET Core project is
// also included in the download zip (located in the GcPdfViewerWeb sub-folder of the
// downloaded zip), which also provides the necessary APIs. In particular, it includes
// a project that implements the APIs and provides them via a special controller.
// It is actually the same controller that is used by this DsPdf demo site, and which
// can be used in any ASP.NET Core site to enable the viewer editing features.
//
// Look at the following files in the sample download zip for more info:
// - GcPdfViewerWeb\SupportApiDemo: the sample ASP.NET Core web site.
// - GcPdfViewerWeb\SupportApiDemo.sln: solution to build/run the sample web site.
// - GcPdfViewerWeb\SupportApi: support API implementation (can be used in any site).
// - GcPdfViewerWeb\SupportApi\Controllers\GcPdfViewerController.cs: support API controller.
//
// Please note that this and other samples in this section are only available in C# at this time.
//
public class ViewerFormFiller
{
public void CreatePDF(Stream stream)
{
CreatePDF(stream, 0);
}
public void CreatePDF(Stream stream, int _)
{
var doc = new GcPdfDocument();
using var fs = File.OpenRead(Path.Combine("Resources", "PDFs", "Commercial-Rental-Application-Form.pdf"));
doc.Load(fs);
doc.Save(stream);
}
public const string JS_CODE = @"
var requiredPhonePattern = '^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$';
var requiredPhoneValidationMessage = 'Valid formats: 1234567890, (123)456-7890,\n 123-456-7890, 123.456.7890, +31636363634, 075-63546725';
var optionalPhonePattern = '^$|^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$';
var optionalPhoneValidationMessage = 'Field is optional, valid formats:\n 1234567890, (123)456-7890,\n 123-456-7890, 123.456.7890, +31636363634, 075-63546725';
var ovnPark_FieldValue_On = 'Has overnight parking.', ovnPark_FieldValue_Off = 'NO';
var updatingFieldsFlag = false;
function combineTwoFieldsIntoOneValue(destfieldName, fieldName2, formFiller) {
var addr1 = formFiller.getFieldByName(destfieldName);
var addr2 = formFiller.getFieldByName(fieldName2);
if(addr1 && addr2) {
if(addr2.fieldValue) {
addr1.fieldValue = addr1.fieldValue + '\n' + addr2.fieldValue;
addr2.fieldValue = '';
formFiller.onFieldChanged(addr1);
formFiller.onFieldChanged(addr2);
}
}
}
function splitFieldValueIntoTwoFields(srcfieldName, fieldName2, formFiller) {
var addr1 = formFiller.getFieldByName(srcfieldName);
var addr2 = formFiller.getFieldByName(fieldName2);
if(addr1 && addr2) {
var s = addr1.fieldValue;
var nlInd = s.indexOf('\n');
if(nlInd !== -1) {
var firstPart = s.substring(0, nlInd);
var secondPart = s.substr(nlInd + 1);
addr1.fieldValue = firstPart;
addr2.fieldValue = secondPart;
} else {
addr2.fieldValue = '';
}
formFiller.onFieldChanged(addr1);
formFiller.onFieldChanged(addr2);
}
}
function createPdfViewer(selector, baseOptions) {
var options = baseOptions || {};
// Form Filler options for 'RentalApplicationForm' document:
var formFiller_RentalApplicationForm = {
onInitialize: function(formFiller) {
combineTwoFieldsIntoOneValue('Addr1', 'Addr2', formFiller);
combineTwoFieldsIntoOneValue('BusAddr1', 'BusAddr2', formFiller);
var ovnParkField = formFiller.getFieldByName('OvnPark');
if(ovnParkField.fieldValue) {
var ovnPark_LowVal = (ovnParkField.fieldValue || '').toLowerCase();
if(!ovnPark_LowVal || ovnPark_LowVal.indexOf('no') !== -1 || ovnPark_LowVal === 'off' || ovnPark_LowVal === 'false') {
ovnParkField.fieldValue = 'Off';
formFiller.onFieldChanged(ovnParkField);
} else {
ovnPark_FieldValue_On = ovnParkField.fieldValue;// remember current On value.
ovnParkField.fieldValue = 'On';
formFiller.onFieldChanged(ovnParkField);
}
}
},
beforeApplyChanges: function(formFiller) {
splitFieldValueIntoTwoFields('Addr1', 'Addr2', formFiller);
splitFieldValueIntoTwoFields('BusAddr1', 'BusAddr2', formFiller);
var ovnParkField = formFiller.getFieldByName('OvnPark');
if(ovnParkField.fieldName === 'OvnPark') {
if(ovnParkField.fieldValue === 'On') {
ovnParkField.fieldValue = ovnPark_FieldValue_On;
} else {
ovnParkField.fieldValue = ovnPark_FieldValue_Off;
}
}
return true;
},
beforeFieldChange: function(changedField, formFiller) {
if(updatingFieldsFlag)
return true;
var setFieldValue = function(chkboxFieldName, newVal) {
var tmpField = formFiller.getFieldByName(chkboxFieldName);
if(tmpField.fieldValue !== newVal) {
tmpField.fieldValue = newVal;
formFiller.onFieldChanged(tmpField);
}
};
updatingFieldsFlag = true;
try {
var fieldName = changedField.fieldName;
var fieldValue = changedField.fieldValue;
if(fieldName === 'Married1CHK' || fieldName === 'Single1CHK') {
if(fieldName === 'Married1CHK')
setFieldValue('Single1CHK', 'Off');
if(fieldName === 'Single1CHK')
setFieldValue('Married1CHK', 'Off');
if(fieldValue === 'Off')
return false; // prevent uncheck
}
if(fieldName === 'CorpCHK' || fieldName === 'GPCHK' || fieldName === 'IndivCHK') {
// Uncheck other fields:
switch(fieldName) {
case 'CorpCHK':
setFieldValue('GPCHK', 'Off');
setFieldValue('IndivCHK', 'Off');
break;
case 'GPCHK':
setFieldValue('CorpCHK', 'Off');
setFieldValue('IndivCHK', 'Off');
break;
case 'IndivCHK':
setFieldValue('CorpCHK', 'Off');
setFieldValue('GPCHK', 'Off');
break;
default:
break;
}
if(fieldValue === 'Off')
return false; // prevent uncheck
}
} finally {
updatingFieldsFlag = false;
}
return true;
},
mappings: {
'CustomContent1': {
type: 'custom-content',
content: '<h2>COMMERCIAL TENANT APPLICATION</h2>'
},
'AppDate': {
title: 'Application date',
displayname: 'Date',
type: 'date',
defaultvalue: new Date().toJSON().slice(0, 10)
},
'Entity': {
autofocus: true,
title: 'Name of individual, partnership, or corporation',
displayname: 'Applicant or Leasing Entity',
placeholder: 'Name of individual, partnership, or corporation',
required: true,
validationmessage: 'Entity name is required',
validateoninput: true
},
'CustomContent2': {
type: 'custom-content',
content: '<table> <tr><td style=\'vertical-align:top;\'> <i><u>Corporation:</u></i> </td><td style=\'vertical-align:top;\'> <i>Articles of Incorporation must be provided and 2 years\' Annual Report and corporate tax return.</i> </td></tr> <tr><td style=\'vertical-align:top;\'> <i><u>Partnership:</u></i> </td><td style=\'vertical-align:top;\'> <i>Partnership Agreement must be provided plus individual partners\' current personal financial statement and 2 years\' personal tax returns.</i> </td></tr> <tr><td style=\'vertical-align:top;\'> <i><u>Individual:</u></i> </td><td style=\'vertical-align:top;\'> <i>Personal balance sheet and 2 years\' personal tax returns must be provided. Must include Drivers\' license number.</i> </td></tr></table>'
},
'Addr1': {
title: 'Current corporate headquarters/home address (For partnership/individuals) (Do not use P.O. Box)',
displayname: 'Current address',
placeholder: 'Current corporate headquarters/home address (For partnership/individuals) (Do not use P.O. Box)',
multiline: true,
required: true,
validationmessage: 'Address is required',
validateoninput: true
},
'Addr2': {
hidden: true,
},
'CorpPhone': {
title: 'Corporate phone number',
displayname: 'Corporate phone #',
placeholder: 'Corporate phone',
type: 'tel',
pattern: requiredPhonePattern,
validationmessage: requiredPhoneValidationMessage,
validateoninput: true
},
'CorpState': {
title: 'State where the company was registered',
displayname: 'State of incorporation',
placeholder: 'State of incorporation',
validateoninput: true,
validator: function(fieldValue, field) {
if(!fieldValue || !fieldValue.trim())
return 'This field cannot be empty';
if(fieldValue.toLowerCase().indexOf('delaware') === -1)
return 'Only Delaware state allowed.';
return true;
}
},
'DBA': {
title: 'DBA (Doing Business As)',
displayname: 'DBA name',
placeholder: 'DBA',
required: true
},
'HomePhone': {
title: 'Home phone number (for partnerships/Individuals)',
displayname: 'Home phone #',
placeholder: 'Home phone (optional)',
type: 'tel',
pattern: optionalPhonePattern,
validationmessage: optionalPhoneValidationMessage,
validateoninput: true
},
'PtnrState': {
title: 'State of partnership formation',
displayname: 'State of partnership formation',
placeholder: 'State of partnership formation'
},
'LocalPhone': {
title: 'Local phone number',
displayname: 'Local phone #',
placeholder: 'Local phone (optional)',
type: 'tel',
pattern: optionalPhonePattern,
validationmessage: optionalPhoneValidationMessage,
validateoninput: true
},
'Use1': {
title: 'Full description of intended use',
displayname: 'Intended use',
placeholder: 'Intended use (line 1)',
required: true
},
'Use2': {
title: 'Full description of intended use',
displayname: '',
placeholder: 'Intended use (line 2)'
},
'Use3': {
title: 'Full description of intended use',
displayname: '',
placeholder: 'Intended use (line 3)'
},
'CustomContent3': {
type: 'custom-content',
content: '<h2>CURRENT BUSINESS LANDLORD</h2>'
},
'CurrLandlord': {
title: 'Current business landlord name',
displayname: 'Name',
placeholder: 'Landlord name'
},
LandLordPhone: {
title: 'Phone number',
displayname: 'Phone #',
placeholder: 'Phone (optional)',
type: 'tel',
pattern: optionalPhonePattern,
validationmessage: optionalPhoneValidationMessage,
validateoninput: true
},
BusAddr1: {
title: 'Present business address',
displayname: 'Present business address',
placeholder: 'Present business address',
multiline: true
},
BusAddr2: {
hidden: true
},
NumYears: {
title: 'Years at this location',
displayname: 'Years at this location',
placeholder: 'Years at this location',
type: 'number',
min: 0,
max: 100
},
NumEmployees: {
title: 'Number of employees',
displayname: 'Number of employees',
placeholder: 'Number of employees',
type: 'number',
min: 0,
max: 1000000
},
PkgSpaces: {
title: 'Number of parking spaces needed',
displayname: 'Number of parking spaces needed',
placeholder: 'parking spaces number',
type: 'number',
min: 0,
max: 1000000
},
OvnPark: {
title: 'Any overnight parking?',
displayname: 'Any overnight parking?',
type: 'checkbox'
},
BankAcct: {
title: 'Bank account number',
displayname: 'Account number',
placeholder: 'Account number',
minlength: 8,
maxlength: 12,
validationmessage: 'Expected value between 8 and 12 digits',
validateoninput: true
},
BankPhone: {
title: 'Bank phone number',
displayname: 'Phone number'
},
BankRef: {
title: 'Bank reference',
displayname: 'Bank reference'
},
BankContact: {
title: 'Contact name',
displayname: 'Contact name'
},
'CustomContent4': {
type: 'custom-content',
content: '<h4>Please list all hazardous substances that will be on the premises and the approximate amounts</h4>'
},
HazSub1: {
title: 'Please list all hazardous substances that will be on the premises and the approximate amounts',
placeholder: 'List all hazardous substances that will be on the premises and the approximate amount (line 1)',
nolabel: true
},
HazSub2: {
title: 'Please list all hazardous substances that will be on the premises and the approximate amounts',
placeholder: 'List all hazardous substances that will be on the premises and the approximate amount (line 2)',
nolabel: true
},
HazSub3: {
title: 'Please list all hazardous substances that will be on the premises and the approximate amounts',
placeholder: 'List all hazardous substances that will be on the premises and the approximate amount (line 3)',
nolabel: true
},
'CustomContent5': {
type: 'custom-content',
content: '<h4>Please check one:</h4>'
},
CorpCHK: {
title: 'Corporate',
displayname: 'Corporate'
},
GPCHK: {
title: 'General partner(s)',
displayname: 'General partner(s)'
},
IndivCHK: {
title: 'Individual(s) signing the lease',
displayname: 'Individual(s) signing the lease'
},
'CustomContent6': {
type: 'custom-content',
content: '<h4>First person</h4>'
},
Fullname1: {
title: 'Full name',
displayname: 'Full name',
placeholder: 'First / M.I./ Last Name'
},
Title1: {
title: 'Title',
displayname: 'Title',
placeholder: 'Title'
},
SSN1: {
title: 'Social Security number (SSN)',
displayname: 'Social Security number',
placeholder: 'SSN (9 digits)'
},
Married1CHK: {
title: 'Married',
displayname: 'Married'
},
Single1CHK: {
title: 'Single',
displayname: 'Single'
},
DL1: {
title: 'Driver License',
displayname: 'Driver License',
placeholder: 'Driver License'
},
DLState1: {
title: 'Driver License state',
displayname: 'Driver License state',
placeholder: 'Driver License state'
},
'CustomContent7': {
type: 'custom-content',
content: '<h4>Name of spouse</h4>'
},
SpFullname1: {
title: 'Full name',
displayname: 'Full name of spouse',
placeholder: 'First / M.I. / Last Name'
},
SpSSN1: {
title: 'Social Security number (SSN)',
displayname: 'Social Security number',
placeholder: 'SSN (9 digits)'
},
'CustomContent8': {
type: 'custom-content',
content: '<h4>Current landlord/mortgage company</h4>'
},
LL1: {
title: 'Company name',
displayname: 'Company name',
placeholder: 'Company name'
},
LLPhone1: {
title: 'Company phone number',
displayname: 'Phone number',
placeholder: 'Phone number'
},
ResAddr1A: {
title: 'Current residence address',
displayname: 'Current residence address',
placeholder: 'Current residence address (line 1)'
},
ResAddr1B: {
title: 'Current residence address',
displayname: '',
placeholder: 'Current residence address (line 2)'
},
HmPhone1: {
title: 'Home phone',
displayname: 'Home phone',
placeholder: 'Home phone'
},
Years1: {
title: 'Years at this location',
displayname: 'Years at this location',
placeholder: 'Years at this location',
type: 'number',
min: 0,
max: 100
},
PrintName1: {
title: 'Signed by (name)',
displayname: 'Signed by (name)',
placeholder: 'Signed by (name)'
},
Title1a: {
title: 'Signed by (title)',
displayname: 'Signed by (title)',
placeholder: 'Signed by (title)'
},
SignedDate: {
title: 'Signed date',
displayname: 'Signed date',
placeholder: 'Signed date',
type: 'date',
defaultvalue: new Date().toJSON().slice(0, 10)
},
Fullname2: {
hidden: true
},
Title2: {
hidden: true
},
SSN2: {
hidden: true
},
Married2CHK: {
hidden: true
},
Single2CHK: {
hidden: true
},
DL2: {
hidden: true
},
DLState2: {
hidden: true
},
SpFullname2: {
hidden: true
},
SpSSN2: {
hidden: true
},
LL2: {
hidden: true
},
LLPhone2: {
hidden: true
},
ResAddr2A: {
hidden: true
},
ResAddr2B: {
hidden: true
},
HmPhone2: {
hidden: true
},
Years2: {
hidden: true
},
TradeRef1: {
title: 'Trade references',
displayname: 'Trade references',
placeholder: 'Trade references (line 1)'
},
TradeRef2: {
title: 'Trade references',
displayname: '',
placeholder: 'Trade references (line 2)'
},
TradeRef3: {
title: 'Trade references',
displayname: '',
placeholder: 'Trade references (line 3)'
},
PrintName2: {
hidden: true
},
Title2a: {
hidden: true
},
SignedDate2: {
hidden: true
}
}
};
var viewer = new GcPdfViewer(selector, options);
// Add default sidebar panels
viewer.addDefaultPanels();
// Configure toolbar buttons:
viewer.toolbarLayout.viewer = {
default: ['open', 'save', 'form-filler', '$navigation', '$split', 'text-selection', 'pan', '$zoom', '$fullscreen', 'print', 'title', 'about'],
mobile: ['open', 'save', 'form-filler', '$navigation', 'title', 'about'],
fullscreen: ['$fullscreen', 'open', 'save', 'form-filler', '$navigation', '$split', 'text-selection', 'pan', '$zoom', 'print', 'title', 'about']
};
if(!viewer.options.supportApi) {
viewer.options.supportApi = {
apiUrl: (window.__baseUrl || '') + 'support-api/gc-pdf-viewer',
token: window.afToken || '',
webSocketUrl: (window.__baseUrl || '') + 'signalr',
suppressInfoMessages: true, suppressErrorMessages: true
};
}
viewer.applyToolbarLayout();
viewer.applyOptions();
viewer.onAfterOpen.register(function(args) {
var fileName = viewer.fileName;
if (fileName.indexOf('viewer-form-filler') !== -1 ||
fileName.indexOf('get-sample-pdf') !== -1 ||
fileName.indexOf('GetSamplePdf') !== -1) {
viewer.options.formFiller = formFiller_RentalApplicationForm;
viewer.showFormFiller();
} else {
viewer.options.formFiller = {};
}
});
return viewer;
}
";
public static List<string[]> GetSampleParamsList()
{
return new List<string[]>()
{
new string[] { "@viewer/Form Filler", "Form filler customized in JS code for a particular PDF form", null },
new string[] { "@use/Tenant Application", "Fill Tenant application form using DsPdfViewer's Form filler dialog", null },
};
}
}
}