Technical Article

Izrada AcroForm polja i akcija pomoću HotPDF-a u Delphiju

AcroForm akcija je rječnik (dictionary) pridružen widgetu koji govori pregledniku što učiniti kada se nešto dogodi s tim widgetom. Kliknite gumb i preglednik čita njegov rječnik akcije: URI akcija otvara web adresu, JavaScript akcija pokreće skriptu, SubmitForm akcija šalje prikupljene vrijednosti polja na krajnju točku, a ResetForm akcija ih vraća na zadane vrijednosti. Akcija je podatak, a ne ponašanje ugrađeno u datoteku. ISO 32000-1 §12.6 definira oblik rječnika; preglednik osigurava pokretač koji ga interpretira. Ta je podjela važna jer akcija koja je savršeno zapisana u PDF i dalje ne čini ništa ako čitač na drugoj strani nema pokretač za nju, a mnogi problemi s AcroFormom proizlaze upravo iz tog jaza, a ne iz neispravnog polja.

HotPDF zapisuje te rječnike izravno iz Delphija i C++Buildera, zajedno s widgetima polja na kojima se nalaze. Dvije su strukture u igri za svaki interaktivni obrazac: widget koji korisnik vidi na stranici i mehanizam polja i akcije ispod njega koji nosi podatke i povezivanje. Oni se uređuju neovisno, pa jedno može biti neispravno dok drugo izgleda u redu. Odjeljci u nastavku bave se imenovanjem polja, samim akcijama gumba, JavaScriptom na razini polja te vrstom pogreške koja preživljava vizualnu provjeru jer živi isključivo u toj drugoj strukturi.

Nazivi polja su ključevi za usmjeravanje, a ne natpisi

Svako AcroForm polje nosi potpuno kvalificirani naziv. ISO 32000-1 §12.7.3 definira taj naziv, a ne vidljivi natpis, kao ključ pod kojim vrijednost polja putuje kada se obrazac izvozi ili šalje. Razvojni programeri koji dolaze iz VCL okruženja skloni su tretirati naziv kontrole kao privatni identifikator koda, no ovdje to nije slučaj. To je format prijenosa.

Prva stvar koja iz toga proizlazi jest da dva polja s istim potpuno kvalificiranim nazivom zapravo nisu dva polja. PDF ih tretira kao dvije widget anotacije jednog polja koje dijele istu vrijednost, pa upisivanje u jedno polje odmah ažurira drugo. To je upravo ono što želite kada se ime klijenta mora ponavljati na svakoj stranici ugovora. No, to je pogreška kada petlja za generiranje slučajno ponovno upotrijebi 'Field1' na tri stranice. Nikakav vizualni pregled ne može otkriti ovaj drugi slučaj. Svaka stranica i dalje iscrtava vlastiti okvir, a povezanost se pojavljuje tek kada netko počne tipkati.

Nazivi s točkom, poput applicant.email, grade hijerarhiju. Roditeljski čvor applicant grupira svoju djecu, što omogućuje da resetiranje ili slanje cilja samo dio obrasca. Imenovanje polja na ovaj način od samog početka ne košta ništa, a isplati se već prvi put kada primateljski sustav zatraži samo blok applicant.

Radio gumbi imaju svoje pravilo. Gumbi koji bi se trebali zajedno prebacivati moraju dijeliti zajednički naziv grupe. U HotPDF-u, pozivi AddRadioButton koji prosljeđuju isti naziv grupe povezuju svoje widgete s jednim roditeljskim poljem, a izvozna vrijednost svakog gumba ('basic' ili 'full') identificira odabranu opciju. Ako svakom gumbu dodijelite jedinstven naziv, dobit ćete niz neovisnih prekidača umjesto jedne međusobno isključive grupe, što se vizualno prikazuje isto, ali se ponaša pogrešno.

Stvaranje skupa polja stranicu po stranicu

HotPDF postavlja polja putem metoda objekta THPDFPage metode, pa svako polje pripada objektu stranice koji ga je stvorio. Zamka u redoslijedu na koju treba paziti jest AddPage. On usmjerava CurrentPage na novu stranicu u trenutku kada se vrati, pa svaki poziv polja nakon toga završava na novoj stranici, čak i kada je polje logički pripadalo stranici koju ste upravo napustili. Dovršite svaku stranicu, nacrtani sadržaj i polja zajedno, prije nego što pozovete AddPage.

Koordinate koriste PDF konvenciju, s ishodištem u donjem lijevom kutu stranice. To je isto ishodište koje TextOut koristi za nacrtani tekst, pa se Rect(50, 100, 200, 120) nalazi blizu dna Letter stranice, a ne na vrhu. VCL postavlja Y na vrh i povećava ga prema dolje, pa tablica rasporeda prenesena izravno bez prilagodbe ispada okomito zrcaljena, a svako polje završava na pogrešnom kraju stranice. Napravite pretvorbu jednom u zajedničkoj pomoćnoj funkciji umjesto na svakom mjestu poziva, i jedna ispravka će riješiti cijeli obrazac.

Povezivanje gumba s URI, JavaScript i akcijama slanja

Običan gumb (push button) je inertan dok mu se ne pridruži akcija. HotPDF nudi vrste akcija iz standarda ISO 32000-1 §12.6.4 putem enumeracije THPDFButtonAction (baURI, baJavaScript, baSubmitURL, baResetForm, baHide, baShow, baNamed) i pruža dvije metode koje stvaraju gumb i povezuju njegovu akciju u jednom pozivu.

