Interactive Dynamic XFA Widget Runtime

TXFAWidgetRuntime は、動的 XFA フォームを AcroForm フィールドへ変換したり内容をフラット化したりせずに、ホスト非依存の対話モデルを提供します

ランタイムは決定的なウィジェット境界と状態を公開するので、デスクトップ・サービス・カスタムレンダラは独自の入力、描画、アクセシビリティ、イベントループを提供できます

Create a runtime

ランタイムは XDP バイトから直接作成するか、AcroForm に単一ストリームまたはパケット配列の /XFA エントリを含む PDF を読み込んだ後に THotPDF.CreateLoadedXFAWidgetRuntime を呼び出して作成します

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;

読み込みドキュメントファクトリは PDF オブジェクトグラフと既存の XFAFlattenWarnings に対して読み取り専用です。ドキュメントを保存すると、元の /XFA と /NeedsRendering エントリが保持されます

Interaction model

インタラクティブなコミットは、実際の繰り返しデータスコープとバイト一致のロールバックを含めて、hidden / invisible のエイリアスにある既存のネイティブスカラー値を同期します

Atomic validation and calculation

コミットは、検証スクリプトと計算スクリプトを実行する前に、明示的な SOM バインディングと現在の繰り返し行データコンテキストを解決します

編集された値、計算された値、データノード、ウィジェットモデル、フォーカスと編集状態、警告、パスカウンタは、検証とレイアウトが安定した後にのみまとめて公開されます

拒否されたスクリプト、予算の枯渇、無効な UTF-16 選択境界、レイアウトやホスト測定の例外は、完全な以前の状態を復元し、LastDiagnostic を設定します

Budgets

TXFAWidgetRuntimeOptions は、ウィジェット数、編集値の長さ、計算パス、リフローパス、レイアウト操作、スクリプト操作、経過スクリプト時間、およびその他の FormCalc や JavaScript リソースを制限します

ウィジェット上限は、レイアウト項目とページネーション断片が追加される間にも適用され、読み込まれる XFA の解凍とパケット組み立ては、パース前に XFA DOM 入力制限で停止します

MaxLayoutOperations のデフォルトは 200000 で、ドキュメント走査とレイアウト処理の両方を境界付けます。レイアウトの深さは 128、イベントターゲットとインスタンス初期化の深さは 64 に制限され、再帰的なイベントディスパッチは拒否されます

Default literal dynamic events

DispatchEvent は、FormCalc または JavaScript のコンテンツタイプを持つ、一致するフィールドイベントスクリプト内のセミコロン区切りのリテラル操作を受け付けます。これらの操作は直接パースされ、JavaScript DLL を必要としません

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

addInstance は 1 つのインスタンスを追加し、merge 引数として true、false、1、0 を受け付けます。引数を省略した場合は true が使われ、省略記法の _row.addInstance(1) も受け付けられます

対応しているモデルは、同じ名前を持つ既存のデータグループをすべて束ねます。そのため新しいインスタンスには、どちらの merge 引数でもテンプレートのデフォルトから初期化された新しいデータグループが割り当てられます。インスタンスの作成が、前の行で入力された値を複製することはありません

removeInstance は、選択されたサブフォームの同名データグループの中から 0 始まりの整数インデックスを使います。サブフォームには繰り返し可能な最大値を持つ occur 要素が必要で、両方の操作がその最小値と最大値(max="-1" を含む)を強制します

インスタンスの変更には、暗黙的な名前付きデータセットバインディングと ASCII の XML データ名が必要です。明示的なデータ参照バインディングとあいまいな親コンテキストは、トランザクションを公開する前に拒否されます

ターゲットは、イベントを囲むスコープ内の名前付きテンプレート子を通じて解決されます。ドット付きパスや this.parent も含まれます。繰り返しスコープの内側にネストしたマネージャーは、イベント自身のデータグループを使います

presence は、テンプレートのフィールド、draw、サブフォーム、exclusion group に対して visible、hidden、invisible を受け付けます。hidden のコンテンツはフロー領域を占有せず、invisible のコンテンツは領域を保持したままウィジェットと flatten 出力から除外されます

