Skip to content

Commit

Permalink
Add a special case to feedback to show correct answers only.
Browse files Browse the repository at this point in the history
If the translation options `showCorrectAnswers`,
`forceShowAttemptResults`, and `forceScaffoldsOpen` are all true, and
the options `showAttemptAnswers`, `showAttemptPreviews`, and
`showMessages` are all false, then correct answers will be shown with no
other content in the feedback popover except a close button.
Furthermore the popover will open automatically on page load. Obviously
scaffold will all be open (since the `forceScaffoldsOpen` option is
true).  Otherwise there would be a problem with popovers opening
immediately from inside a closed scaffold.

A corresponding pull request to webwork2 will utilize this.
  • Loading branch information
drgrice1 committed Apr 23, 2024
1 parent d115315 commit 33f3b7a
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 36 deletions.
11 changes: 8 additions & 3 deletions htdocs/js/Feedback/feedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@
moveToFront();

// Make a click on the popover header close the popover.
feedbackPopover.tip
?.querySelector('.popover-header .btn-close')
?.addEventListener('click', () => feedbackPopover.hide());
feedbackPopover.tip?.querySelector('.btn-close')?.addEventListener('click', () => feedbackPopover.hide());

if (feedbackPopover.tip) feedbackPopover.tip.dataset.iframeHeight = '1';

Expand All @@ -68,6 +66,13 @@
});
}
});

if (feedbackBtn.dataset.showCorrectOnly) {
setTimeout(() => {
feedbackBtn.click();
setTimeout(() => feedbackPopover.update(), 100);
}, 0);
}
};

// Setup feedback popovers already on the page.
Expand Down
6 changes: 6 additions & 0 deletions htdocs/js/MathQuill/mqeditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
if (input.classList.contains('incorrect')) answerQuill.classList.add('incorrect');
if (input.classList.contains('partially-correct')) answerQuill.classList.add('partially-correct');

// Find the feedback button for this input if there is one on the page.
const feedbackBtn = document.querySelector(`button[data-answer-label="${answerLabel}"`);

// Default options.
const cfgOptions = {
spaceBehavesLikeTab: true,
Expand Down Expand Up @@ -261,6 +264,9 @@
answerQuill.input.value = '';
answerQuill.latexInput.value = '';
}

// If the feedback popover is open, then update its position.
if (feedbackBtn) bootstrap.Popover.getInstance(feedbackBtn)?.update();
};

input.after(answerQuill);
Expand Down
23 changes: 20 additions & 3 deletions htdocs/js/Problem/problem.scss
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,26 @@
--bs-popover-max-width: 600px;
--bs-popover-zindex: 17;
position: absolute;
min-width: 200px;

