인터랙티브 동적 XFA 위젯 런타임

TXFAWidgetRuntime은 동적 XFA 폼을 AcroForm 필드로 변환하거나 콘텐츠를 플래트닝하지 않으면서 호스트 중립적인 상호작용 모델을 제공합니다

런타임은 결정적인 위젯 경계와 상태를 노출하므로 데스크톱, 서비스, 사용자 정의 렌더러가 자체 입력, 그리기, 접근성, 이벤트 루프를 공급할 수 있습니다

런타임 만들기

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 항목이 유지됩니다

상호작용 모델

인터랙티브 커밋은 숨겨진 alias와 보이지 않는 alias에 있는 기존 네이티브 scalar 값을 동기화합니다. 실제 반복 데이터 scope와 바이트 정확 rollback이 포함됩니다

원자적 검증 및 계산

커밋은 validate 및 calculate 스크립트를 실행하기 전에 명시적 SOM 바인딩과 현재 반복 행 데이터 컨텍스트를 해석합니다

편집된 값, 계산된 값, 데이터 노드, 위젯 모델, 포커스 및 편집 상태, 경고, 통과 카운터는 검증과 레이아웃이 안정된 뒤에만 함께 발행됩니다

거부된 스크립트, 소진된 예산, 잘못된 UTF-16 선택 경계, 레이아웃 또는 호스트 측정 예외는 이전 상태 전체를 복원하고 LastDiagnostic을 설정합니다

예산

TXFAWidgetRuntimeOptions는 위젯 수, 편집 값 길이, 계산 패스, 리플로 패스, 레이아웃 연산, 스크립트 연산, 경과 스크립트 시간, 기타 FormCalc 또는 JavaScript 리소스를 제한합니다

위젯 상한은 레이아웃 항목과 페이지 매김 조각이 추가되는 동안 적용되고, 로드된 XFA 압축 해제와 패킷 조립은 파싱 전에 XFA DOM 입력 한계에서 멈춥니다

MaxLayoutOperations는 기본값 200000으로 문서 순회와 레이아웃 작업을 함께 묶습니다. 레이아웃 깊이는 128, 이벤트 대상과 인스턴스 초기화 깊이는 64로 제한되며 재귀 이벤트 발송은 거부됩니다

제한된 동적 이벤트

DispatchEvent는 FormCalc 또는 JavaScript 콘텐츠 타입을 가진 일치하는 field 이벤트 스크립트에서 세미콜론으로 구분된 literal 연산을 받습니다. 이 연산들은 직접 파싱되며 JavaScript DLL이 필요하지 않습니다

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

addInstance는 인스턴스 하나를 추가하고 병합 인자로 true, false, 1, 0을 받습니다. 인자를 생략하면 true이며, 축약형 _row.addInstance(1)도 받아들입니다

지원되는 모델은 같은 이름의 기존 data group 전부를 바인딩하므로, 새 인스턴스는 병합 인자와 무관하게 템플릿 기본값으로 초기화된 새 data group을 받습니다. 인스턴스 생성이 이전 행의 입력 값을 복제하지는 않습니다

removeInstance는 선택된 subform의 같은 이름 data group 중 0부터 시작하는 정수 인덱스를 씁니다. subform은 반복 가능한 최댓값을 가진 occur 요소가 있어야 하고, 두 연산 모두 max="-1"을 포함해 최솟값과 최댓값을 강제합니다

인스턴스 변경에는 암시적 named dataset 바인딩과 ASCII XML 데이터 이름이 필요합니다. 명시적 data-reference 바인딩과 모호한 부모 컨텍스트는 트랜잭션을 발행하기 전에 거부됩니다

대상은 점 표기 경로와 this.parent를 포함해 이벤트를 둘러싼 scope의 이름 붙은 템플릿 자식으로 해석됩니다. 반복 scope 안에 중첩된 manager는 이벤트 자신의 data group을 씁니다

presence는 템플릿 field, draw, subform, exclusion group에서 visible, hidden, invisible을 받습니다. hidden 콘텐츠는 흐름 공간을 차지하지 않고, invisible 콘텐츠는 공간을 유지하되 위젯과 flatten 출력에서는 빠집니다

presence 변경은 선택된 템플릿 노드에 적용되므로 반복되는 모든 인스턴스에 함께 적용됩니다. 인스턴스별 인덱스 presence, inactive, 임의 표현식, 변수, 조건문, 반복문, 기타 이벤트 스크립트 연산은 거부됩니다

