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 }, }; } } }