Runtime de widgets XFA dinámicos interactivos

TXFAWidgetRuntime aporta un modelo de interacción neutral al host para formularios XFA dinámicos sin convertirlos en campos AcroForm ni aplanar su contenido

El runtime expone bounds y estado deterministas de los widgets para que un renderizador de escritorio, un servicio o uno propio pueda aportar su propia entrada, pintado, accesibilidad y event loop

Creación de un runtime

Cree el runtime directamente desde bytes XDP o llame a THotPDF.CreateLoadedXFAWidgetRuntime tras cargar un PDF cuyo AcroForm contenga una entrada /XFA de stream único o de array de packets

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 fábrica de documentos cargados es de solo lectura respecto al grafo de objetos PDF y a los XFAFlattenWarnings existentes; al guardar, el documento conserva sus entradas /XFA y /NeedsRendering originales

Modelo de interacción

Los commits interactivos sincronizan los valores escalares nativos existentes en los alias hidden e invisible, incluidos los ámbitos de datos repetidos reales y un rollback byte a byte

Validación y cálculo atómicos

Un commit resuelve los bindings SOM explícitos y el contexto de datos de fila repetida actual antes de ejecutar los scripts validate y calculate

El valor editado, los valores calculados, los nodos de datos, el modelo de widgets, el estado de foco y edición, los avisos y los contadores de pasadas se publican juntos solo después de que la validación y el layout se estabilicen

Los scripts rechazados, los presupuestos agotados, los boundaries de selección UTF-16 no válidos y las excepciones de layout o de medición del host restauran el estado previo completo y establecen LastDiagnostic

Presupuestos

TXFAWidgetRuntimeOptions limita el número de widgets, la longitud del valor editado, las pasadas de cálculo, las pasadas de reflow, las operaciones de layout, las operaciones de script, el tiempo transcurrido de script y otros recursos de FormCalc o JavaScript

El límite de widgets se aplica mientras se añaden items de layout y fragmentos de paginación, mientras que la descompresión del XFA cargado y el ensamblado de packets se detienen en el límite de entrada del XFA DOM antes del parsing

MaxLayoutOperations vale 200000 por defecto y acota tanto el recorrido del documento como el trabajo de layout; la profundidad de layout se limita a 128, la profundidad de destino de eventos y de inicialización de instancias a 64, y el despacho recursivo de eventos se rechaza

Eventos dinámicos literales por defecto

DispatchEvent acepta operaciones literales separadas por punto y coma en scripts de eventos de campo coincidentes con tipos de contenido FormCalc o JavaScript; estas operaciones se analizan directamente y no requieren una DLL de JavaScript

row.instanceManager.addInstance(true);
row.instanceManager.removeInstance(0);
target.presence = "hidden";

addInstance añade una instancia y acepta true, false, 1 o 0 como argumento de merge; un argumento omitido usa true, y la forma abreviada _row.addInstance(1) también se acepta

El modelo soportado vincula todos los grupos de datos homónimos existentes, de modo que una instancia nueva recibe un grupo de datos nuevo inicializado con los valores por defecto de la plantilla para cualquier argumento de merge; la creación de instancias no clona los valores introducidos de la fila anterior

removeInstance usa un índice entero basado en cero entre los grupos de datos homónimos del subform seleccionado; el subform debe tener un elemento occur con un máximo repetible, y ambas operaciones hacen cumplir su mínimo y su máximo, incluido max="-1"

La mutación de instancias exige binding implícito de dataset con nombre y nombres de datos XML ASCII; el binding explícito por referencia de datos y los contextos de padre ambiguos se rechazan antes de publicar la transacción

Los destinos se resuelven a través de hijos con nombre de la plantilla en los ámbitos que envuelven al evento, incluidas las rutas con puntos y this.parent; un manager anidado dentro de un ámbito repetido usa el grupo de datos propio del evento

presence acepta visible, hidden e invisible en campos, draws, subforms y exclusion groups de la plantilla; el contenido hidden no ocupa espacio de flujo, mientras que el contenido invisible conserva su espacio y se omite de los widgets y de la salida del flatten

