Skip to content

Commit d9a487c

Browse files
committed
long image descriptions
1 parent 490900f commit d9a487c

File tree

6 files changed

+139
-26
lines changed

6 files changed

+139
-26
lines changed

htdocs/js/Problem/problem.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,25 @@
203203
}
204204
}
205205

206+
.image-container {
207+
.image-details-content {
208+
position: fixed;
209+
bottom: 0;
210+
left: 50%;
211+
transform: translateX(-50%);
212+
max-width: 90%;
213+
box-shadow: 0 0 100px black;
214+
border-top-left-radius: 4px;
215+
border-top-right-radius: 4px;
216+
z-index: 10;
217+
}
218+
}
219+
220+
.image-details-dismiss {
221+
display: block;
222+
float: right;
223+
}
224+
206225
/* rtl:raw:
207226
.problem-content[dir=ltr] input[type=radio] {
208227
margin-right: 0.25rem;

lib/Plots/JSXGraph.pm

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,14 @@ sub HTML {
3434

3535
my $imageviewClass = $self->plots->axes->style('jsx_navigation') ? '' : ' image-view-elt';
3636
my $tabindex = $self->plots->axes->style('jsx_navigation') ? '' : ' tabindex="0"';
37+
my $details = $self->plots->{description_details} =~ s/LONG-DESCRIPTION-ID/${name}_details/r;
38+
my $aria_details = $details ? qq! aria-details="${name}_details"! : '';
39+
my $divs = qq!<div id="jsxgraph-plot-$name" class="jxgbox plots-jsxgraph$imageviewClass"$tabindex!
40+
. qq!style="width: ${width}px; height: ${height}px;"$aria_details></div>!;
41+
$divs = qq!<div class="image-container">$divs$details</div>! if ($details);
3742

3843
return <<~ "END_HTML";
39-
<div id="jsxgraph-plot-$name" class="jxgbox plots-jsxgraph$imageviewClass"$tabindex
40-
style="width: ${width}px; height: ${height}px;"></div>
44+
$divs
4145
<script>
4246
(async () => {
4347
const jsxPlotDiv = document.getElementById('jsxgraph-plot-$name');

macros/core/PGML.pl

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ sub NOOP {
687687
terminator => qr/!\]/,
688688
terminateMethod => 'terminateGetString',
689689
cancelNL => 1,
690-
options => [ "source", "width", "height", "image_options" ]
690+
options => [ "source", "width", "height", "image_options", "long_description" ]
691691
},
692692
"[<" => {
693693
type => 'tag',
@@ -1484,12 +1484,20 @@ sub Text {
14841484

14851485
sub Image {
14861486
my ($self, $item) = @_;
1487-
my $text = $item->{text};
1488-
my $source = $item->{source};
1489-
my $width = $item->{width} || '';
1490-
my $height = $item->{height} || '';
1491-
my $image_options = $item->{image_options} || {};
1492-
return (main::image($source, alt => $text, width => $width, height => $height, %$image_options));
1487+
my $text = $item->{text};
1488+
my $source = $item->{source};
1489+
my $width = $item->{width} || '';
1490+
my $height = $item->{height} || '';
1491+
my $image_options = $item->{image_options} || {};
1492+
my $long_description = $item->{long_description} || '';
1493+
return (main::image(
1494+
$source,
1495+
alt => $text,
1496+
width => $width,
1497+
height => $height,
1498+
long_description => $long_description,
1499+
%$image_options
1500+
));
14931501
}
14941502

14951503
######################################################################

macros/core/PGbasicmacros.pl

Lines changed: 95 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2737,10 +2737,10 @@ =head2 Macros for displaying images
27372737

27382738
Usage:
27392739

2740-
image($image, width => 200, height => 200, tex_size => 800, valign => 'middle', alt => 'alt text', extra_html_tags => 'style="border:solid black 1pt"');
2740+
image($image, width => ..., height => ..., tex_size => ..., valign => ..., alt => ..., long_description => ... );
27412741

27422742
where C<$image> can be a local file path, URL, WWPlot object, PGlateximage object,
2743-
PGtikz object, or parser::GraphTool object.
2743+
PGtikz object, Plots::Plot object, or parser::GraphTool object.
27442744

27452745
C<width> and C<height> are positive integer pixel counts for HTML display. If both
27462746
are missing, C<width> will default to 200 and C<height> will remain undeclared,
@@ -2757,10 +2757,29 @@ =head2 Macros for displaying images
27572757
C<valign> can be 'top', 'middle', or 'bottom'. This aligns the image relative to
27582758
the surrounding line of text.
27592759

2760-
image([$image1,$image2], width => 200, height => 200, tex_size => 800, alt => ['alt text 1','alt text 2'], extra_html_tags => 'style="border:solid black 1pt"');
2761-
image([$image1,$image2], width => 200, height => 200, tex_size => 800, alt => 'common alt text', extra_html_tags => 'style="border:solid black 1pt"');
2760+
C<alt> should be a string, ideally with fewer than 125 characters, that describes the
2761+
most important features of the image. This should always be used. If the image is
2762+
decorative, C<< alt => '' >> should be used.
27622763

2763-
this produces an array in array context and joins the elements with C<' '> in scalar context
2764+
C<long_description> provides an optional way to give a more complete description of
2765+
an image. This may include a table (for example to describe complex data in a graph).
2766+
It may be helpful to generate blocks of text and tables and store them in a variable,
2767+
and pass that variable to C<long_description>.
2768+
2769+
C<extra_html_tags> [DEPRECATED] can be a string will directly be placed into the
2770+
HTML img element. For example, C<< extra_html_tags => 'style="border:solid black 1pt"' >>.
2771+
2772+
The first argument to C<image()> can alternatively be an array of images:
2773+
2774+
image([$image1, $image2], ...);
2775+
2776+
If so then if C<alt> or C<long_description> are not arrays, they will be used
2777+
repeatedly for each image. Each of C<alt> and C<long_description> can instead be
2778+
arrays of the same length and their entries will be used with the corresponding
2779+
image.
2780+
2781+
In array context, using C<image()> this way will produces an array in array context
2782+
and join the elements with C<' '> in scalar context.
27642783

27652784
=cut
27662785

@@ -2778,8 +2797,9 @@ sub image {
27782797
tex_size => '',
27792798
valign => 'middle',
27802799
# default value for alt is undef, since an empty string is the explicit indicator of a decorative image
2781-
alt => undef,
2782-
extra_html_tags => '',
2800+
alt => undef,
2801+
long_description => undef,
2802+
extra_html_tags => '',
27832803
);
27842804
# handle options
27852805
my %out_options = %known_options;
@@ -2802,9 +2822,11 @@ sub image {
28022822
$tex_size = 1000 if $tex_size > 1000;
28032823

28042824
my $alt = $out_options{alt};
2825+
my $desc = $out_options{long_description};
28052826
my $width_ratio = $tex_size * (.001);
28062827
my @image_list = ();
28072828
my @alt_list = ();
2829+
my @desc_list = ();
28082830
my $valign = 'middle';
28092831
$valign = 'top' if ($out_options{valign} eq 'top');
28102832
$valign = 'bottom' if ($out_options{valign} eq 'bottom');
@@ -2823,16 +2845,56 @@ sub image {
28232845
} else {
28242846
for my $i (@image_list) { push(@alt_list, $alt) }
28252847
}
2848+
if (ref($desc) =~ /ARRAY/) {
2849+
@desc_list = @{$desc};
2850+
} else {
2851+
for my $i (@image_list) { push(@desc_list, $desc) }
2852+
}
28262853

28272854
my @output_list = ();
28282855
while (@image_list) {
2829-
my $image_item = shift @image_list;
2856+
my $image_item = shift @image_list;
2857+
my $description_details = '';
2858+
if ($desc) {
2859+
$description_details = tag(
2860+
'details',
2861+
'aria-live' => 'polite',
2862+
class => 'image-details',
2863+
name => 'image-details',
2864+
tag(
2865+
'summary',
2866+
class => 'mt-1',
2867+
title => 'details',
2868+
tag(
2869+
'span',
2870+
class => 'badge badge-info bg-secondary',
2871+
'aria-hidden' => 'true',
2872+
maketext('image description')
2873+
)
2874+
)
2875+
. tag(
2876+
'div',
2877+
id => 'LONG-DESCRIPTION-ID',
2878+
class => 'image-details-content bg-white py-2 px-3 my-2 border',
2879+
shift(@desc_list)
2880+
. tag('br')
2881+
. tag(
2882+
'button',
2883+
class => 'image-details-dismiss badge badge-info bg-secondary',
2884+
type => 'button',
2885+
onclick => "this.parentElement.parentElement.removeAttribute('open')",
2886+
maketext('Close image description')
2887+
)
2888+
)
2889+
);
2890+
}
28302891
if (ref $image_item eq 'parser::GraphTool') {
28312892
push(
28322893
@output_list,
28332894
$image_item->generateAnswerGraph(
2834-
$out_options{width} || $out_options{height} ? (width => $width, height => $height) : (),
2835-
$out_options{tex_size} || $out_options{width} ? (texSize => $tex_size) : (),
2895+
$out_options{width} || $out_options{height} ? (width => $width, height => $height) : (),
2896+
$out_options{tex_size} || $out_options{width} ? (texSize => $tex_size) : (),
2897+
$desc ? (longDescription => $description_details) : (),
28362898
ariaDescription => shift @alt_list // ''
28372899
)
28382900
);
@@ -2846,6 +2908,7 @@ sub image {
28462908
$image_item->{ariaDescription} = shift @alt_list if $out_options{alt};
28472909

28482910
if ($image_item->ext eq 'html') {
2911+
$image_item->{description_details} = $description_details;
28492912
push(@output_list, $image_item->draw);
28502913
next;
28512914
}
@@ -2862,6 +2925,7 @@ sub image {
28622925
|| ref $image_item eq 'PGtikz');
28632926
my $imageURL = alias($image_item) // '';
28642927
$imageURL = ($envir{use_site_prefix}) ? $envir{use_site_prefix} . $imageURL : $imageURL;
2928+
my $id = $main::PG->getUniqueName('img');
28652929
my $out = "";
28662930

28672931
if ($displayMode eq 'TeX') {
@@ -2889,15 +2953,31 @@ sub image {
28892953
{
28902954
my $altattrib = '';
28912955
if (defined $alt_list[0]) { $altattrib = 'alt="' . encode_pg_and_html(shift @alt_list) . '"' }
2892-
$out =
2893-
qq!<IMG SRC="$imageURL" class="image-view-elt $valign" tabindex="0" role="button"$width_attrib$height_attrib $out_options{extra_html_tags} $altattrib>!;
2956+
if ($desc) {
2957+
$out .= tag(
2958+
'div',
2959+
class => 'image-container pb-2',
2960+
qq!<img src="$imageURL" class="image-view-elt $valign" tabindex="0" role="button"!
2961+
. qq!$width_attrib$height_attrib aria-details="${id}_details" $out_options{extra_html_tags} $altattrib>!
2962+
. ($description_details =~ s/LONG-DESCRIPTION-ID/${id}_details/r)
2963+
);
2964+
} else {
2965+
$out .= qq!<img src="$imageURL" class="image-view-elt $valign" tabindex="0" role="button"!
2966+
. qq!$width_attrib$height_attrib $out_options{extra_html_tags} $altattrib>!;
2967+
}
28942968
} elsif ($displayMode eq 'PTX') {
28952969
my $ptxwidth = ($width ? int($width / 6) : 80);
2970+
$out = qq!<image width="$ptxwidth%" source="$imageURL">!;
28962971
if (defined $alt) {
2897-
$out = qq!<image width="$ptxwidth%" source="$imageURL"><description>$alt</description></image>!;
2898-
} else {
2899-
$out = qq!<image width="$ptxwidth%" source="$imageURL" />!;
2972+
$out .= "\n<shortdescription>$alt</shortdescription>";
2973+
}
2974+
if (defined $desc) {
2975+
$out .= "\n<description>\n" . PTX_cleanup($desc) . "\n</description>";
2976+
}
2977+
if (defined $alt || defined $desc) {
2978+
$out .= "\n";
29002979
}
2980+
$out .= '</image>';
29012981
} else {
29022982
$out = "Error: PGbasicmacros: image: Unknown displayMode: $displayMode.\n";
29032983
}

t/build_PG_envir.pl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
my $macros_dir = "$ENV{PG_ROOT}/macros";
1010

11+
use HTML::Entities;
12+
1113
use WeBWorK::PG::Environment;
1214
use WeBWorK::PG;
1315
use PGcore;

t/tikz_test/tikz_image.t

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ END_TIKZ
2323
ok my $img = image($drawing), 'img tag is generated';
2424

2525
like $img, qr!
26-
^<IMG\s
27-
SRC="/pg_files/tmp/images/([a-z0-9_-]*)\.svg"\s
26+
^<img\s
27+
src="/pg_files/tmp/images/([a-z0-9_-]*)\.svg"\s
2828
class="image-view-elt\smiddle"\s
2929
tabindex="0"\s
3030
role="button"\s

0 commit comments

Comments
 (0)