フォームフィラーを使用して、任意のデバイスでPDFフォームを入力する

このサンプルでは、例として商業用賃貸申込書を読み込みこんでいます。
フォーム入力をより簡単にするため、formFillerオプションを使用し、フォームフィラーダイアログの表示と動作をカスタマイズしています。
ドキュメントを読み込むと、クライアントサイドのshowFormFillerメソッドを使ってフォームフィラーダイアログが表示されます。

window.onload = function(){ //DsPdfViewer.LicenseKey = "***key***"; const requiredPhonePattern = '^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$'; const requiredPhoneValidationMessage = '有効な形式: 1234567890, (123)456-7890,\n 123-456-7890, 123.456.7890, +31636363634, 075-63546725'; const optionalPhonePattern = '^$|^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$'; const optionalPhoneValidationMessage = '入力は任意です。有効な形式:\n 1234567890, (123)456-7890,\n 123-456-7890, 123.456.7890, +31636363634, 075-63546725'; const ovnPark_FieldValue_On = '夜間駐車があります', ovnPark_FieldValue_Off = 'ありません'; let 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); } } const options = { workerSrc: "/diodocs/pdfviewer/demos/product-bundles/build/dspdfviewer.worker.js", supportApi: getSupportApiSettings(), restoreViewStateOnLoad: false }; // 'RentalApplicationForm'ドキュメント用のフォームフィラーオプション let 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;// 現在の'On'の値を記憶 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; // 未チェックは拒否 } if(fieldName === 'CorpCHK' || fieldName === 'GPCHK' || fieldName === 'IndivCHK') { // 他のフィールドのチェックを外す 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; // 未チェックは拒否 } } finally { updatingFieldsFlag = false; } return true; }, mappings: { 'CustomContent1': { type: 'custom-content', content: '<h2>商業用賃貸申込書</h2>' }, 'AppDate': { title: '申請日', displayname: '申請日', type: 'date', defaultvalue: new Date().toJSON().slice(0, 10) }, 'Entity': { autofocus: true, title: '個人・組合・法人名', displayname: '申請者または事業者', placeholder: '個人・組合・法人名', required: true, validationmessage: '入力は必須です', validateoninput: true }, 'CustomContent2': { type: 'custom-content', content: '<table> <tr><td style=\'vertical-align:top;\'> <i><u>法人の方:</u></i> </td><td style=\'vertical-align:top;\'> <i>定款の提出と2年分の年次報告書と法人税申告書の提出が必要です。</i> </td></tr> <tr><td style=\'vertical-align:top;\'> <i><u>組合の方:</u></i> </td><td style=\'vertical-align:top;\'> <i>組合契約書に加えて、パートナーそれぞれの現在の個人財務報告書と2年分の個人納税申告書を提出する必要があります。</i> </td></tr> <tr><td style=\'vertical-align:top;\'> <i><u>個人の方:</u></i> </td><td style=\'vertical-align:top;\'> <i>個人の貸借対照表と2年分の確定申告書を提出してください。運転免許証番号の記載が必要です。</i> </td></tr></table>' }, 'Addr1': { title: '現在の本社または自宅住所(私書箱は不可)', displayname: '現在の住所', placeholder: '現在の本社または自宅住所(私書箱は不可)', multiline: true, required: true, validationmessage: '入力は必須です', validateoninput: true }, 'Addr2': { hidden: true, }, 'CorpPhone': { title: '会社の電話番号', displayname: '会社の電話番号', placeholder: '会社の電話番号', type: 'tel', pattern: requiredPhonePattern, validationmessage: requiredPhoneValidationMessage, validateoninput: true }, 'CorpState': { title: '会社が登録されている自治体', displayname: '会社の登録自治体', placeholder: '会社の登録自治体', validateoninput: true, validator: function(fieldValue, field) { if(!fieldValue || !fieldValue.trim()) return '入力は必須です'; if(fieldValue.toLowerCase().indexOf('宮城県') === -1) return '宮城県のみ入力可能です'; return true; } }, 'DBA': { title: '会社の事業内容', displayname: '会社の事業内容', placeholder: '事業内容', required: true }, 'HomePhone': { title: '自宅の電話番号 (組合または個人の場合)', displayname: '自宅の電話番号', placeholder: '自宅の電話番号 (任意)', type: 'tel', pattern: optionalPhonePattern, validationmessage: optionalPhoneValidationMessage, validateoninput: true }, 'PtnrState': { title: '組合結成の地域', displayname: '組合結成の地域', placeholder: '組合結成の地域' }, 'LocalPhone': { title: '市内電話番号', displayname: '市内電話番号', placeholder: '市内電話番号 (任意)', type: 'tel', pattern: optionalPhonePattern, validationmessage: optionalPhoneValidationMessage, validateoninput: true }, 'Use1': { title: '使用目的の詳細な説明', displayname: '使用目的', placeholder: '使用目的 (1行目)', required: true }, 'Use2': { title: '使用目的の詳細な説明', displayname: '', placeholder: '使用目的 (2行目)' }, 'Use3': { title: '使用目的の詳細な説明', displayname: '', placeholder: '使用目的 (3行目)' }, 'CustomContent3': { type: 'custom-content', content: '<h2>現在の事業概要</h2>' }, 'CurrLandlord': { title: '現在の事業主名', displayname: '事業主名', placeholder: '事業主名' }, LandLordPhone: { title: '電話番号', displayname: '電話番号', placeholder: '電話番号 (任意)', type: 'tel', pattern: optionalPhonePattern, validationmessage: optionalPhoneValidationMessage, validateoninput: true }, BusAddr1: { title: '現在の事業所所在地', displayname: '現在の事業所所在地', placeholder: '現在の事業所所在地', multiline: true }, BusAddr2: { hidden: true }, NumYears: { title: '現在の所在地での年数', displayname: '現在の所在地での年数', placeholder: '現在の所在地での年数', type: 'number', min: 0, max: 100 }, NumEmployees: { title: '従業員数', displayname: '従業員数', placeholder: '従業員数', type: 'number', min: 0, max: 1000000 }, PkgSpaces: { title: '必要な駐車場の数', displayname: '必要な駐車場の数', placeholder: '駐車場の数', type: 'number', min: 0, max: 1000000 }, OvnPark: { title: '夜間駐車はあるか?', displayname: '夜間駐車はあるか?', type: 'checkbox' }, BankAcct: { title: '銀行の口座番号', displayname: '口座番号', placeholder: '口座番号', minlength: 8, maxlength: 12, validationmessage: '8~12桁で入力してください', validateoninput: true }, BankPhone: { title: '銀行の電話番号', displayname: '電話番号' }, BankRef: { title: 'バンク・リファレンス', displayname: 'バンク・リファレンス' }, BankContact: { title: '担当者名', displayname: '担当者名' }, 'CustomContent4': { type: 'custom-content', content: '<h4>敷地内に保有する予定のすべての有害物質とそのおおよその量を記載してください</h4>' }, HazSub1: { title: '敷地内に保有する予定のすべての有害物質とそのおおよその量を記載してください', placeholder: '敷地内に保有する予定のすべての有害物質とそのおおよその量を記載してください (1行目)', nolabel: true }, HazSub2: { title: '敷地内に保有する予定のすべての有害物質とそのおおよその量を記載してください', placeholder: '敷地内に保有する予定のすべての有害物質とそのおおよその量を記載してください (2行目)', nolabel: true }, HazSub3: { title: '敷地内に保有する予定のすべての有害物質とそのおおよその量を記載してください', placeholder: '敷地内に保有する予定のすべての有害物質とそのおおよその量を記載してください (3行目)', nolabel: true }, 'CustomContent5': { type: 'custom-content', content: '<h4>1つチェックしてください</h4>' }, CorpCHK: { title: '法人', displayname: '法人' }, GPCHK: { title: '無限責任組合員', displayname: '無限責任組合員' }, IndivCHK: { title: '賃貸借契約を締結する個人', displayname: '賃貸借契約を締結する個人' }, 'CustomContent6': { type: 'custom-content', content: '<h4>代表者</h4>' }, Fullname1: { title: '氏名', displayname: '氏名', placeholder: '氏名' }, Title1: { title: '役職', displayname: '役職', placeholder: '役職' }, SSN1: { title: '社会保障番号 (SSN)', displayname: '社会保障番号', placeholder: 'SSN (9桁)' }, Married1CHK: { title: '既婚', displayname: '既婚' }, Single1CHK: { title: '未婚', displayname: '未婚' }, DL1: { title: '運転免許証', displayname: '運転免許証', placeholder: '運転免許証' }, DLState1: { title: '運転免許証の発行自治体', displayname: '運転免許証の発行自治体', placeholder: '運転免許証の発行自治体' }, 'CustomContent7': { type: 'custom-content', content: '<h4>配偶者</h4>' }, SpFullname1: { title: '氏名', displayname: '配偶者の氏名', placeholder: '氏名' }, SpSSN1: { title: '社会保障番号 (SSN)', displayname: '社会保障番号', placeholder: 'SSN (9桁)' }, 'CustomContent8': { type: 'custom-content', content: '<h4現在の家主または住宅ローン会社</h4>' }, LL1: { title: '会社名', displayname: '会社名', placeholder: '会社名' }, LLPhone1: { title: '会社の電話番号', displayname: '電話番号', placeholder: '電話番号' }, ResAddr1A: { title: '現在の住所', displayname: '現在の住所', placeholder: '現在の住所 (1行目)' }, ResAddr1B: { title: '現在の住所', displayname: '', placeholder: '現在の住所 (2行目)' }, HmPhone1: { title: '自宅の電話', displayname: '自宅の電話', placeholder: '自宅の電話' }, Years1: { title: '居住年数', displayname: '居住年数', placeholder: '居住年数', type: 'number', min: 0, max: 100 }, PrintName1: { title: '署名 (名前)', displayname: '署名 (名前)', placeholder: '署名 (名前)' }, Title1a: { title: '署名 (役職)', displayname: '署名 (役職)', placeholder: '署名 (役職)' }, SignedDate: { title: '署名日', displayname: '署名日', placeholder: '署名日', 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: 'トレード・レファレンス', displayname: 'トレード・レファレンス', placeholder: 'トレード・レファレンス (1行目)' }, TradeRef2: { title: 'Trade references', displayname: '', placeholder: 'トレード・レファレンス (2行目)' }, TradeRef3: { title: 'Trade references', displayname: '', placeholder: 'トレード・レファレンス (3行目)' }, PrintName2: { hidden: true }, Title2a: { hidden: true }, SignedDate2: { hidden: true } } }; let viewer = new DsPdfViewer("#viewer", options); // デフォルトのサイドバーパネルを追加 viewer.addDefaultPanels(); // ツールバーのボタンを設定 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'] }; viewer.applyToolbarLayout(); viewer.applyOptions(); viewer.onAfterOpen.register(function(args) { var fileName = viewer.fileName; if (fileName.indexOf('commercial-rental-application-form.pdf') !== -1) { viewer.options.formFiller = formFiller_RentalApplicationForm; viewer.showFormFiller(); } else { viewer.options.formFiller = {}; } }); viewer.open("/diodocs/pdfviewer/demos/product-bundles/assets/pdf/commercial-rental-application-form.pdf"); }
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>フォームフィラー</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="./src/styles.css"> <script src="/diodocs/pdfviewer/demos/product-bundles/build/dspdfviewer.js"></script> <script src="/diodocs/pdfviewer/demos/product-bundles/build/wasmSupportApi.js"></script> <script src="/diodocs/pdfviewer/demos/resource/js/init.js"></script> <script src="./src/app.js"></script> </head> <body> <div id="viewer"></div> </body> </html>
#viewer { height: 100%; }