Zastavice za slanje (submit flags) zaslužuju više pažnje nego što im se obično pridaje. AddPushButtonWithSubmitAction prima skup THPDFSubmitFormFlags, a prazan skup proizvodi običan url-kodirani POST, što je format koji mnoge testne krajnje točke prihvaćaju, a mnoge produkcijske odbijaju. Dodavanje sffXFDF prebacuje sadržaj na XFDF. sffGetMethod mijenja HTTP metodu. sffIncludeNoValueFields zadržava prazna polja u sadržaju umjesto da ih tiho odbaci, što je važno u trenutku kada primatelj razlikuje "odsutno" od "praznog". Skup zastavica dio je vašeg sučelja s primateljskom krajnjom točkom, pa to riješite s timom koji analizira slanje podataka, a ne nakon prve odbijene serije.

JavaScript na razini polja: pritisak tipke, format, provjera valjanosti

Klikovi na gumbe nisu jedino mjesto gdje žive akcije. HotPDF također pridružuje JavaScript događajima po polju koje preglednici s podrškom za skripte pokreću dok korisnik unosi podatke. Postoje tri okidača i oni se aktiviraju u različitim točkama životnog ciklusa unosa. Akcija keystroke (pritisak tipke) pokreće se pri unosu svakog znaka i ponovno prilikom potvrde unosa. Akcija format ponovno zapisuje prikazanu vrijednost nakon što je promjena potvrđena, isključivo radi prezentacije. Akcija validate ima zadnju riječ, prihvaćajući ili odbijajući potvrđenu vrijednost prije nego što ona postane stvarna vrijednost polja.

Postavljanje event.rc = false unutar keystroke ili validate skripte govori pregledniku da odbaci unos. Kvaka je u tome što se ništa od ovoga ne izvodi osim ako preglednik ne sadrži JavaScript pokretač. Acrobat i nekoliko stolnih programa ga imaju. Većina mobilnih čitača, preglednika ugrađenih u web-preglednike i sustava za ispis ga nemaju te tiho odbacuju skripte. Dakle, skripte polja poboljšavaju kvalitetu podataka samo za onaj dio korisnika čiji čitač ih izvodi, i to je sve što rade. One nisu sigurnosna granica. Svaka poslana vrijednost i dalje se mora provjeriti na poslužitelju čim stigne, jer ne možete pretpostaviti da je klijent išta provjerio.

Pogreške koje prolaze vizualni pregled

Najteže AcroForm pogreške za uočavanje su one koje žive u strukturi podataka, a ne u renderiranju, ove vam otvaranje datoteke i gledanje u nju ne govori ništa. Četiri se pojavljuju dovoljno često da ih vrijedi spomenuti, a svaka ima mehanički test koji je pronalazi prije objave.

  • Odstupanje izvozne vrijednosti. Okvir stvoren kao AddCheckBox('consent', 'Yes', ...) šalje vrijednost Yes. Primatelj koji očekuje Y odbit će svako slanje iako stranica izgleda savršeno. Popunite obrazac, izvezite ga kao XFDF iz Acrobata i usporedite vrijednosti sa shemom koju primatelj zapravo očekuje.
  • Slučajno zrcaljenje vrijednosti. Dva polja koja dijele potpuno kvalificirani naziv spajaju se u jedno. Simptom se pojavljuje u trenutku unosa podataka, a nikada u trenutku generiranja, pa je test tipkanje u obrazac, a ne renderiranje i puko promatranje rezultata.
  • Vrijednosti kombiniranog okvira izvan popisa opcija. Kada trenutna vrijednost proslijeđena u AddComboBox nije jedna od navedenih opcija, preglednici se ne slažu oko toga treba li je prikazati, isprazniti polje ili je označiti. Zadržite zadanu vrijednost unutar popisa i nesuglasice će nestati.
  • Polja koja se i dalje mogu uređivati nakon završetka tijeka rada. HotPDF nema poziv za izravnavanje izgleda (appearance-flattening) za AcroForm polja. Podržani način za zamrzavanje dovršenog obrasca je stvaranje polja sa zastavicom ffReadOnly, što drži vrijednost vidljivom kroz vlastiti tok izgleda polja dok istovremeno odbija uređivanje. Polja ostaju aktivni objekti obrasca, što je upravo ono što alati za spajanje i potpisivanje dalje u lancu očekuju pronaći.

Jedno ponašanje na strani preglednika vrijedi zabilježiti kao napomenu o regresiji, iako ga nijedna promjena koda ne rješava. Korporativne implementacije Acrobata mogu onemogućiti JavaScript ili ograničiti ciljeve slanja prema sigurnosnim pravilima, pa akcija koja je radila u svakoj razvojnoj verziji može biti neaktivna na zaključanom računalu korisnika. Planirajte vidljivo alternativno rješenje za slučaj kada gumb ne radi ništa, makar to rješenje bila samo tiskana uputa koja korisniku govori što učiniti umjesto toga.

Gdje se rad s obrascima povezuje s ostatkom dokumenta

Polje za potpis je samo po sebi vrsta AcroForm polja. Za obrazac koji će se kasnije certificirati ili supotpisati bolje je rezervirati to polje tijekom generiranja nego ga naknadno dodavati, a razlozi na razini bajtova za to opisani su u pratećem članku o digitalnim potpisima i PAdES potpisivanju s HotPDF-om. Unosi koji stižu kao XFA paketi umjesto izvornog AcroForma predstavljaju drugačiju situaciju: izravnavanje XFA u AcroForm polja zaseban je tijek rada s vlastitim modelom gubitka, jer te dvije tehnologije obrazaca ne mogu istovremeno postojati u jednoj datoteci.

Metode za polja, akcije i okidače prikazane ovdje dio su standardnog API-ja HotPDF komponente za Delphi i C++Builder; stranica proizvoda vodi na cjelovitu dokumentaciju, uključujući preopterećenja zastavica polja i kompletnu enumeraciju zastavica za slanje.