--- loncom/interface/loncommon.pm 2025/02/14 23:10:30 1.1454 +++ loncom/interface/loncommon.pm 2025/03/24 17:05:59 1.1475 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.1454 2025/02/14 23:10:30 raeburn Exp $ +# $Id: loncommon.pm,v 1.1475 2025/03/24 17:05:59 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -966,7 +966,9 @@ ENDSCRT sub select_timezone { my ($name,$selected,$onchange,$includeempty,$id,$disabled)=@_; - my $output='<select name="'.$name.'" '.$id.$onchange.$disabled.'>'."\n"; + my $labeltext = &HTML::Entities::encode(&mt('Select Time Zone')); + my $output='<select name="'.$name.'" '.$id.$onchange.$disabled. + ' aria-label="'.$labeltext.'">'."\n"; if ($includeempty) { $output .= '<option value=""'; if (($selected eq '') || ($selected eq 'local')) { @@ -1351,7 +1353,7 @@ sub help_open_topic { } $template.=' <a'.$target.' href="'.$link.'" title="'.$title.'">' .'<img src="'.$helpicon.'" border="0"' - .' alt="'.&mt('Help: [_1]',$topic).'"' + .' alt="'.&mt('Help icon').'"' .' title="'.$title.'" style="vertical-align:middle;"'.$imgid .' /></a>'; if ($text ne "") { @@ -1460,7 +1462,7 @@ $banner_link <a href="$link" title="$title" $linkattr>$text</a> END } else { - return ' '.$text.' '; + return ' <h1 class="LC_helpmenu">'.$text.'</h1> '; } } @@ -1472,6 +1474,10 @@ sub help_menu_js { my $helptopic=&general_help(); my $details_link = $httphost.'/adm/help/'.$helptopic.'.hlp'; my $nothing=&Apache::lonhtmlcommon::javascript_nothing(); + my $bannertitle = &mt('Help Menu'); + &js_escape(\$bannertitle); + my $bodytitle = &mt('Documentation'); + &js_escape(\$bodytitle); my $start_page = &Apache::loncommon::start_page('Help Menu', undef, {'frameset' => 1, @@ -1483,7 +1489,6 @@ sub help_menu_js { my $end_page = &Apache::loncommon::end_page({'frameset' => 1, 'js_ready' => 1,}); - my $template .= <<"ENDTEMPLATE"; <script type="text/javascript"> // <![CDATA[ @@ -1508,8 +1513,8 @@ function helpMenu(target) { return; } function writeHelp(caller) { - caller.document.writeln('$start_page\\n<frame name="bannerframe" src="'+banner_link+'" marginwidth="0" marginheight="0" frameborder="0">\\n'); - caller.document.writeln('<frame name="bodyframe" src="$details_link" marginwidth="0" marginheight="0" frameborder="0">\\n$end_page'); + caller.document.writeln('$start_page\\n<frame name="bannerframe" title="$bannertitle" src="'+banner_link+'" marginwidth="0" marginheight="0" frameborder="0">\\n'); + caller.document.writeln('<frame name="bodyframe" title="$bodytitle" src="$details_link" marginwidth="0" marginheight="0" frameborder="0">\\n$end_page'); caller.document.close(); caller.focus(); } @@ -2795,7 +2800,7 @@ sub create_text_file { # ------------------------------------------ sub domain_select { - my ($name,$value,$multiple,$incdoms,$excdoms)=@_; + my ($name,$value,$multiple,$incdoms,$excdoms,$id)=@_; my @possdoms; if (ref($incdoms) eq 'ARRAY') { @possdoms = @{$incdoms}; @@ -2816,10 +2821,10 @@ sub domain_select { if ($multiple) { $domains{''}=&mt('Any domain'); $domains{'select_form_order'} = [sort {lc($a) cmp lc($b) } (keys(%domains))]; - return &multiple_select_form($name,$value,4,\%domains); + return &multiple_select_form($name,$value,4,\%domains,undef,$id); } else { $domains{'select_form_order'} = [sort {lc($a) cmp lc($b) } (keys(%domains))]; - return &select_form($name,$value,\%domains); + return &select_form($name,$value,\%domains,'','',$id); } } @@ -2831,7 +2836,7 @@ sub domain_select { =over 4 -=item * &multiple_select_form($name,$value,$size,$hash,$order) +=item * &multiple_select_form($name,$value,$size,$hash,$order,$id) Returns a string containing a <select> element int multiple mode @@ -2843,12 +2848,13 @@ Args: $hash - the elements should be 'option' => 'shown text' (shown text should already have been &mt()) $order - (optional) array ref of the order to show the elements in + $id = (optional) id for <select> element =cut #------------------------------------------- sub multiple_select_form { - my ($name,$value,$size,$hash,$order)=@_; + my ($name,$value,$size,$hash,$order,$id)=@_; my %selected = map { $_ => 1 } ref($value)?@{$value}:($value); my $output=''; if (! defined($size)) { @@ -2857,7 +2863,10 @@ sub multiple_select_form { $size = scalar(keys(%$hash)); } } - $output.="\n".'<select name="'.$name.'" size="'.$size.'" multiple="multiple">'; + if ($id ne '') { + $id = ' id="'.$id.'"'; + } + $output.="\n".'<select name="'.$name.'" size="'.$size.'" multiple="multiple"'.$id.'>'; my @order; if (ref($order) eq 'ARRAY') { @order = @{$order}; @@ -2881,7 +2890,7 @@ sub multiple_select_form { =pod -=item * &select_form($defdom,$name,$hashref,$onchange,$readonly) +=item * &select_form($defdom,$name,$hashref,$onchange,$readonly,$id,$aria_labelledby) Returns a string containing a <select name='$name' size='1'> form to allow a user to select options from a ref to a hash containing: @@ -2889,7 +2898,10 @@ option_name => displayed text. An option a javascript onchange item, e.g., onchange="this.form.submit();". An optional arg -- $readonly -- if true will cause the select form to be disabled, e.g., for the case where an instructor has a section- -specific role, and is viewing/modifying parameters. +specific role, and is viewing/modifying parameters. An optional arg +-- $id -- will be used as the id attribute of the select element. An +optional arg -- $aria_labelledby -- will be included as the aria-labelledby +attribute of the select element. See lonrights.pm for an example invocation and use. @@ -2897,7 +2909,7 @@ See lonrights.pm for an example invocati #------------------------------------------- sub select_form { - my ($def,$name,$hashref,$onchange,$readonly) = @_; + my ($def,$name,$hashref,$onchange,$readonly,$id,$aria_labelledby) = @_; return unless (ref($hashref) eq 'HASH'); if ($onchange) { $onchange = ' onchange="'.$onchange.'"'; @@ -2906,7 +2918,13 @@ sub select_form { if ($readonly) { $disabled = ' disabled="disabled"'; } - my $selectform = "<select name=\"$name\" size=\"1\"$onchange$disabled>\n"; + if ($id ne '') { + $id = ' id="'.$id.'"'; + } + if ($aria_labelledby ne '') { + $aria_labelledby = ' aria-labelledby="'.$aria_labelledby.'"'; + } + my $selectform = "<select name=\"$name\" size=\"1\"$onchange$disabled$id$aria_labelledby>\n"; my @keys; if (exists($hashref->{'select_form_order'})) { @keys=@{$hashref->{'select_form_order'}}; @@ -2957,7 +2975,7 @@ sub display_filter { my $onchange = "javascript:toggleHistoryOptions(this,'containingphrase','$context', '$secondid','$thirdid')"; return '<span class="LC_nobreak"><label>'.&mt('Records: [_1]', - &Apache::lonmeta::selectbox('show',$env{'form.show'},'',undef, + &Apache::lonmeta::selectbox('show',$env{'form.show'},'','',undef, (&mt('all'),10,20,50,100,1000,10000))). '</label></span> <span class="LC_nobreak">'. &mt('Filter: [_1]', @@ -3059,9 +3077,12 @@ sub gradeleveldescription { } sub select_level_form { - my ($deflevel,$name)=@_; + my ($deflevel,$name,$id)=@_; + if ($id ne '') { + $id = ' id="'.$id.'"'; + } unless ($deflevel) { $deflevel=0; } - my $selectform = "<select name=\"$name\" size=\"1\">\n"; + my $selectform = "<select name=\"$name\" size=\"1\"$id>\n"; for (my $i=0; $i<=18; $i++) { $selectform.="<option value=\"$i\" ". ($i==$deflevel ? 'selected="selected" ' : ''). @@ -4856,9 +4877,10 @@ sub filemimetype { sub filecategoryselect { - my ($name,$value)=@_; + my ($name,$value,$id)=@_; return &select_form($value,$name, - {'' => &mt('Any category'), map { $_,$_ } sort(keys(%category_extensions))}); + {'' => &mt('Any category'), map { $_,$_ } sort(keys(%category_extensions))}, + '','',$id); } =pod @@ -5342,6 +5364,7 @@ sub get_student_view { $userview=~s/\<\/html\>//gi; $userview=~s/\<head\>//gi; $userview=~s/\<\/head\>//gi; + $userview=~s/\Q<div class="LC_landmark" role="main"\E/<div class="LC_landmark"/; $userview=~s/action\s*\=/would_be_action\=/gi; $userview=&relative_to_absolute($feedurl,$userview); if (wantarray) { @@ -7035,7 +7058,7 @@ sub bodytag { my $alttext = &mt('menu state: '.$menustate); my $tooltip = &mt($tiptext.' standard menus'); $bodytag .= <<"END"; -<div id="LC_expandingContainer" style="display:inline;"> +<div id="LC_expandingContainer" style="display:inline;" role="navigation"> <div id="LC_collapsible" class="LC_collapse_trigger" style="position: absolute;top: -5px;left: 0px; z-index:101; display:inline;"> <a href="#" style="text-decoration:none;"><img class="LC_collapsible_indicator" alt="$alttext" title="$tooltip" src="/res/adm/pages/$menustate.png" style="border:0;margin:0;padding:0;max-width:100%;height:auto" /></a></div> <div class="LC_menus_content $divclass"> @@ -7051,7 +7074,7 @@ END if ($dc_info) { $dc_info = qq|<span class="LC_cusr_subheading">$dc_info</span>|; } - $bodytag .= qq|<div id="LC_nav_bar" role="navigation" aria-label="$labeltext">$left $role<br />|; + $bodytag .= qq|<div id="LC_nav_bar" role="navigation" aria-label="$labeltext">$left $role</div>|; unless (($realm eq '') && ($dc_info eq '')) { $bodytag .= qq|<div id="LC_realm" role="complementary"><em>$realm</em> $dc_info</div>|; } @@ -7061,7 +7084,7 @@ END return $bodytag; } - $bodytag .= '<div class="LC_landmark" role="navigation" aria-label="'.$labeltext.'">'; + $bodytag .= '<div class="LC_landmark" style="margin: 3px 0 0 0;" role="navigation" aria-label="'.$labeltext.'">'; unless ($env{'request.symb'} =~ m/\.page___\d+___/) { $bodytag .= qq|<div id="LC_nav_bar">$left $role</div>|; } @@ -7072,8 +7095,9 @@ END $dc_info = &dc_courseid_toggle($dc_info); } unless (($realm eq '') && ($dc_info eq '')) { - $bodytag .= qq|<div id="LC_realm">$realm $dc_info</div>|; + $bodytag .= qq|<div id="LC_realm" role="complementary">$realm $dc_info</div>|; } + $bodytag .= qq|<div style="clear: both; margin: 5px 0 0 0;"></div>|; } #if directed to not display the secondary menu, don't. @@ -7086,11 +7110,13 @@ END #don't show menus for public users if (!$public){ unless ($args->{'no_inline_menu'}) { - $bodytag .= Apache::lonmenu::secondary_menu($httphost,$ltiscope,$ltimenu, + $bodytag .= '<div class="LC_landmark" role="navigation" aria-label="Secondary Links">'. + Apache::lonmenu::secondary_menu($httphost,$ltiscope,$ltimenu, $args->{'no_primary_menu'}, $menucoll,$menuref, $args->{'links_disabled'}, - $args->{'links_target'}); + $args->{'links_target'}). + '</div>'; } $bodytag .= Apache::lonmenu::serverform(); if ($need_endlcint) { @@ -7105,7 +7131,7 @@ END $args->{'group'},$args->{'hide_buttons'}, $hostname,$ltiscope,$ltiuri,$showncrumbsref); } else { - $bodytag .= + $bodytag .= &Apache::lonmenu::prepare_functions($env{'request.noversionuri'}, $forcereg,$args->{'group'}, $args->{'bread_crumbs'}, @@ -7114,7 +7140,7 @@ END } else { # this is to separate menu from content when there's no secondary # menu. Especially needed for publicly accessible resources. - $bodytag .= '<hr style="clear:both" />'; + $bodytag .= '<hr style="clear:both" role="complementary" />'; if ($need_endlcint) { $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); } @@ -7334,8 +7360,15 @@ form, .inline { .LC_heading_2 { font-size: 1.17em; - margin-top: 1em; - margin-bottom: 1em; +} + +.LC_heading_3 { + font-size: 1.0em; +} + +h1.LC_search_results { + font-size: 1.0em; + font-weight: normal; } .LC_menus_content.shown{ @@ -7350,6 +7383,10 @@ form, .inline { text-align:right; } +.LC_left { + text-align:left; +} + .LC_center { text-align:center; } @@ -7358,6 +7395,10 @@ form, .inline { vertical-align:middle; } +.LC_bottom { + vertical-align:bottom; +} + .LC_floatleft { float: left; } @@ -7443,6 +7484,14 @@ div.LC_confirm_box .LC_success img { height: auto; } +div.LC_minheight { + min-height: 24px; + border: 0; + margin: 4px 0 0 0; + padding: 0; + vertical-align: middle; +} + .LC_textsize_mobile { \@media only screen and (max-device-width: 480px) { -webkit-text-size-adjust:100%; -moz-text-size-adjust:100%; -ms-text-size-adjust:100%; @@ -7497,9 +7546,10 @@ div.LC_confirm_box .LC_success img { padding: 4px; } -table.LC_pastsubmission { +.LC_pastsubmission { border: 1px solid black; margin: 2px; + padding: 2px; } table#LC_menubuttons { @@ -7734,11 +7784,13 @@ table.LC_data_table tr td.LC_leftcol_hea } table.LC_data_table tr.LC_empty_row td, -table.LC_nested tr.LC_empty_row td { +table.LC_nested tr.LC_empty_row td, +table.LC_nested tr.LC_empty_row th { font-weight: bold; font-style: italic; text-align: center; padding: 8px; + border: 0; } table.LC_data_table tr.LC_empty_row td, @@ -7746,15 +7798,19 @@ table.LC_data_table tr.LC_footer_row td background-color: $sidebg; } +table.LC_nested tr.LC_empty_row th, table.LC_nested tr.LC_empty_row td { + padding: 4ex; background-color: #FFFFFF; } table.LC_caption { } -table.LC_nested tr.LC_empty_row td { - padding: 4ex +caption.LC_caption_prefs { + font-weight: normal; + text-align: left; + padding-bottom: 0.8em; } table.LC_nested_outer tr th { @@ -7773,14 +7829,17 @@ table.LC_nested_outer tr td.LC_subheader text-align: right; } -table.LC_nested tr.LC_info_row td { +table.LC_nested tr.LC_info_row td, +table.LC_nested tr.LC_info_row th { background-color: #CCCCCC; font-weight: bold; font-size: small; text-align: center; + border: 0; } table.LC_nested tr.LC_info_row td.LC_left_item, +table.LC_nested tr.LC_info_row th.LC_left_item, table.LC_nested_outer tr th.LC_left_item { text-align: left; } @@ -7923,6 +7982,10 @@ table.LC_data_table tr > td.LC_roles_sel border-right: 8px solid #11CC55; } +table.LC_data_table tr.LC_prefs_row { + line-height: 250%; +} + span.LC_current_location { font-size:larger; background: $pgbg; @@ -7996,39 +8059,68 @@ table.LC_parm_overview_restrictions th { border-color: $pgbg; } -table#LC_helpmenu { - border: none; - height: 55px; - border-spacing: 0; +h1.LC_helpmenu { + display: inline; + font-size: 100%; + font-weight: normal; + line-height: 1em; + margin: 0; + padding: 0; + border: 0; } -table#LC_helpmenu fieldset legend { - font-size: larger; +.LC_helpdesk_headbox { + border: 2px groove threedface; + padding: 1em; } -table#LC_helpmenu_links { - width: 100%; - border: 1px solid black; +h1.LC_helpdesk_legend { + float: left; + margin: -1.7em 0 0; + padding: 0 .5em; background: $pgbg; + font-size: 1em; + font-weight: bold; +} + +h1.LC_helpdesk_title { + display: inline; + font-size: 1em; + line-height: 2.5em; + margin: 0; padding: 0; - border-spacing: 1px; + vertical-align: bottom; } -table#LC_helpmenu_links tr td { - padding: 1px; +.LC_helpdesk_links { + border: 1px solid black; + padding: 3px; background: $tabbg; text-align: center; font-weight: bold; + display: inline; + margin-right: -6px; } -table#LC_helpmenu_links a:link, -table#LC_helpmenu_links a:visited, -table#LC_helpmenu_links a:active { +.LC_helpdesk_img, +.LC_helpdesk_text { + padding: 0; + margin: 0; + border: 0; + display: inline; +} + +.LC_helpdesk_img a:link, +.LC_helpdesk_img a:visited, +.LC_helpdesk_img a:active, +.LC_helpdesk_text a:link, +.LC_helpdesk_text a:visited, +.LC_helpdesk_text a:active { text-decoration: none; color: $font; } -table#LC_helpmenu_links a:hover { +div.LC_helpdesk_text a:hover { text-decoration: underline; color: $vlink; } @@ -8096,6 +8188,13 @@ table.LC_pick_box td.LC_oddrow_value { background-color: $data_table_light; } +td.LC_log_filter, +th.LC_log_filter { + vertical-align: top; + text-align: left; + padding: 0 4px; +} + span.LC_helpform_receipt_cat { font-weight: bold; } @@ -8258,12 +8357,27 @@ table.LC_prior_tries td { padding: 6px; } -.LC_prob_status { - margin-top: 5px; - padding-top: 0; - padding-left: 0; - padding-bottom: 0; - padding-right: 5px; +span.LC_prob_status { + margin: 5px 0 0 0; + padding: 0 5px 0 0; + vertical-align: middle; +} + +div.LC_prob_status_outer { + display: inline-block; + margin: -5px 0 0 0; + padding: 0; +} + +div.LC_prob_status_inner { + display: inline-block; + margin: 0 5px 0 0; + padding: 5px; +} + +caption.LC_filesub_status { + text-align: left; + font-weight: bold; } .LC_mail_actions { @@ -8434,6 +8548,10 @@ div.LC_grade_show_user div.LC_Box { margin-right: 50px; } +div.LC_grade_show_user div.LC_Box table tr th { + font-weight: normal; +} + div.LC_grade_submissions, div.LC_grade_message_center, div.LC_grade_info_links { @@ -8464,6 +8582,12 @@ table.LC_scantron_action tr th { font-style:normal; } +div.LC_edit_problem_daxe_header { + padding: 3px; + background: $tabbg; + z-index: 100; +} + .LC_edit_problem_header, div.LC_edit_problem_footer { font-weight: normal; @@ -8529,8 +8653,9 @@ img.stift { vertical-align: middle; } -table td.LC_mainmenu_col_fieldset { - vertical-align: top; +div.LC_mainmenu { + margin: 3px 2px 2px 1px; + float: left; } div.LC_createcourse { @@ -8612,8 +8737,23 @@ fieldset { } fieldset#LC_selectuser { - margin: 0; - padding: 0; + margin: -1px 0 0 0; + padding: 0; + border: 0; +} + +fieldset.LC_delete_slot { + display:inline; + margin: 0 4px 4px; + padding: 4px; +} + +fieldset.LC_delete_slot > legend { + font-weight: normal; +} + +p.LC_medium_line { + line-height: 0.85em; } article.geogebraweb div { @@ -9310,13 +9450,39 @@ pre.LC_wordwrap { /* styles used for response display */ -div.LC_radiofoil, div.LC_rankfoil { +div.LC_radiofoil, div.LC_rankfoil, div.LC_optionfoil, div.LC_matchfoil, div.LC_login_links { margin: .5em 0em .5em 0em; } table.LC_itemgroup { margin-top: 1em; } +table.LC_itemgroup tr th { + font-weight: normal; +} + +fieldset.LC_webbubbles { + margin: 2px 0 0 0; + padding: 0; + border: 0; +} + +ul.LC_webbubbles { + list-style: none; + padding: 0; + margin: 0; + text-align: left; + float: left; +} + +ul.LC_webbubbles li { + line-height: 1.8em; + border: 1px solid black; + padding: 0 2px 0 5px; + margin: 0 0 0 -1px; + float: left; +} + /* styles used by TTH when "Default set of options to pass to tth/m when converting TeX" in course settings has been set @@ -9740,7 +9906,11 @@ OFFLOAD <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="apple-mobile-web-app-capable" content="yes" />'; } - $result .= '<meta name="google" content="notranslate" />'."\n"; + $result .= '<meta name="google" content="notranslate"'; + if (!$args->{'frameset'}) { + $result .= ' /'; + } + $result .= '>'."\n"; return $result.'</head>'; } @@ -9871,7 +10041,7 @@ sub xml_begin { .'xmlns="http://www.w3.org/1999/xhtml">'; } elsif ($is_frameset) { $output='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'."\n". - '<html>'."\n"; + '<html lang="en">'."\n"; } else { $output='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n". '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'."\n"; @@ -10784,8 +10954,10 @@ sub simple_error_page { } my $page = - &Apache::loncommon::start_page($title,'',\%displayargs). + &Apache::loncommon::start_page($title,'',\%displayargs)."\n". + '<div class="LC_landmark" style="clear:both" role="main">'. '<p class="LC_error">'.$msg.'</p>'. + '</div>'. &Apache::loncommon::end_page(); if (ref($r)) { $r->print($page); @@ -10807,6 +10979,11 @@ sub simple_error_page { return; } + sub set_data_table_count { + my ($count) = @_; + unshift(@row_count,$count); + } + sub start_data_table { my ($add_class,$id) = @_; my $css_class = (join(' ','LC_data_table',$add_class)); @@ -10854,7 +11031,11 @@ sub simple_error_page { } sub start_data_table_header_row { - return '<tr class="LC_header_row">'."\n";; + my ($add_class,$id) = @_; + my $css_class = 'LC_header_row'; + $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq ''); + $id = (' id="'.$id.'"') unless ($id eq ''); + return '<tr class="'.$css_class.'"'.$id.'>'."\n"; } sub end_data_table_header_row { @@ -10862,8 +11043,8 @@ sub simple_error_page { } sub data_table_caption { - my $caption = shift; - return "<caption class=\"LC_caption\">$caption</caption>"; + my ($caption,$css_class) = @_; + return "<caption class=\"LC_caption $css_class\">$caption</caption>"; } } @@ -15533,12 +15714,12 @@ sub upfile_select_html { tab => &mt('Tabulator separated'), # xml => &mt('HTML/XML'), ); - my $Str = '<input type="file" name="upfile" size="50" />'. - '<br />'.&mt('Type').': <select name="upfiletype">'; + my $Str = '<input type="file" name="upfile" id="upfile" size="50" />'. + '<br /><label>'.&mt('Type').': <select name="upfiletype">'; foreach my $type (sort(keys(%Types))) { $Str .= '<option value="'.$type.'" >'.$Types{$type}."</option>\n"; } - $Str .= "</select>\n"; + $Str .= "</select></label>\n"; return $Str; } @@ -15622,9 +15803,9 @@ sub csv_print_select_table { &end_data_table_header_row()."\n"); foreach my $array_ref (@$d) { my ($value,$display,$defaultcol)=@{ $array_ref }; - $r->print(&start_data_table_row().'<td>'.$display.'</td>'); + $r->print(&start_data_table_row().'<td><label for="f'.$i.'">'.$display.'</label></td>'); - $r->print('<td><select name="f'.$i.'"'. + $r->print('<td><select name="f'.$i.'" id="f'.$i.'"'. ' onchange="javascript:flip(this.form,'.$i.');">'); $r->print('<option value="none"></option>'); foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) { @@ -15669,8 +15850,10 @@ sub csv_samples_select_table { &end_data_table_header_row()); foreach my $key (sort(keys(%{ $samples->[0] }))) { + my $num = $i+1; + my $labeltext = &HTML::Entities::encode(&mt('Field for data in column [_1]',$num)); $r->print(&start_data_table_row().'<td><select name="f'.$i.'"'. - ' onchange="javascript:flip(this.form,'.$i.');">'); + ' onchange="javascript:flip(this.form,'.$i.');" aria-label="'.$labeltext.'">'); foreach my $option (@$d) { my ($value,$display,$defaultcol)=@{ $option }; $r->print('<option value="'.$value.'"'. @@ -18981,7 +19164,7 @@ Returns: HTML to display with informatio sub check_release_result { my ($switchwarning,$switchserver) = @_; my $output = &start_page('Selected course unavailable on this server'). - '<p class="LC_warning">'; + '<div class="LC_landmark" role="main"><p class="LC_warning">'; if ($switchwarning) { $output .= $switchwarning.'<br /><a href="/adm/roles">'; if (&show_course()) { @@ -18997,7 +19180,7 @@ sub check_release_result { &mt('Switch Server'). '</a>'; } - $output .= '</p>'.&end_page(); + $output .= '</p></div>'.&end_page(); return $output; } @@ -19614,7 +19797,7 @@ sub create_captcha { $output = '<input type="hidden" name="crypt" value="'.$md5sum.'" />'."\n". '<span class="LC_nobreak">'. '<label>'.&mt('Type in the letters/numbers shown below').' '. - '<input type="text" size="5" name="code" value="" autocomplete="new-password" />'. + '<input type="text" size="5" name="code" value="" autocomplete="new-password" aria-required="true" />'. '</label></span><br />'. '<img src="'.$captcha_params{'www_output_dir'}.'/'.$md5sum.'.png" alt="captcha" />'; last;