Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402]
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/>. 16 17 /** 18 * Contains renderer used for displaying rubric 19 * 20 * @package gradingform_rubric 21 * @copyright 2011 Marina Glancy 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 /** 28 * Grading method plugin renderer 29 * 30 * @package gradingform_rubric 31 * @copyright 2011 Marina Glancy 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 class gradingform_rubric_renderer extends plugin_renderer_base { 35 36 /** 37 * This function returns html code for displaying criterion. Depending on $mode it may be the 38 * code to edit rubric, to preview the rubric, to evaluate somebody or to review the evaluation. 39 * 40 * This function may be called from display_rubric() to display the whole rubric, or it can be 41 * called by itself to return a template used by JavaScript to add new empty criteria to the 42 * rubric being designed. 43 * In this case it will use macros like {NAME}, {LEVELS}, {CRITERION-id}, etc. 44 * 45 * When overriding this function it is very important to remember that all elements of html 46 * form (in edit or evaluate mode) must have the name $elementname. 47 * 48 * Also JavaScript relies on the class names of elements and when developer changes them 49 * script might stop working. 50 * 51 * @param int $mode rubric display mode, see {@link gradingform_rubric_controller} 52 * @param array $options display options for this rubric, defaults are: {@link gradingform_rubric_controller::get_default_options()} 53 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode) 54 * @param array|null $criterion criterion data 55 * @param string $levelsstr evaluated templates for this criterion levels 56 * @param array|null $value (only in view mode) teacher's feedback on this criterion 57 * @return string 58 */ 59 public function criterion_template($mode, $options, $elementname = '{NAME}', $criterion = null, $levelsstr = '{LEVELS}', $value = null) { 60 // TODO MDL-31235 description format, remark format 61 if ($criterion === null || !is_array($criterion) || !array_key_exists('id', $criterion)) { 62 $criterion = array('id' => '{CRITERION-id}', 'description' => '{CRITERION-description}', 'sortorder' => '{CRITERION-sortorder}', 'class' => '{CRITERION-class}'); 63 } else { 64 foreach (array('sortorder', 'description', 'class') as $key) { 65 // set missing array elements to empty strings to avoid warnings 66 if (!array_key_exists($key, $criterion)) { 67 $criterion[$key] = ''; 68 } 69 } 70 } 71 $criteriontemplate = html_writer::start_tag('tr', array('class' => 'criterion'. $criterion['class'], 'id' => '{NAME}-criteria-{CRITERION-id}')); 72 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { 73 $criteriontemplate .= html_writer::start_tag('td', array('class' => 'controls')); 74 foreach (array('moveup', 'delete', 'movedown', 'duplicate') as $key) { 75 $value = get_string('criterion'.$key, 'gradingform_rubric'); 76 $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[criteria][{CRITERION-id}]['.$key.']', 77 'id' => '{NAME}-criteria-{CRITERION-id}-'.$key, 'value' => $value)); 78 $criteriontemplate .= html_writer::tag('div', $button, array('class' => $key)); 79 } 80 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 81 'name' => '{NAME}[criteria][{CRITERION-id}][sortorder]', 82 'value' => $criterion['sortorder'])); 83 $criteriontemplate .= html_writer::end_tag('td'); // .controls 84 85 // Criterion description text area. 86 $descriptiontextareaparams = array( 87 'name' => '{NAME}[criteria][{CRITERION-id}][description]', 88 'id' => '{NAME}-criteria-{CRITERION-id}-description', 89 'aria-label' => get_string('criterion', 'gradingform_rubric', ''), 90 'cols' => '10', 'rows' => '5' 91 ); 92 $description = html_writer::tag('textarea', s($criterion['description']), $descriptiontextareaparams); 93 } else { 94 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) { 95 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder'])); 96 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][description]', 'value' => $criterion['description'])); 97 } 98 $description = s($criterion['description']); 99 } 100 $descriptionclass = 'description'; 101 if (isset($criterion['error_description'])) { 102 $descriptionclass .= ' error'; 103 } 104 105 // Description cell params. 106 $descriptiontdparams = array( 107 'class' => $descriptionclass, 108 'id' => '{NAME}-criteria-{CRITERION-id}-description-cell' 109 ); 110 if ($mode != gradingform_rubric_controller::DISPLAY_EDIT_FULL && 111 $mode != gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) { 112 // Set description's cell as tab-focusable. 113 $descriptiontdparams['tabindex'] = '0'; 114 // Set label for the criterion cell. 115 $descriptiontdparams['aria-label'] = get_string('criterion', 'gradingform_rubric', s($criterion['description'])); 116 } 117 118 // Description cell. 119 $criteriontemplate .= html_writer::tag('td', $description, $descriptiontdparams); 120 121 // Levels table. 122 $levelsrowparams = [ 123 'id' => '{NAME}-criteria-{CRITERION-id}-levels', 124 'aria-label' => get_string('levelsgroup', 'gradingform_rubric'), 125 ]; 126 // Add radiogroup role only when not previewing or editing. 127 $isradiogroup = !in_array($mode, [ 128 gradingform_rubric_controller::DISPLAY_EDIT_FULL, 129 gradingform_rubric_controller::DISPLAY_EDIT_FROZEN, 130 gradingform_rubric_controller::DISPLAY_PREVIEW, 131 gradingform_rubric_controller::DISPLAY_PREVIEW_GRADED, 132 ]); 133 $levelsrowparams['role'] = $isradiogroup ? 'radiogroup' : 'list'; 134 $levelsrow = html_writer::tag('tr', $levelsstr, $levelsrowparams); 135 136 $levelstableparams = [ 137 'id' => '{NAME}-criteria-{CRITERION-id}-levels-table', 138 'role' => 'none', 139 ]; 140 $levelsstrtable = html_writer::tag('table', $levelsrow, $levelstableparams); 141 $levelsclass = 'levels'; 142 if (isset($criterion['error_levels'])) { 143 $levelsclass .= ' error'; 144 } 145 $criteriontemplate .= html_writer::tag('td', $levelsstrtable, array('class' => $levelsclass)); 146 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { 147 $value = get_string('criterionaddlevel', 'gradingform_rubric'); 148 $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][addlevel]', 149 'id' => '{NAME}-criteria-{CRITERION-id}-levels-addlevel', 'value' => $value, 'class' => 'btn btn-secondary')); 150 $criteriontemplate .= html_writer::tag('td', $button, array('class' => 'addlevel')); 151 } 152 $displayremark = ($options['enableremarks'] && ($mode != gradingform_rubric_controller::DISPLAY_VIEW || $options['showremarksstudent'])); 153 if ($displayremark) { 154 $currentremark = ''; 155 if (isset($value['remark'])) { 156 $currentremark = $value['remark']; 157 } 158 159 // Label for criterion remark. 160 $remarkinfo = new stdClass(); 161 $remarkinfo->description = s($criterion['description']); 162 $remarkinfo->remark = $currentremark; 163 $remarklabeltext = get_string('criterionremark', 'gradingform_rubric', $remarkinfo); 164 165 if ($mode == gradingform_rubric_controller::DISPLAY_EVAL) { 166 // HTML parameters for remarks text area. 167 $remarkparams = array( 168 'name' => '{NAME}[criteria][{CRITERION-id}][remark]', 169 'id' => '{NAME}-criteria-{CRITERION-id}-remark', 170 'cols' => '10', 'rows' => '5', 171 'aria-label' => $remarklabeltext 172 ); 173 $input = html_writer::tag('textarea', s($currentremark), $remarkparams); 174 $criteriontemplate .= html_writer::tag('td', $input, array('class' => 'remark')); 175 } else if ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN) { 176 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][remark]', 'value' => $currentremark)); 177 }else if ($mode == gradingform_rubric_controller::DISPLAY_REVIEW || $mode == gradingform_rubric_controller::DISPLAY_VIEW) { 178 // HTML parameters for remarks cell. 179 $remarkparams = array( 180 'class' => 'remark', 181 'tabindex' => '0', 182 'id' => '{NAME}-criteria-{CRITERION-id}-remark', 183 'aria-label' => $remarklabeltext 184 ); 185 $criteriontemplate .= html_writer::tag('td', s($currentremark), $remarkparams); 186 } 187 } 188 $criteriontemplate .= html_writer::end_tag('tr'); // .criterion 189 190 $criteriontemplate = str_replace('{NAME}', $elementname, $criteriontemplate); 191 $criteriontemplate = str_replace('{CRITERION-id}', $criterion['id'], $criteriontemplate); 192 return $criteriontemplate; 193 } 194 195 /** 196 * This function returns html code for displaying one level of one criterion. Depending on $mode 197 * it may be the code to edit rubric, to preview the rubric, to evaluate somebody or to review the evaluation. 198 * 199 * This function may be called from display_rubric() to display the whole rubric, or it can be 200 * called by itself to return a template used by JavaScript to add new empty level to the 201 * criterion during the design of rubric. 202 * In this case it will use macros like {NAME}, {CRITERION-id}, {LEVEL-id}, etc. 203 * 204 * When overriding this function it is very important to remember that all elements of html 205 * form (in edit or evaluate mode) must have the name $elementname. 206 * 207 * Also JavaScript relies on the class names of elements and when developer changes them 208 * script might stop working. 209 * 210 * @param int $mode rubric display mode see {@link gradingform_rubric_controller} 211 * @param array $options display options for this rubric, defaults are: {@link gradingform_rubric_controller::get_default_options()} 212 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode) 213 * @param string|int $criterionid either id of the nesting criterion or a macro for template 214 * @param array|null $level level data, also in view mode it might also have property $level['checked'] whether this level is checked 215 * @return string 216 */ 217 public function level_template($mode, $options, $elementname = '{NAME}', $criterionid = '{CRITERION-id}', $level = null) { 218 // TODO MDL-31235 definition format 219 if (!isset($level['id'])) { 220 $level = array('id' => '{LEVEL-id}', 'definition' => '{LEVEL-definition}', 'score' => '{LEVEL-score}', 'class' => '{LEVEL-class}', 'checked' => false); 221 } else { 222 foreach (array('score', 'definition', 'class', 'checked', 'index') as $key) { 223 // set missing array elements to empty strings to avoid warnings 224 if (!array_key_exists($key, $level)) { 225 $level[$key] = ''; 226 } 227 } 228 } 229 230 // Get level index. 231 $levelindex = isset($level['index']) ? $level['index'] : '{LEVEL-index}'; 232 233 // Template for one level within one criterion 234 $tdattributes = array( 235 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}', 236 'class' => 'text-break level' . $level['class'] 237 ); 238 if (isset($level['tdwidth'])) { 239 $tdattributes['style'] = "width: " . round($level['tdwidth']).'%;'; 240 } 241 242 $leveltemplate = html_writer::start_tag('div', array('class' => 'level-wrapper')); 243 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { 244 $definitionparams = array( 245 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-definition', 246 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][definition]', 247 'aria-label' => get_string('leveldefinition', 'gradingform_rubric', $levelindex), 248 'cols' => '10', 'rows' => '4' 249 ); 250 $definition = html_writer::tag('textarea', s($level['definition']), $definitionparams); 251 252 $scoreparams = array( 253 'type' => 'text', 254 'id' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][score]', 255 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][score]', 256 'aria-label' => get_string('scoreinputforlevel', 'gradingform_rubric', $levelindex), 257 'size' => '3', 258 'value' => $level['score'] 259 ); 260 $score = html_writer::empty_tag('input', $scoreparams); 261 } else { 262 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) { 263 $leveltemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][definition]', 'value' => $level['definition'])); 264 $leveltemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][score]', 'value' => $level['score'])); 265 } 266 $definition = s($level['definition']); 267 $score = $level['score']; 268 } 269 if ($mode == gradingform_rubric_controller::DISPLAY_EVAL) { 270 $levelradioparams = array( 271 'type' => 'radio', 272 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-definition', 273 'name' => '{NAME}[criteria][{CRITERION-id}][levelid]', 274 'value' => $level['id'] 275 ); 276 if ($level['checked']) { 277 $levelradioparams['checked'] = 'checked'; 278 } 279 $input = html_writer::empty_tag('input', $levelradioparams); 280 $leveltemplate .= html_writer::div($input, 'radio'); 281 } 282 if ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN && $level['checked']) { 283 $leveltemplate .= html_writer::empty_tag('input', 284 array( 285 'type' => 'hidden', 286 'name' => '{NAME}[criteria][{CRITERION-id}][levelid]', 287 'value' => $level['id'] 288 ) 289 ); 290 } 291 $score = html_writer::tag('span', $score, array('id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-score', 'class' => 'scorevalue')); 292 $definitionclass = 'definition'; 293 if (isset($level['error_definition'])) { 294 $definitionclass .= ' error'; 295 } 296 297 if ($mode != gradingform_rubric_controller::DISPLAY_EDIT_FULL && 298 $mode != gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) { 299 300 $tdattributes['tabindex'] = '0'; 301 $levelinfo = new stdClass(); 302 $levelinfo->definition = s($level['definition']); 303 $levelinfo->score = $level['score']; 304 $tdattributes['aria-label'] = get_string('level', 'gradingform_rubric', $levelinfo); 305 306 if ($mode != gradingform_rubric_controller::DISPLAY_PREVIEW && 307 $mode != gradingform_rubric_controller::DISPLAY_PREVIEW_GRADED) { 308 // Add role of radio button to level cell if not in edit and preview mode. 309 $tdattributes['role'] = 'radio'; 310 if ($level['checked']) { 311 $tdattributes['aria-checked'] = 'true'; 312 } else { 313 $tdattributes['aria-checked'] = 'false'; 314 } 315 } else { 316 $tdattributes['role'] = 'listitem'; 317 } 318 } else { 319 $tdattributes['role'] = 'listitem'; 320 } 321 322 $leveltemplateparams = array( 323 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-definition-container' 324 ); 325 $leveltemplate .= html_writer::div($definition, $definitionclass, $leveltemplateparams); 326 $displayscore = true; 327 if (!$options['showscoreteacher'] && in_array($mode, array(gradingform_rubric_controller::DISPLAY_EVAL, gradingform_rubric_controller::DISPLAY_EVAL_FROZEN, gradingform_rubric_controller::DISPLAY_REVIEW))) { 328 $displayscore = false; 329 } 330 if (!$options['showscorestudent'] && in_array($mode, array(gradingform_rubric_controller::DISPLAY_VIEW, gradingform_rubric_controller::DISPLAY_PREVIEW_GRADED))) { 331 $displayscore = false; 332 } 333 if ($displayscore) { 334 $scoreclass = 'score d-inline'; 335 if (isset($level['error_score'])) { 336 $scoreclass .= ' error'; 337 } 338 $leveltemplate .= html_writer::tag('div', get_string('scorepostfix', 'gradingform_rubric', $score), array('class' => $scoreclass)); 339 } 340 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { 341 $value = get_string('leveldelete', 'gradingform_rubric', $levelindex); 342 $buttonparams = array( 343 'type' => 'submit', 344 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][delete]', 345 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-delete', 346 'value' => $value 347 ); 348 $button = html_writer::empty_tag('input', $buttonparams); 349 $leveltemplate .= html_writer::tag('div', $button, array('class' => 'delete')); 350 } 351 $leveltemplate .= html_writer::end_tag('div'); // .level-wrapper 352 353 $leveltemplate = html_writer::tag('td', $leveltemplate, $tdattributes); // The .level cell. 354 355 $leveltemplate = str_replace('{NAME}', $elementname, $leveltemplate); 356 $leveltemplate = str_replace('{CRITERION-id}', $criterionid, $leveltemplate); 357 $leveltemplate = str_replace('{LEVEL-id}', $level['id'], $leveltemplate); 358 return $leveltemplate; 359 } 360 361 /** 362 * This function returns html code for displaying rubric template (content before and after 363 * criteria list). Depending on $mode it may be the code to edit rubric, to preview the rubric, 364 * to evaluate somebody or to review the evaluation. 365 * 366 * This function is called from display_rubric() to display the whole rubric. 367 * 368 * When overriding this function it is very important to remember that all elements of html 369 * form (in edit or evaluate mode) must have the name $elementname. 370 * 371 * Also JavaScript relies on the class names of elements and when developer changes them 372 * script might stop working. 373 * 374 * @param int $mode rubric display mode see {@link gradingform_rubric_controller} 375 * @param array $options display options for this rubric, defaults are: {@link gradingform_rubric_controller::get_default_options()} 376 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode) 377 * @param string $criteriastr evaluated templates for this rubric's criteria 378 * @return string 379 */ 380 protected function rubric_template($mode, $options, $elementname, $criteriastr) { 381 $classsuffix = ''; // CSS suffix for class of the main div. Depends on the mode 382 switch ($mode) { 383 case gradingform_rubric_controller::DISPLAY_EDIT_FULL: 384 $classsuffix = ' editor editable'; break; 385 case gradingform_rubric_controller::DISPLAY_EDIT_FROZEN: 386 $classsuffix = ' editor frozen'; break; 387 case gradingform_rubric_controller::DISPLAY_PREVIEW: 388 case gradingform_rubric_controller::DISPLAY_PREVIEW_GRADED: 389 $classsuffix = ' editor preview'; break; 390 case gradingform_rubric_controller::DISPLAY_EVAL: 391 $classsuffix = ' evaluate editable'; break; 392 case gradingform_rubric_controller::DISPLAY_EVAL_FROZEN: 393 $classsuffix = ' evaluate frozen'; break; 394 case gradingform_rubric_controller::DISPLAY_REVIEW: 395 $classsuffix = ' review'; break; 396 case gradingform_rubric_controller::DISPLAY_VIEW: 397 $classsuffix = ' view'; break; 398 } 399 400 $rubrictemplate = html_writer::start_tag('div', array('id' => 'rubric-{NAME}', 'class' => 'clearfix gradingform_rubric'.$classsuffix)); 401 402 // Rubric table. 403 $rubrictableparams = [ 404 'class' => 'criteria', 405 'id' => '{NAME}-criteria', 406 ]; 407 $caption = html_writer::tag('caption', get_string('rubric', 'gradingform_rubric'), ['class' => 'sr-only']); 408 $rubrictable = html_writer::tag('table', $caption . $criteriastr, $rubrictableparams); 409 $rubrictemplate .= $rubrictable; 410 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { 411 $value = get_string('addcriterion', 'gradingform_rubric'); 412 $criteriainputparams = array( 413 'type' => 'submit', 414 'name' => '{NAME}[criteria][addcriterion]', 415 'id' => '{NAME}-criteria-addcriterion', 416 'value' => $value 417 ); 418 $input = html_writer::empty_tag('input', $criteriainputparams); 419 $rubrictemplate .= html_writer::tag('div', $input, array('class' => 'addcriterion btn btn-secondary')); 420 } 421 $rubrictemplate .= $this->rubric_edit_options($mode, $options); 422 $rubrictemplate .= html_writer::end_tag('div'); 423 424 return str_replace('{NAME}', $elementname, $rubrictemplate); 425 } 426 427 /** 428 * Generates html template to view/edit the rubric options. Expression {NAME} is used in 429 * template for the form element name 430 * 431 * @param int $mode rubric display mode see {@link gradingform_rubric_controller} 432 * @param array $options display options for this rubric, defaults are: {@link gradingform_rubric_controller::get_default_options()} 433 * @return string 434 */ 435 protected function rubric_edit_options($mode, $options) { 436 if ($mode != gradingform_rubric_controller::DISPLAY_EDIT_FULL 437 && $mode != gradingform_rubric_controller::DISPLAY_EDIT_FROZEN 438 && $mode != gradingform_rubric_controller::DISPLAY_PREVIEW) { 439 // Options are displayed only for people who can manage 440 return; 441 } 442 $html = html_writer::start_tag('div', array('class' => 'options')); 443 $html .= html_writer::tag('div', get_string('rubricoptions', 'gradingform_rubric'), array('class' => 'optionsheading')); 444 $attrs = array('type' => 'hidden', 'name' => '{NAME}[options][optionsset]', 'value' => 1); 445 foreach ($options as $option => $value) { 446 $html .= html_writer::start_tag('div', array('class' => 'option '.$option)); 447 $attrs = array('name' => '{NAME}[options]['.$option.']', 'id' => '{NAME}-options-'.$option); 448 switch ($option) { 449 case 'sortlevelsasc': 450 // Display option as dropdown 451 $html .= html_writer::label(get_string($option, 'gradingform_rubric'), $attrs['id'], false); 452 $value = (int)(!!$value); // make sure $value is either 0 or 1 453 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { 454 $selectoptions = array(0 => get_string($option.'0', 'gradingform_rubric'), 1 => get_string($option.'1', 'gradingform_rubric')); 455 $valuestr = html_writer::select($selectoptions, $attrs['name'], $value, false, array('id' => $attrs['id'])); 456 $html .= html_writer::tag('span', $valuestr, array('class' => 'value')); 457 } else { 458 $html .= html_writer::tag('span', get_string($option.$value, 'gradingform_rubric'), array('class' => 'value')); 459 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) { 460 $html .= html_writer::empty_tag('input', $attrs + array('type' => 'hidden', 'value' => $value)); 461 } 462 } 463 break; 464 default: 465 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN && $value) { 466 // Id should be different then the actual input added later. 467 $attrs['id'] .= '_hidden'; 468 $html .= html_writer::empty_tag('input', $attrs + array('type' => 'hidden', 'value' => $value)); 469 } 470 // Display option as checkbox 471 $attrs['type'] = 'checkbox'; 472 $attrs['value'] = 1; 473 if ($value) { 474 $attrs['checked'] = 'checked'; 475 } 476 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN || $mode == gradingform_rubric_controller::DISPLAY_PREVIEW) { 477 $attrs['disabled'] = 'disabled'; 478 unset($attrs['name']); 479 // Id should be different then the actual input added later. 480 $attrs['id'] .= '_disabled'; 481 } 482 $html .= html_writer::empty_tag('input', $attrs); 483 $html .= html_writer::tag('label', get_string($option, 'gradingform_rubric'), array('for' => $attrs['id'])); 484 break; 485 } 486 if (get_string_manager()->string_exists($option.'_help', 'gradingform_rubric')) { 487 $html .= $this->help_icon($option, 'gradingform_rubric'); 488 } 489 $html .= html_writer::end_tag('div'); // .option 490 } 491 $html .= html_writer::end_tag('div'); // .options 492 return $html; 493 } 494 495 /** 496 * This function returns html code for displaying rubric. Depending on $mode it may be the code 497 * to edit rubric, to preview the rubric, to evaluate somebody or to review the evaluation. 498 * 499 * It is very unlikely that this function needs to be overriden by theme. It does not produce 500 * any html code, it just prepares data about rubric design and evaluation, adds the CSS 501 * class to elements and calls the functions level_template, criterion_template and 502 * rubric_template 503 * 504 * @param array $criteria data about the rubric design 505 * @param array $options display options for this rubric, defaults are: {@link gradingform_rubric_controller::get_default_options()} 506 * @param int $mode rubric display mode, see {@link gradingform_rubric_controller} 507 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode) 508 * @param array $values evaluation result 509 * @return string 510 */ 511 public function display_rubric($criteria, $options, $mode, $elementname = null, $values = null) { 512 $criteriastr = ''; 513 $cnt = 0; 514 foreach ($criteria as $id => $criterion) { 515 $criterion['class'] = $this->get_css_class_suffix($cnt++, sizeof($criteria) -1); 516 $criterion['id'] = $id; 517 $levelsstr = ''; 518 $levelcnt = 0; 519 if (isset($values['criteria'][$id])) { 520 $criterionvalue = $values['criteria'][$id]; 521 } else { 522 $criterionvalue = null; 523 } 524 $index = 1; 525 foreach ($criterion['levels'] as $levelid => $level) { 526 $level['id'] = $levelid; 527 $level['class'] = $this->get_css_class_suffix($levelcnt++, sizeof($criterion['levels']) -1); 528 $level['checked'] = (isset($criterionvalue['levelid']) && ((int)$criterionvalue['levelid'] === $levelid)); 529 if ($level['checked'] && ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN || $mode == gradingform_rubric_controller::DISPLAY_REVIEW || $mode == gradingform_rubric_controller::DISPLAY_VIEW)) { 530 $level['class'] .= ' checked'; 531 //in mode DISPLAY_EVAL the class 'checked' will be added by JS if it is enabled. If JS is not enabled, the 'checked' class will only confuse 532 } 533 if (isset($criterionvalue['savedlevelid']) && ((int)$criterionvalue['savedlevelid'] === $levelid)) { 534 $level['class'] .= ' currentchecked'; 535 } 536 $level['tdwidth'] = 100/count($criterion['levels']); 537 $level['index'] = $index; 538 $levelsstr .= $this->level_template($mode, $options, $elementname, $id, $level); 539 $index++; 540 } 541 $criteriastr .= $this->criterion_template($mode, $options, $elementname, $criterion, $levelsstr, $criterionvalue); 542 } 543 return $this->rubric_template($mode, $options, $elementname, $criteriastr); 544 } 545 546 /** 547 * Help function to return CSS class names for element (first/last/even/odd) with leading space 548 * 549 * @param int $idx index of this element in the row/column 550 * @param int $maxidx maximum index of the element in the row/column 551 * @return string 552 */ 553 protected function get_css_class_suffix($idx, $maxidx) { 554 $class = ''; 555 if ($idx == 0) { 556 $class .= ' first'; 557 } 558 if ($idx == $maxidx) { 559 $class .= ' last'; 560 } 561 if ($idx%2) { 562 $class .= ' odd'; 563 } else { 564 $class .= ' even'; 565 } 566 return $class; 567 } 568 569 /** 570 * Displays for the student the list of instances or default content if no instances found 571 * 572 * @param array $instances array of objects of type gradingform_rubric_instance 573 * @param string $defaultcontent default string that would be displayed without advanced grading 574 * @param boolean $cangrade whether current user has capability to grade in this context 575 * @return string 576 */ 577 public function display_instances($instances, $defaultcontent, $cangrade) { 578 $return = ''; 579 if (sizeof($instances)) { 580 $return .= html_writer::start_tag('div', array('class' => 'advancedgrade')); 581 $idx = 0; 582 foreach ($instances as $instance) { 583 $return .= $this->display_instance($instance, $idx++, $cangrade); 584 } 585 $return .= html_writer::end_tag('div'); 586 } 587 return $return. $defaultcontent; 588 } 589 590 /** 591 * Displays one grading instance 592 * 593 * @param gradingform_rubric_instance $instance 594 * @param int $idx unique number of instance on page 595 * @param bool $cangrade whether current user has capability to grade in this context 596 */ 597 public function display_instance(gradingform_rubric_instance $instance, $idx, $cangrade) { 598 $criteria = $instance->get_controller()->get_definition()->rubric_criteria; 599 $options = $instance->get_controller()->get_options(); 600 $values = $instance->get_rubric_filling(); 601 if ($cangrade) { 602 $mode = gradingform_rubric_controller::DISPLAY_REVIEW; 603 $showdescription = $options['showdescriptionteacher']; 604 } else { 605 $mode = gradingform_rubric_controller::DISPLAY_VIEW; 606 $showdescription = $options['showdescriptionstudent']; 607 } 608 $output = ''; 609 if ($showdescription) { 610 $output .= $this->box($instance->get_controller()->get_formatted_description(), 'gradingform_rubric-description'); 611 } 612 $output .= $this->display_rubric($criteria, $options, $mode, 'rubric'.$idx, $values); 613 return $output; 614 } 615 616 /** 617 * Displays confirmation that students require re-grading 618 * 619 * @param string $elementname 620 * @param int $changelevel 621 * @param string $value 622 * @return string 623 */ 624 public function display_regrade_confirmation($elementname, $changelevel, $value) { 625 $html = html_writer::start_tag('div', array('class' => 'gradingform_rubric-regrade', 'role' => 'alert')); 626 if ($changelevel<=2) { 627 $html .= html_writer::label(get_string('regrademessage1', 'gradingform_rubric'), 'menu' . $elementname . 'regrade'); 628 $selectoptions = array( 629 0 => get_string('regradeoption0', 'gradingform_rubric'), 630 1 => get_string('regradeoption1', 'gradingform_rubric') 631 ); 632 $html .= html_writer::select($selectoptions, $elementname.'[regrade]', $value, false); 633 } else { 634 $html .= get_string('regrademessage5', 'gradingform_rubric'); 635 $html .= html_writer::empty_tag('input', array('name' => $elementname.'[regrade]', 'value' => 1, 'type' => 'hidden')); 636 } 637 $html .= html_writer::end_tag('div'); 638 return $html; 639 } 640 641 /** 642 * Generates and returns HTML code to display information box about how rubric score is converted to the grade 643 * 644 * @param array $scores 645 * @return string 646 */ 647 public function display_rubric_mapping_explained($scores) { 648 $html = ''; 649 if (!$scores) { 650 return $html; 651 } 652 if ($scores['minscore'] <> 0) { 653 $html .= $this->output->notification(get_string('zerolevelsabsent', 'gradingform_rubric'), 'error'); 654 } 655 $html .= $this->output->notification(get_string('rubricmappingexplained', 'gradingform_rubric', (object)$scores), 'info'); 656 return $html; 657 } 658 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body