AcroForm-toiminto on widgetiin kiinnitetty sanakirja, joka kertoo katselijalle, mitä tehdä, kun kyseiselle widgetille tapahtuu jotain. Napsauta painiketta ja katseluohjelma lukee sen toimintasanakirjan: URI-toiminto avaa verkko-osoitteen, JavaScript-toiminto suorittaa skriptin, SubmitForm-toiminto lähettää kerätyt kenttien arvot päätepisteeseen, ResetForm-toiminto tyhjentää ne takaisin oletuksiin. Toiminto on dataa, ei tiedostoon leivottu käyttäytyminen. ISO 32000-1 §12.6 määrittelee sanakirjan muodon; katsoja toimittaa moottorin, joka tulkitsee sen. Tuolla jaolla on merkitystä, koska täydellisesti PDF-tiedostoon kirjoitettu toiminto ei tee silti mitään, jos toisessa päässä olevalla lukijalla ei ole sille moottoria, ja suuri osa AcroForm-ongelmista johtuu tuosta aukosta eikä väärin muotoillusta kentästä
HotPDF kirjoittaa nämä sanakirjat suoraan Delphistä ja C++Builderistä niiden kenttä-widgetien viereen, joista ne riippuvat. Jokaisessa interaktiivisessa muodossa pelataan kahta rakennetta: widgettiä, jonka käyttäjä näkee sivulla, ja sen alla olevaa kenttää ja toimintokoneistoa, joka kantaa dataa ja johdotusta. Niitä muokataan itsenäisesti, ja toinen voi olla väärässä samalla kun toinen näyttää hyvältä. Alla olevat osiot käsittelevät kenttien nimeämistä, itse painiketoimintoja, kenttätason JavaScriptiä ja vikaluokkaa, joka selviää visuaalisesta tarkistuksesta, koska se elää kokonaan toisessa rakenteessa
Kenttien nimet ovat reititysavaimia, eivät kuvatekstejä
Jokaisessa AcroForm-kentässä on täysin pätevä nimi. ISO 32000-1 §12.7.3 tekee tuosta nimestä, ei näkyvästä kuvatekstistä, avaimen, jonka alla kentän arvo kulkee, kun lomake viedään tai lähetetään. VCL-suunnittelusta saapuvilla kehittäjillä on tapana käsitellä ohjaimen nimeä yksityisenä kooditunnisteena, eikä se ole täällä sitä. Se on lankamuoto
Ensimmäinen asia, joka tästä seuraa, on, että kaksi kenttää samalla täysin pätevällä nimellä eivät ole kaksi kenttää. PDF käsittelee niitä yhden kentän kahtena widget-merkintänä, joilla on yksi yhteinen arvo, joten kirjoittaminen yhteen päivittää toisen paikan päällä. Juuri sitä haluat, kun asiakkaan nimen on toistettava sopimuksen jokaisella sivulla. Se on virhe, kun sukupolvisilmukka käyttää satunnaisesti uudelleen 'Field1'-nimeä kolmella sivulla. Mikään visuaalinen tarkastus ei huomaa toista tapausta. Jokainen sivu piirtää edelleen oman laatikkonsa, ja yhteys tulee pintaan vasta kun joku alkaa kirjoittaa
Pisteviivalliset nimet, kuten applicant.email, rakentavat hierarkian. Ylätason solmu applicant ryhmittelee lapsensa, mikä antaa nollauksen tai lähetyksen kohdistaa vain osaan lomaketta. Kenttien nimeäminen tällä tavalla alusta alkaen ei maksa mitään, ja se maksaa itsensä takaisin heti, kun vastaanottava järjestelmä pyytää vain hakijalohkoa
Valintanapeilla on oma sääntönsä. Painikkeiden, joiden tulisi kytkeytyä yhteen, on jaettava ryhmän nimi. HotPDF:ssä AddRadioButton-kutsut, jotka välittävät saman ryhmän nimen, kiinnittävät niiden widgetit yhteen yläkenttään, ja kunkin painikkeen vientiarvo ('basic' tai 'full') yksilöi valitun vaihtoehdon. Anna jokaiselle painikkeelle erillinen nimi, niin saat rivin itsenäisiä on/off-kytkimiä yhden toisensa poissulkevan ryhmän sijaan, joka renderöityy identtisesti ja käyttäytyy väärin
Kenttäjoukon luominen sivu kerrallaan
HotPDF sijoittaa kentät THPDFPage-menetelmien avulla, joten jokainen kenttä kuuluu sen luoneelle sivuobjektille. Jaksotusansa, jota kannattaa varoa, on AddPage. Se osoittaa koodin CurrentPage takaisin uudelle sivulle sillä hetkellä, kun se palaa, joten sen jälkeen tullut kenttäkutsu osuu uudelle sivulle silloinkin, kun kenttä loogisesti kuului juuri poistumallesi sivulle. Viimeistele jokainen sivu, piirretty sisältö ja kentät yhdessä, ennen kuin kutsut AddPage
procedure BuildClaimForm(Pdf: THotPDF);
begin
// Sivu 1: hakijalohko
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; // CurrentPage osoittaa nyt sivulle 2
Pdf.CurrentPage.AddListBox('riders', 'None',
['None', 'Flood', 'Earthquake'], Rect(50, 500, 200, 600));
end;
Koordinaatit käyttävät PDF-käytäntöä, jossa alkuperä on sivun vasemmassa alakulmassa. Tämä on sama alkuperä, jota TextOut käyttää piirretylle tekstille, joten Rect(50, 100, 200, 120) on lähellä Letter-sivun alareunaa, ei yläreunaa. VCL asettaa Y:n yläosaan ja kasvattaa sitä alaspäin, joten suoraan poikki siirretty asettelutaulukko tulee ulos pystysuunnassa peilattuna, jokainen kenttä käännettynä sivun väärään päähän. Tee muunnos kerran jaetussa apuohjelmassa kunkin puhelusivuston sijaan, niin yksittäinen korjaus korjaa koko lomakkeen
Painikkeiden kytkeminen URI-, JavaScript- ja lähetystoimintoihin
Painopainike on inertti, kunnes siihen on liitetty toiminto. HotPDF paljastaa toimintatyypit standardista ISO 32000-1 §12.6.4 THPDFButtonAction-luettelon (baURI, baJavaScript, baSubmitURL, baResetForm, baHide, baShow, baNamed) kautta ja tarjoaa kaksi menetelmää, jotka luovat painikkeen ja sitovat sen toiminnan yhdessä puhelussa
// Avaa ohjesivu järjestelmän selaimessa
Pdf.CurrentPage.AddPushButtonWithAction('btnHelp', 'Help',
'https://www.example.com/claims-help', Rect(320, 700, 420, 730), baURI);
// Suorita katseluohjelman puolen JavaScript
Pdf.CurrentPage.AddPushButtonWithAction('btnRecalc', 'Recalculate',
'app.alert("Totals updated.");', Rect(320, 660, 420, 690), baJavaScript);
// Lähetä nimellä XFDF ja pidä tyhjät kentät hyötykuormassa
Pdf.CurrentPage.AddPushButtonWithSubmitAction('btnSubmit', 'Submit claim',
'https://api.example.com/claims', Rect(320, 620, 420, 650),
[sffXFDF, sffIncludeNoValueFields]);
Lähetysliput ansaitsevat enemmän ajattelua kuin he yleensä saavat. AddPushButtonWithSubmitAction ottaa koodin THPDFSubmitFormFlags-joukon, ja tyhjä joukko tuottaa tavallisen url-koodatun postauksen, mikä on muoto, jonka monet esimerkkipäätepisteet hyväksyvät ja monet tuotannon päätepisteet hylkäävät. sffXFDF:n lisääminen vaihtaa hyötykuorman arvoon XFDF. sffGetMethod muuttaa HTTP-verbiä. sffIncludeNoValueFields pitää tyhjät kentät hyötykuormassa sen sijaan, että pudottaisi ne äänettömästi, mikä on tärkeää heti, kun kuluttaja erottaa "poissa" sanasta "tyhjä". Lippusarja on osa käyttöliittymäsopimustasi vastaanottavan päätepisteen kanssa, joten selvitä se lähetyksen jäsentävän tiimin kanssa, ei ensimmäisen hylätyn erän jälkeen
Kenttätason JavaScript: näppäinpainallus, muoto, vahvistus
Painikkeen napsautukset eivät ole ainoa paikka, jossa toiminnot asuvat. HotPDF liittää JavaScriptin myös kenttäkohtaisiin tapahtumiin, jotka komentosarjakykenevät katseluohjelmat käynnistävät käyttäjän syöttäessä tietoja. Laukaisimia on kolme, ja ne laukaisevat syöttämisen elinkaaren eri kohdissa. Näppäinpainallustoiminto suoritetaan jokaisen merkin saapuessa ja uudelleen vahvistuksessa. Muototoiminto kirjoittaa näytettävän arvon uudelleen sen jälkeen, kun muutos on sitoutunut, puhtaasti esittelyä varten. Vahvistustoiminto saa viimeisen sanan hyväksymällä tai kieltäytymällä sitoutuneesta arvosta ennen kuin siitä tulee kentän arvo
// Hylkää sitoutuneet arvot, jotka eivät ole uskottavia sähköpostiosoitteita
Pdf.AttachFieldKeyStrokeAction('applicant.email',
'if (event.willCommit && !/^[\w.-]+@[\w.-]+\.\w+$/.test(event.value)) event.rc = false;');
// Näytä Yhdysvaltain puhelinnumerot muodossa (NNN) NNN-NNNN
Pdf.AttachFieldFormatAction('applicant.phone',
'event.value = event.value.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");');
// Kieltäytyy alle 18-vuotiaista hakijoista sitoutumisaikana
Pdf.AttachFieldValidateAction('applicant.age',
'if (parseInt(event.value) < 18) event.rc = false;');
event.rc = false-asetuksen asettaminen näppäinpainalluksen tai vahvistuskomentosarjan sisällä kehottaa katseluohjelmaa hylkäämään syötteen. Juju on siinä, että mikään tästä ei toimi, ellei katsoja toimita JavaScript-moottoria. Acrobatissa ja muutamassa työpöytätuotteessa on sellainen. Useimmissa mobiililukijoissa, selaimen sisäänrakennetuissa renderöijissä ja tulostusputkissa ei ole, ja ne pudottavat skriptit lattialle ilman valituksia. Joten kenttäskriptit parantavat niiden käyttäjien tiedonlaatua, joiden lukija ajaa niitä, ja se on kaikki, mitä he tekevät. Ne eivät ole turvaraja. Jokainen lähetetty arvo on edelleen vahvistettava palvelimella, kun se saapuu, koska et voi olettaa asiakkaan tarkistaneen mitään
Viat, jotka läpäisevät visuaalisen tarkastuksen
Vaikeimmin havaittavat AcroForm-viat ovat ne, jotka elävät tietorakenteessa renderöinnin sijaan, koska tiedoston avaaminen ja sen katsominen ei kerro sinulle mitään. Neljä nousee esiin riittävän usein ollakseen nimeämisen arvoinen, ja jokaisella on mekaaninen testi, joka löytää sen ennen julkaisua
- Vientiarvo ryömintä. Komennolla
AddCheckBox('consent', 'Yes', ...)luotu valintaruutu kirjaaYes. Kuluttaja, joka vastaa hakutermiäY, hylkää kaikki lähetetyt tiedot, vaikka sivu näyttää täydelliseltä. Täytä lomake, vie se XFDF-muodossa Acrobatista ja vertaa arvoja skeemaan, jota kuluttaja todella odottaa - Satunnainen arvon peilaus. Kaksi kenttää, joilla on sama täysin pätevä nimi, sulautuvat yhdeksi. Oire ilmenee tiedonsyöttöhetkellä eikä koskaan generoinnin hetkellä, joten testi on kirjoittaa lomakkeeseen, ei renderöidä sitä ja arvioida tulosta silmämääräisesti
- Yhdistelmäarvot asetusluettelon ulkopuolella. Kun kohtaan
AddComboBoxvälitetty nykyinen arvo ei ole mikään luetelluista vaihtoehdoista, katselijat ovat eri mieltä siitä, näytetäänkö se, jätetäänkö se tyhjäksi vai merkitäänkö se. Pidä oletusarvo luettelon sisällä, ja erimielisyys katoaa - Kenttiä voidaan muokata edelleen työnkulun sulkemisen jälkeen. HotPDF:ssä ei ole ulkonäön litistävää kutsua AcroForm-kentille. Tuettu tapa jäädyttää valmis lomake on luoda kentät lipulla
ffReadOnly, mikä pitää arvon näkyvissä kentän oman ulkonäkövirran kautta samalla, kun kieltäydytään muokkauksista. Kenttä pysyy elävänä lomakeobjektina, ja sen loppupään kokoamis- ja allekirjoitustyökalut odottavat löytävän
Yksi katsojapuolen käyttäytyminen on huomioimisen arvoinen, vaikka yksikään koodimuutos ei koske sitä. Enterprise Acrobatin käyttöönotot voivat poistaa JavaScriptin käytöstä tai rajoittaa kohteiden lähetystä käytäntöjen perusteella, jolloin toiminto, joka on toiminut jokaisen kehitysversion läpi, voi olla kuollut lukitun asiakkaan työpöydällä. Suunnittele näkyvä varatoimi siinä tapauksessa, että painike ei tee mitään, vaikka kyseinen varajärjestely olisikin vain painettu ohje, jossa käyttäjää neuvotaan, mitä tehdä sen sijaan
Missä muototyöt yhdistyvät muuhun asiakirjaan
Allekirjoituskenttä on itsessään AcroForm-kenttätyyppi. Lomake, joka sertifioidaan tai allekirjoitetaan vastavuoroisesti myöhemmin, on parempi varata tämä kenttä sukupolven aikana kuin liittää se myöhemmin. Tavutason syyt tähän ovat digitaalisia allekirjoituksia ja PAdES-allekirjoittamista HotPDF:n avulla käsittelevässä rinnakkaisartikkelissa. Syötteet, jotka saapuvat XFA-paketteina natiivi AcroFormin sijaan, ovat erilainen tilanne: XFA:n tasoittaminen AcroForm-kentiksi on oma työnkulkunsa ja oma tappiomallinsa, koska kaksi muototekniikkaa eivät voi olla rinnakkain yhdessä tiedostossa
Tässä esitetyt kenttä-, toiminta- ja laukaisumenetelmät ovat osa standardia HotPDF Component API:a Delphille ja C++Builderille; Tuotesivulla on linkki täyteen referenssiin, mukaan lukien field-flag-ylikuormitukset ja koko submit-lippujen luettelointi