diff --git a/crates/xfa/src/fixtures.rs b/crates/xfa/src/fixtures.rs index a46bee5a2..b075cc811 100644 --- a/crates/xfa/src/fixtures.rs +++ b/crates/xfa/src/fixtures.rs @@ -114,10 +114,6 @@ fn assemble(objs: Vec>) -> Vec { out } -/// A scripted form (JavaScript events): `qty` (initialised to 2, validated ≤ 100) × `price` -/// (5) = `total` (calculated); a check box `more` that shows the hidden `details` subform; -/// a table whose `row` (item, amount) repeats, with `addRow`, `removeRow` and `hello` buttons; -/// `grand`, the calculated sum of the amounts. /// A hidden subform `details` a script may show, holding a named field and three unnamed /// objects: a caption, an old caption the form keeps hidden, and a hidden subform. Unnamed /// objects have no SOM name of their own, so showing `details` must leave the hidden ones hidden. @@ -142,6 +138,10 @@ pub fn unnamed_hidden_template() -> String { .to_string() } +/// A scripted form (JavaScript events): `qty` (initialised to 2, validated ≤ 100) × `price` +/// (5) = `total` (calculated); a check box `more` that shows the hidden `details` subform; +/// a table whose `row` (item, amount) repeats, with `addRow`, `removeRow` and `hello` buttons; +/// `grand`, the calculated sum of the amounts. pub fn scripted_template() -> String { r##" diff --git a/crates/xfa/src/script.rs b/crates/xfa/src/script.rs index df7ba2fdf..1d0dc8a86 100644 --- a/crates/xfa/src/script.rs +++ b/crates/xfa/src/script.rs @@ -237,6 +237,9 @@ impl Walker<'_> { self.ov.access.get(som).cloned().unwrap_or_else(|| access_name(a).to_string()) } + /// The live node of field `f`, child `index` of `parent_som`, with its scripts recorded. In an + /// exclusion group (`radio` is the group's selected value) its value is its on value when picked, + /// else empty; elsewhere it is its data value (as saved) or its template default. fn field(&mut self, f: &Field, parent_som: &str, index: usize, radio: Option<&str>) -> FormNode { let som = child_som(parent_som, f.common.name.as_deref().or(Some("field")), index); let data_value = self.data.and_then(|d| d.value_at(&data_path(self.tpl, &som))).map(|t| t.trim().to_string()).filter(|t| !t.is_empty()); @@ -276,6 +279,9 @@ impl Walker<'_> { } } + /// The live nodes of `nodes`, the children of `parent_som`, with their scripts recorded: one per + /// instance of a repeating subform (what the data holds, else its initial count). Nothing past + /// [`MAX_DEPTH`] is built, and building stops once the object budget is spent. fn children(&mut self, nodes: &[Node], parent_som: &str, depth: usize) -> Vec { let mut out = Vec::new(); if depth > MAX_DEPTH { @@ -445,6 +451,9 @@ pub fn has_scripts(tpl: &Template) -> bool { /// The template with `ov` applied to its objects (instance 0 of each; scripts that hide one /// instance of a repeating subform hide them all). pub fn apply_overrides(tpl: &Template, ov: &Overrides) -> Template { + /// Set the presence `ov` gives each of `nodes` (children of `parent_som`) and their descendants, + /// down to [`MAX_DEPTH`], and the access it gives a field outside an exclusion group. An unnamed + /// draw, area or subform shares its parent's SOM path, so it takes no override of its own. fn walk(nodes: &mut [Node], parent_som: &str, ov: &Overrides, depth: usize) { if depth > MAX_DEPTH { return; diff --git a/crates/xfa/src/tests.rs b/crates/xfa/src/tests.rs index d1503527c..ab49e26bf 100644 --- a/crates/xfa/src/tests.rs +++ b/crates/xfa/src/tests.rs @@ -716,6 +716,9 @@ fn overrides_live_in_the_acroform_and_hide_objects_in_the_layout() { assert!(overrides(&doc).is_empty()); } +/// Showing a hidden subform through an override leaves its unnamed hidden draw and subform hidden, +/// in the layout and in the live form scripts see: they share the subform's SOM path, so its +/// override is not theirs. #[test] fn showing_a_subform_leaves_its_unnamed_hidden_objects_hidden() { let (tpl, _) = parse(&unnamed_hidden_template()).unwrap();