diff --git a/grade/grading/form/rubric/edit_form.php b/grade/grading/form/rubric/edit_form.php index ba234a199d3..1341dc48c89 100644 --- a/grade/grading/form/rubric/edit_form.php +++ b/grade/grading/form/rubric/edit_form.php @@ -57,9 +57,9 @@ class gradingform_rubric_editrubric extends moodleform { $form->setType('description_editor', PARAM_RAW); // rubric editor - $element = $form->addElement('rubriceditor', 'rubric_criteria', 'Rubric 1'); // todo label - $form->setType('rubric_criteria', PARAM_RAW); - $form->addRule('rubric_criteria', '', 'rubriceditorcompleted'); //TODO how to add this rule automatically????? + $element = $form->addElement('rubriceditor', 'rubric', get_string('rubric', 'gradingform_rubric')); + $form->setType('rubric', PARAM_RAW); + $form->addRule('rubric', '', 'rubriceditorcompleted'); //TODO how to add this rule automatically????? if (array_key_exists('freezerubric', $this->_customdata) && $this->_customdata['freezerubric']) { $element->freeze(); } diff --git a/grade/grading/form/rubric/js/rubriceditor.js b/grade/grading/form/rubric/js/rubriceditor.js index 64da044c5f5..4d1fc763787 100644 --- a/grade/grading/form/rubric/js/rubriceditor.js +++ b/grade/grading/form/rubric/js/rubriceditor.js @@ -92,10 +92,10 @@ M.gradingform_rubriceditor.buttonclick = function(e, Y, name, confirmed) { if (e.target.get('type') != 'submit') return; var chunks = e.target.get('id').split('-'), action = chunks[chunks.length-1] - if (chunks[0] != name) return; + if (chunks[0] != name || chunks[1] != 'criteria') return; var elements_str - if (chunks.length>3 || action == 'addlevel') { - elements_str = '#rubric-'+name+' #'+name+'-'+chunks[1]+'-levels .level' + if (chunks.length>4 || action == 'addlevel') { + elements_str = '#rubric-'+name+' #'+name+'-criteria-'+chunks[2]+'-levels .level' } else { elements_str = '#rubric-'+name+' .criterion' } @@ -112,38 +112,44 @@ M.gradingform_rubriceditor.buttonclick = function(e, Y, name, confirmed) { 'callbackargs' : [e, Y, name, true], 'callback' : M.gradingform_rubriceditor.buttonclick }; - if (chunks.length == 2 && action == 'addcriterion') { + if (chunks.length == 3 && action == 'addcriterion') { // ADD NEW CRITERION var newcriterion = M.gradingform_rubriceditor.templates[name]['criterion']. replace(/\{CRITERION-id\}/g, 'NEWID'+newid).replace(/\{.+?\}/g, '') - Y.one('#'+name+'-criteria').append(newcriterion) + var parentel = Y.one('#'+name+'-criteria') + if (parentel.one('>tbody')) parentel = parentel.one('>tbody') + parentel.append(newcriterion) M.gradingform_rubriceditor.addhandlers(Y, name); - } else if (chunks.length == 4 && action == 'addlevel') { + } else if (chunks.length == 5 && action == 'addlevel') { // ADD NEW LEVEL var newlevel = M.gradingform_rubriceditor.templates[name]['level']. - replace(/\{CRITERION-id\}/g, chunks[1]).replace(/\{LEVEL-id\}/g, 'NEWID'+newid).replace(/\{.+?\}/g, '') - Y.one('#'+name+'-'+chunks[1]+'-levels').append(newlevel) + replace(/\{CRITERION-id\}/g, chunks[2]).replace(/\{LEVEL-id\}/g, 'NEWID'+newid).replace(/\{.+?\}/g, '') + Y.one('#'+name+'-criteria-'+chunks[2]+'-levels').append(newlevel) + var levels = Y.all('#'+name+'-criteria-'+chunks[2]+'-levels .level') + if (levels.size()) levels.set('width', Math.round(100/levels.size())+'%') M.gradingform_rubriceditor.addhandlers(Y, name); - } else if (chunks.length == 3 && action == 'moveup') { + } else if (chunks.length == 4 && action == 'moveup') { // MOVE CRITERION UP - el = Y.one('#'+name+'-'+chunks[1]) + el = Y.one('#'+name+'-criteria-'+chunks[2]) if (el.previous()) el.get('parentNode').insertBefore(el, el.previous()) - } else if (chunks.length == 3 && action == 'movedown') { + } else if (chunks.length == 4 && action == 'movedown') { // MOVE CRITERION DOWN - el = Y.one('#'+name+'-'+chunks[1]) + el = Y.one('#'+name+'-criteria-'+chunks[2]) if (el.next()) el.get('parentNode').insertBefore(el.next(), el) - } else if (chunks.length == 3 && action == 'delete') { + } else if (chunks.length == 4 && action == 'delete') { // DELETE CRITERION if (confirmed) { - Y.one('#'+name+'-'+chunks[1]).remove() + Y.one('#'+name+'-criteria-'+chunks[2]).remove() } else { dialog_options['message'] = M.str.gradingform_rubric.confirmdeletecriterion M.util.show_confirm_dialog(e, dialog_options); } - } else if (chunks.length == 5 && action == 'delete') { + } else if (chunks.length == 6 && action == 'delete') { // DELETE LEVEL if (confirmed) { - Y.one('#'+name+'-'+chunks[1]+'-'+chunks[2]+'-'+chunks[3]).remove() + Y.one('#'+name+'-criteria-'+chunks[2]+'-'+chunks[3]+'-'+chunks[4]).remove() + levels = Y.all('#'+name+'-criteria-'+chunks[2]+'-levels .level') + if (levels.size()) levels.set('width', Math.round(100/levels.size())+'%') } else { dialog_options['message'] = M.str.gradingform_rubric.confirmdeletelevel M.util.show_confirm_dialog(e, dialog_options); diff --git a/grade/grading/form/rubric/lang/en/gradingform_rubric.php b/grade/grading/form/rubric/lang/en/gradingform_rubric.php index a634486d330..21b2bbbd43b 100644 --- a/grade/grading/form/rubric/lang/en/gradingform_rubric.php +++ b/grade/grading/form/rubric/lang/en/gradingform_rubric.php @@ -37,8 +37,21 @@ $string['criterionmoveup'] = 'Move up'; $string['criteriondelete'] = 'Delete criterion'; $string['criterionmovedown'] = 'Move down'; $string['criterionaddlevel'] = 'Add level'; -$string['scorepostfix'] = ' pts'; +$string['scorepostfix'] = ' points'; $string['leveldelete'] = 'Delete level'; $string['criterionempty'] = 'Click to edit criterion'; $string['levelempty'] = 'Click to edit level'; + +$string['rubric'] = 'Rubric'; +$string['rubricoptions'] = 'Rubric options'; + +$string['sortlevelsasc'] = 'Sort order for levels:'; +$string['sortlevelsasc1'] = 'Ascending by number of points'; +$string['sortlevelsasc0'] = 'Descending by number of points'; +$string['showdescriptionteacher'] = 'Display rubric description during evaluation'; +$string['showdescriptionstudent'] = 'Display rubric description to those being graded'; +$string['showscoreteacher'] = 'Display points for each level during evaluation'; +$string['showscorestudent'] = 'Display points for each level to those being graded'; +$string['enableremarks'] = 'Allow grader to add text remarks for each criteria'; +$string['showremarksstudent'] = 'Show remarks to those being graded'; diff --git a/grade/grading/form/rubric/lib.php b/grade/grading/form/rubric/lib.php index 0be5fa62b14..63e08acf084 100644 --- a/grade/grading/form/rubric/lib.php +++ b/grade/grading/form/rubric/lib.php @@ -38,7 +38,8 @@ class gradingform_rubric_controller extends gradingform_controller { const DISPLAY_PREVIEW = 3; // Preview the rubric design const DISPLAY_EVAL = 4; // For evaluation, enabled (teacher grades a student) const DISPLAY_EVAL_FROZEN = 5; // For evaluation, with hidden fields - const DISPLAY_REVIEW = 6; // Dispaly filled rubric (i.e. students see their grades) + const DISPLAY_REVIEW = 6; // Teacher reviews filled rubric + const DISPLAY_VIEW = 7; // Dispaly filled rubric (i.e. students see their grades) /** * Extends the module settings navigation with the rubric grading settings @@ -73,8 +74,12 @@ class gradingform_rubric_controller extends gradingform_controller { parent::update_definition((object)array('descriptionformat' => FORMAT_MOODLE), $usermodified); parent::load_definition(); } - $options = self::description_form_field_options($this->get_context()); - $newdefinition = file_postupdate_standard_editor($newdefinition, 'description', $options, $this->get_context(), + if (!isset($newdefinition->rubric['options'])) { + $newdefinition->rubric['options'] = self::get_default_options(); + } + $newdefinition->options = json_encode($newdefinition->rubric['options']); + $editoroptions = self::description_form_field_options($this->get_context()); + $newdefinition = file_postupdate_standard_editor($newdefinition, 'description', $editoroptions, $this->get_context(), 'gradingform_rubric', 'definition_description', $this->definition->id); parent::update_definition($newdefinition, $usermodified); @@ -83,10 +88,10 @@ class gradingform_rubric_controller extends gradingform_controller { // update rubric data $haschanges = false; - if (empty($newdefinition->rubric_criteria)) { + if (empty($newdefinition->rubric['criteria'])) { $newcriteria = array(); } else { - $newcriteria = $newdefinition->rubric_criteria; // new ones to be saved + $newcriteria = $newdefinition->rubric['criteria']; // new ones to be saved } $currentcriteria = $currentdefinition->rubric_criteria; $criteriafields = array('sortorder', 'description', 'descriptionformat'); @@ -175,7 +180,6 @@ class gradingform_rubric_controller extends gradingform_controller { */ protected function load_definition() { global $DB; - $sql = "SELECT gd.*, rc.id AS rcid, rc.sortorder AS rcsortorder, rc.description AS rcdescription, rc.descriptionformat AS rcdescriptionformat, rl.id AS rlid, rl.score AS rlscore, rl.definition AS rldefinition, rl.definitionformat AS rldefinitionformat @@ -213,6 +217,37 @@ class gradingform_rubric_controller extends gradingform_controller { } } $rs->close(); + $options = $this->get_options(); + if (!$options['sortlevelsasc']) { + foreach (array_keys($this->definition->rubric_criteria) as $rcid) { + $this->definition->rubric_criteria[$rcid]['levels'] = array_reverse($this->definition->rubric_criteria[$rcid]['levels'], true); + } + } + } + + public static function get_default_options() { + $options = array( + 'sortlevelsasc' => 1, + //'showdescriptionteacher' => 1, + //'showdescriptionstudent' => 1, + 'showscoreteacher' => 1, + 'showscorestudent' => 1, + 'enableremarks' => 1, + 'showremarksstudent' => 1 + ); + // TODO description options + return $options; + } + + public function get_options() { + $options = self::get_default_options(); + if (!empty($this->definition->options)) { + $thisoptions = json_decode($this->definition->options); + foreach ($thisoptions as $option => $value) { + $options[$option] = $value; + } + } + return $options; } /** @@ -226,17 +261,16 @@ class gradingform_rubric_controller extends gradingform_controller { $properties = new stdClass(); $properties->areaid = $this->areaid; if ($definition) { - foreach (array('id', 'name', 'description', 'descriptionformat', 'options', 'status') as $key) { + foreach (array('id', 'name', 'description', 'descriptionformat', 'status') as $key) { $properties->$key = $definition->$key; } $options = self::description_form_field_options($this->get_context()); $properties = file_prepare_standard_editor($properties, 'description', $options, $this->get_context(), 'gradingform_rubric', 'definition_description', $definition->id); } + $properties->rubric = array('criteria' => array(), 'options' => $this->get_options()); if (!empty($definition->rubric_criteria)) { - $properties->rubric_criteria = $definition->rubric_criteria; - } else { - $properties->rubric_criteria = array(); + $properties->rubric['criteria'] = $definition->rubric_criteria; } return $properties; @@ -252,11 +286,12 @@ class gradingform_rubric_controller extends gradingform_controller { public function get_definition_copy(gradingform_controller $target) { $new = parent::get_definition_copy($target); - $old = $this->get_definition(); - $new->rubric_criteria = array(); + $old = $this->get_definition_for_editing(); + $new->description_editor = $old->description_editor; + $new->rubric = array('criteria' => array(), 'options' => $old->rubric['options']); $newcritid = 1; $newlevid = 1; - foreach ($old->rubric_criteria as $oldcritid => $oldcrit) { + foreach ($old->rubric['criteria'] as $oldcritid => $oldcrit) { unset($oldcrit['id']); if (isset($oldcrit['levels'])) { foreach ($oldcrit['levels'] as $oldlevid => $oldlev) { @@ -268,7 +303,7 @@ class gradingform_rubric_controller extends gradingform_controller { } else { $oldcrit['levels'] = array(); } - $new->rubric_criteria['NEWID'.$newcritid] = $oldcrit; + $new->rubric['criteria']['NEWID'.$newcritid] = $oldcrit; $newcritid++; } @@ -337,7 +372,8 @@ class gradingform_rubric_controller extends gradingform_controller { // append the rubric itself, using own renderer $output = $this->get_renderer($page); $criteria = $this->definition->rubric_criteria; - $rubric = $output->display_rubric($criteria, self::DISPLAY_PREVIEW, 'rubric'); + $options = $this->get_options(); + $rubric = $output->display_rubric($criteria, $options, self::DISPLAY_PREVIEW, 'rubric'); return $header . $rubric; } @@ -556,10 +592,11 @@ class gradingform_rubric_instance extends gradingform_instance { } } $criteria = $this->get_controller()->get_definition()->rubric_criteria; + $options = $this->get_controller()->get_options(); $value = $gradingformelement->getValue(); if ($value === null) { $value = $this->get_rubric_filling(); } - return $this->get_controller()->get_renderer($page)->display_rubric($criteria, $mode, $gradingformelement->getName(), $value); + return $this->get_controller()->get_renderer($page)->display_rubric($criteria, $options, $mode, $gradingformelement->getName(), $value); } } \ No newline at end of file diff --git a/grade/grading/form/rubric/renderer.php b/grade/grading/form/rubric/renderer.php index 6b326ef1646..489977890e0 100644 --- a/grade/grading/form/rubric/renderer.php +++ b/grade/grading/form/rubric/renderer.php @@ -22,7 +22,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - defined('MOODLE_INTERNAL') || die(); /** @@ -31,11 +30,28 @@ defined('MOODLE_INTERNAL') || die(); class gradingform_rubric_renderer { /** + * This function returns html code for displaying criterion. Depending on $mode it may be the + * code to edit rubric, to preview the rubric, to evaluate somebody or to review the evaluation. * - * @param int $mode @see gradingform_rubric_controller + * This function may be called from display_rubric() to display the whole rubric, or it can be + * called by itself to return a template used by JavaScript to add new empty criteria to the + * rubric being designed. + * In this case it will use macros like {NAME}, {LEVELS}, {CRITERION-id}, etc. + * + * When overriding this function it is very important to remember that all elements of html + * form (in edit or evaluate mode) must have the name $elementname. + * + * Also JavaScript relies on the class names of elements and when developer changes them + * script might stop working. + * + * @param int $mode rubric display mode @see gradingform_rubric_controller + * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode) + * @param array|null $criterion criterion data + * @param string $levels_str evaluated templates for this criterion levels + * @param array|null $value (only in view mode) teacher's feedback on this criterion * @return string */ - public function criterion_template($mode, $elementname = '{NAME}', $criterion = null, $levels_str = '{LEVELS}', $value = null) { + public function criterion_template($mode, $options, $elementname = '{NAME}', $criterion = null, $levels_str = '{LEVELS}', $value = null) { // TODO description format, remark format if ($criterion === null || !is_array($criterion) || !array_key_exists('id', $criterion)) { $criterion = array('id' => '{CRITERION-id}', 'description' => '{CRITERION-description}', 'sortorder' => '{CRITERION-sortorder}', 'class' => '{CRITERION-class}'); @@ -47,56 +63,78 @@ class gradingform_rubric_renderer { } } } - $criterion_template = html_writer::start_tag('div', array('class' => 'clearfix criterion'. $criterion['class'], 'id' => '{NAME}-{CRITERION-id}')); + $criterion_template = html_writer::start_tag('tr', array('class' => 'criterion'. $criterion['class'], 'id' => '{NAME}-criteria-{CRITERION-id}')); if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { - $criterion_template .= html_writer::start_tag('div', array('class' => 'controls')); + $criterion_template .= html_writer::start_tag('td', array('class' => 'controls')); foreach (array('moveup', 'delete', 'movedown') as $key) { $value = get_string('criterion'.$key, 'gradingform_rubric'); - $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[{CRITERION-id}]['.$key.']', - 'id' => '{NAME}-{CRITERION-id}-'.$key, 'value' => $value, 'title' => $value)); + $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[criteria][{CRITERION-id}]['.$key.']', + 'id' => '{NAME}-criteria-{CRITERION-id}-'.$key, 'value' => $value, 'title' => $value)); $criterion_template .= html_writer::tag('div', $button, array('class' => $key)); } - $criterion_template .= html_writer::end_tag('div'); // .controls - $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder'])); - $description = html_writer::tag('textarea', htmlspecialchars($criterion['description']), array('name' => '{NAME}[{CRITERION-id}][description]', 'cols' => '10', 'rows' => '5')); + $criterion_template .= html_writer::end_tag('td'); // .controls + $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder'])); + $description = html_writer::tag('textarea', htmlspecialchars($criterion['description']), array('name' => '{NAME}[criteria][{CRITERION-id}][description]', 'cols' => '10', 'rows' => '5')); } else { if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) { - $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder'])); - $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][description]', 'value' => $criterion['description'])); + $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder'])); + $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][description]', 'value' => $criterion['description'])); } $description = $criterion['description']; } - $criterion_template .= html_writer::tag('div', $description, array('class' => 'description', 'id' => '{NAME}-{CRITERION-id}-description')); - $criterion_template .= html_writer::tag('div', $levels_str, array('class' => 'clearfix levels', 'id' => '{NAME}-{CRITERION-id}-levels')); + $criterion_template .= html_writer::tag('td', $description, array('class' => 'description', 'id' => '{NAME}-criteria-{CRITERION-id}-description')); + $levels_str_table = html_writer::tag('table', html_writer::tag('tr', $levels_str, array('id' => '{NAME}-criteria-{CRITERION-id}-levels'))); + $criterion_template .= html_writer::tag('td', $levels_str_table, array('class' => 'levels')); if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { $value = get_string('criterionaddlevel', 'gradingform_rubric'); - $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[{CRITERION-id}][levels][addlevel]', - 'id' => '{NAME}-{CRITERION-id}-levels-addlevel', 'value' => $value, 'title' => $value)); //TODO '{NAME}-{CRITERION-id}-levels-addlevel - $criterion_template .= html_writer::tag('div', $button, array('class' => 'addlevel')); + $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][addlevel]', + 'id' => '{NAME}-criteria-{CRITERION-id}-levels-addlevel', 'value' => $value, 'title' => $value)); + $criterion_template .= html_writer::tag('td', $button, array('class' => 'addlevel')); } - if (isset($value['remark'])) { - $currentremark = $value['remark']; - } else { + $displayremark = ($options['enableremarks'] && ($mode != gradingform_rubric_controller::DISPLAY_VIEW || $options['showremarksstudent'])); + if ($displayremark) { $currentremark = ''; + if (isset($value['remark'])) { + $currentremark = $value['remark']; + } + if ($mode == gradingform_rubric_controller::DISPLAY_EVAL) { + $input = html_writer::tag('textarea', htmlspecialchars($currentremark), array('name' => '{NAME}[criteria][{CRITERION-id}][remark]', 'cols' => '10', 'rows' => '5')); + $criterion_template .= html_writer::tag('td', $input, array('class' => 'remark')); + } else if ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN) { + $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][remark]', 'value' => $currentremark)); + }else if ($mode == gradingform_rubric_controller::DISPLAY_REVIEW || $mode == gradingform_rubric_controller::DISPLAY_VIEW) { + $criterion_template .= html_writer::tag('td', $currentremark, array('class' => 'remark')); // TODO maybe some prefix here like 'Teacher remark:' + } } - if ($mode == gradingform_rubric_controller::DISPLAY_EVAL) { - $input = html_writer::tag('textarea', htmlspecialchars($currentremark), array('name' => '{NAME}[criteria][{CRITERION-id}][remark]', 'cols' => '10', 'rows' => '5')); - $criterion_template .= html_writer::tag('div', $input, array('class' => 'remark')); - } - if ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN) { - $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][remark]', 'value' => $currentremark)); - } - if ($mode == gradingform_rubric_controller::DISPLAY_REVIEW) { - $criterion_template .= html_writer::tag('div', $currentremark, array('class' => 'remark')); // TODO maybe some prefix here like 'Teacher remark:' - } - $criterion_template .= html_writer::end_tag('div'); // .criterion + $criterion_template .= html_writer::end_tag('tr'); // .criterion $criterion_template = str_replace('{NAME}', $elementname, $criterion_template); $criterion_template = str_replace('{CRITERION-id}', $criterion['id'], $criterion_template); return $criterion_template; } - public function level_template($mode, $elementname = '{NAME}', $criterionid = '{CRITERION-id}', $level = null) { + /** + * This function returns html code for displaying one level of one criterion. Depending on $mode + * it may be the code to edit rubric, to preview the rubric, to evaluate somebody or to review the evaluation. + * + * This function may be called from display_rubric() to display the whole rubric, or it can be + * called by itself to return a template used by JavaScript to add new empty level to the + * criterion during the design of rubric. + * In this case it will use macros like {NAME}, {CRITERION-id}, {LEVEL-id}, etc. + * + * When overriding this function it is very important to remember that all elements of html + * form (in edit or evaluate mode) must have the name $elementname. + * + * Also JavaScript relies on the class names of elements and when developer changes them + * script might stop working. + * + * @param int $mode rubric display mode @see gradingform_rubric_controller + * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode) + * @param string|int $criterionid either id of the nesting criterion or a macro for template + * @param array|null $level level data, also in view mode it might also have property $level['checked'] whether this level is checked + * @return string + */ + public function level_template($mode, $options, $elementname = '{NAME}', $criterionid = '{CRITERION-id}', $level = null) { // TODO definition format if (!isset($level['id'])) { $level = array('id' => '{LEVEL-id}', 'definition' => '{LEVEL-definition}', 'score' => '{LEVEL-score}', 'class' => '{LEVEL-class}', 'checked' => false); @@ -110,14 +148,19 @@ class gradingform_rubric_renderer { } // Template for one level within one criterion - $level_template = html_writer::start_tag('div', array('id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}', 'class' => 'clearfix level'. $level['class'])); + $tdattributes = array('id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}', 'class' => 'level'. $level['class']); + if (isset($level['tdwidth'])) { + $tdattributes['width'] = round($level['tdwidth']).'%'; + } + $level_template = html_writer::start_tag('td', $tdattributes); + $level_template .= html_writer::start_tag('div', array('class' => 'level-wrapper')); if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { - $definition = html_writer::tag('textarea', htmlspecialchars($level['definition']), array('name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][definition]', 'cols' => '10', 'rows' => '4')); - $score = html_writer::empty_tag('input', array('type' => 'text', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][score]', 'size' => '4', 'value' => $level['score'])); + $definition = html_writer::tag('textarea', htmlspecialchars($level['definition']), array('name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][definition]', 'cols' => '10', 'rows' => '4')); + $score = html_writer::empty_tag('input', array('type' => 'text', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][score]', 'size' => '4', 'value' => $level['score'])); } else { if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) { - $level_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][definition]', 'value' => $level['definition'])); - $level_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][score]', 'value' => $level['score'])); + $level_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][definition]', 'value' => $level['definition'])); + $level_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][score]', 'value' => $level['score'])); } $definition = $level['definition']; $score = $level['score']; @@ -130,15 +173,25 @@ class gradingform_rubric_renderer { if ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN && $level['checked']) { $level_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][levelid]', 'value' => $level['id'])); } - $score = html_writer::tag('span', $score, array('id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}-score')); - $level_template .= html_writer::tag('div', $definition, array('class' => 'definition', 'id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}-definition')); - $level_template .= html_writer::tag('div', $score. get_string('scorepostfix', 'gradingform_rubric'), array('class' => 'score')); + $score = html_writer::tag('span', $score, array('id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-score')); + $level_template .= html_writer::tag('div', $definition, array('class' => 'definition', 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-definition')); + $displayscore = true; + if (!$options['showscoreteacher'] && in_array($mode, array(gradingform_rubric_controller::DISPLAY_EVAL, gradingform_rubric_controller::DISPLAY_EVAL_FROZEN, gradingform_rubric_controller::DISPLAY_REVIEW))) { + $displayscore = false; + } + if (!$options['showscorestudent'] && $mode == gradingform_rubric_controller::DISPLAY_VIEW) { + $displayscore = false; + } + if ($displayscore) { + $level_template .= html_writer::tag('div', $score. get_string('scorepostfix', 'gradingform_rubric'), array('class' => 'score')); + } if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { $value = get_string('leveldelete', 'gradingform_rubric'); - $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][delete]', 'id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}-delete', 'value' => $value, 'title' => $value)); + $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][delete]', 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-delete', 'value' => $value, 'title' => $value)); $level_template .= html_writer::tag('div', $button, array('class' => 'delete')); } - $level_template .= html_writer::end_tag('div'); // .level + $level_template .= html_writer::end_tag('div'); // .level-wrapper + $level_template .= html_writer::end_tag('td'); // .level $level_template = str_replace('{NAME}', $elementname, $level_template); $level_template = str_replace('{CRITERION-id}', $criterionid, $level_template); @@ -146,7 +199,25 @@ class gradingform_rubric_renderer { return $level_template; } - protected function rubric_template($mode, $elementname = '{NAME}', $criteria_str = '{CRITERIA}') { + /** + * This function returns html code for displaying rubric template (content before and after + * criteria list). Depending on $mode it may be the code to edit rubric, to preview the rubric, + * to evaluate somebody or to review the evaluation. + * + * This function is called from display_rubric() to display the whole rubric. + * + * When overriding this function it is very important to remember that all elements of html + * form (in edit or evaluate mode) must have the name $elementname. + * + * Also JavaScript relies on the class names of elements and when developer changes them + * script might stop working. + * + * @param int $mode rubric display mode @see gradingform_rubric_controller + * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode) + * @param string $criteria_str evaluated templates for this rubric's criteria + * @return string + */ + protected function rubric_template($mode, $options, $elementname, $criteria_str) { $classsuffix = ''; // CSS suffix for class of the main div. Depends on the mode switch ($mode) { case gradingform_rubric_controller::DISPLAY_EDIT_FULL: @@ -161,34 +232,98 @@ class gradingform_rubric_renderer { $classsuffix = ' evaluate frozen'; break; case gradingform_rubric_controller::DISPLAY_REVIEW: $classsuffix = ' review'; break; + case gradingform_rubric_controller::DISPLAY_VIEW: + $classsuffix = ' view'; break; } - $rubric_template = html_writer::start_tag('div', array('id' => 'rubric-{NAME}', 'class' => 'clearfix form_rubric'.$classsuffix)); - $rubric_template .= html_writer::tag('div', $criteria_str, array('class' => 'criteria', 'id' => '{NAME}-criteria')); + $rubric_template = html_writer::start_tag('div', array('id' => 'rubric-{NAME}', 'class' => 'clearfix gradingform_rubric'.$classsuffix)); + $rubric_template .= html_writer::tag('table', $criteria_str, array('class' => 'criteria', 'id' => '{NAME}-criteria')); if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { $value = get_string('addcriterion', 'gradingform_rubric'); - $input = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[addcriterion]', 'id' => '{NAME}-addcriterion', 'value' => $value, 'title' => $value)); + $input = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[criteria][addcriterion]', 'id' => '{NAME}-criteria-addcriterion', 'value' => $value, 'title' => $value)); $rubric_template .= html_writer::tag('div', $input, array('class' => 'addcriterion')); } + $rubric_template .= $this->rubric_edit_options($mode, $options); $rubric_template .= html_writer::end_tag('div'); return str_replace('{NAME}', $elementname, $rubric_template); } + protected function rubric_edit_options($mode, $options) { + if ($mode != gradingform_rubric_controller::DISPLAY_EDIT_FULL + && $mode != gradingform_rubric_controller::DISPLAY_EDIT_FROZEN + && $mode != gradingform_rubric_controller::DISPLAY_PREVIEW) { + // Options are displayed only in edit mode + return; + } + $html = html_writer::start_tag('div', array('class' => 'options')); + $html .= html_writer::tag('div', get_string('rubricoptions', 'gradingform_rubric'), array('class' => 'optionsheading')); + $attrs = array('type' => 'hidden', 'name' => '{NAME}[options][optionsset]', 'value' => 1); + foreach ($options as $option => $value) { + $html .= html_writer::start_tag('div', array('class' => 'option '.$option)); + $attrs = array('name' => '{NAME}[options]['.$option.']', 'id' => '{NAME}-options-'.$option); + switch ($option) { + case 'sortlevelsasc': + // Display option as dropdown + $html .= html_writer::tag('span', get_string($option, 'gradingform_rubric'), array('class' => 'label')); + $value = (int)(!!$value); // make sure $value is either 0 or 1 + if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) { + $selectoptions = array(0 => get_string($option.'0', 'gradingform_rubric'), 1 => get_string($option.'1', 'gradingform_rubric')); + $value_str = html_writer::select($selectoptions, $attrs['name'], $value, false, array('id' => $attrs['id'])); + $html .= html_writer::tag('span', $value_str, array('class' => 'value')); + // TODO add here button 'Sort levels' + } else { + $html .= html_writer::tag('span', get_string($option.$value, 'gradingform_rubric'), array('class' => 'value')); + if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) { + $html .= html_writer::empty_tag('input', $attrs + array('type' => 'hidden', 'value' => $value)); + } + } + break; + default: + // Display option as checkbox + $attrs['type'] = 'checkbox'; + $attrs['value'] = 1; + if ($value) { + $attrs['checked'] = 'checked'; + } + if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) { + $attrs['disabled'] = 'disabled'; + } + if ($mode == gradingform_rubric_controller::DISPLAY_PREVIEW) { + $attrs['disabled'] = 'disabled'; + unset($attrs['name']); + } + $html .= html_writer::empty_tag('input', $attrs); + $html .= html_writer::tag('label', get_string($option, 'gradingform_rubric'), array('for' => $attrs['id'])); + break; + } + $html .= html_writer::end_tag('div'); // .option + } + $html .= html_writer::end_tag('div'); // .options + return $html; + } + /** - * Returns html code for displaying the rubric in the specified mode + * This function returns html code for displaying rubric. Depending on $mode it may be the code + * to edit rubric, to preview the rubric, to evaluate somebody or to review the evaluation. * - * @param array $criteria - * @param int $mode - * @param string $elementname - * @param array $values + * It is very unlikely that this function needs to be overriden by theme. It does not produce + * any html code, it just prepares data about rubric design and evaluation, adds the CSS + * class to elements and calls the functions level_template, criterion_template and + * rubric_template + * + * @param array $criteria data about the rubric design + * @param int $mode rubric display mode @see gradingform_rubric_controller + * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode) + * @param array $values evaluation result * @return string */ - public function display_rubric($criteria, $mode, $elementname = null, $values = null) { + public function display_rubric($criteria, $options, $mode, $elementname = null, $values = null) { $criteria_str = ''; $cnt = 0; foreach ($criteria as $id => $criterion) { $criterion['class'] = $this->get_css_class_suffix($cnt++, sizeof($criteria) -1); + $criterion['id'] = $id; $levels_str = ''; $levelcnt = 0; if (isset($values['criteria'][$id])) { @@ -197,28 +332,30 @@ class gradingform_rubric_renderer { $criterionvalue = null; } foreach ($criterion['levels'] as $levelid => $level) { + $level['id'] = $levelid; $level['score'] = (float)$level['score']; // otherwise the display will look like 1.00000 $level['class'] = $this->get_css_class_suffix($levelcnt++, sizeof($criterion['levels']) -1); $level['checked'] = (isset($criterionvalue['levelid']) && ((int)$criterionvalue['levelid'] === $levelid)); - if ($level['checked'] && ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN || $mode == gradingform_rubric_controller::DISPLAY_REVIEW)) { + if ($level['checked'] && ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN || $mode == gradingform_rubric_controller::DISPLAY_REVIEW || $mode == gradingform_rubric_controller::DISPLAY_VIEW)) { $level['class'] .= ' checked'; - //in mode DISPLAY_EVAL the class 'checked' will be added by JS if it is enabled. If it is not enabled, the 'checked' class will only confuse + //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 } - $levels_str .= $this->level_template($mode, $elementname, $id, $level); + $level['tdwidth'] = 100/count($criterion['levels']); + $levels_str .= $this->level_template($mode, $options, $elementname, $id, $level); } - $criteria_str .= $this->criterion_template($mode, $elementname, $criterion, $levels_str, $criterionvalue); + $criteria_str .= $this->criterion_template($mode, $options, $elementname, $criterion, $levels_str, $criterionvalue); } - return $this->rubric_template($mode, $elementname, $criteria_str); + return $this->rubric_template($mode, $options, $elementname, $criteria_str); } /** - * Help function to return CSS class names for element (first/last/even/odd) + * Help function to return CSS class names for element (first/last/even/odd) with leading space * - * @param $cnt - * @param $maxcnt + * @param int $cnt + * @param int $maxcnt * @return string */ - private function get_css_class_suffix($cnt, $maxcnt) { + protected function get_css_class_suffix($cnt, $maxcnt) { $class = ''; if ($cnt == 0) { $class .= ' first'; @@ -261,7 +398,9 @@ class gradingform_rubric_renderer { */ public function display_instance(gradingform_rubric_instance $instance, $idx) { $criteria = $instance->get_controller()->get_definition()->rubric_criteria; + $options = $instance->get_controller()->get_options(); $values = $instance->get_rubric_filling(); - return $this->display_rubric($criteria, gradingform_rubric_controller::DISPLAY_REVIEW, 'rubric'.$idx, $values); + // TODO mode should be DISPLAY_REVIEW if this user is a teacher + return $this->display_rubric($criteria, $options, gradingform_rubric_controller::DISPLAY_VIEW, 'rubric'.$idx, $values); } } diff --git a/grade/grading/form/rubric/rubriceditor.php b/grade/grading/form/rubric/rubriceditor.php index 1b403660976..5146149df1a 100644 --- a/grade/grading/form/rubric/rubriceditor.php +++ b/grade/grading/form/rubric/rubriceditor.php @@ -50,6 +50,7 @@ class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input { global $PAGE; $html = $this->_getTabs(); $renderer = $PAGE->get_renderer('gradingform_rubric'); + $data = $this->prepare_non_js_data(); if (!$this->_flagFrozen) { $mode = gradingform_rubric_controller::DISPLAY_EDIT_FULL; $module = array('name'=>'gradingform_rubriceditor', 'fullpath'=>'/grade/grading/form/rubric/js/rubriceditor.js', @@ -58,32 +59,54 @@ class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input { )); $PAGE->requires->js_init_call('M.gradingform_rubriceditor.init', array( array('name' => $this->getName(), - 'criteriontemplate' => $renderer->criterion_template($mode, $this->getName()), - 'leveltemplate' => $renderer->level_template($mode, $this->getName()) + 'criteriontemplate' => $renderer->criterion_template($mode, $data['options'], $this->getName()), + 'leveltemplate' => $renderer->level_template($mode, $data['options'], $this->getName()) )), true, $module); } else { + // Rubric is frozen, no javascript needed if ($this->_persistantFreeze) { $mode = gradingform_rubric_controller::DISPLAY_EDIT_FROZEN; } else { $mode = gradingform_rubric_controller::DISPLAY_PREVIEW; } } - $html .= $renderer->display_rubric($this->prepare_non_js_data(), $mode, $this->getName()); + $html .= $renderer->display_rubric($data['criteria'], $data['options'], $mode, $this->getName()); return $html; } - function prepare_non_js_data() { - $return = array(); - $criteria = $this->getValue(); - if (empty($criteria)) { - $criteria = array(); + /** + * Prepares the data passed in $_POST: + * - processes the pressed buttons 'addlevel', 'addcriterion', 'moveup', 'movedown', 'delete' (when JavaScript is disabled) + * - if options not passed (i.e. we create a new rubric) fills the options array with the default values + * - if options are passed completes the options array with unchecked checkboxes + * + * @param array $value + * @return array + */ + function prepare_non_js_data($value = null) { + if (null === $value) { + $value = $this->getValue(); + } + $return = array('criteria' => array(), 'options' => gradingform_rubric_controller::get_default_options()); + if (!isset($value['criteria'])) { + $value['criteria'] = array(); + } + if (!empty($value['options'])) { + foreach (array_keys($return['options']) as $option) { + // special treatment for checkboxes + if (!empty($value['options'][$option])) { + $return['options'][$option] = $value['options'][$option]; + } else { + $return['options'][$option] = null; + } + } } $lastaction = null; $lastid = null; - foreach ($criteria as $id => $criterion) { + foreach ($value['criteria'] as $id => $criterion) { if ($id == 'addcriterion') { - $id = $this->get_next_id(array_keys($criteria)); + $id = $this->get_next_id(array_keys($value['criteria'])); $criterion = array('description' => ''); } $levels = array(); @@ -105,12 +128,12 @@ class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input { if (array_key_exists('moveup', $criterion) || $lastaction == 'movedown') { unset($criterion['moveup']); if ($lastid !== null) { - $lastcriterion = $return[$lastid]; - unset($return[$lastid]); - $return[$id] = $criterion; - $return[$lastid] = $lastcriterion; + $lastcriterion = $return['criteria'][$lastid]; + unset($return['criteria'][$lastid]); + $return['criteria'][$id] = $criterion; + $return['criteria'][$lastid] = $lastcriterion; } else { - $return[$id] = $criterion; + $return['criteria'][$id] = $criterion; } $lastaction = null; $lastid = $id; @@ -120,13 +143,13 @@ class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input { unset($criterion['movedown']); $lastaction = 'movedown'; } - $return[$id] = $criterion; + $return['criteria'][$id] = $criterion; $lastid = $id; } } $csortorder = 1; - foreach (array_keys($return) as $id) { - $return[$id]['sortorder'] = $csortorder++; + foreach (array_keys($return['criteria']) as $id) { + $return['criteria'][$id]['sortorder'] = $csortorder++; } return $return; } @@ -143,8 +166,8 @@ class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input { function _ruleIsCompleted($elementValue) { //echo "_ruleIsCompleted"; - if (is_array($elementValue)) { - foreach ($elementValue as $criterionid => $criterion) { + if (isset($elementValue['criteria'])) { + foreach ($elementValue['criteria'] as $criterionid => $criterion) { if ($criterionid == 'addcriterion') { return false; } @@ -177,4 +200,16 @@ class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input { return parent::onQuickFormEvent($event, $arg, $caller); } + /** + * Prepares the data for saving + * @see prepare_non_js_data + * + * @param array $submitValues + * @param boolean $assoc + * @return array + */ + function exportValue(&$submitValues, $assoc = false) { + $value = $this->prepare_non_js_data($this->_findValue($submitValues)); + return $this->_prepareValue($value, $assoc); + } } \ No newline at end of file diff --git a/grade/grading/form/rubric/styles.css b/grade/grading/form/rubric/styles.css index 0802227a57f..66dc3c01a09 100644 --- a/grade/grading/form/rubric/styles.css +++ b/grade/grading/form/rubric/styles.css @@ -1,6 +1,7 @@ /* -.form_rubric.editor[.frozen|.editable] - .criterion[.first][.last].odd/even +.gradingform_rubric.editor[.frozen|.editable] + .criteria + .criterion[.first][.last][.odd|.even] .controls .moveup [input type=submit] @@ -10,84 +11,95 @@ [input type=submit] .description .levels - .level[.first][.last].odd/even - .definition - [textarea] - .score - span - [input type=text] - .delete - [input type=submit] + td.level[.first][.last][.odd|.even] + div.level-wrapper + .definition + [textarea] + .score + span + [input type=text] + .delete + [input type=submit] .addlevel [input type=submit] .remark textarea .addcriterion [input type=submit] + .options + .optionsheading + .option.OPTIONNAME -.form_rubric.evaluate - .criterion[.first][.last].odd/even +.gradingform_rubric[.review][.evaluate[.editable|.frozen]] + .criteria + .criterion[.first][.last][.odd|.even] .description .levels - .level[.first][.last].odd/even - .radio - input - .definition - .score - span + td.level[.first][.last][.odd|.even] + div.level-wrapper + div.radio + input + .definition + .score + span */ +.gradingform_rubric.editor .criterion .controls, +.gradingform_rubric .criterion .description, +.gradingform_rubric .criterion .levels, +.gradingform_rubric.editor .criterion .addlevel, +.gradingform_rubric .criterion .remark, +.gradingform_rubric .criterion .levels .level {vertical-align: top;} -.form_rubric.editor .criterion .controls, -.form_rubric .criterion .description, -.form_rubric .criterion .levels, -.form_rubric.editor .criterion .addlevel, -.form_rubric .criterion .remark, -.form_rubric .criterion .levels .level {display: inline-block; vertical-align: top;overflow: hidden;} +.gradingform_rubric.editor .criterion .controls, +.gradingform_rubric .criterion .description, +.gradingform_rubric.editor .criterion .addlevel, +.gradingform_rubric .criterion .remark, +.gradingform_rubric .criterion .levels .level {padding:3px;} -.form_rubric.editor .criterion .controls, -.form_rubric .criterion .description, -.form_rubric.editor .criterion .addlevel, -.form_rubric .criterion .remark, -.form_rubric .criterion .levels .level {padding:3px;} +.gradingform_rubric .criteria {height:100%;} +.gradingform_rubric .criterion {border:1px solid #DDD;overflow: hidden;} +.gradingform_rubric .criterion.even {background:#F0F0F0;} -/* Those divs should extend vertically and fill 100% of parent element height */ -.form_rubric .criterion .levels .level, -.form_rubric .criterion .description, -.form_rubric .criterion .levels {padding-bottom: 32767px;margin-bottom: -32767px;} +.gradingform_rubric .criterion .description {width:150px;font-weight:bold;} -.form_rubric .criterion {border:1px solid #DDD;overflow: hidden;} -.form_rubric .criterion.even {background:#F0F0F0;} +.gradingform_rubric .criterion .levels table {width:100%;height:100%;} +.gradingform_rubric .criterion .levels, +.gradingform_rubric .criterion .levels table, +.gradingform_rubric .criterion .levels table tbody {padding:0;margin:0;} +.gradingform_rubric .criterion .levels .level {border-left:1px solid #DDD;max-width:150px;} +.gradingform_rubric .criterion .levels .level .level-wrapper {position:relative;} +.gradingform_rubric .criterion .levels .level.last {border-right:1px solid #DDD;} -.form_rubric .criterion .description {width:150px;font-weight:bold;} +.gradingform_rubric .plainvalue.empty {font-style: italic; color: #AAA;} -.form_rubric .criterion .levels .level {border-left:1px solid #DDD;min-width:80px;max-width:150px;position:relative;} -.form_rubric .criterion .levels .level.last {border-right:1px solid #DDD;} - -.form_rubric .plainvalue.empty {font-style: italic; color: #AAA;} - -.form_rubric.editor .criterion .levels .level .delete {position:absolute;right:0px;bottom:32767px;} -.form_rubric .criterion .levels .level .score {display:block;} +.gradingform_rubric.editor .criterion .levels .level .delete {position:absolute;right:0;bottom:0;} +.gradingform_rubric .criterion .levels .level .score {font-style:italic;color:#575;font-weight: bold;margin-top:5px;} /* Make invisible the buttons 'Move up' for the first criterion and 'Move down' for the last, because those buttons will make no change */ -.form_rubric.editor .criterion.first .controls .moveup input, -.form_rubric.editor .criterion.last .controls .movedown input {display:none;} +.gradingform_rubric.editor .criterion.first .controls .moveup input, +.gradingform_rubric.editor .criterion.last .controls .movedown input {display:none;} /* evaluation */ -.form_rubric .criterion .levels .level.checked {background:#d0ffd0;} -.form_rubric.evaluate .criterion .levels .level:hover {background:#30ff30;} +.gradingform_rubric .criterion .levels .level.checked {background:#d0ffd0;} +.gradingform_rubric.evaluate .criterion .levels .level:hover {background:#30ff30;} /* replace buttons with images */ -.form_rubric.editor .delete input, -.form_rubric.editor .moveup input, -.form_rubric.editor .movedown input{text-indent: -1000em;cursor:pointer;border:none;} -.form_rubric.editor .criterion .controls .delete input {width:20px;height:16px;background: transparent url([[pix:i/cross_red_big]]) no-repeat center top;} -.form_rubric.editor .levels .level .delete input {width:20px;height:16px;background: transparent url([[pix:i/cross_red_small]]) no-repeat center top;} -.form_rubric.editor .moveup input {width:20px;height:15px;background: transparent url([[pix:t/up]]) no-repeat center top;margin-top:4px;} -.form_rubric.editor .movedown input {width:20px;height:15px;background: transparent url([[pix:t/down]]) no-repeat center top;margin-top:4px;} +.gradingform_rubric.editor .delete input, +.gradingform_rubric.editor .moveup input, +.gradingform_rubric.editor .movedown input{text-indent: -1000em;cursor:pointer;border:none;} +.gradingform_rubric.editor .criterion .controls .delete input {width:20px;height:16px;background: transparent url([[pix:i/cross_red_big]]) no-repeat center top;} +.gradingform_rubric.editor .levels .level .delete input {width:20px;height:16px;background: transparent url([[pix:i/cross_red_small]]) no-repeat center top;} +.gradingform_rubric.editor .moveup input {width:20px;height:15px;background: transparent url([[pix:t/up]]) no-repeat center top;margin-top:4px;} +.gradingform_rubric.editor .movedown input {width:20px;height:15px;background: transparent url([[pix:t/down]]) no-repeat center top;margin-top:4px;} -.form_rubric.editor .addcriterion input, -.form_rubric.editor .addlevel input {background: transparent url([[pix:t/addgreen]]) no-repeat;display:block;color:#555555;font-weight:bold;text-decoration:none;} -.form_rubric.editor .addcriterion input {background-position: 5px 8px;height:30px;line-height:29px;margin-bottom:14px;padding-left:20px;padding-right:10px;} -.form_rubric.editor .addlevel input {background-position: 5px 6px;height:25px;line-height:24px;margin-bottom:10px;padding-left:18px;padding-right:8px;} +.gradingform_rubric.editor .addcriterion input, +.gradingform_rubric.editor .addlevel input {background: transparent url([[pix:t/addgreen]]) no-repeat;display:block;color:#555555;font-weight:bold;text-decoration:none;} +.gradingform_rubric.editor .addcriterion input {background-position: 5px 8px;height:30px;line-height:29px;margin-bottom:14px;padding-left:20px;padding-right:10px;} +.gradingform_rubric.editor .addlevel input {background-position: 5px 6px;height:25px;line-height:24px;margin-bottom:10px;padding-left:18px;padding-right:8px;} + +.gradingform_rubric .options .optionsheading {font-weight:bold;font-size:1.1em;padding-bottom:5px;} +.gradingform_rubric .options .option {padding-bottom:2px;} +.gradingform_rubric .options .option label {margin-left: 5px;} +.gradingform_rubric .options .option .value {margin-left: 5px;font-weight:bold;}