From b244b9b776b05b10bd61f9d2d653fa8aa8befc26 Mon Sep 17 00:00:00 2001 From: nicolasconnault Date: Fri, 18 Apr 2008 19:30:28 +0000 Subject: [PATCH] MDL-14163 YUI implementation complete, new grader_report preference and admin setting for enabling ajax. --- grade/lib.php | 119 ++++- grade/report/grader/ajax.php | 582 +++++++++++++++++++++++ grade/report/grader/ajax_callbacks.php | 139 ++++++ grade/report/grader/ajaxlib.php | 527 ++++++++++++++++++++ grade/report/grader/index.php | 52 +- grade/report/grader/preferences_form.php | 2 +- grade/report/grader/settings.php | 4 +- lang/en_utf8/grades.php | 1 + lib/ajax/ajaxlib.php | 3 + 9 files changed, 1412 insertions(+), 17 deletions(-) create mode 100644 grade/report/grader/ajax.php create mode 100644 grade/report/grader/ajax_callbacks.php create mode 100644 grade/report/grader/ajaxlib.php diff --git a/grade/lib.php b/grade/lib.php index 79228c744d..a4952a2986 100644 --- a/grade/lib.php +++ b/grade/lib.php @@ -987,7 +987,7 @@ class grade_structure { } if ($url) { - return ''.$stredit.''; + return ''.$stredit.''; } else { return ''; @@ -1022,13 +1022,13 @@ class grade_structure { $url = $CFG->wwwroot.'/grade/edit/tree/action.php?id='.$this->courseid.'&action=show&sesskey='.sesskey() . '&eid='.$element['eid']; $url = $gpr->add_url_params($url); - $action = ''.$strshow.''; + $action = ''.$strshow.''; } else { $url = $CFG->wwwroot.'/grade/edit/tree/action.php?id='.$this->courseid.'&action=hide&sesskey='.sesskey() . '&eid='.$element['eid']; $url = $gpr->add_url_params($url); - $action = ''.$strhide.''; + $action = ''.$strhide.''; } return $action; } @@ -1066,7 +1066,7 @@ class grade_structure { $url = $CFG->wwwroot.'/grade/edit/tree/action.php?id='.$this->courseid.'&action=unlock&sesskey='.sesskey() . '&eid='.$element['eid']; $url = $gpr->add_url_params($url); - $action = ''.$strunlock.''; + $action = ''.$strunlock.''; } else { if (!has_capability('moodle/grade:manage', $this->context) and !has_capability('moodle/grade:lock', $this->context)) { @@ -1075,7 +1075,7 @@ class grade_structure { $url = $CFG->wwwroot.'/grade/edit/tree/action.php?id='.$this->courseid.'&action=lock&sesskey='.sesskey() . '&eid='.$element['eid']; $url = $gpr->add_url_params($url); - $action = ''.$strlock.''.$strlock.''; } return $action; @@ -1111,7 +1111,7 @@ class grade_structure { } $url = $CFG->wwwroot.'/grade/edit/tree/calculation.php?courseid='.$this->courseid.'&id='.$object->id; $url = $gpr->add_url_params($url); - $calculation_icon = ''
+                $calculation_icon = '<a href='
                                        . $streditcalculation.''. "\n"; } } @@ -1548,6 +1548,113 @@ class grade_tree extends grade_structure { return null; } + + /** + * Returns a well-formed XML representation of the grade-tree using recursion. + * @param array $root The current element in the recursion. If null, starts at the top of the tree. + * @return string $xml + */ + function exportToXML($root=null, $tabs="\t") { + $xml = null; + $first = false; + if (is_null($root)) { + $root = $this->top_element; + $xml = '' . "\n"; + $xml .= "\n"; + $first = true; + } + + $type = 'undefined'; + if (strpos($root['object']->table, 'grade_categories') !== false) { + $type = 'category'; + } elseif (strpos($root['object']->table, 'grade_items') !== false) { + $type = 'item'; + } elseif (strpos($root['object']->table, 'grade_outcomes') !== false) { + $type = 'outcome'; + } + + $xml .= "$tabs\n"; + foreach ($root['object'] as $var => $value) { + if (!is_object($value) && !is_array($value) && !empty($value)) { + $xml .= "$tabs\t<$var>$value\n"; + } + } + + if (!empty($root['children'])) { + $xml .= "$tabs\t\n"; + foreach ($root['children'] as $sortorder => $child) { + $xml .= $this->exportToXML($child, $tabs."\t\t"); + } + $xml .= "$tabs\t\n"; + } + + $xml .= "$tabs\n"; + + if ($first) { + $xml .= ""; + } + + return $xml; + } + + /** + * Returns a JSON representation of the grade-tree using recursion. + * @param array $root The current element in the recursion. If null, starts at the top of the tree. + * @param string $tabs Tab characters used to indent the string nicely for humans to enjoy + * @param int $switch The position (first or last) of the aggregations + * @return string $xml + */ + function exportToJSON($root=null, $tabs="\t") { + $json = null; + $first = false; + if (is_null($root)) { + $root = $this->top_element; + $first = true; + } + + $name = ''; + + + if (strpos($root['object']->table, 'grade_categories') !== false) { + $name = $root['object']->fullname; + if ($name == '?') { + $name = $root['object']->get_name(); + } + } elseif (strpos($root['object']->table, 'grade_items') !== false) { + $name = $root['object']->itemname; + } elseif (strpos($root['object']->table, 'grade_outcomes') !== false) { + $name = $root['object']->itemname; + } + + $json .= "$tabs {\n"; + $json .= "$tabs\t \"type\": \"{$root['type']}\",\n"; + $json .= "$tabs\t \"name\": \"$name\",\n"; + + foreach ($root['object'] as $var => $value) { + if (!is_object($value) && !is_array($value) && !empty($value)) { + $json .= "$tabs\t \"$var\": \"$value\",\n"; + } + } + + $json = substr($json, 0, strrpos($json, ',')); + + if (!empty($root['children'])) { + $json .= ",\n$tabs\t\"children\": [\n"; + foreach ($root['children'] as $sortorder => $child) { + $json .= $this->exportToJSON($child, $tabs."\t\t"); + } + $json = substr($json, 0, strrpos($json, ',')); + $json .= "\n$tabs\t]\n"; + } + + if ($first) { + $json .= "\n}"; + } else { + $json .= "\n$tabs},\n"; + } + + return $json; + } } ?> diff --git a/grade/report/grader/ajax.php b/grade/report/grader/ajax.php new file mode 100644 index 0000000000..c289315332 --- /dev/null +++ b/grade/report/grader/ajax.php @@ -0,0 +1,582 @@ + diff --git a/grade/report/grader/ajax_callbacks.php b/grade/report/grader/ajax_callbacks.php new file mode 100644 index 0000000000..c221628da9 --- /dev/null +++ b/grade/report/grader/ajax_callbacks.php @@ -0,0 +1,139 @@ +libdir.'/gradelib.php'; +require_once $CFG->dirroot.'/grade/lib.php'; +// require_once $CFG->dirroot.'/grade/report/grader/ajaxlib.php'; +// require_once $CFG->dirroot.'/grade/report/grader/lib.php'; + +$courseid = required_param('id'); // course id +$userid = optional_param('userid', false, PARAM_INT); +$itemid = optional_param('itemid', false, PARAM_INT); +$type = optional_param('type', false, PARAM_ALPHA); +$action = optional_param('action', false, PARAM_ALPHA); +$newvalue = optional_param('newvalue', false, PARAM_MULTILANG); + +switch ($action) { + case 'update': + if (!empty($userid) && !empty($itemid) && $newvalue !== false && !empty($type)) { + // Save the grade or feedback + if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$courseid))) { // we must verify course id here! + print_error('Incorrect grade item id'); + } + + /** + * Code copied from grade/report/grader/lib.php line 187+ + */ + $warnings = array(); + $finalvalue = null; + $finalgrade = null; + $feedback = null; + $json_object = new stdClass(); + // Pre-process grade + if ($type == 'value' || $type == 'scale') { + $feedback = false; + $feedbackformat = false; + if ($grade_item->gradetype == GRADE_TYPE_SCALE) { + if ($newvalue == -1) { // -1 means no grade + $finalgrade = null; + } else { + $finalgrade = $newvalue; + } + } else { + $finalgrade = unformat_float($newvalue); + } + + $errorstr = ''; + // Warn if the grade is out of bounds. + if (is_null($finalgrade)) { + // ok + } else if ($finalgrade < $grade_item->grademin) { + $errorstr = 'lessthanmin'; + } else if ($finalgrade > $grade_item->grademax) { + $errorstr = 'morethanmax'; + } + + if ($errorstr) { + $user = get_record('user', 'id', $userid, '', '', '', '', 'id, firstname, lastname'); + $gradestr = new object(); + $gradestr->username = fullname($user); + $gradestr->itemname = $grade_item->get_name(); + $json_object->message = get_string($errorstr, 'grades', $gradestr); + $json_object->result = "error"; + + } + + $finalvalue = $finalgrade; + + } else if ($type == 'feedback') { + $finalgrade = false; + $trimmed = trim($newvalue); + if (empty($trimmed)) { + $feedback = NULL; + } else { + $feedback = stripslashes($newvalue); + } + + $finalvalue = $feedback; + } + + if (!empty($json_object->result) && $json_object->result == 'error') { + echo json_encode($json_object); + die(); + } else { + $json_object->gradevalue = $finalvalue; + + if ($grade_item->update_final_grade($userid, $finalgrade, 'gradebook', $feedback, FORMAT_MOODLE)) { + $json_object->result = 'success'; + $json_object->message = false; + } else { + $json_object->result = 'error'; + $json_object->message = "TO BE LOCALISED: Failure to update final grade!"; + echo json_encode(); + die(); + } + + // Get row data + $sql = "SELECT gg.id, gi.id AS itemid, gi.scaleid AS scale, gg.userid AS userid, finalgrade, gg.overridden AS overridden " + . "FROM {$CFG->prefix}grade_grades gg, {$CFG->prefix}grade_items gi WHERE " + . "gi.courseid = $courseid AND gg.itemid = gi.id AND gg.userid = $userid"; + $records = get_records_sql($sql); + $json_object->row = $records; + echo json_encode($json_object); + die(); + } + } else { + $json_object = new stdClass(); + $json_object->result = "error"; + $json_object->message = "Missing parameter to ajax UPDATE callback: \n" . + " userid: $userid,\n itemid: $itemid\n, type: $type\n, newvalue: $newvalue"; + echo json_encode($json_object); + } + + break; +} + +?> diff --git a/grade/report/grader/ajaxlib.php b/grade/report/grader/ajaxlib.php new file mode 100644 index 0000000000..47358a1614 --- /dev/null +++ b/grade/report/grader/ajaxlib.php @@ -0,0 +1,527 @@ +dirroot . '/grade/report/grader/lib.php'); + +/** + * Class providing an API for the grader report building and displaying. + * @uses grade_report + * @package gradebook + */ +class grade_report_grader_ajax extends grade_report_grader { + + /** + * An array of feedbacks, indexed by userid_itemid, used for JS caching + * @var array $feedbacks + */ + var $feedbacks = array(); + + /** + * Length at which feedback will be truncated (to the nearest word) and an ellipsis be added. + * TODO replace this by a report preference + * @var int $feedback_trunc_length + */ + var $feedback_trunc_length = 50; + + /** + * Self-incrementing variable, tracking the tabindex. Depending on the tabindex option ("all values, then feedbacks" is default) + * Increments by one between each user for the gradevalues, and by 1 + usercount for the gradefeedback + * @var int $tabindex + */ + var $tabindex = 0; + + /** + * Constructor. Sets local copies of user preferences and initialises grade_tree. + * @param int $courseid + * @param object $gpr grade plugin return tracking object + * @param string $context + * @param int $page The current page being viewed (when report is paged) + * @param int $sortitemid The id of the grade_item by which to sort the table + */ + function grade_report_grader_ajax($courseid, $gpr, $context, $page=null, $sortitemid=null) { + parent::grade_report_grader($courseid, $gpr, $context, $page, $sortitemid); + } + + /** + * Loads, stores and returns the array of scales used in this course. + * @return array + */ + function get_scales_array() { + if (empty($this->gtree->items)) { + return false; + } + + if (!empty($this->scales_array)) { + return $this->scales_array; + } + + $scales_list = ''; + $scales_array = array(); + + foreach ($this->gtree->items as $item) { + if (!empty($item->scaleid)) { + $scales_list .= "$item->scaleid,"; + } + } + + if (!empty($scales_list)) { + $scales_list = substr($scales_list, 0, -1); + $scales_array = get_records_list('scale', 'id', $scales_list); + $this->scales_array = $scales_array; + return $scales_array; + } else { + return null; + } + } + + /** + * Processes the data sent by the form (grades and feedbacks). + * Caller is responsible for all access control checks + * @param array $data form submission (with magic quotes) + * @return array empty array if success, array of warnings if something fails. + */ + function process_data($data) { + return parent::process_data($data); + } + + /** + * Builds and returns a div with on/off toggles. + * @return string HTML code + */ + function get_toggles_html() { + return parent::get_toggles_html(); + } + + /** + * Shortcut function for printing the grader report toggles. + * @param string $type The type of toggle + * @param bool $return Whether to return the HTML string rather than printing it + * @return void + */ + function print_toggle($type, $return=false) { + return parent::print_toggle($type, $return); + } + + /** + * Builds and returns the HTML code for the headers. + * @return string $headerhtml + */ + function get_headerhtml() { + return parent::get_headerhtml(); + } + + /** + * Builds and return the HTML rows of the table (grades headed by student). + * @return string HTML + */ + function get_studentshtml() { + if (empty($this->users)) { + print_error('nousersloaded', 'grades'); + } + + $this->numusers = count($this->users); + + $studentshtml = ''; + + foreach ($this->users as $userid => $user) { + $this->tabindex++; + $studentshtml .= $this->get_studentrowhtml($user); + } + + return $studentshtml; + } + + + /** + * Given a userid, and provided the gtree is correctly loaded, returns a complete HTML row for this user. + * + * @param object $user + * @return string + */ + function get_studentrowhtml($user) { + global $CFG; + $showuserimage = $this->get_pref('showuserimage'); + $showuseridnumber = $this->get_pref('showuseridnumber'); + $studentrowhtml = ''; + $row_classes = array(' even ', ' odd '); + + if ($this->canviewhidden) { + $altered = array(); + $unknown = array(); + } else { + $hiding_affected = grade_grade::get_hiding_affected($this->grades[$userid], $this->gtree->items); + $altered = $hiding_affected['altered']; + $unknown = $hiding_affected['unknown']; + unset($hiding_affected); + } + + $columncount = 0; + // Student name and link + $user_pic = null; + if ($showuserimage) { + $user_pic = '