デフォルトのリテラルパーサーでは、presence の変更は選択されたテンプレートノード、したがってその繰り返しインスタンスすべてに適用されます。インデックス付きのインスタンス単位の presence、inactive、任意の式、変数、条件分岐、ループ、その他のイベントスクリプト操作には、追加のイベントホストが必要です

イベントバッチは、リフローが安定した後にデータ変更、計算、レイアウト、フォーカス、編集状態をまとめて公開します。拒否された操作や、入力・操作・インスタンス・値・ウィジェット・レイアウト・経過時間の各予算の枯渇があれば、完全な以前のドキュメント状態とインタラクション状態が復元されます

行の削除では、ウィジェットのインデックスが変わっても、残存するデータグループのフォーカスと未確定の編集が保持されます。フォーカス済みウィジェットの削除や非表示化があればフォーカスはクリアされ、成功後に対応するフォーカスコールバックが公開されます

General JavaScript and FormCalc event execution

TXFAWidgetRuntimeOptions.ScriptOptions.EnableJavaScript を設定すると、同梱の境界付き QuickJS ブリッジでイベントを実行できます。JavaScript イベントは、デフォルトのリテラル文法の代わりに関数、クロージャ、配列、条件分岐、ループ、例外をサポートします

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

イベントホストは this、囲んでいる名前付きフィールドとサブフォーム、parent、書き込み可能な rawValue、presence、access、instanceManager.count / min / max、addInstance、removeInstance、insertInstance、moveInstance、setInstances、xfa.resolveNode、xfa.resolveNodes、ノード単位の解決、xfa.layout.relayout を公開します

ノードリストは数値インデックス、length、item をサポートします。繰り返しフィールドの値はそれぞれ独自の dataset ターゲットを保持し、ライブホストノードの SOM パスは数値またはワイルドカードインデックス付きの名前付き子を受け付けます

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

繰り返しサブフォームごとに独自のライブオブジェクトと子フィールドがあります。index、親の子 getter、後続の SOM 照会は、スクリプト内の insert・move・remove 操作を直ちに反映します

addInstance と insertInstance は、テンプレートデフォルトで初期化されたライブなサブツリーを返します。イベントが公開される前にスクリプトはそのフィールド値を書き込めます。削除されたハンドルへの読み書きは拒否されます

一般スクリプトによる presence と access の変更は、インスタンスごとに標準の XFA form パケットに保存され、フィールド値と繰り返し操作は datasets に保存されます。insert・move・remove は、対応するフォーム状態をデータグループと一致させ続けます

同じオプトインで、FormCalc イベントスクリプトは境界付きエンジンにコンパイルされ、var、if / elseif / else、upto / downto 付きの for、while、foreach、暗黙結果の func、算術と比較、文字列連結、ワイルドカードノード集計、暗黙的なフィールド値代入をサポートします

イベント関数ライブラリには、Sum、Count、Avg、Min、Max、Round、一般的な数学関数、文字列スライス、大文字小文字変換、トリム、置換、HasValue、Exists、Within、Oneof、Choose が含まれます。組み込み名は大文字小文字を区別せず、At(source, search) は空検索の挙動を含めて XFA の引数順に従い、財務関数は XFA のパラメータ順に従います。日付と財務のカタログは FormCalc Functions に記載されています

スクリプトによる変更はエンジン内に記録され、ランタイムトランザクションの中で検証・リプレイされます。例外、割り込み、無効な Unicode、無効なホスト操作、予算の枯渇があった場合、部分的なドキュメント変更は公開されません

一般スクリプト実行はデフォルトでオフです。ブラウザも外部プロセスも使わず、ファイルシステム・ネットワーク・アプリケーション API を公開しません。ブリッジの代わりに JavaScriptEvaluator を供給することもできます

Persistent script objects

サブフォームの variables 要素内にある JavaScript の script オブジェクトは、スクリプト名を通じて変数と関数を公開します。レキシカル変数、オブジェクト状態、ネストしたクロージャはランタイムセッションの間生き続け、通常のレキシカルシャドーイングと strict 指令も保持されます

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

