diff --git a/grade/amd/build/edittree_index.min.js b/grade/amd/build/edittree_index.min.js
index cc73e30640c..4692f4a738a 100644
--- a/grade/amd/build/edittree_index.min.js
+++ b/grade/amd/build/edittree_index.min.js
@@ -1,2 +1,2 @@
-define ("core_grades/edittree_index",["jquery"],function(a){var b=function(){a("body").on("change",".itemselect.ignoredirty",b.checkMoveMenuState);a("body").on("click","[data-action=\"grade_edittree-index-bulkselect\"]",b.toggleAllSelectItems);a("body").on("change",".weightoverride",b.toggleWeightInput);a("#menumoveafter").on("change",function(){var b=a(this).closest("form"),c=b.find("#bulkmoveinput");c.val(1);b.submit()});b.checkMoveMenuState()};b.toggleWeightInput=function(b){b.preventDefault();var c=a(this),d=c.closest("tr");a("input[name=\"weight_"+d.data("itemid")+"\"]").prop("disabled",!c.prop("checked"))};b.toggleAllSelectItems=function(c){c.preventDefault();var d=a(this),e=d.closest("tr");a("."+e.data("category")+" .itemselect").prop("checked",d.data("checked"));b.checkMoveMenuState()};b.getMoveMenu=function(){return a("#menumoveafter")};b.checkMoveMenuState=function(){var c=b.getMoveMenu();if(!c.length){return!1}var d;a(".itemselect").each(function(){d=a(this).prop("checked");return!d});c.prop("disabled",!d);return d};return{enhance:b}});
+define ("core_grades/edittree_index",["jquery"],function(a){var b=function(){a("body").on("change",".weightoverride",b.toggleWeightInput);a("#menumoveafter").on("change",function(){var b=a(this).closest("form"),c=b.find("#bulkmoveinput");c.val(1);b.submit()})};b.toggleWeightInput=function(b){b.preventDefault();var c=a(this),d=c.closest("tr");a("input[name=\"weight_"+d.data("itemid")+"\"]").prop("disabled",!c.prop("checked"))};return{enhance:b}});
//# sourceMappingURL=edittree_index.min.js.map
diff --git a/grade/amd/build/edittree_index.min.js.map b/grade/amd/build/edittree_index.min.js.map
index e3569f3a6ac..26c6df9e44e 100644
--- a/grade/amd/build/edittree_index.min.js.map
+++ b/grade/amd/build/edittree_index.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/edittree_index.js"],"names":["define","$","edittree","on","checkMoveMenuState","toggleAllSelectItems","toggleWeightInput","form","closest","bulkmove","find","val","submit","e","preventDefault","node","row","data","prop","getMoveMenu","menu","length","selected","each","enhance"],"mappings":"AAuBAA,OAAM,8BAAC,CACH,QADG,CAAD,CAEH,SAASC,CAAT,CAAY,CAMX,GAAIC,CAAAA,CAAQ,CAAG,UAAW,CAEtBD,CAAC,CAAC,MAAD,CAAD,CAAUE,EAAV,CAAa,QAAb,CAAuB,yBAAvB,CAAkDD,CAAQ,CAACE,kBAA3D,EAGAH,CAAC,CAAC,MAAD,CAAD,CAAUE,EAAV,CAAa,OAAb,CAAsB,mDAAtB,CAAyED,CAAQ,CAACG,oBAAlF,EAGAJ,CAAC,CAAC,MAAD,CAAD,CAAUE,EAAV,CAAa,QAAb,CAAuB,iBAAvB,CAA0CD,CAAQ,CAACI,iBAAnD,EAGAL,CAAC,CAAC,gBAAD,CAAD,CAAoBE,EAApB,CAAuB,QAAvB,CAAiC,UAAW,CACxC,GAAII,CAAAA,CAAI,CAAGN,CAAC,CAAC,IAAD,CAAD,CAAQO,OAAR,CAAgB,MAAhB,CAAX,CACIC,CAAQ,CAAGF,CAAI,CAACG,IAAL,CAAU,gBAAV,CADf,CAGAD,CAAQ,CAACE,GAAT,CAAa,CAAb,EACAJ,CAAI,CAACK,MAAL,EACH,CAND,EASAV,CAAQ,CAACE,kBAAT,EACH,CArBD,CA8BAF,CAAQ,CAACI,iBAAT,CAA6B,SAASO,CAAT,CAAY,CACrCA,CAAC,CAACC,cAAF,GACA,GAAIC,CAAAA,CAAI,CAAGd,CAAC,CAAC,IAAD,CAAZ,CACIe,CAAG,CAAGD,CAAI,CAACP,OAAL,CAAa,IAAb,CADV,CAGAP,CAAC,CAAC,uBAAwBe,CAAG,CAACC,IAAJ,CAAS,QAAT,CAAxB,CAA6C,KAA9C,CAAD,CAAqDC,IAArD,CAA0D,UAA1D,CAAsE,CAACH,CAAI,CAACG,IAAL,CAAU,SAAV,CAAvE,CACH,CAND,CAeAhB,CAAQ,CAACG,oBAAT,CAAgC,SAASQ,CAAT,CAAY,CACxCA,CAAC,CAACC,cAAF,GAEA,GAAIC,CAAAA,CAAI,CAAGd,CAAC,CAAC,IAAD,CAAZ,CACIe,CAAG,CAAGD,CAAI,CAACP,OAAL,CAAa,IAAb,CADV,CAEAP,CAAC,CAAC,IAAMe,CAAG,CAACC,IAAJ,CAAS,UAAT,CAAN,CAA6B,cAA9B,CAAD,CAA+CC,IAA/C,CAAoD,SAApD,CAA+DH,CAAI,CAACE,IAAL,CAAU,SAAV,CAA/D,EAEAf,CAAQ,CAACE,kBAAT,EACH,CARD,CAiBAF,CAAQ,CAACiB,WAAT,CAAuB,UAAW,CAC9B,MAAOlB,CAAAA,CAAC,CAAC,gBAAD,CACX,CAFD,CAWAC,CAAQ,CAACE,kBAAT,CAA8B,UAAW,CACrC,GAAIgB,CAAAA,CAAI,CAAGlB,CAAQ,CAACiB,WAAT,EAAX,CACA,GAAI,CAACC,CAAI,CAACC,MAAV,CAAkB,CACd,QACH,CAED,GAAIC,CAAAA,CAAJ,CACArB,CAAC,CAAC,aAAD,CAAD,CAAiBsB,IAAjB,CAAsB,UAAW,CAC7BD,CAAQ,CAAGrB,CAAC,CAAC,IAAD,CAAD,CAAQiB,IAAR,CAAa,SAAb,CAAX,CAGA,MAAO,CAACI,CACX,CALD,EAOAF,CAAI,CAACF,IAAL,CAAU,UAAV,CAAsB,CAACI,CAAvB,EAEA,MAAOA,CAAAA,CACV,CAjBD,CAmBA,MAAuD,CACnDE,OAAO,CAAEtB,CAD0C,CAG1D,CAvGK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Enhance the gradebook tree setup with various facilities.\n *\n * @module core_grades/edittree_index\n * @package core_grades\n * @copyright 2016 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n], function($) {\n /**\n * Enhance the edittree functionality.\n *\n * @method edittree\n */\n var edittree = function() {\n // Watch items and toggle the move menu accordingly.\n $('body').on('change', '.itemselect.ignoredirty', edittree.checkMoveMenuState);\n\n // Watch for the 'All' and 'None' links.\n $('body').on('click', '[data-action=\"grade_edittree-index-bulkselect\"]', edittree.toggleAllSelectItems);\n\n // Watch for the weight override checkboxes.\n $('body').on('change', '.weightoverride', edittree.toggleWeightInput);\n\n // Watch changes to the bulk move menu and submit.\n $('#menumoveafter').on('change', function() {\n var form = $(this).closest('form'),\n bulkmove = form.find('#bulkmoveinput');\n\n bulkmove.val(1);\n form.submit();\n });\n\n // CHeck the initial state of the move menu.\n edittree.checkMoveMenuState();\n };\n\n /**\n * Toggle the weight input field based on its checkbox.\n *\n * @method toggleWeightInput\n * @param {EventFacade} e\n * @private\n */\n edittree.toggleWeightInput = function(e) {\n e.preventDefault();\n var node = $(this),\n row = node.closest('tr');\n\n $('input[name=\"weight_' + row.data('itemid') + '\"]').prop('disabled', !node.prop('checked'));\n };\n\n /**\n * Toggle all select boxes on or off.\n *\n * @method toggleAllSelectItems\n * @param {EventFacade} e\n * @private\n */\n edittree.toggleAllSelectItems = function(e) {\n e.preventDefault();\n\n var node = $(this),\n row = node.closest('tr');\n $('.' + row.data('category') + ' .itemselect').prop('checked', node.data('checked'));\n\n edittree.checkMoveMenuState();\n };\n\n /**\n * Get the move menu.\n *\n * @method getMoveMenu\n * @private\n * @return {jQuery}\n */\n edittree.getMoveMenu = function() {\n return $('#menumoveafter');\n };\n\n /**\n * Check whether any checkboxes are ticked.\n *\n * @method checkMoveMenuState\n * @private\n * @return {Boolean}\n */\n edittree.checkMoveMenuState = function() {\n var menu = edittree.getMoveMenu();\n if (!menu.length) {\n return false;\n }\n\n var selected;\n $('.itemselect').each(function() {\n selected = $(this).prop('checked');\n\n // Return early if any are checked.\n return !selected;\n });\n\n menu.prop('disabled', !selected);\n\n return selected;\n };\n\n return /** @alias module:core_grades/edittree_index */ {\n enhance: edittree\n };\n});\n"],"file":"edittree_index.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/edittree_index.js"],"names":["define","$","edittree","on","toggleWeightInput","form","closest","bulkmove","find","val","submit","e","preventDefault","node","row","data","prop","enhance"],"mappings":"AAuBAA,OAAM,8BAAC,CACH,QADG,CAAD,CAEH,SAASC,CAAT,CAAY,CAMX,GAAIC,CAAAA,CAAQ,CAAG,UAAW,CAEtBD,CAAC,CAAC,MAAD,CAAD,CAAUE,EAAV,CAAa,QAAb,CAAuB,iBAAvB,CAA0CD,CAAQ,CAACE,iBAAnD,EAGAH,CAAC,CAAC,gBAAD,CAAD,CAAoBE,EAApB,CAAuB,QAAvB,CAAiC,UAAW,CACxC,GAAIE,CAAAA,CAAI,CAAGJ,CAAC,CAAC,IAAD,CAAD,CAAQK,OAAR,CAAgB,MAAhB,CAAX,CACIC,CAAQ,CAAGF,CAAI,CAACG,IAAL,CAAU,gBAAV,CADf,CAGAD,CAAQ,CAACE,GAAT,CAAa,CAAb,EACAJ,CAAI,CAACK,MAAL,EACH,CAND,CAOH,CAZD,CAqBAR,CAAQ,CAACE,iBAAT,CAA6B,SAASO,CAAT,CAAY,CACrCA,CAAC,CAACC,cAAF,GACA,GAAIC,CAAAA,CAAI,CAAGZ,CAAC,CAAC,IAAD,CAAZ,CACIa,CAAG,CAAGD,CAAI,CAACP,OAAL,CAAa,IAAb,CADV,CAGAL,CAAC,CAAC,uBAAwBa,CAAG,CAACC,IAAJ,CAAS,QAAT,CAAxB,CAA6C,KAA9C,CAAD,CAAqDC,IAArD,CAA0D,UAA1D,CAAsE,CAACH,CAAI,CAACG,IAAL,CAAU,SAAV,CAAvE,CACH,CAND,CAQA,MAAuD,CACnDC,OAAO,CAAEf,CAD0C,CAG1D,CAxCK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Enhance the gradebook tree setup with various facilities.\n *\n * @module core_grades/edittree_index\n * @package core_grades\n * @copyright 2016 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n], function($) {\n /**\n * Enhance the edittree functionality.\n *\n * @method edittree\n */\n var edittree = function() {\n // Watch for the weight override checkboxes.\n $('body').on('change', '.weightoverride', edittree.toggleWeightInput);\n\n // Watch changes to the bulk move menu and submit.\n $('#menumoveafter').on('change', function() {\n var form = $(this).closest('form'),\n bulkmove = form.find('#bulkmoveinput');\n\n bulkmove.val(1);\n form.submit();\n });\n };\n\n /**\n * Toggle the weight input field based on its checkbox.\n *\n * @method toggleWeightInput\n * @param {EventFacade} e\n * @private\n */\n edittree.toggleWeightInput = function(e) {\n e.preventDefault();\n var node = $(this),\n row = node.closest('tr');\n\n $('input[name=\"weight_' + row.data('itemid') + '\"]').prop('disabled', !node.prop('checked'));\n };\n\n return /** @alias module:core_grades/edittree_index */ {\n enhance: edittree\n };\n});\n"],"file":"edittree_index.min.js"}
\ No newline at end of file
diff --git a/grade/amd/src/edittree_index.js b/grade/amd/src/edittree_index.js
index 9316f842f6b..bb9aa792b2e 100644
--- a/grade/amd/src/edittree_index.js
+++ b/grade/amd/src/edittree_index.js
@@ -30,12 +30,6 @@ define([
* @method edittree
*/
var edittree = function() {
- // Watch items and toggle the move menu accordingly.
- $('body').on('change', '.itemselect.ignoredirty', edittree.checkMoveMenuState);
-
- // Watch for the 'All' and 'None' links.
- $('body').on('click', '[data-action="grade_edittree-index-bulkselect"]', edittree.toggleAllSelectItems);
-
// Watch for the weight override checkboxes.
$('body').on('change', '.weightoverride', edittree.toggleWeightInput);
@@ -47,9 +41,6 @@ define([
bulkmove.val(1);
form.submit();
});
-
- // CHeck the initial state of the move menu.
- edittree.checkMoveMenuState();
};
/**
@@ -67,60 +58,6 @@ define([
$('input[name="weight_' + row.data('itemid') + '"]').prop('disabled', !node.prop('checked'));
};
- /**
- * Toggle all select boxes on or off.
- *
- * @method toggleAllSelectItems
- * @param {EventFacade} e
- * @private
- */
- edittree.toggleAllSelectItems = function(e) {
- e.preventDefault();
-
- var node = $(this),
- row = node.closest('tr');
- $('.' + row.data('category') + ' .itemselect').prop('checked', node.data('checked'));
-
- edittree.checkMoveMenuState();
- };
-
- /**
- * Get the move menu.
- *
- * @method getMoveMenu
- * @private
- * @return {jQuery}
- */
- edittree.getMoveMenu = function() {
- return $('#menumoveafter');
- };
-
- /**
- * Check whether any checkboxes are ticked.
- *
- * @method checkMoveMenuState
- * @private
- * @return {Boolean}
- */
- edittree.checkMoveMenuState = function() {
- var menu = edittree.getMoveMenu();
- if (!menu.length) {
- return false;
- }
-
- var selected;
- $('.itemselect').each(function() {
- selected = $(this).prop('checked');
-
- // Return early if any are checked.
- return !selected;
- });
-
- menu.prop('disabled', !selected);
-
- return selected;
- };
-
return /** @alias module:core_grades/edittree_index */ {
enhance: edittree
};
diff --git a/grade/edit/tree/lib.php b/grade/edit/tree/lib.php
index 86cf33e4942..8eac5fe2528 100644
--- a/grade/edit/tree/lib.php
+++ b/grade/edit/tree/lib.php
@@ -840,20 +840,39 @@ class grade_edit_tree_column_select extends grade_edit_tree_column {
}
public function get_category_cell($category, $levelclass, $params) {
+ global $OUTPUT;
+
if (empty($params['eid'])) {
throw new Exception('Array key (eid) missing from 3rd param of grade_edit_tree_column_select::get_category_cell($category, $levelclass, $params)');
}
- $selectall = html_writer::link('#', get_string('all'), [
- 'data-action' => 'grade_edittree-index-bulkselect',
- 'data-checked' => true,
- ]);
- $selectnone = html_writer::link('#', get_string('none'), [
- 'data-action' => 'grade_edittree-index-bulkselect',
- 'data-checked' => false,
+
+ // Get toggle group for this master checkbox.
+ $togglegroup = $this->get_checkbox_togglegroup($category);
+ // Set label for this master checkbox.
+ $masterlabel = get_string('all');
+ // Use category name if available.
+ if ($category->fullname !== '?') {
+ $masterlabel = format_string($category->fullname);
+ // Limit the displayed category name to prevent the Select column from getting too wide.
+ if (core_text::strlen($masterlabel) > 20) {
+ $masterlabel = get_string('textellipsis', 'core', core_text::substr($masterlabel, 0, 12));
+ }
+ }
+ // Build the master checkbox.
+ $mastercheckbox = new \core\output\checkbox_toggleall($togglegroup, true, [
+ 'id' => $togglegroup,
+ 'name' => $togglegroup,
+ 'value' => 1,
+ 'classes' => 'itemselect ignoredirty',
+ 'label' => $masterlabel,
+ // Consistent label to prevent the select column from resizing.
+ 'selectall' => $masterlabel,
+ 'deselectall' => $masterlabel,
+ 'labelclasses' => 'm-0',
]);
$categorycell = parent::get_category_cell($category, $levelclass, $params);
- $categorycell->text = $selectall . ' / ' . $selectnone;
+ $categorycell->text = $OUTPUT->render($mastercheckbox);
return $categorycell;
}
@@ -864,12 +883,43 @@ class grade_edit_tree_column_select extends grade_edit_tree_column {
$itemcell = parent::get_item_cell($item, $params);
if ($params['itemtype'] != 'course' && $params['itemtype'] != 'category') {
- $itemcell->text = '
- ';
+ global $OUTPUT;
+
+ // Fetch the grade item's category.
+ $category = grade_category::fetch(['id' => $item->categoryid]);
+ $togglegroup = $this->get_checkbox_togglegroup($category);
+
+ $checkboxid = 'select_' . $params['eid'];
+ $checkbox = new \core\output\checkbox_toggleall($togglegroup, false, [
+ 'id' => $checkboxid,
+ 'name' => $checkboxid,
+ 'label' => get_string('select', 'grades', $item->itemname),
+ 'labelclasses' => 'accesshide',
+ 'classes' => 'itemselect ignoredirty',
+ ]);
+ $itemcell->text = $OUTPUT->render($checkbox);
}
return $itemcell;
}
+
+ /**
+ * Generates a toggle group name for a bulk-action checkbox based on the given grade category.
+ *
+ * @param grade_category $category The grade category.
+ * @return string
+ */
+ protected function get_checkbox_togglegroup(grade_category $category): string {
+ $levels = [];
+ $categories = explode('/', $category->path);
+ foreach ($categories as $categoryid) {
+ $level = 'category' . $categoryid;
+ if (!in_array($level, $levels)) {
+ $levels[] = 'category' . $categoryid;
+ }
+ }
+ $togglegroup = implode(' ', $levels);
+
+ return $togglegroup;
+ }
}
diff --git a/grade/templates/edit_tree.mustache b/grade/templates/edit_tree.mustache
index 5c4c539cf10..5767d761ddc 100644
--- a/grade/templates/edit_tree.mustache
+++ b/grade/templates/edit_tree.mustache
@@ -17,11 +17,20 @@
{{!
@template core_grades/edit_tree
- Edit tree.
+ Edit tree template.
+
+ Context variables required for this template:
+ * actionurl - string - Form action URL.
+ * sesskey - string - The session key.
+ * notification - object - Context data for the notification.
+ * showsave - boolean - Whether to show the save changes button.
+ * showbulkmove - boolean - Whether to show the bulk move select menu.
+ * table - string - HTML content of the grade items table.
+ * bulkmoveoptions - array - Key-value pair array for the options of the the bulk move select menu element.
Example context (json):
{
- "actionurl": "https://domain.example/grade/edit/tree/index.php?id=4",
+ "actionurl": "#",
"sesskey": "fakesesskey",
"notification": "",
"table": "