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

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