イベントコードから Helpers.next() を呼べます。繰り返しサブフォームのインスタンスごとに独立したスクリプトオブジェクトを所有し、関数は現在のライブフォームコンテキストに対して名前付きフィールドを解決します

キャプチャされたフィールドノードとマネージャーは、移動や新規インスタンスの公開をまたいで安定したデータ同一性に従います。削除されたノードへのアクセスはイベントを拒否し、モジュール状態をロールバックします

一般の calculate / validate スクリプトはセッションとスクリプトオブジェクトを共有します。JavaScript は暗黙の完了値と明示的な return をサポートし、FormCalc は最後の式の値を返します

失敗したトランザクションは、記録された時刻とランダム入力とともに、コミット済みの仮想ジャーナルをリプレイしてレキシカルとクロージャの状態を復元します。リプレイと現在の実行はトランザクションの期限を共有し、ジャーナルのデフォルト上限はスクリプト / 結果合計 64 MiB、8192 エントリです

スクリプトオブジェクトの状態はランタイムセッションに存在し、XDP 再読み込み後は再度初期化されます。標準のドキュメント値とフォームオーバーライドは、引き続き SaveToBytes で保存されます

カスタムの JavaScriptEvaluator コールバックは、既存のネイティブ calculate / validate エンベロープをそのまま使います。永続セッションは同梱エンジンから供給されます

Configure explicit host transport

TXFAWidgetRuntimeOptions に HostTransport とオプションの OnHostTransactionCompleted を設定すると、ホストのダイアログ、印刷、ナビゲーション、送信、データ転送をアプリケーションコールバックで実行できます

明示的な XFA ホストトランスポートは、xfa.host.messageBox、response、beep、print、gotoURL、submitForm、importData、exportData と FormCalc の Get・Post・Put を提供します。アプリケーションが型付きの結果を返し、外部への副作用を制御します

リトライとセッションリプレイは記録された応答を使うため、コールバックはディスパッチされた要求ごとに 1 回だけ実行されます。失敗完了時には、アプリケーションがステージング済みの副作用を破棄したり、可逆な操作を補償したりできます

正の HostTransportLimits は、囲んでいるランタイムトランザクション全体で、要求回数、引数の数、要求 / 応答の合計バイト数を上限付けます

Locale and picture execution

一般の FormCalc イベントと calculate / validate スクリプトは、ロケールとピクチャ関数をサポートします。Format、Parse、ローカライズされた日付 / 時刻変換、単位、エンコーディング、UUID、英語の数詞などが含まれます

動的 FormCalc Eval は、動的に供給された計算を、分離された変数と関数、相対フィールドアクセス、ネイティブコンパイル、記録された応答、トランザクションロールバック付きで実行します

明示的な FormCalc 参照は、ライトスルー代入、再バインド、null 切り離し、関数引数、そして繰り返しインスタンスの移動をまたいでスクリプトオブジェクトが保持する安定したハンドルをサポートします

ライブ SOM パスは、推論・絶対・相対の各インスタンスインデックス、クラスと子孫セレクタ、透過コンテナ、候補述語、FormCalc からの直接のインデックス代入をサポートします

ネイティブ Data DOM は $data と $record を通じて datasets を公開し、バインドされたフォームの読み書きを即時に同期し、繰り返しインスタンスをミラーし、ネイティブの同一性公開を通じて保持されたデータ参照を保存します

ネイティブ Property DOM は、宣言された value・font・UI などのプロパティの子を公開し、型付きフィールド値を同期し、フォント計測とサポート対象の flatten スタイリングで使われるインスタンスごとの属性を保存します

実行ノードは最も近いロケール属性を継承します。ドキュメントの localeSet エントリはシステムのシンボルとパターンを上書きし、計算されたロケール名は境界付きの内部要求で解決され、セッションジャーナルに保持されます

ピクチャなしの Num2Date は、周囲のデフォルト日付パターンを使うようになりました。ISO 出力が必要なら YYYY-MM-DD を明示的に指定してください

Stateful host model

XFA ホストモデルは、アプリケーションメタデータ、実際のページ数、ページナビゲーション、Unicode タイトル、calculate / validate フラグ、スコープ付きリセット、トランザクション的な enter / exit ライフサイクルを持つフィールドフォーカスを提供します

