Műszaki cikk

AcroForm mezők és műveletek létrehozása HotPDF-fel Delphi-ben

Az AcroForm-művelet egy widgethez csatolt szótár, amely megmondja a megjelenítőnek, mit tegyen, ha valami történik azzal a widgettel. Kattintson egy gombra, és a megjelenítő elolvassa a művelet szótárát: a URI-művelet webcímet nyit meg, a JavaScript-művelet szkriptet futtat, a SubmitForm-művelet elküldi az összegyűjtött mezőértékeket egy végpontra, a ResetForm-művelet pedig visszaállítja őket az alapértékekre. A művelet adat, nem a fájlba sütött viselkedés. Az ISO 32000-1 §12.6 a szótár alakját definiálja; az azt értelmező motort a megjelenítő adja. Ez a szétválás azért számít, mert a PDF-be tökéletesen beírt művelet is tétlen marad, ha a túloldali olvasónak nincs hozzá motorja, és az AcroForm körüli bosszúságok jó része inkább erre a résre vezethető vissza, mint egy hibás mezőre

A HotPDF ezeket a szótárakat közvetlenül Delphiből és C++Builderből írja, azoknak a mezőwidgeteknek a mellé, amelyekre felfüggeszti őket. Minden interaktív űrlapnál két szerkezet játszik: az oldalon látható widget, és alatta a mező- és műveletgépezet, amely az adatot és a bekötést hordozza. Ezeket egymástól függetlenül szerkeszti az ember, és bármelyik lehet hibás úgy, hogy a másik jónak látszik. Az alábbi szakaszok a mezők elnevezését, magukat a gombműveleteket, a mezőszintű JavaScriptet, valamint azt a hibaosztályt járják körül, amely azért éli túl a szemrevételezést, mert teljes egészében a második szerkezetben lakik

AcroForm widget réteg a HotPDF-ben, hozzárendelve az alapul szolgáló mezőértékekhez, a submit műveletszótárhoz és egy hozzájárulási exportérték-eltéréshez
A felhasználók a widgetrétegre kattintanak, miközben az értékek az alatta lévő mező- és műveletrétegen utaznak, ahol az eltérések láthatatlanok maradnak

A mezőnevek útválasztási kulcsok, nem feliratok

Minden AcroForm-mező visel egy teljesen minősített nevet. Az ISO 32000-1 §12.7.3 szerint ez a név – nem a látható felirat – az a kulcs, amellyel a mező értéke utazik, amikor az űrlapot exportálják vagy elküldik. A VCL-tervezés felől érkező fejlesztők hajlamosak egy vezérlő nevét belső kódazonosítónak tekinteni, itt viszont nem az. Itt ez az átviteli formátum

Ebből először is az következik, hogy két azonos teljesen minősített nevű mező nem két mező. A PDF egyetlen mező két widget-jegyzeteként kezeli őket, közös értékkel, így az egyikbe gépelve a másik azonnal frissül. Pontosan ezt akarja az ember, amikor egy ügyfélnévnek egy szerződés minden oldalán ismétlődnie kell. Hibává akkor válik, amikor egy generálóciklus véletlenül három oldalon át újrahasználja a 'Field1' nevet. A második esetet semmilyen szemrevételezés nem fogja meg. Minden oldal továbbra is kirajzolja a saját dobozát, és az összekötés csak akkor bukkan elő, amikor valaki gépelni kezd

A pontozott nevek, például az applicant.email, hierarchiát építenek. Az applicant szülőcsomópont csoportosítja a gyermekeit, és ez teszi lehetővé, hogy egy visszaállítás vagy beküldés csak az űrlap egy részét célozza. Ha a mezőket kezdettől így nevezi el, az semmibe nem kerül, és már az első alkalommal megtérül, amikor a fogadó rendszer csak a jelentkezői blokkot kéri