이벤트 배치는 리플로가 안정된 뒤 데이터 변경, 계산, 레이아웃, 포커스, 편집 상태를 함께 발행합니다. 거부된 연산이나 소진된 입력·연산·인스턴스·값·위젯·레이아웃·경과 시간 예산은 이전 문서와 상호작용 상태 전체를 복원합니다

행을 제거해도 살아남은 data group의 위젯 인덱스가 바뀌더라도 포커스와 대기 중인 편집은 유지됩니다. 포커스된 위젯을 제거하거나 숨기면 포커스가 지워지고 성공 후 대응하는 포커스 콜백이 발행됩니다

일반 JavaScript 및 FormCalc event 실행

TXFAWidgetRuntimeOptions.ScriptOptions.EnableJavaScript를 설정하면 event 실행에 내장된 상한이 적용된 QuickJS 브리지가 켜집니다. JavaScript event는 기본 literal 문법 대신 함수, 클로저, 배열, 조건문, 반복문, 예외를 지원합니다

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

event 호스트는 this, 둘러싼 이름 붙은 field와 subform, parent, 쓰기 가능한 rawValue, presence와 access, instanceManager.count/min/max, addInstance, removeInstance, insertInstance, moveInstance, setInstances, xfa.resolveNode, xfa.resolveNodes, 노드 수준 해석, xfa.layout.relayout을 노출합니다

노드 목록은 숫자 인덱싱, length, item을 지원합니다. 반복 field 값은 자기 dataset 대상을 유지하고, SOM 경로는 live 호스트 노드에 대해 숫자나 와일드카드 인덱스가 붙은 이름 자식을 받습니다

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

반복 subform마다 자기 live 객체와 자식 field가 있습니다. index, 부모 자식 getter, 이후 SOM query는 insert, move, remove 연산 직후 스크립트 안에서 즉시 따라갑니다

addInstance와 insertInstance는 템플릿 기본값으로 초기화된 live 하위 트리를 반환하므로, 스크립트가 event 공개 전에 필드 값을 쓸 수 있습니다. 제거된 handle은 이후 읽기와 쓰기를 거부합니다

일반 스크립트의 presence와 access 변경은 occurrence별 표준 XFA form packet에 영속되고, field 값과 repeat 연산은 datasets에 영속됩니다. insert, move, remove는 대응하는 form 상태를 data group과 맞춰 둡니다

같은 opt-in으로 FormCalc event 스크립트도 상한이 적용된 엔진으로 컴파일되며 var, if/elseif/else, upto 또는 downto가 붙은 for, while, foreach, 암시적 결과를 반환하는 func, 산술과 비교, 문자열 연결, 와일드카드 노드 집계, 암시적 field 값 대입을 지원합니다

event 함수 라이브러리에는 Sum, Count, Avg, Min, Max, Round, 일반 수학 함수, 문자열 자르기, 대소문자 변환, trim, 치환, HasValue, Exists, Within, Oneof, Choose가 있습니다. 내장 이름은 대소문자를 구분하지 않고, At(source, search)는 빈 검색 동작을 포함한 XFA 인수 순서를 따르며, 재무 함수는 XFA 매개변수 순서를 쓰고, 날짜와 재무 카탈로그는 FormCalc 함수에 설명되어 있습니다

스크립트 변경은 엔진 안에서 기록되고, 런타임 트랜잭션 안에서 검증·재생됩니다. 예외, 중단, 잘못된 Unicode, 잘못된 호스트 연산, 소진된 예산은 부분 문서 변경을 공개하지 않습니다

일반 스크립트 실행은 기본 꺼져 있고, 브라우저나 외부 프로세스를 쓰지 않으며, 파일 시스템, 네트워크, 애플리케이션 API를 노출하지 않습니다. 호출자는 브리지 대신 JavaScriptEvaluator를 공급할 수 있습니다

영구 script 객체

subform의 variables 요소 안에 있는 JavaScript script 객체는 변수와 함수를 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>

event 코드는 Helpers.next()를 호출할 수 있습니다. 반복 subform occurrence는 독립적인 script 객체를 소유하고, 함수는 현재 live form 컨텍스트를 기준으로 이름 붙은 field를 해석합니다