Con el parser literal por defecto, los cambios de presence se aplican al nodo de plantilla seleccionado y por tanto a todas sus ocurrencias repetidas; la presence indexada por instancia, inactive, las expresiones arbitrarias, las variables, las condicionales, los bucles y otras operaciones de scripts de evento exigen un host de eventos adicional

Un lote de eventos publica cambios de datos, cálculos, layout, foco y estado de edición juntos después de que el reflow se estabilice; cualquier operación rechazada o presupuesto de entrada, operación, instancia, valor, widget, layout o tiempo transcurrido agotado restaura el estado previo completo del documento y de la interacción

Eliminar una fila preserva el foco y las ediciones pendientes de los grupos de datos supervivientes incluso cuando cambian sus índices de widget; eliminar u ocultar el widget enfocado limpia el foco y publica el callback de foco correspondiente después del éxito

Ejecución general de eventos JavaScript y FormCalc

Establezca TXFAWidgetRuntimeOptions.ScriptOptions.EnableJavaScript para habilitar el puente QuickJS acotado incluido en la ejecución de eventos; los eventos JavaScript soportan entonces funciones, closures, arrays, condicionales, bucles y excepciones en lugar de la gramática literal por defecto

Options := TXFAWidgetRuntimeOptions.Default;
Options.ScriptOptions.EnableJavaScript := True;
Runtime := TXFAWidgetRuntime.Create(XDPBytes, 595, 842, Options);

El host de eventos expone this, los campos y subforms con nombre que envuelven, parent, rawValue escribible, presence y access, instanceManager.count/min/max, addInstance, removeInstance, insertInstance, moveInstance y setInstances, xfa.resolveNode, xfa.resolveNodes, resolución a nivel de nodo y xfa.layout.relayout

Las listas de nodos soportan indexado numérico, length e item; los valores de campos repetidos retienen sus propios destinos de dataset, y los paths SOM aceptan hijos con nombre con índices numéricos o wildcard para nodos vivos del host

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";

Cada subform repetido tiene su propio objeto vivo y campos hijos; index, los getters de hijos del padre y las consultas SOM posteriores siguen insert, move y remove inmediatamente dentro del script

addInstance e insertInstance devuelven un subárbol vivo inicializado con los defaults de la plantilla, de modo que el script puede escribir los valores de sus campos antes de que el evento publique; los manejadores eliminados rechazan lecturas o escrituras posteriores

Los cambios generales de presence y access de scripts persisten en el packet form estándar de XFA por ocurrencia, mientras que los valores de campos y las operaciones de repetición persisten en datasets; insert, move y remove mantienen el estado de formulario correspondiente alineado con los grupos de datos

Con el mismo opt-in, los scripts de eventos FormCalc se compilan al engine acotado y soportan var, if/elseif/else, for con upto o downto, while, foreach, func con resultados implícitos, aritmética y comparaciones, concatenación de cadenas, agregación de nodos wildcard y asignación implícita de valores de campo

La librería de funciones de eventos incluye Sum, Count, Avg, Min, Max, Round, funciones matemáticas comunes, troceado de cadenas, conversión de mayúsculas y minúsculas, recorte, reemplazo, HasValue, Exists, Within, Oneof y Choose; los nombres integrados no distinguen mayúsculas, At(source, search) sigue el orden de argumentos de XFA incluido el comportamiento de búsqueda vacía, las funciones financieras siguen el orden de parámetros de XFA, y los catálogos de fechas y finanzas se describen en FormCalc Functions

Las mutaciones de scripts se graban dentro del engine, se validan y se reproducen dentro de la transacción del runtime; las excepciones, la interrupción, el Unicode no válido, las operaciones de host no válidas y los presupuestos agotados no publican cambios parciales del documento

La ejecución general de scripts sigue desactivada por defecto, no usa navegador ni proceso externo y no expone APIs de sistema de archivos, red ni aplicación; el llamador puede suministrar JavaScriptEvaluator en lugar del puente

Objetos de script persistentes

