PDF formos laukas pats savaime yra tik langelis, kuriame saugoma reikšmė. Tai, kas priverčia formą veikti kaip nedidelę programą, yra prie jos pridėtas veiksmas: spustelėjimas, kuris paslepia sekciją, ištraukia išsaugotas reikšmes iš failo, peršoka į paskutinį puslapį arba paleidžia scenarijų, kuris susumuoja stulpelį. Nieko iš to nėra pačiame lauke. Tai yra veiksmų žodyne, o ISO 32000-1 visą šeimą organizuoja §12.6 skyriuje. Šiame straipsnyje apžvelgiami veiksmai, kuriuos Delphi programa naudoja dažniausiai, ir parodoma, kaip PDFlibPas susieja kiekvieną iš jų su lauku arba nuoroda
Verta atsiminti protinį modelį, kad laukas ir veiksmas yra atskiri objektai, sujungti nuoroda. Valdiklio anotacija (angl. widget annotation) arba nuorodos anotacija nešiojasi veiksmą savo /A įraše. Veiksmas nurodo lauką, kurį jis valdo, pagal pavadinimą, o ne pagal indeksą, todėl laukui suteiktas pavadinimas yra rankena, kurią visi vėlesni veiksmai naudoja jam rasti. Kai šis atskyrimas tampa aiškus, API nustoja atrodyti kaip atsitiktinių iškvietimų rinkinys ir pradeda atrodyti kaip vienas modelis, taikomas keturių rūšių veiksmams
Vardiniai veiksmai: navigacija be puslapio numerio
Paprasčiausi veiksmai išvis neturi jokių parametrų. ISO 32000-1 §12.6.4.11 skyriuje, 194 lentelėje, apibrėžiami vardiniai veiksmai: peržiūros programa vykdymo metu interpretuoja simbolinį pavadinimą, užuot sekusi išsaugotą paskirties vietą. Visuotinai palaikomi keturi pavadinimai, ir jie yra būtent tie, kurių skaitytojas tikisi iš įrankių juostos: NextPage, PrevPage, FirstPage ir LastPage. Kadaangi paskirties vieta yra santykinė su puslapiu, kurį šiuo metu rodo peržiūros programa, tokiu būdu sukurtas mygtukas „Kitas“ veikia kiekviename puslapyje, jums neapskaičiuojant tikslo
PDFlibPas programoje vardinis veiksmas yra pridedamas prie aktyviosios srities stačiakampio dabartiniame puslapyje. Ketvirtasis ir penktasis sveikojo skaičiaus argumentai parenka veiksmą ir išvaizdą
// NamedActionType: 0 = NextPage, 1 = PrevPage, 2 = FirstPage, 3 = LastPage
// Options bit 0 (value 1) draws a border around the hotspot
Pdf.AddLinkToNamedAction(500, 560, 60, 18, 0, 1); // Next
Pdf.AddLinkToNamedAction(40, 560, 60, 18, 1, 1); // Previous
Pdf.AddLinkToNamedAction(110, 560, 60, 18, 3, 1); // jump to last page
Nėra jokios paskirties vietos, kurią reikėtų sinchronizuoti, ir tai yra visa esmė. Vardinis veiksmas išlieka po puslapio įterpimo ir ištrynimo, nes jis niekada nenurodo paties puslapio. Palyginkite tai su aiškia nuoroda „eiti į“, kurioje saugomas tikslinio puslapio indeksas, kurį turite pernumeruoti, kai tik dokumentas padidėja
Veiksmas Hide ir jo masyvo spąstai
Veiksmas Hide, apibrėžtas ISO 32000-1 §12.6.4.10 skyriuje, 196 lentelėje, perjungia vieno ar kelių laukų matomumą. Tai yra švariausias būdas sukurti rodymo ir slėpimo elgseną be scenarijų, ir būtent to norite nuorodai „Rodyti išsamią informaciją“ arba dviem viena kitą išskiriančioms panelėms, kur vienos atskleidimas paslepia kitą. Veiksmas nešiojasi tikslą savo /T įraše ir loginę reikšmę /H, kuri nustato kryptį: paslėpti, kai true, rodyti, kai false
Subtilumas slypi tame, kaip tas tikslas yra koduojamas, ir tai yra tokia detalė, dėl kurios forma gali veikti jūsų kompiuteryje, bet neveikti kliento. Kai veiksmas nurodo vieną lauką, /T rašomas kaip viena teksto eilutė. Kai nurodo kelis, /T rašomas kaip teksto eilučių masyvas. Senesnės peržiūros programos vieno elemento masyvo nevertina taip pat, kaip paprastos eilutės, todėl kodavimas turi priklausyti nuo skaičiaus: vienas pavadinimas turi būti išsiųstas kaip eilutė, o ne kaip vieno ilgio masyvas, kad jį gerbtų kuo daugiau skaitytuvų. PDFlibPas priima šį sprendimą už jus. Lauko pavadinimus perduodate atskirtus kableliais, kabliataškiais arba eilučių lūžiais, o rašytuvas išveda vieną eilutę vienam pavadinimui ir masyvą dviem ar daugiau
// HideFlag non-zero hides the listed fields (/H true); zero shows them.
// One name -> /T is a text string. Two or more -> /T is an array of strings.
Pdf.AddLinkToHideField(40, 700, 90, 18, 'ShippingAddress', 1, 1);
Pdf.AddLinkToHideField(140, 700, 90, 18,
'ShippingName,ShippingAddress,ShippingZip', 1, 1);
Kadangi veiksmas nenurodo jokio išorinio ištekliaus, jis išlieka suderinamas su PDF/A. Pavadinimai, kuriuos perduodate, yra pilnai kvalifikuoti laukų pavadinimai, todėl antrinis laukas grupėje turi būti adresuojamas per visą jo taškais atskirtą kelią, o ne tik pagal jo tiesioginį pavadinimą
ImportData: išankstinis užpildymas iš FDF
Kai veiksmas Hide pertvarko tai, kas jau yra puslapyje, duomenų importavimo veiksmas įneša reikšmes iš išorės. ISO 32000-1 §12.6.4.8 skyriuje, 198 lentelėje, jis apibrėžiamas kaip veiksmas, kuris užpildo AcroForm iš diske esančio Forms Data Format failo. Tai yra veiksmas, stovintis už valdiklio „Įkelti pavyzdinius duomenis iš naujo“ arba „Atstatyti numatytuosius nustatymus“, kai FDF failas pristatomas šalia PDF ir jame saugomos kanoninės lauko reikšmės. Iškvietimas atspindi kitus, priimdamas aktyviosios srities stačiakampį, kelią iki FDF ir išvaizdos bitų kaukę: Pdf.AddLinkToImportData(40, 660, 120, 18, 'defaults.fdf', 1). Failas neprivalo egzistuoti, kai kuriamas PDF, tačiau jis turi būti, kai vartotojas spusteli, o bet kokie atgaliniai brūkšniai kelyje yra perrašomi į PDF kanoninę brūkšnio formą už jus
Vieną apribojimą verta įvardyti aiškiai, nes jis dažnai stebina. Duomenų importavimo veiksmas nurodo išorinį failą, todėl jis neleidžiamas PDF/A. Kai dokumentas yra PDF/A režime, iškvietimas grąžina nulį ir nieko neprideda, užuot sukūręs failą, kuris nepraeina patvirtinimo. Jei jūsų konvejeris orientuotas į archyvinę išvestį, išankstinis užpildymas turi įvykti generavimo metu tiesiogiai įrašant lauko reikšmes, o ne atidedant jas spustelėjimui
JavaScript: globalūs paketai ir scenarijai atskiriems veiksmams
Logikai, kuri viršija rodymą, slėpimą ir importavimą, veiksmų šeima naudoja dokumento lygio JavaScript. Yra dvi skirtingos vietos, kuriose gali gyventi scenarijus, ir šis skirtumas yra svarbus. Dokumento lygio JavaScript paketas saugomas vieną kartą visam failui ir paleidžiamas atidarius dokumentą, todėl tai yra tinkama vieta funkcijų apibrėžimams ir bendrai būsenai. Vieno veiksmo scenarijus yra pridedamas prie vienos nuorodos ar lauko ir veikia tik tada, kai tas objektas yra aktyvuojamas, todėl tai yra tinkama vieta vienai eilutei, kuri iškviečia paketų jau apibrėžtą funkciją
PDFlibPas atskleidžia abu. AddGlobalJavaScript išsaugo įvardytą paketą dokumento lygyje; pakartotinis pavadinimo naudojimas pakeičia viską, kas buvo po juo saugoma. AddLinkToJavaScript prideda scenarijų prie aktyviosios srities, kad spustelėjimas jį įvykdytų
// Document-level package: define a reusable function once.
Pdf.AddGlobalJavaScript('Totals',
'function recalcTotal() {' +
' var net = this.getField("Net").value;' +
' var tax = this.getField("Tax").value;' +
' this.getField("Gross").value = Number(net) + Number(tax);' +
'}');
// Per-action script on a link: just call the shared function.
Pdf.AddLinkToJavaScript(40, 620, 100, 18, 'recalcTotal();', 1);
Funkcijos laikymas globaliame pakete, o iškvietimo – nuorodoje nėra stiliaus pasirinkimas. Taip išvengiama to paties turinio dubliavimo kiekviename valdiklyje, kuriam jo reikia, o tai reiškia, kad peržiūros programa su išjungtais scenarijais tiesiog nieko nedaro spustelėjus, užuot užspringusi dėl netinkamai suformuoto inline objekto. Tai taip pat išlaiko mažus atskirų veiksmų įrašus, todėl failas lieka skaitomas, kai jį vėliau tikrinate
Laukai, antriniai laukai ir rezultato užšaldymas
Veiksmams reikia laukų, kuriuos jie galėtų paveikti, todėl naudinga pamatyti, kaip atsiranda laukas. NewFormField sukuria lauką dabartiniame puslapyje ir grąžina jo indeksą; sveikojo skaičiaus tipas pasirenka rūšį, kur 1 yra tekstas, 2 yra mygtukas, 3 yra žymimasis langelis, 4 yra radijo mygtukas, 5 yra pasirinkimas, 6 yra parašas, o 7 yra pirminis laukas, kuriam priklauso antriniai laukai, bet pats nieko nebrėžia. Perduodamas pavadinimas negali turėti taško, nes taškas yra separatorius pilnai kvalifikuotuose pavadinimuose, kuriuos veiksmai naudoja antriniams laukams adresuoti
Radijo mygtukų grupės ir hierarchinės formos yra kuriamos suteikiant pirminiam laukui antrinius laukus. NewChildFormField prideda antrinį lauką po įvardytu pirminiu, o radijo ir pasirinkimo atvejais AddFormFieldSub prideda atskiras parinktis ir grąžina laikiną indeksą, kurį naudojate kiekvieno iš jo padėčiai nustatyti. Kai interaktyvioji fazė baigiasi ir norite užšaldyti lauką, kad dabartinė jo išvaizda taptų nuolatiniu puslapio turiniu, FlattenFormField nupiešia lauką puslapyje ir pašalina jį iš formos. Po užšaldymo vėlesnių laukų indeksai pasislenka žemyn per vieną, ir tai yra vienintelis dalykas, kurį reikia atsiminti, jei užšaldote kelis laukus cikle
var
Pdf: TPDFlib;
FldShip: Integer;
begin
Pdf := TPDFlib.Create;
try
Pdf.SetOrigin(1); // top-left origin
Pdf.SetPageSize('A4');
Pdf.NewPage;
// A text field the Hide action will target by its title.
FldShip := Pdf.NewFormField('ShippingAddress', 1);
Pdf.SetFormFieldBounds(FldShip, 40, 120, 240, 20);
Pdf.SetFormFieldValue(FldShip, '');
// Wire a Hide link and a navigation link to this page.
Pdf.DrawText(40, 110, 'Toggle shipping block:');
Pdf.AddLinkToHideField(220, 100, 70, 16, 'ShippingAddress', 1, 1);
Pdf.AddLinkToNamedAction(500, 800, 60, 18, 3, 1); // Last page
// A document-level script available to every event in the file.
Pdf.AddGlobalJavaScript('OnOpen',
'app.alert("Form ready", 3);');
// Freeze the field if the output should no longer be editable.
// Pdf.FlattenFormField(FldShip);
if Pdf.SaveToFile('form_actions.pdf') <> 1 then
raise Exception.Create('Save failed');
finally
Pdf.Free;
end;
end;
Užšaldymo iškvietimas yra užkomentuotas tyčia. Palikite jį nuošalyje, ir dokumentas bus išsiųstas kaip gyva forma, kurios veiksmai bus suaktyvinti skaitytuve. Įjunkite jį, ir laukas bus paverstas statinėmis žymėmis, o to norite, kai forma yra užpildyta ir rezultatas turi keliauti kaip fiksuotas įrašas. Tas pats laukas, tas pats kodas, du labai skirtingi dokumentai, priklausomai nuo to, ar jį užšaldysite
Tinkamo veiksmo parinkimas
Keturi veiksmai aiškiai pasiskirsto pagal tai, ką jie veikia. Vardinis veiksmas perkelia žiūrėjimo sritį ir jam nereikia jokio lauko. Veiksmas Hide keičia matomumą ir jam reikia laukų pavadinimų, o eilutės ir masyvo kodavimas atliekamas už jus. Duomenų importavimo veiksmas pasiekia faile esantį diską, todėl jis neleidžiamas PDF/A. JavaScript veiksmas paleidžia savavališką logiką ir jį geriausia padalyti į globalų funkcijų paketą bei mažuosius iškvietimus atskiriems veiksmams. Naudokite paprasčiausią, kuris atlieka darbą: Hide veiksmas yra labiau nešiojamas nei scenarijus, nustatantis paslėptą vėliavėlę, o vardinis veiksmas yra patvaresnis nei išsaugota puslapio paskirties vieta, nes nereikia prižiūrėti jokio numerio
Toliau vaizdą užbaigia dvi gretimos temos. Jei forma yra prieinamo dokumento dalis, struktūros medis, kuriuo vaikšto ekrano skaitytuvai, yra aprašytas mūsų straipsnyje apie pažymėtą PDF ir prieinamumo struktūrą. Kai užpildyta forma turi būti užrakinta ir pasirašyta, darbo eiga aprašoma atitikties ir pasirašymo darbo stalo apžvalgoje. Visi trys yra sukurti naudojant tą patį variklį, kuris platinamas kaip PDF biblioteka, skirta Delphi šalia kūrimo, formų ir parašų API, aprašytų kitur šiame tinklaraštyje