캡처한 field 노드와 manager는 새로 만든 인스턴스의 이동과 공개를 거치며 안정적인 데이터 identity를 따릅니다. 제거된 노드에 접근하면 event가 거부되고 모듈 상태가 rollback됩니다

일반 calculate와 validate 스크립트는 세션과 script 객체를 공유합니다. JavaScript는 암시적 완료 값과 명시적 return을 지원하고, FormCalc는 마지막 표현식을 반환합니다

실패한 트랜잭션은 기록된 시간과 난수 입력과 함께 커밋된 가상 저널을 재생해 어휘와 클로저 상태를 복원합니다. 재생과 현재 실행은 트랜잭션 마감 시한을 공유하고, 기본 저널 한도는 스크립트/결과 64 MiB와 8192항목입니다

script 객체 상태는 런타임 세션에 살아 있고 XDP를 다시 읽으면 다시 초기화됩니다. 표준 문서 값과 form override는 SaveToBytes로 계속 영속됩니다

사용자 지정 JavaScriptEvaluator 콜백은 기존 네이티브 calculate/validate 봉투를 유지합니다. 영구 세션은 내장 엔진이 공급합니다

명시적 호스트 transport 설정

TXFAWidgetRuntimeOptions에 HostTransport와 선택적 OnHostTransactionCompleted를 설정하면 호스트 대화상자, 인쇄, 내비게이션, 제출, 데이터 전송을 애플리케이션 콜백으로 실행합니다

명시적 XFA 호스트 transport는 xfa.host.messageBox, response, beep, print, gotoURL, submitForm, importData, exportData와 FormCalc Get, Post, Put을 공급합니다. 애플리케이션이 타입이 붙은 결과를 반환하고 외부 효과를 통제합니다

재시도와 세션 재생은 기록된 응답을 쓰므로, 콜백은 발송된 요청마다 한 번 실행됩니다. 실패 완료는 애플리케이션이 스테이징된 효과를 버리거나 되돌릴 수 있는 연산을 보상하게 합니다

양수 HostTransportLimits는 둘러싼 런타임 트랜잭션에 걸쳐 요청 수, 인수 수, 집계 요청/응답 바이트를 제한합니다

locale 및 picture 실행

일반 FormCalc event와 calculate, validate 스크립트는 locale 및 picture 함수를 지원합니다. Format, Parse, 지역화된 날짜/시간 변환, 단위, 인코딩, UUID, 영어 숫자 단어가 포함됩니다

동적 FormCalc Eval은 격리된 변수와 함수, 상대 field 접근, 네이티브 컴파일, 기록된 응답, 트랜잭션 rollback과 함께 동적으로 공급된 계산을 실행합니다

명시적 FormCalc 참조는 write-through 대입, 재바인딩, null 분리, 함수 인수, 반복 인스턴스 이동을 거치며 script 객체가 유지하는 안정 handle을 지원합니다

live SOM 경로는 추론/절대/상대 occurrence 인덱스, 클래스와 자손 selector, 투명 컨테이너, 후보 predicate, direct FormCalc 인덱스 대입을 지원합니다

네이티브 Data DOM은 $data와 $record로 datasets를 노출하고, 바인딩된 form 읽기/쓰기를 즉시 동기화하며, 반복 인스턴스를 미러링하고, 네이티브 identity 공개를 통해 유지된 데이터 참조를 보존합니다

네이티브 Property DOM은 선언된 value, font, UI 등 property 자식을 노출하고, 타입별 field 값을 동기화하며, 폰트 측정과 지원되는 flatten 스타일링이 쓰는 인스턴스별 속성을 영속합니다

실행 중인 노드는 가장 가까운 locale 속성을 상속합니다. 문서 localeSet 항목이 시스템 심볼과 패턴을 덮어쓰고, 계산된 locale 이름은 상한이 적용된 내부 요청으로 해석되어 세션 저널에 보존됩니다

picture가 없는 Num2Date는 이제 주변 기본 날짜 패턴을 씁니다. ISO 출력이 필요하면 YYYY-MM-DD를 명시적으로 넣으십시오

상태를 가진 호스트 모델

XFA 호스트 모델은 애플리케이션 메타데이터, 실제 페이지 수, 페이지 내비게이션, Unicode 제목, calculate/validate 플래그, 범위가 지정된 리셋, 트랜잭션 enter/exit 수명 주기를 갖춘 field 포커스를 공급합니다

