@@ -128,6 +128,7 @@ public function subquestion(question_attempt $qa,
128
128
} else {
129
129
throw new coding_exception ('Unexpected subquestion type. ' , $ subq );
130
130
}
131
+ /** @var qtype_multianswer_subq_renderer_base $renderer */
131
132
$ renderer = $ this ->page ->get_renderer ('qtype_multianswer ' , $ subrenderer );
132
133
return $ renderer ->subquestion ($ qa , $ options , $ index , $ subq );
133
134
}
@@ -147,6 +148,12 @@ public function correct_response(question_attempt $qa) {
147
148
*/
148
149
abstract class qtype_multianswer_subq_renderer_base extends qtype_renderer {
149
150
151
+ /** @var int[] Stores the counts of answer instances for questions. */
152
+ protected static $ answercount = [];
153
+
154
+ /** @var question_display_options Question display options instance for any necessary information for rendering the question. */
155
+ protected $ displayoptions ;
156
+
150
157
abstract public function subquestion (question_attempt $ qa ,
151
158
question_display_options $ options , $ index ,
152
159
question_graded_automatically $ subq );
@@ -198,6 +205,36 @@ protected function feedback_popup(question_graded_automatically $subq,
198
205
return html_writer::tag ('span ' , implode ('<br /> ' , $ feedback ),
199
206
array ('class ' => 'feedbackspan accesshide ' ));
200
207
}
208
+
209
+ /**
210
+ * Generates a label for an answer field.
211
+ *
212
+ * If the question number is set ({@see qtype_renderer::$questionnumber}), the label will
213
+ * include the question number in order to indicate which question the answer field belongs to.
214
+ *
215
+ * @param string $langkey The lang string key for the lang string that does not include the question number.
216
+ * @param string $component The Frankenstyle component name.
217
+ * @return string
218
+ * @throws coding_exception
219
+ */
220
+ protected function get_answer_label (
221
+ string $ langkey = 'answerx ' ,
222
+ string $ component = 'question '
223
+ ): string {
224
+ // There may be multiple answer fields for a question, so we need to increment the answer fields in order to distinguish
225
+ // them from one another.
226
+ $ questionnumber = $ this ->displayoptions ->questionidentifier ?? '' ;
227
+ $ questionnumberindex = $ questionnumber !== '' ? $ questionnumber : 0 ;
228
+ if (isset (self ::$ answercount [$ questionnumberindex ][$ langkey ])) {
229
+ self ::$ answercount [$ questionnumberindex ][$ langkey ]++;
230
+ } else {
231
+ self ::$ answercount [$ questionnumberindex ][$ langkey ] = 1 ;
232
+ }
233
+
234
+ $ params = self ::$ answercount [$ questionnumberindex ][$ langkey ];
235
+
236
+ return $ this ->displayoptions ->add_question_identifier_to_label (get_string ($ langkey , $ component , $ params ));
237
+ }
201
238
}
202
239
203
240
@@ -213,6 +250,8 @@ class qtype_multianswer_textfield_renderer extends qtype_multianswer_subq_render
213
250
public function subquestion (question_attempt $ qa , question_display_options $ options ,
214
251
$ index , question_graded_automatically $ subq ) {
215
252
253
+ $ this ->displayoptions = $ options ;
254
+
216
255
$ fieldprefix = 'sub ' . $ index . '_ ' ;
217
256
$ fieldname = $ fieldprefix . 'answer ' ;
218
257
@@ -272,7 +311,8 @@ public function subquestion(question_attempt $qa, question_display_options $opti
272
311
s ($ correctanswer ->answer ), $ options );
273
312
274
313
$ output = html_writer::start_tag ('span ' , array ('class ' => 'subquestion form-inline d-inline ' ));
275
- $ output .= html_writer::tag ('label ' , get_string ('answer ' ),
314
+
315
+ $ output .= html_writer::tag ('label ' , $ this ->get_answer_label (),
276
316
array ('class ' => 'subq accesshide ' , 'for ' => $ inputattributes ['id ' ]));
277
317
$ output .= html_writer::empty_tag ('input ' , $ inputattributes );
278
318
$ output .= $ feedbackimg ;
@@ -296,6 +336,8 @@ class qtype_multianswer_multichoice_inline_renderer
296
336
public function subquestion (question_attempt $ qa , question_display_options $ options ,
297
337
$ index , question_graded_automatically $ subq ) {
298
338
339
+ $ this ->displayoptions = $ options ;
340
+
299
341
$ fieldprefix = 'sub ' . $ index . '_ ' ;
300
342
$ fieldname = $ fieldprefix . 'answer ' ;
301
343
@@ -340,7 +382,7 @@ public function subquestion(question_attempt $qa, question_display_options $opti
340
382
$ qa , 'question ' , 'answer ' , $ rightanswer ->id ), $ options );
341
383
342
384
$ output = html_writer::start_tag ('span ' , array ('class ' => 'subquestion ' ));
343
- $ output .= html_writer::tag ('label ' , get_string ( ' answer ' ),
385
+ $ output .= html_writer::tag ('label ' , $ this -> get_answer_label ( ),
344
386
array ('class ' => 'subq accesshide ' , 'for ' => $ inputattributes ['id ' ]));
345
387
$ output .= $ select ;
346
388
$ output .= $ feedbackimg ;
@@ -364,13 +406,16 @@ class qtype_multianswer_multichoice_vertical_renderer extends qtype_multianswer_
364
406
public function subquestion (question_attempt $ qa , question_display_options $ options ,
365
407
$ index , question_graded_automatically $ subq ) {
366
408
409
+ $ this ->displayoptions = $ options ;
410
+
367
411
$ fieldprefix = 'sub ' . $ index . '_ ' ;
368
412
$ fieldname = $ fieldprefix . 'answer ' ;
369
413
$ response = $ qa ->get_last_qt_var ($ fieldname );
370
414
371
415
$ inputattributes = array (
372
416
'type ' => 'radio ' ,
373
417
'name ' => $ qa ->get_qt_field_name ($ fieldname ),
418
+ 'class ' => 'form-check-input ' ,
374
419
);
375
420
if ($ options ->readonly ) {
376
421
$ inputattributes ['disabled ' ] = 'disabled ' ;
@@ -392,7 +437,7 @@ public function subquestion(question_attempt $qa, question_display_options $opti
392
437
unset($ inputattributes ['checked ' ]);
393
438
}
394
439
395
- $ class = 'r ' . ( $ value % 2 ) ;
440
+ $ class = 'form-check text-wrap text-break ' ;
396
441
if ($ options ->correctness && $ isselected ) {
397
442
$ feedbackimg = $ this ->feedback_image ($ ans ->fraction );
398
443
$ class .= ' ' . $ this ->feedback_class ($ ans ->fraction );
@@ -404,7 +449,7 @@ public function subquestion(question_attempt $qa, question_display_options $opti
404
449
$ result .= html_writer::empty_tag ('input ' , $ inputattributes );
405
450
$ result .= html_writer::tag ('label ' , $ subq ->format_text ($ ans ->answer ,
406
451
$ ans ->answerformat , $ qa , 'question ' , 'answer ' , $ ansid ),
407
- array ('for ' => $ inputattributes ['id ' ]));
452
+ array ('for ' => $ inputattributes ['id ' ], ' class ' => ' form-check-label text-body ' ));
408
453
$ result .= $ feedbackimg ;
409
454
410
455
if ($ options ->feedback && $ isselected && trim ($ ans ->feedback )) {
@@ -465,14 +510,17 @@ protected function choice_wrapper_end() {
465
510
* @return string HTML to go before all the choices.
466
511
*/
467
512
protected function all_choices_wrapper_start () {
468
- return html_writer::start_tag ('div ' , array ('class ' => 'answer ' ));
513
+ $ wrapperstart = html_writer::start_tag ('fieldset ' , array ('class ' => 'answer ' ));
514
+ $ legendtext = $ this ->get_answer_label ('multichoicex ' , 'qtype_multianswer ' );
515
+ $ wrapperstart .= html_writer::tag ('legend ' , $ legendtext , ['class ' => 'sr-only ' ]);
516
+ return $ wrapperstart ;
469
517
}
470
518
471
519
/**
472
520
* @return string HTML to go after all the choices.
473
521
*/
474
522
protected function all_choices_wrapper_end () {
475
- return html_writer::end_tag ('div ' );
523
+ return html_writer::end_tag ('fieldset ' );
476
524
}
477
525
}
478
526
@@ -488,21 +536,22 @@ class qtype_multianswer_multichoice_horizontal_renderer
488
536
extends qtype_multianswer_multichoice_vertical_renderer {
489
537
490
538
protected function choice_wrapper_start ($ class ) {
491
- return html_writer::start_tag ('td ' , array ('class ' => $ class ));
539
+ return html_writer::start_tag ('div ' , array ('class ' => $ class . ' form-check-inline ' ));
492
540
}
493
541
494
542
protected function choice_wrapper_end () {
495
- return html_writer::end_tag ('td ' );
543
+ return html_writer::end_tag ('div ' );
496
544
}
497
545
498
546
protected function all_choices_wrapper_start () {
499
- return html_writer::start_tag ('table ' , array ('class ' => 'answer ' )) .
500
- html_writer::start_tag ('tbody ' ) . html_writer::start_tag ('tr ' );
547
+ $ wrapperstart = html_writer::start_tag ('fieldset ' , ['class ' => 'answer ' ]);
548
+ $ captiontext = $ this ->get_answer_label ('multichoicex ' , 'qtype_multianswer ' );
549
+ $ wrapperstart .= html_writer::tag ('legend ' , $ captiontext , ['class ' => 'sr-only ' ]);
550
+ return $ wrapperstart ;
501
551
}
502
552
503
553
protected function all_choices_wrapper_end () {
504
- return html_writer::end_tag ('tr ' ) . html_writer::end_tag ('tbody ' ) .
505
- html_writer::end_tag ('table ' );
554
+ return html_writer::end_tag ('fieldset ' );
506
555
}
507
556
}
508
557
0 commit comments