Los objetos script de JavaScript dentro del elemento variables de un subform exponen sus variables y funciones a través del nombre del script; las variables léxicas, el estado de objetos y las closures anidadas siguen vivos durante la sesión del runtime, con el sombreado léxico normal y las directivas estrictas preservados

<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>

El código de eventos puede llamar a Helpers.next(); las ocurrencias repetidas de subforms poseen objetos de script independientes, y las funciones resuelven los campos con nombre contra el contexto vivo actual del formulario

Los nodos de campos y managers capturados siguen identidades de datos estables a través de movimientos y de la publicación de instancias recién creadas; acceder a un nodo eliminado rechaza el evento y hace rollback de su estado de módulo

Los scripts generales de calculate y validate comparten la sesión y los objetos de script; JavaScript soporta valores de finalización implícitos y return explícito, mientras que FormCalc devuelve su expresión final

Las transacciones fallidas restauran el estado léxico y de closures reproduciendo el journal virtual comprometido, con tiempos e entradas aleatorias grabados; el replay y la ejecución actual comparten el deadline de la transacción, y los límites por defecto del journal son 64 MiB de scripts/resultados y 8192 entradas

El estado de los objetos de script vive en la sesión del runtime y se inicializa de nuevo tras recargar el XDP; los valores estándar del documento y las anulaciones de formulario siguen persistiendo a través de SaveToBytes

Los callbacks personalizados de JavaScriptEvaluator retienen el envolvente nativo existente de calculate/validate; la sesión persistente la suministra el engine incluido

Configurar el transporte de host explícito

Establezca HostTransport y el OnHostTransactionCompleted opcional en TXFAWidgetRuntimeOptions para ejecutar diálogos del host, impresión, navegación, submission y transferencia de datos mediante callbacks de la aplicación

El transporte de host XFA explícito suministra xfa.host.messageBox, response, beep, print, gotoURL, submitForm, importData, exportData y FormCalc Get, Post y Put; la aplicación devuelve resultados tipados y controla los efectos externos

Los reintentos y el replay de sesión usan respuestas grabadas, así que los callbacks se ejecutan una vez por petición despachada; la finalización con fallo permite a la aplicación descartar efectos preparados o compensar operaciones reversibles

Los HostTransportLimits positivos acotan el recuento de peticiones, el de argumentos y los bytes agregados de petición/respuesta a través de la transacción del runtime que los envuelve

Ejecución de locale y pictures

Los eventos generales de FormCalc y los scripts calculate y validate soportan funciones de locale y pictures, incluidos Format, Parse, conversiones localizadas de fecha/hora, unidades, codificación, UUIDs y palabras numéricas en inglés

FormCalc Eval dinámico ejecuta cálculos suministrados dinámicamente con variables y funciones aisladas, acceso relativo a campos, compilación nativa, respuestas grabadas y rollback transaccional

Referencias FormCalc explícitas soportan asignación write-through, rebinding, desvinculación nula, argumentos de funciones y manejadores estables retenidos por objetos de script a través de movimientos de instancias repetidas

Paths SOM vivos soportan índices de ocurrencia inferidos, absolutos y relativos, selectores de clase y descendientes, contenedores transparentes, predicados candidatos y asignación indexada directa de FormCalc

El Data DOM nativo expone los datasets mediante $data y $record, sincroniza inmediatamente las lecturas y escrituras enlazadas del formulario, espeja instancias repetidas y preserva referencias de datos retenidas mediante publicación de identidad nativa

El Property DOM nativo expone hijos declarados de propiedades de valor, fuente, UI y otras, sincroniza valores de campos tipados y persiste atributos por instancia usados por la medición de fuentes y el styling de flatten soportado

El nodo en ejecución hereda su atributo de locale más cercano; las entradas localeSet del documento anulan los símbolos y patrones del sistema, mientras que los nombres de locale calculados se resuelven mediante peticiones internas acotadas y se preservan en el journal de la sesión

Num2Date sin picture usa ahora el patrón de fecha por defecto del entorno; suministre YYYY-MM-DD explícitamente cuando se requiera salida ISO

Modelo de host con estado