TXFAWidgetRuntimeOptions.HostModel が初期アプリケーション状態を設定し、TXFAWidgetRuntime.HostModel が現在の状態を返します。失敗したイベントは、ドキュメントとインタラクションのスナップショットとともに状態を復元します

enter / exit スクリプトも未確定編集も初期化済みライフサイクルもないフォーカス移動は、スクリプト計算や期限処理を始めずにフォーカスだけを変えます。スクリプトによるフォーカスと未確定編集のコミットは、引き続きトランザクション予算、検証、再計算を使います

高度なピクチャ句は、同じランタイムトランザクション、ロケールリトライジャーナル、計算ライフサイクルを通じて、境界付きの複合解析付きで実行されます

Initialize and maintain the lifecycle

ランタイムとコールバックを設定したら InitializeForm を呼び出します。テンプレート順に initialize イベントを実行し、次に calculate と validate、form-ready イベント、layout-ready イベントを実行します。成功後の呼び出しは冪等です

初期化や ready イベントで作成された新しいインスタンスは、ready ハンドラの前に独自の initialize イベントを受け取ります。layout-ready の実行は、レイアウトが変わったときにだけ、リフローとトランザクションの予算内で繰り返されます

初期化後は、イベントディスパッチや編集コミットが成功するたびに、新しく作成されたインスタンスが初期化され、calculate・validate・layout-ready が実行されます。既存のインスタンスは、移動やトランザクションロールバックをまたいで初期化状態を保持します

ライフサイクルの失敗は、ドキュメントバイト、ウィジェットインタラクション、初期化の管理情報をまとめてロールバックします。コールバックは、囲んでいるトランザクションが成功した後にだけ公開されます

Save the updated form

SaveToBytes は、変更された datasets と標準のインスタンスごとのフォーム状態を含む、ランタイムの完全な更新済み XDP を返します。リテラルパーサーの presence 変更はテンプレート属性のままです。PDF を書き出すときはこのバイトを SetXFADocument に、更新後の flatten 出力には HPDFXFAFlatten に渡してください

ロード済みドキュメントのファクトリは独立したランタイムを作成するため、ランタイムのイベントがソース PDF のオブジェクトグラフを自動的に変更することはありません

Optional instance presentation profile

Dynamic XFA Instance Presentation は、独立したヘルパーを通じて、明示的な繰り返しバインディング、インスタンスごとの安定した ID、インデックス付き presence と access、境界付き条件イベント、ホストキャンバス描画、アクセシビリティを追加します。デフォルトランタイムとその制限付きイベント文法は互換性を保ちます

UpdateDocument はトランザクション的なドキュメント操作を提供します。オプションのランタイムプロパティ、バインディングスコープ、同一性、解決開始、ドキュメント検証の各コールバックがヘルパーを支援します。デフォルトの nil は既存の呼び出し側をそのまま保ちます

Lower-level event and form APIs

HPDFXFACompileFormCalcEvent はイベント構文をコンパイルし、HPDFXFAExecuteJavaScriptEvent は TXFAEventBinding と TXFAEventBindings で記述された仮想コンテキストを実行します

TXFAJavaScriptSession は、下位レベルの呼び出し側に永続実行と境界付きチェックポイントを提供します

戻り値の TXFAEventAction は TXFAEventActionKind を使います。トランザクションリプレイはランタイムが提供します

HPDFXFAResolveFormInstanceNode と HPDFXFAResolveFormInstanceProperty は、境界付きの標準 form パケット検索を提供します

Current boundaries

ランタイムはシングルスレッドのホストオブジェクトです。GUI と描画はホスト、またはオプションのプレゼンテーションヘルパーの責任です

サポート対象のホスト状態、ライブフォーム DOM、ライフサイクルは、Acrobat のホストプロパティすべて、alternate-era やローカライズされた数字ピクチャ、同期ダイナミックリフロー照会、すべての SOM 演算子をまだカバーしていません

Bounded XFA FormCalc and JavaScript、XFA Packet DOM、Interactive Document Processing を参照してください