A választógomboknak saját szabályuk van. Azoknak a gomboknak, amelyeknek együtt kell váltakozniuk, közös csoportnevet kell viselniük. A HotPDF-ben az azonos csoportnevet átadó AddRadioButton hívások egyetlen szülőmezőhöz kapcsolják a widgetjeiket, és az egyes gombok exportértéke ('basic' vagy 'full') azonosítja a választott lehetőséget. Adjon minden gombnak külön nevet, és egy kölcsönösen kizáró csoport helyett független be- és kikapcsolók sorát kapja, amely ugyanúgy jelenik meg, de rosszul viselkedik

A mezőkészlet felépítése oldalról oldalra

A HotPDF a THPDFPage metódusain keresztül helyezi el a mezőket, tehát minden mező ahhoz az oldalobjektumhoz tartozik, amely létrehozta. A figyelendő sorrendi csapda az AddPage. Ez a visszatérés pillanatában az új oldalra irányítja át a CurrentPage hivatkozást, így minden utána következő mezőhívás az új oldalra kerül akkor is, ha a mező logikailag az imént elhagyott oldalhoz tartozott. Fejezzen be minden oldalt – a rajzolt tartalmat és a mezőket együtt –, mielőtt meghívja az AddPage metódust

procedure BuildClaimForm(Pdf: THotPDF);
begin
  // 1. oldal: jelentkezői blokk
  Pdf.CurrentPage.AddTextField('applicant.name', '', Rect(50, 700, 300, 722));
  Pdf.CurrentPage.AddTextField('applicant.email', '', Rect(50, 660, 300, 682));
  Pdf.CurrentPage.AddCheckBox('consent', 'Y', Rect(50, 620, 70, 640), False);
  Pdf.CurrentPage.AddRadioButton('coverage', 'basic', Rect(50, 580, 70, 600), True);
  Pdf.CurrentPage.AddRadioButton('coverage', 'full', Rect(90, 580, 110, 600), False);
  Pdf.CurrentPage.AddComboBox('plan', 'Standard',
    ['Basic', 'Standard', 'Premium'], Rect(50, 540, 200, 565));

  Pdf.AddPage;  // a CurrentPage mostantól a 2. oldalra mutat
  Pdf.CurrentPage.AddListBox('riders', 'None',
    ['None', 'Flood', 'Earthquake'], Rect(50, 500, 200, 600));
end;

A koordináták a PDF konvencióját követik, az origó az oldal bal alsó sarkában van. Ugyanez az origó, amelyet a TextOut használ a rajzolt szöveghez, tehát a Rect(50, 100, 200, 120) egy Letter méretű oldal alján ül, nem a tetején. A VCL az Y-t felülre teszi, és lefelé növeli, így egy közvetlenül átemelt elrendezési táblázat függőlegesen tükrözve jön ki, minden mező az oldal rossz végére fordítva. Végezze el az átváltást egyszer, egy közös segédfüggvényben, ne pedig minden hívási helyen, és egyetlen javítás rendbe teszi az egész űrlapot

Gombok bekötése URI-, JavaScript- és beküldési műveletekhez

A nyomógomb tétlen, amíg műveletet nem csatolnak hozzá. A HotPDF az ISO 32000-1 §12.6.4 művelettípusait a THPDFButtonAction felsorolásban teszi elérhetővé (baURI, baJavaScript, baSubmitURL, baResetForm, baHide, baShow, baNamed), és két olyan metódust ad, amely egyetlen hívásban hozza létre a gombot és köti be a műveletét

HotPDF nyomógombművelet-típusok Delphi-ben: baURI hivatkozások, baJavaScript szkriptek és SubmitForm küldés explicit formátumjelzőkkel
Egyetlen kötő hívás a három műveletszótár bármelyikét hozzácsatolja, és csak a submit változat hordoz jelzőszerződést a fogadó végponttal
// Súgóoldal megnyitása a rendszerböngészőben
Pdf.CurrentPage.AddPushButtonWithAction('btnHelp', 'Help',
  'https://www.example.com/claims-help', Rect(320, 700, 420, 730), baURI);