' . print_user_picture($user, $this->courseid, true, 0, true) . '
'; + } + + $studentrowhtml .= '' + .''.$user_pic + .'' + .fullname($user).''; + + if ($showuseridnumber) { + $studentrowhtml .= ''. $user->idnumber.''; + } + + $columntabcount = 0; + $feedback_tabindex_modifier = 1; // Used to offset the grade value at the beginning of each new column + + if ($this->get_pref('showquickfeedback')) { + $feedback_tabindex_modifier = 2; + } + + foreach ($this->gtree->items as $itemid=>$unused) { + + $nexttabindex = $this->tabindex + $columntabcount * $feedback_tabindex_modifier * $this->numusers; + $studentrowhtml .= $this->get_gradecellhtml($user, $itemid, $columncount, $nexttabindex, $altered, $unknown); + $columntabcount++; + } + + $studentrowhtml .= ''; + return $studentrowhtml; + + } + + /** + * Retuns the HTML table cell for a user's grade for a grade_item + * + * @param object $user + * @param int $itemid + * @param int $columncount + * @param int $nexttabindex + * @param array $altered + * @param array $unknown + * + * @return string + */ + function get_gradecellhtml($user, $itemid, $columncount, $nexttabindex, $altered=array(), $unknown=array()) { + global $CFG, $USER; + + $strfeedback = $this->get_lang_string("feedback"); + $strgrade = $this->get_lang_string('grade'); + + // Preload scale objects for items with a scaleid + $scales_array = $this->get_scales_array(); + + $userid = $user->id; + $item =& $this->gtree->items[$itemid]; + $grade = $this->grades[$userid][$item->id]; + + // Get the decimal points preference for this item + $decimalpoints = $item->get_decimals(); + + if (in_array($itemid, $unknown)) { + $gradeval = null; + } else if (array_key_exists($itemid, $altered)) { + $gradeval = $altered[$itemid]; + } else { + $gradeval = $grade->finalgrade; + } + + $gradecellhtml = ''; + + // MDL-11274 + // Hide grades in the grader report if the current grader doesn't have 'moodle/grade:viewhidden' + if (!$this->canviewhidden and $grade->is_hidden()) { + if (!empty($CFG->grade_hiddenasdate) and $grade->get_datesubmitted() and !$item->is_category_item() and !$item->is_course_item()) { + // the problem here is that we do not have the time when grade value was modified, 'timemodified' is general modification date for grade_grades records + $gradecellhtml .= ''.userdate($grade->get_datesubmitted(),get_string('strftimedatetimeshort')).''; + } else { + $gradecellhtml .= '-'; + } + continue; + } + + // emulate grade element + $eid = $this->gtree->get_grade_eid($grade); + $element = array('eid'=>$eid, 'object'=>$grade, 'type'=>'grade'); + + $cellclasses = 'cell c'.$columncount++; + if ($item->is_category_item()) { + $cellclasses .= ' cat'; + } + if ($item->is_course_item()) { + $cellclasses .= ' course'; + } + if ($grade->is_overridden()) { + $cellclasses .= ' overridden'; + } + + if ($grade->is_excluded()) { + $cellclasses .= ' excluded'; + } + + $gradecellhtml .= ""; + + if ($grade->is_excluded()) { + $gradecellhtml .= get_string('excluded', 'grades') . ' '; + } + + // Do not show any icons if no grade (no record in DB to match) + if (!$item->needsupdate and $USER->gradeediting[$this->courseid]) { + $gradecellhtml .= $this->get_icons($element); + } + + $hidden = ''; + if ($grade->is_hidden()) { + $hidden = ' hidden '; + } + + $gradepass = ' gradefail '; + if ($grade->is_passed($item)) { + $gradepass = ' gradepass '; + } elseif (is_null($grade->is_passed($item))) { + $gradepass = ''; + } + + // if in editting mode, we need to print either a text box + // or a drop down (for scales) + // grades in item of type grade category or course are not directly editable + if ($item->needsupdate) { + $gradecellhtml .= ''.get_string('error').''; + + } else if ($USER->gradeediting[$this->courseid]) { + $anchor_id = "gradevalue_$userid-i$itemid"; + + if ($item->scaleid && !empty($scales_array[$item->scaleid])) { + $scale = $scales_array[$item->scaleid]; + $gradeval = (int)$gradeval; // scales use only integers + $scales = explode(",", $scale->scale); + // reindex because scale is off 1 + + // MDL-12104 some previous scales might have taken up part of the array + // so this needs to be reset + $scaleopt = array(); + $i = 0; + foreach ($scales as $scaleoption) { + $i++; + $scaleopt[$i] = $scaleoption; + } + + if ($this->get_pref('quickgrading') and $grade->is_editable()) { + $oldval = empty($gradeval) ? -1 : $gradeval; + if (empty($item->outcomeid)) { + $nogradestr = $this->get_lang_string('nograde'); + } else { + $nogradestr = $this->get_lang_string('nooutcome', 'grades'); + } + + $gradecellhtml .= '\n"; + + } elseif(!empty($scale)) { + $scales = explode(",", $scale->scale); + + // invalid grade if gradeval < 1 + if ($gradeval < 1) { + $gradecellhtml .= '-'; + } else { + //just in case somebody changes scale + $gradeval = (int)bounded_number($grade->grade_item->grademin, $gradeval, $grade->grade_item->grademax); + $gradecellhtml .= ''.$scales[$gradeval-1].''; + } + } else { + // no such scale, throw error? + } + + } else if ($item->gradetype != GRADE_TYPE_TEXT) { // Value type + $value = $gradeval; + if ($this->get_pref('quickgrading') and $grade->is_editable()) { + $gradecellhtml .= '' .$value.''; + } else { + $gradecellhtml .= ''.$value.''; + } + } + + + // If quickfeedback is on, print an input element + if ($this->get_pref('showquickfeedback') and $grade->is_editable()) { + if ($this->get_pref('quickgrading')) { + $gradecellhtml .= '
'; + } + $feedback = s($grade->feedback); + $anchor_id = "gradefeedback_$userid-i$itemid"; + + if (empty($feedback)) { + $feedback = get_string('addfeedback', 'grades'); + $gradecellhtml .= 'feedback, $grade->feedbackformat))); + $overlib = "return overlib('$full_feedback', BORDER, 0, FGCLASS, 'feedback', " + ."CAPTIONFONTCLASS, 'caption', CAPTION, '$strfeedback');"; + $gradecellhtml .= 'numusers; + + $short_feedback = shorten_text($feedback, $this->feedback_trunc_length); + $gradecellhtml .= ' tabindex="'.$feedback_tabindex .'" id="' + . $anchor_id . '" class="gradefeedback editable">' . $short_feedback . ''; + $this->feedbacks[$userid][$item->id] = $feedback; + } + + } else { // Not editing + $gradedisplaytype = $item->get_displaytype(); + + // If feedback present, surround grade with feedback tooltip: Open span here + if (!empty($grade->feedback)) { + $overlib = ''; + $feedback = addslashes_js(trim(format_string($grade->feedback, $grade->feedbackformat))); + $overlib = "return overlib('$feedback', BORDER, 0, FGCLASS, 'feedback', " + ."CAPTIONFONTCLASS, 'caption', CAPTION, '$strfeedback');"; + $gradecellhtml .= ''; + } + + if ($item->needsupdate) { + $gradecellhtml .= ''.get_string('error').''; + + } else { + $gradecellhtml .= ''.grade_format_gradevalue($gradeval, $item, true, $gradedisplaytype, null).''; + } + + // Close feedback span + if (!empty($grade->feedback)) { + $gradecellhtml .= ''; + } + } + + if (!empty($this->gradeserror[$item->id][$userid])) { + $gradecellhtml .= $this->gradeserror[$item->id][$userid]; + } + + $gradecellhtml .= '' . "\n"; + return $gradecellhtml; + } + + /** + * Builds and return the HTML row of column totals. + * @param bool $grouponly Whether to return only group averages or all averages. + * @return string HTML + */ + function get_avghtml($grouponly=false) { + return parent::get_avghtml(); + } + + /** + * Builds and return the HTML row of ranges for each column (i.e. range). + * @return string HTML + */ + function get_rangehtml() { + return parent::get_rangehtml(); + } + + /** + * Builds and return the HTML row of ranges for each column (i.e. range). + * @return string HTML + */ + function get_iconshtml() { + return parent::get_iconshtml(); + } + + /** + * Given a grade_category, grade_item or grade_grade, this function + * figures out the state of the object and builds then returns a div + * with the icons needed for the grader report. + * + * @param object $object + * @return string HTML + */ + function get_icons($element) { + return parent::get_icons($element); + } + + /** + * Given a category element returns collapsing +/- icon if available + * @param object $object + * @return string HTML + */ + function get_collapsing_icon($element) { + return parent::get_collapsing_icon($element); + } + + /** + * Processes a single action against a category, grade_item or grade. + * @param string $target eid ({type}{id}, e.g. c4 for category4) + * @param string $action Which action to take (edit, delete etc...) + * @return + */ + function process_action($target, $action) { + return parent::process_action($target, $action); + } + + /** + * Returns a valid JSON object with feedbacks indexed by userid and itemid. + * Paging is taken into account: this needs to be reloaded at each new page (not page load, just page of data); + */ + function getFeedbackJsArray() { + if (!empty($this->feedbacks)) { + return json_encode($this->feedbacks); + } else { + return null; + } + } + + /** + * Returns a json_encoded hash of itemid => decimalpoints preferences + */ + function getItemsDecimalPoints() { + $decimals = array(); + foreach ($this->gtree->items as $itemid=>$item) { + $decimals[$itemid] = $item->get_decimals(); + } + return json_encode($decimals); + } +} +?> diff --git a/grade/report/grader/index.php b/grade/report/grader/index.php index 5fe42bf527..0232337a0d 100644 --- a/grade/report/grader/index.php +++ b/grade/report/grader/index.php @@ -113,14 +113,40 @@ if (!is_null($toggle) && !empty($toggle_type)) { //first make sure we have proper final grades - this must be done before constructing of the grade tree grade_regrade_final_grades($courseid); -// Perform actions +// Perform actions. if (!empty($target) && !empty($action) && confirm_sesskey()) { grade_report_grader::process_action($target, $action); } -// Initialise the grader report object +$bodytags = ''; $report = new grade_report_grader($courseid, $gpr, $context, $page, $sortitemid); +// Initialise the grader report object +if (ajaxenabled() && $report->get_pref('enableajax')) { + require_once $CFG->dirroot.'/grade/report/grader/ajaxlib.php'; + + require_js(array('yui_yahoo', + 'yui_dom', + 'yui_event', + 'yui_json', + 'yui_connection', + 'yui_dragdrop', + 'yui_animation')); + + if (debugging('', DEBUG_DEVELOPER)) { + require_js(array('yui_logger')); + + $bodytags = 'onload = "javascript: + show_logger = function() { + var logreader = new YAHOO.widget.LogReader(); + logreader.newestOnTop = false; + logreader.setTitle(\'Moodle Debug: YUI Log Console\'); + }; + show_logger(); + "'; + } + $report = new grade_report_grader_ajax($courseid, $gpr, $context, $page, $sortitemid); +} /// processing posted grades & feedback here if ($data = data_submitted() and confirm_sesskey() and has_capability('moodle/grade:edit', $context)) { @@ -141,8 +167,7 @@ $numusers = $report->get_numusers(); $report->load_final_grades(); /// Print header -print_header_simple($strgrades.': '.$reportname, ': '.$strgrades, $navigation, - '', '', true, $buttons, navmenu($course)); +print_header_simple($strgrades.': '.$reportname, ': '.$strgrades, $navigation, '', '', true, $buttons, navmenu($course), false, $bodytags); /// Print the plugin selector at the top print_grade_plugin_selector($courseid, 'report', 'grader'); @@ -168,17 +193,21 @@ if (!empty($studentsperpage)) { $reporthtml = ''; +$reporthtml .= '
' . "\n"; $reporthtml .= ''; +$reporthtml .= ''; $reporthtml .= $report->get_headerhtml(); $reporthtml .= $report->get_iconshtml(); $reporthtml .= $report->get_rangehtml(); -$reporthtml .= $report->get_studentshtml(); +$reporthtml .= "\n"; $reporthtml .= $report->get_avghtml(true); $reporthtml .= $report->get_avghtml(); -$reporthtml .= "
"; +$reporthtml .= "\n"; +$reporthtml .= $report->get_studentshtml(); +$reporthtml .= "\n"; // print submit button -if ($USER->gradeediting[$course->id]) { +if ($USER->gradeediting[$course->id] and !$report->get_pref('enableajax')) { echo '
'; echo '
'; echo ''; @@ -189,7 +218,9 @@ if ($USER->gradeediting[$course->id]) { echo $reporthtml; // print submit button -if ($USER->gradeediting[$course->id] && ($report->get_pref('showquickfeedback') || $report->get_pref('quickgrading'))) { +if ($USER->gradeediting[$course->id] && ($report->get_pref('showquickfeedback') + || + $report->get_pref('quickgrading')) && !$report->get_pref('enableajax')) { echo '
'; echo '
'; } @@ -199,6 +230,11 @@ if (!empty($studentsperpage) && $studentsperpage >= 20) { print_paging_bar($numusers, $report->page, $studentsperpage, $report->pbarurl); } +// Print AJAX code +if ($report->get_pref('enableajax')) { + require_once 'ajax.php'; +} + print_footer($course); ?> diff --git a/grade/report/grader/preferences_form.php b/grade/report/grader/preferences_form.php index 3033f23e1c..a32a63f828 100644 --- a/grade/report/grader/preferences_form.php +++ b/grade/report/grader/preferences_form.php @@ -115,7 +115,7 @@ class grader_report_preferences_form extends moodleform { $preferences['prefgeneral']['aggregationposition'] = array(GRADE_REPORT_PREFERENCE_DEFAULT => '*default*', GRADE_REPORT_AGGREGATION_POSITION_FIRST => get_string('positionfirst', 'grades'), GRADE_REPORT_AGGREGATION_POSITION_LAST => get_string('positionlast', 'grades')); - // $preferences['prefgeneral']['enableajax'] = $checkbox_default; + $preferences['prefgeneral']['enableajax'] = $checkbox_default; $preferences['prefshow']['showuserimage'] = $checkbox_default; $preferences['prefshow']['showuseridnumber'] = $checkbox_default; diff --git a/grade/report/grader/settings.php b/grade/report/grader/settings.php index e23afc0334..0522779a67 100644 --- a/grade/report/grader/settings.php +++ b/grade/report/grader/settings.php @@ -50,8 +50,8 @@ $settings->add(new admin_setting_configselect('grade_report_meanselection', get_ array(GRADE_REPORT_MEAN_ALL => get_string('meanall', 'grades'), GRADE_REPORT_MEAN_GRADED => get_string('meangraded', 'grades')))); -// $settings->add(new admin_setting_configcheckbox('grade_report_enableajax', get_string('enableajax', 'grades'), -// get_string('configenableajax', 'grades'), 0)); +$settings->add(new admin_setting_configcheckbox('grade_report_enableajax', get_string('enableajax', 'grades'), + get_string('configenableajax', 'grades'), 0)); $settings->add(new admin_setting_configcheckbox('grade_report_showcalculations', get_string('showcalculations', 'grades'), get_string('configshowcalculations', 'grades'), 0)); diff --git a/lang/en_utf8/grades.php b/lang/en_utf8/grades.php index 8b22667af4..f5b7688ad0 100644 --- a/lang/en_utf8/grades.php +++ b/lang/en_utf8/grades.php @@ -345,6 +345,7 @@ $string['nopublish'] = 'Do not publish'; $string['noselectedcategories'] = 'no categories were selected.'; $string['noselecteditems'] = 'no items were selected.'; $string['notteachererror'] = 'You must be a teacher to use this feature.'; +$string['nousersloaded'] = 'No users loaded'; $string['numberofgrades'] = 'Number of grades'; $string['onascaleof'] = ' on a scale of $a->grademin to $a->grademax'; $string['operations'] = 'Operations'; diff --git a/lib/ajax/ajaxlib.php b/lib/ajax/ajaxlib.php index 787e5a735b..84f5d7e78b 100644 --- a/lib/ajax/ajaxlib.php +++ b/lib/ajax/ajaxlib.php @@ -20,10 +20,13 @@ function ajax_get_lib($libname) { 'yui_calendar' => '/lib/yui/calendar/calendar-min.js', 'yui_connection' => '/lib/yui/connection/connection-min.js', 'yui_container' => '/lib/yui/container/container-min.js', + 'yui_datasource' => '/lib/yui/datasource/datasource-beta-min.js', 'yui_dom' => '/lib/yui/dom/dom-min.js', 'yui_dom-event' => '/lib/yui/yahoo-dom-event/yahoo-dom-event.js', 'yui_dragdrop' => '/lib/yui/dragdrop/dragdrop-min.js', + 'yui_ddsend' => '/lib/yui/dragdrop/ddsend.js', 'yui_event' => '/lib/yui/event/event-min.js', + 'yui_json' => '/lib/yui/json/json-min.js', 'yui_logger' => '/lib/yui/logger/logger-min.js', 'yui_menu' => '/lib/yui/menu/menu-min.js', 'yui_tabview' => '/lib/yui/tabview/tabview-min.js', -- 2.39.5