diff --git a/t/ui-lib-widgets.t b/t/ui-lib-widgets.t index 161b7c751..26a5d91f7 100644 --- a/t/ui-lib-widgets.t +++ b/t/ui-lib-widgets.t @@ -391,7 +391,7 @@ like(main::ui_form_columns_table('x.cgi', [ [ 'go', 'Go' ] ], 0, undef, undef, [ [ 'a', 'A' ], { 'value' => 'b', 'label' => 'B', 'suffix' => '.x', 'level' => 1, 'tag' => 'Plan' }, - [ 'c', 'C' ] ], + [ 'c', 'C' ], map { [ $_, uc($_) ] } qw(d e f g h) ], { 'modes' => { 'name' => 'all', 'value' => 1, 'options' => [ [ 1, 'All' ], [ 0, 'Some' ] ], 'hide' => [ 1 ] } }); @@ -417,7 +417,7 @@ like(main::ui_form_columns_table('x.cgi', [ [ 'go', 'Go' ] ], 0, undef, undef, 'the links are laid out by ui_links_row'); unlike($html, qr/
\s*]*ui_search/, 'without the line break that row ends with'); - unlike(main::ui_multi_select_list('x', [ ], [ [ 'a', 'A' ] ], { 'disabled' => 1 }), + unlike(main::ui_multi_select_list('x', [ ], [ map { [ $_, $_ ] } 1..9 ], { 'disabled' => 1 }), qr/select_all/, 'a disabled widget has no links'); like($html, qr/]*name="mode"/, + 'the mode selector remains available without a counter'); + my $long = main::ui_multi_select_list('quiet_long', [ 1 ], + [ map { [ $_, $_ ] } 1..9 ], { 'count' => 0 }); + unlike($long, qr/ui_multi_count/, 'long lists can also omit the counter'); + like($long, qr/data-ui-multi-action="all"/, + 'counter-free long lists retain bulk selection'); + like($long, qr/data-ui-multi-search="1"/, + 'counter-free long lists retain filtering'); } # Legacy attributes must retain row presentation and checkbox behavior. diff --git a/ui-lib.pl b/ui-lib.pl index 6435b1dfd..78d448770 100755 --- a/ui-lib.pl +++ b/ui-lib.pl @@ -5741,7 +5741,9 @@ Size, add-if-missing, titles and width are ignored. =item opts - Optional hash reference with the keys : -=item search - Show or hide the filter button; defaults to on above eight entries. The input opens to its left in reserved space. Selection links affect visible, enabled entries and are omitted when disabled. +=item search - Show or hide the filter button; defaults to on above eight entries. The input opens to its left in reserved space. Selection links appear above eight entries, affect visible, enabled entries and are omitted when disabled. + +=item count - Show the selection count; defaults to on. Set to 0 to omit it. =item placeholder - Hint text of the filter box. @@ -5845,12 +5847,15 @@ my $children = ref($opts->{'children'}) eq 'HASH' && $opts->{'children'} : undef; my $folded = $children && $children->{'checked'} ? 1 : 0; -# Exclude folded children from the count, retaining their submitted values. -my $nchosen = grep { !$folded || !$_->{'level'} } @chosen; -my $cattrs = { 'class' => 'ui_multi_count' }; -$cattrs->{'hidden'} = undef if (!$nchosen || $hidden); -my $count = &ui_tag('span', - &html_escape(&text('ui_multi_selected', $nchosen)), $cattrs); +my $count = ''; +if (!defined($opts->{'count'}) || $opts->{'count'}) { + # Exclude folded children, retaining their submitted values. + my $nchosen = grep { !$folded || !$_->{'level'} } @chosen; + my $cattrs = { 'class' => 'ui_multi_count' }; + $cattrs->{'hidden'} = undef if (!$nchosen || $hidden); + $count = &ui_tag('span', + &html_escape(&text('ui_multi_selected', $nchosen)), $cattrs); + } my $counted = 0; my $search = defined($opts->{'search'}) ? $opts->{'search'} : @items > 8; @@ -5902,9 +5907,9 @@ if ($hasmodes) { $counted = 1; } -# Use themed selection links, with actions scoped to this list. +# Larger lists get themed selection links, with actions scoped to this list. my $tools = ""; -if (!$dis) { +if (!$dis && @items > 8) { my $links = &ui_links_row([ &ui_tag('a', &html_escape($text{'ui_selall'}), { 'href' => '#', 'class' => 'select_all', @@ -5947,7 +5952,7 @@ if ($search) { $tools .= &ui_tag('span', $filter, { 'class' => 'ui_search ui_multi_filter' }); } -my $body = &ui_tag('div', $tools, { 'class' => 'ui_multi_tools' }); +my $body = $tools ? &ui_tag('div', $tools, { 'class' => 'ui_multi_tools' }) : ''; # Render themed checkboxes with optional suffixes, child counts and tags. my $rows = ""; diff --git a/unauthenticated/css/ui-lib.css b/unauthenticated/css/ui-lib.css index 7a272b030..30fd65a6c 100644 --- a/unauthenticated/css/ui-lib.css +++ b/unauthenticated/css/ui-lib.css @@ -1069,6 +1069,8 @@ a.ui_list_link:hover { color: var(--ui-accent) !important; } align-items: center; gap: 4px 0; } +/* A hidden count alone does not need a toolbar row. */ +.ui_multi_tools:not(:has(> :not([hidden]))) { display: none; } /* ui_links_row handles link spacing; add room for the count. */ .ui_multi_links { min-width: 0; } .ui_multi_tools .ui_multi_count:not(:first-child) {