// Megjelenítő oldali JavaScript futtatása
Pdf.CurrentPage.AddPushButtonWithAction('btnRecalc', 'Recalculate',
  'app.alert("Totals updated.");', Rect(320, 660, 420, 690), baJavaScript);

// Beküldés XFDF formátumban, az üres mezőket is megtartva a törzsben
Pdf.CurrentPage.AddPushButtonWithSubmitAction('btnSubmit', 'Submit claim',
  'https://api.example.com/claims', Rect(320, 620, 420, 650),
  [sffXFDF, sffIncludeNoValueFields]);

A beküldési jelzők több gondolkodást érdemelnek, mint amennyit kapni szoktak. Az AddPushButtonWithSubmitAction egy THPDFSubmitFormFlags halmazt vár, és az üres halmaz egyszerű url-kódolt küldést eredményez – ezt a formátumot sok mintavégpont elfogadja, és sok éles végpont elutasítja. Az sffXFDF hozzáadása XFDF-re váltja a törzset. Az sffGetMethod a HTTP-igét változtatja meg. Az sffIncludeNoValueFields az üres mezőket is a törzsben tartja, ahelyett hogy némán eldobná őket, és ez abban a pillanatban számít, amikor a fogadó fél megkülönbözteti a „hiányzik” és a „üres” esetet. A jelzőhalmaz része a fogadó végponttal kötött illesztési szerződésnek, ezért a beküldést feldolgozó csapattal együtt tegye rendbe, ne az első visszautasított köteg után

Mezőszintű JavaScript: billentyűleütés, formázás, ellenőrzés

A műveletek nem csak a gombkattintásoknál laknak. A HotPDF azokhoz a mezőnkénti eseményekhez is csatol JavaScriptet, amelyeket a szkriptképes megjelenítők adatbevitel közben váltanak ki. Három kiváltó esemény van, és ezek a bevitel életciklusának különböző pontjain sülnek el. A billentyűleütés-művelet minden karakter érkezésekor lefut, majd véglegesítéskor még egyszer. A formázási művelet a véglegesített változás után írja át a megjelenített értéket, tisztán a megjelenítés kedvéért. Az ellenőrzési műveleté az utolsó szó: elfogadja vagy visszautasítja a véglegesített értéket, mielőtt az a mező értékévé válna

HotPDF mezőszintű JavaScript események életciklusa a billentyűleütéstől a validate-en át a formatig, alatta a szerveroldali validációs figyelmeztetéssel
A leütés- és validate szkriptek visszautasíthatják a bemenetet, míg a format csak retusálja a megjelenítést, és egyetlen szkript sem éli túl az olvasót JavaScript-motor nélkül
// Utasítsd vissza azokat a véglegesített értékeket, amelyek nem valószerű e-mail-címek
Pdf.AttachFieldKeyStrokeAction('applicant.email',
  'if (event.willCommit && !/^[\w.-]+@[\w.-]+\.\w+$/.test(event.value)) event.rc = false;');

// Az amerikai telefonszámok megjelenítése (NNN) NNN-NNNN alakban
Pdf.AttachFieldFormatAction('applicant.phone',
  'event.value = event.value.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");');

// A 18 év alatti jelentkezők visszautasítása véglegesítéskor
Pdf.AttachFieldValidateAction('applicant.age',
  'if (parseInt(event.value) < 18) event.rc = false;');

Az event.rc = false beállítása egy billentyűleütés- vagy ellenőrzési szkriptben azt mondja a megjelenítőnek, hogy utasítsa vissza a bevitelt. A bökkenő az, hogy ebből semmi nem fut le, ha a megjelenítőben nincs JavaScript-motor. Az Acrobatban és néhány asztali termékben van. A legtöbb mobilolvasóban, böngészőbe ágyazott rajzolóban és nyomtatási feldolgozósorban nincs, és ezek szó nélkül a földre ejtik a szkripteket. A mezőszkriptek tehát a felhasználóknak abban a részhalmazában javítják az adatminőséget, amelynek az olvasója lefuttatja őket, és ennyit tesznek. Nem biztonsági határvonalak. Minden beküldött értéket ugyanúgy validálni kell a kiszolgálón, amint megérkezik, mert nem feltételezheti, hogy a kliens bármit is ellenőrzött