TXFAWidgetRuntimeOptions.HostModel이 초기 애플리케이션 상태를 설정하고, TXFAWidgetRuntime.HostModel은 현재 상태를 반환합니다. 실패한 event는 문서와 상호작용 스냅샷과 함께 이를 복원합니다

enter/exit 스크립트도 대기 중인 편집도 초기화된 수명 주기도 없는 포커스 이동은 스크립트 계산이나 마감 시한 처리를 시작하지 않고 포커스만 바꿉니다. 스크립트가 붙은 포커스와 대기 중인 편집 커밋은 여전히 트랜잭션 예산, 검증, 재계산을 씁니다

고급 picture 절은 같은 런타임 트랜잭션, locale 재시도 저널, 계산 수명 주기를 거쳐 상한이 적용된 복합 파싱으로 실행됩니다

수명 주기 초기화와 유지

런타임과 콜백을 설정한 뒤 InitializeForm을 호출하면 템플릿 순서로 initialize event, 그다음 calculate와 validate, form-ready event, layout-ready event를 실행합니다. 성공 후 이 호출은 멱등합니다

초기화나 ready event가 만든 새 인스턴스는 자기 ready 핸들러 전에 자기 initialize event를 받습니다. layout-ready 실행은 레이아웃이 바뀔 때만 리플로와 트랜잭션 예산 안에서 반복됩니다

초기화 뒤에는 성공한 event 발송과 편집 커밋이 새로 만든 인스턴스를 초기화하고 calculate, validate, layout-ready를 실행합니다. 기존 occurrence는 이동과 트랜잭션 rollback을 거쳐 초기화 상태를 유지합니다

수명 주기 실패는 문서 바이트, 위젯 상호작용, 초기화 부기책을 함께 rollback하고, 콜백은 둘러싼 트랜잭션이 성공한 뒤에만 공개됩니다

갱신된 폼 저장

SaveToBytes는 수정된 dataset과 표준 occurrence별 form 상태를 포함해 런타임의 갱신된 XDP 전체를 반환합니다. literal 파서의 presence 변경은 템플릿 속성으로 남습니다. PDF를 쓸 때는 이 바이트를 SetXFADocument에, 갱신된 flatten 출력에는 HPDFXFAFlatten에 넘기면 됩니다

로드 문서 팩토리는 독립된 런타임을 만들므로, 런타임 이벤트가 소스 PDF의 객체 그래프를 자동으로 바꾸지는 않습니다

선택적 instance presentation 프로필

Dynamic XFA Instance Presentation은 독립 헬퍼를 통해 명시적 반복 바인딩, 안정적인 인스턴스별 ID, 인덱스가 붙은 presence와 access, 상한이 적용된 조건부 event, 호스트 canvas 그리기, 접근성을 더합니다. 기본 런타임과 제한된 event 문법은 호환을 유지합니다

UpdateDocument는 트랜잭션 문서 액션을 제공합니다. 선택적 런타임 property, 바인딩 scope, identity, resolution-started, 문서 검증 콜백이 이 헬퍼를 지원하며, nil 기본값은 기존 호출자를 유지합니다

하위 수준 event 및 form API

HPDFXFACompileFormCalcEvent는 event 문법을 컴파일하고, HPDFXFAExecuteJavaScriptEvent는 TXFAEventBinding과 TXFAEventBindings가 기술하는 가상 컨텍스트를 실행합니다

TXFAJavaScriptSession은 하위 수준 호출자를 위한 영구 실행과 상한이 적용된 checkpoint를 공급합니다

반환되는 TXFAEventAction 값은 TXFAEventActionKind를 씁니다. 트랜잭션 재생은 런타임이 공급합니다

HPDFXFAResolveFormInstanceNode와 HPDFXFAResolveFormInstanceProperty는 상한이 적용된 표준 form-packet 조회를 제공합니다

현재 경계

런타임은 단일 스레드 호스트 객체이며 GUI와 그리기는 호스트나 선택적 presentation 헬퍼가 담당합니다

지원되는 호스트 상태, live form DOM, 수명 주기는 아직 모든 Acrobat 호스트 property, 대체 시대 및 지역화된 숫자 picture, 동적 reflow 동기 질의, 모든 SOM 연산자를 커버하지 않습니다

제한된 XFA FormCalc 및 JavaScript, XFA Packet DOM, 대화형 문서 처리를 참고하세요