Merge branch 'MDL-70248-310' of https://github.com/HuongNV13/moodle into MOODLE_310_S...
[moodle.git] / question / type / ddmarker / renderer.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * Drag-and-drop markers question renderer class.
19  *
20  * @package   qtype_ddmarker
21  * @copyright 2012 The Open University
22  * @author    Jamie Pratt <me@jamiep.org>
23  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
27 defined('MOODLE_INTERNAL') || die();
29 require_once($CFG->dirroot . '/question/type/rendererbase.php');
30 require_once($CFG->dirroot . '/question/type/ddimageortext/rendererbase.php');
33 /**
34  * Generates the output for drag-and-drop markers questions.
35  *
36  * @copyright  2010 The Open University
37  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class qtype_ddmarker_renderer extends qtype_ddtoimage_renderer_base {
40     public function formulation_and_controls(question_attempt $qa,
41             question_display_options $options) {
43         $question = $qa->get_question();
44         $response = $qa->get_last_qt_data();
45         $componentname = $question->qtype->plugin_name();
47         $questiontext = $question->format_questiontext($qa);
49         $dropareaclass = 'droparea';
50         $draghomesclass = 'draghomes';
51         if ($options->readonly) {
52             $dropareaclass .= ' readonly';
53             $draghomesclass .= ' readonly';
54         }
56         $output = html_writer::div($questiontext, 'qtext');
58         $output .= html_writer::start_div('ddarea');
59         $output .= html_writer::start_div($dropareaclass);
60         $output .= html_writer::img(self::get_url_for_image($qa, 'bgimage'), get_string('dropbackground', 'qtype_ddmarker'),
61                 ['class' => 'dropbackground img-fluid w-100']);
63         $output .= html_writer::div('', 'dropzones');
64         $output .= html_writer::div('', 'markertexts');
66         $output .= html_writer::end_div();
67         $output .= html_writer::start_div($draghomesclass);
69         $orderedgroup = $question->get_ordered_choices(1);
70         $hiddenfields = '';
71         foreach ($orderedgroup as $choiceno => $drag) {
72             $classes = ['marker', 'choice' . $choiceno];
73             $attr = [];
74             if ($drag->infinite) {
75                 $classes[] = 'infinite';
76             } else {
77                 $classes[] = 'dragno' . $drag->noofdrags;
78             }
79             if (!$options->readonly) {
80                 $attr['tabindex'] = 0;
81             }
82             $dragoutput = html_writer::start_span(join(' ', $classes), $attr);
83             $targeticonhtml = $this->output->image_icon('crosshairs', '', $componentname, ['class' => 'target']);
84             $markertext = html_writer::span($drag->text, 'markertext');
85             $dragoutput .= $targeticonhtml . $markertext;
86             $dragoutput .= html_writer::end_span();
87             $output .= $dragoutput;
88             $hiddenfields .= $this->hidden_field_choice($qa, $choiceno, $drag->infinite, $drag->noofdrags);
89         }
91         $output .= html_writer::end_div();
92         $output .= html_writer::end_div();
94         if ($question->showmisplaced && $qa->get_state()->is_finished()) {
95             $visibledropzones = $question->get_drop_zones_without_hit($response);
96         } else {
97             $visibledropzones = [];
98         }
100         if ($qa->get_state() == question_state::$invalid) {
101             $output .= html_writer::div($question->get_validation_error($qa->get_last_qt_data()), 'validationerror');
102         }
104         if ($question->showmisplaced && $qa->get_state()->is_finished()) {
105             $wrongparts = $question->get_drop_zones_without_hit($response);
106             if (count($wrongparts) !== 0) {
107                 $wrongpartsstringspans = [];
108                 foreach ($wrongparts as $wrongpart) {
109                     $wrongpartsstringspans[] = html_writer::span($wrongpart->markertext, 'wrongpart');
110                 }
111                 $wrongpartsstring = join(', ', $wrongpartsstringspans);
112                 $output .= html_writer::span(get_string('followingarewrongandhighlighted', 'qtype_ddmarker', $wrongpartsstring),
113                         'wrongparts');
114             }
115         }
117         $output .= html_writer::div($hiddenfields, 'ddform');
119         $this->page->requires->js_call_amd('qtype_ddmarker/question', 'init',
120                 [$qa->get_outer_question_div_unique_id(), $options->readonly, $visibledropzones]);
122         return $output;
123     }
125     protected function hidden_field_choice(question_attempt $qa, $choiceno, $infinite, $noofdrags, $value = null) {
126         $varname = 'c'.$choiceno;
127         $classes = array('choices', 'choice'.$choiceno, 'noofdrags'.$noofdrags);
128         if ($infinite) {
129             $classes[] = 'infinite';
130         }
131         list(, $html) = $this->hidden_field_for_qt_var($qa, $varname, null, $classes);
132         return $html;
133     }
135     protected function hint(question_attempt $qa, question_hint $hint) {
136         $output = '';
137         $question = $qa->get_question();
138         $response = $qa->get_last_qt_data();
139         if ($hint->statewhichincorrect) {
140             $wrongdrags = $question->get_wrong_drags($response);
141             $wrongparts = array();
142             foreach ($wrongdrags as $wrongdrag) {
143                 $wrongparts[] = html_writer::nonempty_tag('span',
144                                                 $wrongdrag, array('class' => 'wrongpart'));
145             }
146             $output .= html_writer::nonempty_tag('div',
147                     get_string('followingarewrong', 'qtype_ddmarker', join(', ', $wrongparts)),
148                     array('class' => 'wrongparts'));
149         }
150         $output .= parent::hint($qa, $hint);
151         return $output;
152     }