]*\bui_multi_note\b)(?=[^>]*\bhidden\b)/,
+ 'count shown while on');
+ my $open = main::ui_multi_select_list('d', [ 'p' ], \@opts,
+ { 'children' => { 'name' => 'sub', 'label' => 'With children',
+ 'note' => 'ui_multi_test_note' } });
+ my @shown = $open =~ /(]*\bui_multi_item\b)(?=[^>]*\bhidden\b)[^>]*>)/g;
+ is(scalar(@shown), 0, 'entries shown while off');
+ like($open, qr/]*\bui_multi_note\b)(?=[^>]*\bhidden\b)/,
+ 'count hidden while off');
+
+ # Initial counts must match JavaScript without losing folded selections.
+ my $selected = [ 'p', 'c1', 'c2' ];
+ my $closed = main::ui_multi_select_list('d', $selected, \@opts,
+ { 'children' => { 'name' => 'sub', 'checked' => 1 } });
+ like($closed, qr/]*\bui_multi_count\b)[^>]*>1 selected,
+ 'folded count includes only the selected parent');
+ like($closed, qr/type='hidden'[^>]*name="d"[^>]*value="p\nc1\nc2"/,
+ 'folded children retain their submitted selections');
+ my $expanded = main::ui_multi_select_list('d', $selected, \@opts,
+ { 'children' => { 'name' => 'sub' } });
+ like($expanded, qr/]*\bui_multi_count\b)[^>]*>3 selected,
+ 'expanded count includes selected children');
+ my $only_children = main::ui_multi_select_list('d', [ 'c1' ], \@opts,
+ { 'children' => { 'name' => 'sub', 'checked' => 1 } });
+ like($only_children, qr/]*\bui_multi_count\b)(?=[^>]*\bhidden\b)[^>]*>0 selected,
+ 'count is hidden when only folded children are selected');
+ like($only_children, qr/type='hidden'[^>]*name="d"[^>]*value="c1"/,
+ 'folding retains child selections even without a selected parent');
+}
+
done_testing();
diff --git a/ui-lib.pl b/ui-lib.pl
index 4450abc86..48adcb3d2 100755
--- a/ui-lib.pl
+++ b/ui-lib.pl
@@ -1261,7 +1261,8 @@ return $rv;
Returns HTML for selecting many of many from a list. By default, this is
implemented using two