Runtime Interattivo dei Widget XFA Dinamici
TXFAWidgetRuntime offre un modello di interazione neutrale rispetto all'host per i form XFA dinamici, senza convertirli in campi AcroForm né appiattirne il contenuto
Il runtime espone bounds e stato deterministici dei widget, così un desktop, un servizio o un renderer personalizzato può fornire il proprio input, la propria pittura, la propria accessibilità e il proprio event loop
Creare un runtime
Creare il runtime direttamente dai byte XDP oppure chiamare THotPDF.CreateLoadedXFAWidgetRuntime dopo aver caricato un PDF il cui AcroForm contiene una voce /XFA a stream singolo o a array di pacchetti
var
Runtime: TXFAWidgetRuntime;
State: TXFAWidgetState;
begin
Runtime := PDF.CreateLoadedXFAWidgetRuntime;
try
if (Runtime <> nil) and (Runtime.WidgetCount > 0) then
begin
State := Runtime.Widgets[0];
Runtime.FocusWidget(State.ID);
Runtime.BeginEdit(State.ID);
Runtime.ReplaceSelection(0, Length(State.Value), 'Updated value');
if not Runtime.CommitEdit then
raise Exception.Create(Runtime.LastDiagnostic);
end;
finally
Runtime.Free;
end;
end;
La factory del documento caricato è di sola lettura rispetto al grafo di oggetti PDF e agli XFAFlattenWarnings esistenti; il salvataggio del documento conserva le sue voci originali /XFA e /NeedsRendering
Modello di interazione
FocusWidgeteClearFocusmantengono un unico widget con focus e pubblicano callback di focus ordinateBeginEdit,ReplaceSelection,CancelEditeCommitEditpreservano il testo Unicode inclusi gli spazi iniziali e finaliHitTestmappa le coordinate di pagina sul widget visibile più in altoOnWidgetInvalidated,OnLayoutChangedeOnFocusChangedpermettono all'host di aggiornare solo lo stato interessato
I commit interattivi sincronizzano i valori scalari nativi esistenti negli alias nascosti e invisibili, inclusi i veri scope di dati ripetuti e il rollback byte-esatto
Validazione e calcolo atomici
Un commit risolve i binding SOM espliciti e il contesto dati corrente delle righe ripetute prima di eseguire gli script validate e calculate
Il valore modificato, i valori calcolati, i nodi dati, il modello del widget, lo stato di focus ed editing, gli avvisi e i contatori dei passaggi vengono pubblicati insieme solo dopo che validazione e layout si sono stabilizzati
Script rifiutati, budget esauriti, confini di selezione UTF-16 non validi ed eccezioni di layout o di misura dell'host ripristinano lo stato precedente completo e impostano LastDiagnostic
Budget
TXFAWidgetRuntimeOptions limita il numero di widget, la lunghezza dei valori modificati, i passaggi di calcolo, i passaggi di reflow, le operazioni di layout, le operazioni degli script, il tempo trascorso negli script e altre risorse FormCalc o JavaScript
Il tetto sui widget si applica mentre gli elementi di layout e i frammenti di impaginazione vengono aggiunti, mentre la decompressione XFA del documento caricato e l'assemblaggio dei pacchetti si fermano al limite di input del DOM XFA, prima del parsing
MaxLayoutOperations vale 200000 per default e limita sia l'attraversamento del documento sia il lavoro di layout; la profondità del layout è limitata a 128, quella dei target di evento e dell'inizializzazione delle istanze a 64, e il dispatch ricorsivo di eventi viene rifiutato
Eventi dinamici ristretti
DispatchEvent accetta operazioni letterali separate da punto e virgola negli event script dei campi corrispondenti con content type FormCalc o JavaScript; queste operazioni vengono analizzate direttamente e non richiedono una DLL JavaScript
row.instanceManager.addInstance(true);
row.instanceManager.removeInstance(0);
target.presence = "hidden";
addInstance aggiunge un'istanza e accetta true, false, 1 o 0 come argomento di merge; un argomento omesso usa true, e la forma breve _row.addInstance(1) è accettata allo stesso modo
Il modello supportato lega ogni gruppo dati omonimo esistente, così una nuova istanza riceve un nuovo gruppo dati inizializzato dai valori predefiniti del template per entrambi gli argomenti di merge; la creazione di istanze non clona i valori inseriti nella riga precedente
removeInstance usa un indice intero a base zero tra i gruppi dati omonimi del subform selezionato; il subform deve avere un elemento occur con un massimo ripetibile, ed entrambe le operazioni fanno rispettare il suo minimo e massimo, incluso max="-1"
La mutazione delle istanze richiede binding implicito a dataset nominato e nomi dati XML ASCII; il binding esplicito per riferimento dati e i contesti padre ambigui vengono rifiutati prima di pubblicare la transazione
I target si risolvono attraverso i figli nominati del template negli ambiti che contengono l'evento, inclusi i path puntati e this.parent; un manager annidato dentro un ambito ripetuto usa il gruppo dati dell'evento stesso
presence accetta visible, hidden e invisible su campi, draw, subform ed exclusion group del template; il contenuto hidden non occupa spazio nel flusso, mentre il contenuto invisible conserva il suo spazio e viene omesso dai widget e dall'output del flatten
Le modifiche di presence si applicano al nodo del template selezionato e quindi a tutte le sue occorrenze ripetute; la presence indicizzata per istanza, inactive, espressioni arbitrarie, variabili, condizionali, cicli e altre operazioni di event script vengono rifiutate
Un batch di eventi pubblica insieme modifiche dei dati, calcoli, layout, focus e stato di editing dopo che il reflow si è stabilizzato; qualsiasi operazione rifiutata o budget esaurito di input, operazioni, istanze, valori, widget, layout o tempo trascorso ripristina il completo stato precedente del documento e dell'interazione
La rimozione di una riga preserva focus e modifiche in sospeso per i gruppi dati superstiti anche quando i loro indici di widget cambiano; rimuovere o nascondere il widget con focus azzera il focus e pubblica il callback di focus corrispondente dopo il successo
Esecuzione generale di eventi JavaScript e FormCalc
Impostate TXFAWidgetRuntimeOptions.ScriptOptions.EnableJavaScript per abilitare il bridge QuickJS limitato fornito per l'esecuzione degli eventi; gli eventi JavaScript supportano allora funzioni, closure, array, condizioni, cicli ed eccezioni anziché la grammatica letterale predefinita
Options := TXFAWidgetRuntimeOptions.Default;
Options.ScriptOptions.EnableJavaScript := True;
Runtime := TXFAWidgetRuntime.Create(XDPBytes, 595, 842, Options);
L'host degli eventi espone this, i campi e i subform nominati circostanti, parent, rawValue scrivibile, presence e access, instanceManager.count/min/max, addInstance, removeInstance, insertInstance, moveInstance e setInstances, xfa.resolveNode, xfa.resolveNodes, risoluzione a livello di nodo e xfa.layout.relayout
Le liste di nodi supportano indicizzazione numerica, length e item; i valori ripetuti dei campi conservano i propri dataset target, e i path SOM accettano figli nominati con indici numerici o wildcard per i nodi host vivi
const values = xfa.resolveNodes("main.row[*].amount[*]");
let total = 0;
for (const field of values) total += Number(field.rawValue);
xfa.resolveNode("main.total").rawValue = total;
if (total > 100) this.parent.warning.presence = "visible";
Ogni subform ripetuto ha il proprio oggetto vivo e i propri campi figli; index, i getter dei figli del padre e le query SOM successive seguono immediatamente dentro lo script le operazioni di insert, move e remove
addInstance e insertInstance restituiscono un sottoalbero vivo inizializzato dai valori predefiniti del template, così lo script può scrivere i valori dei suoi campi prima che l'evento pubblichi; gli handle rimossi respingono letture o scritture successive
Le modifiche di presence e access degli script generali persistono nel consueto pacchetto form XFA per occorrenza, mentre i valori dei campi e le operazioni di ripetizione persistono in datasets; insert, move e remove mantengono lo stato di form corrispondente allineato ai gruppi di dati
Con lo stesso opt-in, gli script di eventi FormCalc vengono compilati nel motore limitato e supportano var, if/elseif/else, for con upto o downto, while, foreach, func con risultati impliciti, aritmetica e confronti, concatenazione di stringhe, aggregazione di nodi wildcard e assegnazione implicita del valore dei campi
La libreria di funzioni degli eventi include Sum, Count, Avg, Min, Max, Round, le comuni funzioni matematiche, slicing di stringhe, conversione di maiuscole/minuscole, trimming, sostituzione, HasValue, Exists, Within, Oneof e Choose; i nomi integrati non distinguono il maiuscolo, At(source, search) segue l'ordine degli argomenti XFA compreso il comportamento di ricerca vuota, le funzioni finanziarie seguono l'ordine dei parametri XFA, e i cataloghi di date e finanza sono descritti in Funzioni FormCalc
Le mutazioni degli script vengono registrate dentro il motore, validate e rieseguite dentro la transazione del runtime; eccezioni, interruzioni, Unicode non valido, operazioni host non valide e budget esauriti non pubblicano alcuna modifica parziale del documento
L'esecuzione generale degli script resta disattivata per impostazione predefinita, non usa browser né processi esterni, e non espone API del filesystem, di rete o dell'applicazione; il chiamante può fornire JavaScriptEvaluator al posto del bridge
Oggetti script persistenti
Gli oggetti script JavaScript dentro l'elemento variables di un subform espongono le loro variabili e funzioni attraverso il nome dello script; le variabili lessicali, lo stato degli oggetti e le closure annidate restano vivi per la sessione del runtime, con il consueto shadowing lessicale e le direttive strict preservati
<variables>
<script name="Helpers" contentType="application/x-javascript"><![CDATA[
let count = 0;
const nextPrivate = (() => { let value = 0; return () => ++value; })();
function next() { return ++count + ":" + nextPrivate(); }
]]></script>
</variables>
Il codice degli eventi può chiamare Helpers.next(); le occorrenze ripetute dei subform possiedono oggetti script indipendenti, e le funzioni risolvono i campi nominati contro il contesto form vivo corrente
I nodi di campo e i manager catturati seguono l'identità stabile dei dati attraverso gli spostamenti e la pubblicazione di istanze appena create; accedere a un nodo rimosso respinge l'evento e ripristina lo stato del suo modulo
Gli script generali di calculate e validate condividono la sessione e gli oggetti script; JavaScript supporta valori di completamento impliciti e return esplicito, mentre FormCalc restituisce la sua espressione finale
Le transazioni fallite ripristinano lo stato lessicale e delle closure rieseguendo il giornale virtuale confermato, con tempo e input casuali registrati; replay ed esecuzione corrente condividono il deadline della transazione, e i limiti predefiniti del giornale sono 64 MiB di script/risultati e 8192 voci
Lo stato degli script-object vive nella sessione del runtime e viene inizializzato di nuovo dopo il ricaricamento dell'XDP; i valori standard del documento e gli override del form continuano a persistere attraverso SaveToBytes
I callback personalizzati JavaScriptEvaluator conservano l'esistente envelope nativo calculate/validate; la sessione persistente è fornita dal motore fornito
Configurare il trasporto host esplicito
Impostate HostTransport e l'opzionale OnHostTransactionCompleted in TXFAWidgetRuntimeOptions per eseguire dialoghi dell'host, stampa, navigazione, submission e trasferimento dati attraverso callback dell'applicazione
Il trasporto host XFA esplicito fornisce xfa.host.messageBox, response, beep, print, gotoURL, submitForm, importData, exportData e FormCalc Get, Post e Put; l'applicazione restituisce risultati tipizzati e controlla gli effetti esterni
I retry e il replay della sessione usano le risposte registrate, così i callback vengono eseguiti una volta per richiesta inviata; il completamento con fallimento permette all'applicazione di scartare gli effetti preparati o di compensare le operazioni reversibili
HostTransportLimits positivi limitano il numero di richieste, il numero di argomenti e i byte aggregati di richiesta/risposta attraverso la transazione del runtime circostante
Esecuzione di locale e picture
Gli eventi FormCalc generali e gli script calculate e validate supportano le funzioni di locale e picture, comprese Format, Parse, conversioni di data/ora localizzate, unità, codifica, UUID e numeri in parole inglesi
L'Eval FormCalc dinamico esegue calcoli forniti dinamicamente con variabili e funzioni isolate, accesso relativo ai campi, compilazione nativa, risposte registrate e rollback transazionale
I riferimenti FormCalc espliciti supportano assegnazione write-through, rebind, distacco di null, argomenti di funzione e handle stabili trattenuti dagli script-object attraverso il movimento di istanze ripetute
I path SOM vivi supportano indici di occorrenza dedotti, assoluti e relativi, selettori di classe e discendenti, contenitori trasparenti, predicati candidati e assegnazione indicizzata FormCalc diretta
Il Data DOM nativo espone i datasets attraverso $data e $record, sincronizza immediatamente letture e scritture del form agganciate, rispecchia le istanze ripetute e preserva i riferimenti ai dati trattenuti attraverso la pubblicazione di identità nativa
Il Property DOM nativo espone i figli di proprietà dichiarati value, font, UI e altri, sincronizza i valori tipizzati dei campi e persiste gli attributi per istanza usati dalla misura dei font e dallo stile flatten supportato
Il nodo in esecuzione eredita il suo attributo locale più vicino; le voci localeSet del documento sovrascrivono simboli e pattern di sistema, mentre i nomi di locale calcolati vengono risolti attraverso richieste interne limitate e preservati nel giornale di sessione
Num2Date senza picture usa ora il pattern di data predefinito ambiente; fornite YYYY-MM-DD esplicitamente quando serve output ISO
Modello host con stato
Il modello host XFA fornisce metadati dell'applicazione, conteggio reale delle pagine, navigazione delle pagine, titolo Unicode, flag di calcolo/validazione, reset con scope e focus dei campi con ciclo di vita transazionale enter/exit
TXFAWidgetRuntimeOptions.HostModel configura lo stato iniziale dell'applicazione; TXFAWidgetRuntime.HostModel restituisce lo stato corrente, e gli eventi falliti lo ripristinano insieme agli snapshot del documento e dell'interazione
Uno spostamento di focus senza script enter/exit, modifica in sospeso o ciclo di vita inizializzato cambia il focus senza avviare calcolo degli script o elaborazione del deadline; focus scripted e commit di modifiche in sospeso usano comunque budget transazionali, validazione e ricalcolo
Le clausole picture avanzate vengono eseguite attraverso le stesse transazioni del runtime, il giornale di retry della locale e il ciclo di vita dei calcoli, con parsing composto limitato
Inizializzare e mantenere il ciclo di vita
Chiamate InitializeForm dopo aver configurato il runtime e i callback per eseguire gli eventi initialize nell'ordine del template, poi calculate e validate, gli eventi form-ready e gli eventi layout-ready; la chiamata è idempotente dopo il successo
Le nuove istanze create dall'inizializzazione o dagli eventi ready ricevono i propri eventi initialize prima dei loro handler ready; l'esecuzione layout-ready si ripete solo quando il layout cambia, entro i budget di reflow e transazione
Dopo l'inizializzazione, un dispatch di evento riuscito e un commit di modifica inizializzano le istanze appena create ed eseguono calculate, validate e layout-ready; le occorrenze esistenti conservano il loro stato di inizializzazione attraverso spostamenti e rollback transazionale
I fallimenti del ciclo di vita ripristinano insieme byte del documento, interazione dei widget e contabilità di inizializzazione, e i callback pubblicano solo dopo che la transazione circostante ha successo
Salvare il form aggiornato
SaveToBytes restituisce l'XDP aggiornato completo del runtime, inclusi i dataset modificati e gli attributi di presence del template; usa questi byte con SetXFADocument quando scrivi un PDF o con HPDFXFAFlatten per l'output del flatten aggiornato
La factory del documento caricato crea un runtime indipendente, quindi gli eventi del runtime non modificano automaticamente il grafo di oggetti del PDF sorgente
Profilo opzionale di presentazione delle istanze
Dynamic XFA Instance Presentation aggiunge binding ripetuti espliciti, ID stabili per istanza, presence e access indicizzati, eventi condizionali limitati, pittura della canvas dell'host e accessibilità attraverso un helper indipendente; il runtime predefinito e la sua grammatica di eventi ristretta restano compatibili
UpdateDocument fornisce azioni documentali transazionali; callback opzionali di proprietà del runtime, scope di binding, identità, risoluzione avviata e validazione del documento supportano l'helper, mentre i default nil preservano i chiamanti esistenti
API di eventi e form di livello più basso
HPDFXFACompileFormCalcEvent compila la sintassi degli eventi; HPDFXFAExecuteJavaScriptEvent esegue il contesto virtuale descritto da TXFAEventBinding e TXFAEventBindings
TXFAJavaScriptSession fornisce esecuzione persistente e checkpoint limitati per i chiamanti di livello più basso
I valori TXFAEventAction restituiti usano TXFAEventActionKind; il replay transazionale è fornito dal runtime
HPDFXFAResolveFormInstanceNode e HPDFXFAResolveFormInstanceProperty forniscono una ricerca limitata del pacchetto form standard
Confini attuali
Il runtime è un oggetto host single-thread e non fornisce una GUI, un painter o un motore generale di event-script XFA
L'ingresso e l'uscita dal focus sono supportati direttamente quando non esiste un event script corrispondente; le operazioni di evento ristrette non implicano il supporto di JavaScript completo, FormCalc, eventi del ciclo di vita XFA o un form DOM separato con override di presentazione per istanza
Vedere FormCalc e JavaScript XFA limitati, DOM dei pacchetti XFA e Elaborazione interattiva dei documenti