Hibák, amelyek átmennek a szemrevételezésen

A legnehezebben elkapható AcroForm-hibák azok, amelyek a rajzolás helyett az adatszerkezetben laknak, mert a fájl megnyitása és nézegetése semmit nem árul el. Négy elég gyakran előjön ahhoz, hogy nevet érdemeljen, és mindegyikhez tartozik egy gépies teszt, amely kiadás előtt megtalálja

  • Exportérték-elcsúszás. Az AddCheckBox('consent', 'Yes', ...) hívással létrehozott jelölőnégyzet a Yes értéket küldi. Az a fogadó fél, amely a Y értékre illeszt, minden beküldést elutasít, miközben az oldal tökéletesen néz ki. Töltse ki az űrlapot, exportálja XFDF-be az Acrobatból, és hasonlítsa össze az értékeket azzal a sémával, amelyet a fogadó fél valóban elvár
  • Véletlen értéktükrözés. Két azonos teljesen minősített nevű mező eggyé olvad. A tünet adatbeviteli időben jelentkezik, generáláskor soha, ezért a teszt az, hogy gépeljen az űrlapba, nem az, hogy kirajzolja és megnézze az eredményt
  • Az opciólistán kívüli kombinált értékek. Ha az AddComboBox hívásnak átadott aktuális érték nem szerepel a felsorolt lehetőségek között, a megjelenítők nem értenek egyet abban, hogy megmutassák, kiürítsék vagy megjelöljék-e. Tartsa az alapértéket a listán belül, és a nézeteltérés eltűnik
  • A munkamenet lezárása után is szerkeszthető mezők. A HotPDF-ben nincs megjelenéslapító hívás az AcroForm-mezőkhöz. A kész űrlap befagyasztásának támogatott módja az, hogy a mezőket az ffReadOnly jelzővel hozza létre, ami a mező saját megjelenésfolyamán át láthatóan tartja az értéket, miközben visszautasítja a szerkesztést. A mező élő űrlapobjektum marad, és az alsóbb összeállító és aláíró eszközök pontosan ezt várják

Egy megjelenítő oldali viselkedés regressziós megjegyzést érdemel akkor is, ha semmilyen kódváltoztatás nem orvosolja. A vállalati Acrobat-telepítések szabályzattal letilthatják a JavaScriptet vagy korlátozhatják a beküldési célokat, így egy olyan művelet, amely minden fejlesztői buildben működött, holtan ülhet egy lezárt ügyfélgépen. Tervezzen látható tartalék megoldást arra az esetre, amikor a gomb nem csinál semmit, még ha ez a tartalék csak egy nyomtatott utasítás is, amely megmondja a felhasználónak, mit tegyen helyette

Hol kapcsolódik az űrlapmunka a dokumentum többi részéhez

Az aláírásmező maga is AcroForm-mezőtípus. Az az űrlap, amelyet később hitelesíteni vagy ellenjegyezni fognak, jobban jár, ha ezt a mezőt már a generáláskor lefoglalja, mint ha utólag foltozzák bele, és a bájtszintű okok a digitális aláírásokról és a HotPDF-fel végzett PAdES-aláírásról szóló társcikkben szerepelnek. A natív AcroForm helyett XFA-csomagként érkező bemenet más helyzet: az XFA lapítása AcroForm-mezőkké önálló munkamenet a maga veszteségmodelljével, mert a két űrlaptechnológia nem élhet együtt egy fájlban

Az itt bemutatott mező-, művelet- és eseménykezelő metódusok a Delphihez és C++Builderhez készült szabványos HotPDF Delphi Component API részei; a termékoldal a teljes referenciára hivatkozik, beleértve a mezőjelzős túlterheléseket és a beküldési jelzők teljes felsorolását