&:not(.correct-only) {
min-width: 200px;

.popover-body {
.card {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
}

&.correct-only {
.popover-body {
.card {
--bs-card-spacer-x: 0.25rem;
--bs-card-spacer-y: 0.25rem;
}
}
}

.popover-header {
text-align: center;
Expand Down Expand Up @@ -262,8 +281,6 @@

.popover-body {
.card {
border-top-left-radius: 0;
border-top-right-radius: 0;
--bs-card-spacer-y: 0.5rem;
--bs-card-cap-bg: #ddd;

Expand Down
10 changes: 9 additions & 1 deletion lib/WeBWorK/PG.pm
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,8 @@ the value of this option.
=item showAttemptAnswers (boolean, default: 1)
Determines if the student's evaluated (i.e. "Entered") answers will be shown in feedback.
Determines if the student's evaluated (i.e. "Entered") answers will be shown in
feedback.
=item showAttemptPreviews (boolean, default: 1)
Expand Down Expand Up @@ -520,6 +521,13 @@ shown. If set to 1, then correct answers are shown but hidden, and a "Reveal"
button is shown at first. If that button is clicked, then the answer is shown.
If set to 2, then correct answers are shown immediately.
There is one special case that needs extra explanation. If this is true
(greater than zero), C<forceShowAttemptResults> is true, C<forceScaffoldsOpen>
is true, and C<showAttemptAnswers>, C<showAttemptPreviews>, and C<showMessages>
are all false, then correct answers will be shown with no other content in the
feedback popover except a close button, and the popover will open automatically
on page load.
=item answerPrefix (string, default: '')
A prefix to prepend to all answer labels. Note that other prefixes may be
Expand Down
87 changes: 58 additions & 29 deletions macros/PG.pl
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,14 @@ sub ENDDOCUMENT {

my @answerNames = keys %{ $PG->{PG_ANSWERS_HASH} };

my $showCorrectOnly =
$rh_envir->{showCorrectAnswers}
&& $rh_envir->{forceScaffoldsOpen}
&& $rh_envir->{forceShowAttemptResults}
&& !$rh_envir->{showAttemptAnswers}
&& !$rh_envir->{showAttemptPreviews}
&& !$rh_envir->{showMessages};

for my $answerLabel (@answerNames) {
my $response_obj = $PG->{PG_ANSWERS_HASH}{$answerLabel}->response_obj;
my $ansHash = $PG->{PG_ANSWERS_HASH}{$answerLabel}{ans_eval}{rh_ans};
Expand Down Expand Up @@ -1072,11 +1080,12 @@ sub ENDDOCUMENT {
push(@{ $options{feedbackElements} }, @$elements);
}

my $showResults = ($rh_envir->{showAttemptResults} && $PG->{flags}{showPartialCorrectAnswers})
|| $rh_envir->{forceShowAttemptResults};

if ($showResults) {
if ($answerScore >= 1) {
if (($rh_envir->{showAttemptResults} && $PG->{flags}{showPartialCorrectAnswers})
|| $rh_envir->{forceShowAttemptResults})
{
if ($showCorrectOnly) {
$options{resultClass} = 'correct-only';
} elsif ($answerScore >= 1) {
$options{resultTitle} = maketext('Correct');
$options{resultClass} = 'correct';
$options{btnClass} = 'btn-success';
Expand Down Expand Up @@ -1111,6 +1120,8 @@ sub ENDDOCUMENT {
|| $ansHash->{ans_message}
|| $rh_envir->{showCorrectAnswers});

next if $showCorrectOnly && !$options{showCorrect};

# Find an element to insert the button in or around if one has not been provided.
unless ($options{insertElement}) {
# Use the last feedback element by default.
Expand Down Expand Up @@ -1144,8 +1155,7 @@ sub ENDDOCUMENT {
if $options{insertElement} && $options{insertElement}->attr->{'data-feedback-insert-method'};
}

# Add the correct/incorrect/partially-correct class and
# aria-described by attribute to the feedback elements.
# Add the correct/incorrect/partially-correct class to the feedback elements.
for (@{ $options{feedbackElements} }) {
$_->attr(class => join(' ', $options{resultClass}, $_->attr->{class} || ()))
if $options{resultClass};
Expand Down Expand Up @@ -1183,8 +1193,7 @@ sub ENDDOCUMENT {

my $answerPreview = $previewAnswer->($ansHash->{preview_latex_string}, $options{wrapPreviewInTex});

# Create the screen reader only span holding the aria description, create the feedback button and
# popover, and insert the button at the requested location.
# Create the feedback button and popover, and insert the button at the requested location.
my $feedback = Mojo::DOM->new_tag(
'button',
type => 'button',
Expand All @@ -1196,27 +1205,30 @@ sub ENDDOCUMENT {
: $options{resultTitle}
),
data => {
bs_title => Mojo::DOM->new_tag(
'div',
class => 'd-flex align-items-center justify-content-between',
'data-bs-theme' => 'dark',
sub {
Mojo::DOM->new_tag('span', style => 'width:20.4px')
. Mojo::DOM->new_tag('span', class => 'mx-3', $options{resultTitle})
. Mojo::DOM->new_tag(
'button',
type => 'button',
class => 'btn-close',
'aria-label' => maketext('Close')
);
}
)->to_string,
$showCorrectOnly ? (show_correct_only => 1) : (
bs_title => Mojo::DOM->new_tag(
'div',
class => 'd-flex align-items-center justify-content-between',
'data-bs-theme' => 'dark',
sub {
Mojo::DOM->new_tag('span', style => 'width:20.4px')
. Mojo::DOM->new_tag('span', class => 'mx-3', $options{resultTitle})
. Mojo::DOM->new_tag(
'button',
type => 'button',
class => 'btn-close',
'aria-label' => maketext('Close')
);
}
)->to_string
),
answer_label => $answerLabel,
bs_toggle => 'popover',
bs_trigger => 'click',
bs_placement => 'bottom',
bs_placement => $showCorrectOnly ? 'right' : 'bottom',
bs_html => 'true',
bs_custom_class => join(' ', 'ww-feedback-popover', $options{resultClass} || ()),
bs_fallback_placements => '[]',
bs_fallback_placements => $showCorrectOnly ? '["left","top","bottom"]' : '[]',
bs_content => Mojo::DOM->new_tag(
'div',
id => "$answerLabel-feedback",
Expand Down Expand Up @@ -1257,10 +1269,27 @@ sub ENDDOCUMENT {
$options{wrapPreviewInTex},
$ansHash->{correct_ans}
);
$feedbackLine->(
$showCorrectOnly
? $feedbackLine->(
'',
Mojo::DOM->new_tag(
'div',
class =>
'd-flex justify-content-between align-items-center gap-2',
sub {
$correctAnswer
. Mojo::DOM->new_tag(
'button',
type => 'button',
class => 'btn-close',
'aria-label' => maketext('Close')
);
}
)
)
: $feedbackLine->(
maketext('Correct Answer'),
$rh_envir->{showCorrectAnswers} > 1
? $correctAnswer
$rh_envir->{showCorrectAnswers} > 1 ? $correctAnswer
: Mojo::DOM->new_tag(
'button',
type => 'button',
Expand Down
1 change: 1 addition & 0 deletions macros/core/PGessaymacros.pl
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ sub essay_cmp {
$options->{manuallyGraded} = 1;

if ($envir{needs_grading}
|| !defined $ansHash->{ans_label}
|| !defined $inputs_ref->{"previous_$ansHash->{ans_label}"}
|| $inputs_ref->{ $ansHash->{ans_label} } ne $inputs_ref->{"previous_$ansHash->{ans_label}"})
{
Expand Down

0 comments on commit 33f3b7a

Please sign in to comment.