El modelo de host XFA suministra metadatos de la aplicación, recuento real de páginas, navegación de páginas, título Unicode, flags de cálculo/validación, reset con ámbito y foco de campo con un ciclo de vida transaccional de enter/exit

TXFAWidgetRuntimeOptions.HostModel configura el estado inicial de la aplicación; TXFAWidgetRuntime.HostModel devuelve el estado actual, y los eventos fallidos lo restauran junto con las instantáneas del documento y de la interacción

Un movimiento de foco sin script de enter/exit, edición pendiente ni ciclo de vida inicializado cambia el foco sin arrancar cálculo de scripts ni procesado de deadlines; el foco con scripts y los commits con edición pendiente siguen usando presupuestos transaccionales, validación y recálculo

Las cláusulas picture avanzadas se ejecutan a través de las mismas transacciones del runtime, el journal de reintentos de locale y el ciclo de vida de cálculo, con parseo compuesto acotado

Inicializar y mantener el ciclo de vida

Llame a InitializeForm tras configurar el runtime y los callbacks para ejecutar los eventos initialize en el orden de la plantilla, luego calculate y validate, los eventos form-ready y los eventos layout-ready; la llamada es idempotente tras el éxito

Las instancias nuevas creadas por la inicialización o por los eventos ready reciben sus propios eventos initialize antes de sus handlers ready; la ejecución de layout-ready se repite solo cuando cambia el layout, dentro de los presupuestos de reflow y transacción

Tras la inicialización, el despacho exitoso de eventos y el commit de ediciones inicializan las instancias recién creadas y ejecutan calculate, validate y layout-ready; las ocurrencias existentes retienen su estado de inicialización a través de movimientos y rollback transaccional

Los fallos del ciclo de vida hacen rollback juntos de los bytes del documento, la interacción de widgets y la contabilidad de inicialización, y los callbacks publican solo después de que la transacción que los envuelve tenga éxito

Guardar el formulario actualizado

SaveToBytes devuelve el XDP completo actualizado del runtime, incluidos los datasets modificados y el estado de formulario estándar por instancia; los cambios de presence del parser literal permanecen como atributos de plantilla; use estos bytes con SetXFADocument al escribir un PDF o con HPDFXFAFlatten para la salida de flatten actualizada

La fábrica de documentos cargados crea un runtime independiente, de modo que los eventos del runtime no modifican automáticamente el grafo de objetos del PDF de origen

Perfil opcional de presentación de instancias

Presentación de instancias XFA dinámicas añade bindings repetidos explícitos, IDs estables por instancia, presence y acceso indexados, eventos condicionales acotados, pintado en canvas del host y accesibilidad mediante un helper independiente; el runtime por defecto y su gramática de eventos restringida siguen siendo compatibles

UpdateDocument proporciona acciones de documento transaccionales; los callbacks opcionales del runtime de propiedad, ámbito de binding, identidad, resolución iniciada y validación de documentos soportan al helper, mientras que los defaults nil preservan a los llamadores existentes

APIs de eventos y formularios de nivel inferior

HPDFXFACompileFormCalcEvent compila la sintaxis de eventos; HPDFXFAExecuteJavaScriptEvent ejecuta el contexto virtual descrito por TXFAEventBinding y TXFAEventBindings

TXFAJavaScriptSession suministra ejecución persistente y checkpoints acotados para llamadores de nivel inferior

Los valores TXFAEventAction devueltos usan TXFAEventActionKind; el replay transaccional lo suministra el runtime

HPDFXFAResolveFormInstanceNode y HPDFXFAResolveFormInstanceProperty proporcionan búsqueda acotada estándar del form packet

Límites actuales

El runtime es un objeto de host de hilo único; la GUI y el pintado siguen siendo responsabilidad del host o del helper opcional de presentación

El estado de host soportado, el form DOM vivo y el ciclo de vida aún no cubren todas las propiedades del host de Acrobat, las pictures de dígitos de otra era y localizadas, las consultas síncronas de reflow dinámico ni todos los operadores SOM

Consulte FormCalc y JavaScript de XFA acotados, XFA Packet DOM y Procesamiento de documentos interactivos