diff --git a/course/classes/management_renderer.php b/course/classes/management_renderer.php index 61973b1b683..688e304925a 100644 --- a/course/classes/management_renderer.php +++ b/course/classes/management_renderer.php @@ -209,7 +209,8 @@ class core_course_management_renderer extends plugin_renderer_base { 'name' => 'bcat[]', 'value' => $category->id, 'class' => 'bulk-action-checkbox', - 'aria-label' => get_string('bulkactionselect', 'moodle', $text) + 'aria-label' => get_string('bulkactionselect', 'moodle', $text), + 'data-action' => 'select' ); if (!$category->can_resort_subcategories() && !$category->has_manage_capability()) { @@ -615,7 +616,8 @@ class core_course_management_renderer extends plugin_renderer_base { 'name' => 'bc[]', 'value' => $course->id, 'class' => 'bulk-action-checkbox', - 'aria-label' => get_string('bulkactionselect', 'moodle', $text) + 'aria-label' => get_string('bulkactionselect', 'moodle', $text), + 'data-action' => 'select' ); if (!$category->has_manage_capability()) { // Very very hardcoded here. diff --git a/course/tests/behat/behat_course.php b/course/tests/behat/behat_course.php index 3b32a9451f9..a35cdddd02c 100644 --- a/course/tests/behat/behat_course.php +++ b/course/tests/behat/behat_course.php @@ -946,7 +946,7 @@ class behat_course extends behat_base { protected function get_management_category_listing_node_by_name($name, $link = false) { $selector = "//div[@id='category-listing']//li[contains(concat(' ', normalize-space(@class), ' '), ' listitem-category ')]//a[text()='{$name}']"; if ($link === false) { - $selector .= "/ancestor::li[@data-id]"; + $selector .= "/ancestor::li[@data-id][1]"; } return $this->find('xpath', $selector); } @@ -1001,39 +1001,70 @@ class behat_course extends behat_base { } /** - * Clicks on a category checkbox in the management interface. + * Clicks on a category checkbox in the management interface, if not checked. * * @Given /^I select category "(?P[^"]*)" in the management interface$/ * @param string $name */ public function i_select_category_in_the_management_interface($name) { $node = $this->get_management_category_listing_node_by_name($name); - $node->checkField('bcat[]'); + $node = $node->findField('bcat[]'); + if (!$node->isChecked()) { + $node->click(); + } } /** - * Clicks course checkbox in the management interface. + * Clicks on a category checkbox in the management interface, if checked. + * + * @Given /^I unselect category "(?P[^"]*)" in the management interface$/ + * @param string $name + */ + public function i_unselect_category_in_the_management_interface($name) { + $node = $this->get_management_category_listing_node_by_name($name); + $node = $node->findField('bcat[]'); + if ($node->isChecked()) { + $node->click(); + } + } + + /** + * Clicks course checkbox in the management interface, if not checked. * * @Given /^I select course "(?P[^"]*)" in the management interface$/ * @param string $name */ public function i_select_course_in_the_management_interface($name) { $node = $this->get_management_course_listing_node_by_name($name); - $node->checkField('bc[]'); + $node = $node->findField('bc[]'); + if (!$node->isChecked()) { + $node->click(); + } + } + + /** + * Clicks course checkbox in the management interface, if checked. + * + * @Given /^I unselect course "(?P[^"]*)" in the management interface$/ + * @param string $name + */ + public function i_unselect_course_in_the_management_interface($name) { + $node = $this->get_management_course_listing_node_by_name($name); + $node = $node->findField('bc[]'); + if ($node->isChecked()) { + $node->click(); + } } /** * Move selected categories to top level in the management interface. * - * @Given /^I move category "(?P[^"]*)" to top level in the management interface$/ - * @param string $idnumber + * @Given /^I move category "(?P[^"]*)" to top level in the management interface$/ + * @param string $name * @return Given[] */ - public function i_move_category_to_top_level_in_the_management_interface($idnumber) { - $id = $this->get_category_id($idnumber); - $selector = sprintf('.listitem-category[data-id="%d"] > div', $id); - $node = $this->find('css', $selector); - $node->checkField('bcat[]'); + public function i_move_category_to_top_level_in_the_management_interface($name) { + $this->i_select_category_in_the_management_interface($name); return array( new Given('I select "' . coursecat::get(0)->get_formatted_name() . '" from "menumovecategoriesto"'), new Given('I press "bulkmovecategories"'), diff --git a/course/tests/behat/category_management.feature b/course/tests/behat/category_management.feature index 5b6693b75a7..baed279b412 100644 --- a/course/tests/behat/category_management.feature +++ b/course/tests/behat/category_management.feature @@ -231,7 +231,104 @@ Feature: Test category management actions And I click on category "Cat 1" in the management interface # Redirect Then I should see category "CAT3" as subcategory of "CAT1" in the management interface - And I move category "CAT3" to top level in the management interface + And I move category "Cat 3" to top level in the management interface # Redirect And I should not see category "CAT3" as subcategory of "CAT1" in the management interface Then I should see category "CAT2" as subcategory of "CAT1" in the management interface + + @javascript + Scenario: Test bulk action is shown only when some category/course is selected + Given the following "categories" exists: + | name | category | idnumber | + | Cat 1 | 0 | CAT1 | + | Cat 2 | 0 | CAT2 | + | Cat 3 | 0 | CAT3 | + And the following "courses" exists: + | category | fullname | shortname | idnumber | + | CAT3 | Course 1 | Course 1 | C1 | + | CAT3 | Course 2 | Course 2 | C2 | + + And I log in as "admin" + And I go to the courses management page + And I should see the "Course categories" management page + And I should see "Cat 1" in the "#category-listing ul.ml" "css_element" + And I should see "Cat 2" in the "#category-listing ul.ml" "css_element" + And I should see "Cat 3" in the "#category-listing ul.ml" "css_element" + And the "movecategoriesto" "select" should be disabled + And the "resortcategoriesby" "select" should be disabled + And the "resortcoursesby" "select" should be disabled + When I select "allcategories" from "selectsortby" + Then the "resortcategoriesby" "select" should be enabled + And the "resortcoursesby" "select" should be enabled + And the "movecategoriesto" "select" should be disabled + And I select category "Cat 2" in the management interface + And the "movecategoriesto" "select" should be enabled + And the "resortcategoriesby" "select" should be enabled + And the "resortcoursesby" "select" should be enabled + And I select "selectedcategories" from "selectsortby" + And the "movecategoriesto" "select" should be enabled + And the "resortcategoriesby" "select" should be enabled + And the "resortcoursesby" "select" should be enabled + And I unselect category "Cat 2" in the management interface + And the "movecategoriesto" "select" should be disabled + And the "resortcategoriesby" "select" should be disabled + And the "resortcoursesby" "select" should be disabled + And I select category "Cat 3" in the management interface + And the "movecategoriesto" "select" should be enabled + And the "resortcategoriesby" "select" should be enabled + And the "resortcoursesby" "select" should be enabled + And I select category "Cat 2" in the management interface + And the "movecategoriesto" "select" should be enabled + And the "resortcategoriesby" "select" should be enabled + And the "resortcoursesby" "select" should be enabled + And I unselect category "Cat 2" in the management interface + And I unselect category "Cat 3" in the management interface + And the "movecategoriesto" "select" should be disabled + And the "resortcategoriesby" "select" should be disabled + And the "resortcoursesby" "select" should be disabled + And I click on category "Cat 1" in the management interface + # Redirect. + And I should see the "Course categories and courses" management page + And the "movecategoriesto" "select" should be disabled + And the "resortcategoriesby" "select" should be disabled + And the "resortcoursesby" "select" should be disabled + And the "movecoursesto" "select" should be disabled + And I click on category "Cat 3" in the management interface + #Redirect + And I should see the "Course categories and courses" management page + And I should see "Course 1" in the "#course-listing ul.ml" "css_element" + And I should see "Course 2" in the "#course-listing ul.ml" "css_element" + And the "movecategoriesto" "select" should be disabled + And the "resortcategoriesby" "select" should be disabled + And the "resortcoursesby" "select" should be disabled + And the "movecoursesto" "select" should be disabled + And I select course "Course 1" in the management interface + And the "movecoursesto" "select" should be enabled + And the "movecategoriesto" "select" should be disabled + And the "resortcategoriesby" "select" should be disabled + And the "resortcoursesby" "select" should be disabled + And I select course "Course 2" in the management interface + And the "movecoursesto" "select" should be enabled + And the "movecategoriesto" "select" should be disabled + And the "resortcategoriesby" "select" should be disabled + And the "resortcoursesby" "select" should be disabled + And I select category "Cat 3" in the management interface + And the "movecoursesto" "select" should be enabled + And the "movecategoriesto" "select" should be enabled + And the "resortcategoriesby" "select" should be enabled + And the "resortcoursesby" "select" should be enabled + And I unselect course "Course 2" in the management interface + And the "movecoursesto" "select" should be enabled + And the "movecategoriesto" "select" should be enabled + And the "resortcategoriesby" "select" should be enabled + And the "resortcoursesby" "select" should be enabled + And I unselect course "Course 1" in the management interface + And the "movecoursesto" "select" should be disabled + And the "movecategoriesto" "select" should be enabled + And the "resortcategoriesby" "select" should be enabled + And the "resortcoursesby" "select" should be enabled + And I unselect category "Cat 3" in the management interface + And the "movecoursesto" "select" should be disabled + And the "movecategoriesto" "select" should be disabled + And the "resortcategoriesby" "select" should be disabled + And the "resortcoursesby" "select" should be disabled diff --git a/course/yui/build/moodle-course-management/moodle-course-management-debug.js b/course/yui/build/moodle-course-management/moodle-course-management-debug.js index 1b26a5790bf..d1ce9ef7973 100644 --- a/course/yui/build/moodle-course-management/moodle-course-management-debug.js +++ b/course/yui/build/moodle-course-management/moodle-course-management-debug.js @@ -252,6 +252,21 @@ Console.prototype = { if (!listing) { return false; } + + // Disable category bulk actions as nothing will be selected on initialise. + var menumovecatto = listing.one('#menumovecategoriesto'); + if (menumovecatto) { + menumovecatto.setAttribute('disabled', true); + } + var menuresortcategoriesby = listing.one('#menuresortcategoriesby'); + if (menuresortcategoriesby) { + menuresortcategoriesby.setAttribute('disabled', true); + } + var menuresortcoursesby = listing.one('#menuresortcoursesby'); + if (menuresortcoursesby) { + menuresortcoursesby.setAttribute('disabled', true); + } + listing.all('.listitem[data-id]').each(function(node){ this.set('categories', new Category({ node : node, @@ -261,6 +276,8 @@ Console.prototype = { }, this); if (!this.categoriesinit) { this.get('categorylisting').delegate('click', this.handleCategoryDelegation, 'a[data-action]', this); + this.get('categorylisting').delegate('click', this.handleCategoryDelegation, 'input[name="bcat[]"]', this); + this.get('categorylisting').delegate('click', this.handleBulkSortByaction, '#menuselectsortby', this); this.categoriesinit = true; Y.log(count+' categories being managed', 'info', 'moodle-course-management'); } else { @@ -281,6 +298,13 @@ Console.prototype = { if (!listing) { return false; } + + // Disable course move to bulk action as nothing will be selected on initialise. + var menumovecoursesto = listing.one('#menumovecoursesto'); + if (menumovecoursesto) { + menumovecoursesto.setAttribute('disabled', true); + } + listing.all('.listitem[data-id]').each(function(node){ this.registerCourse(new Course({ node : node, @@ -290,6 +314,7 @@ Console.prototype = { count++; }, this); listing.delegate('click', this.handleCourseDelegation, 'a[data-action]', this); + listing.delegate('click', this.handleCourseDelegation, 'input[name="bc[]"]', this); Y.log(count+' courses being managed', 'info', 'moodle-course-management'); }, @@ -342,6 +367,118 @@ Console.prototype = { } }, + /** + * Check if any course is selected. + * + * @method isCourseSelected + * @param {Node} checkboxnode Checkbox node on which action happened. + * @return bool + */ + isCourseSelected : function(checkboxnode) { + var selected = false; + + // If any course selected then show move to category select box. + if (checkboxnode && checkboxnode.get('checked')) { + selected = true; + } else { + var i, + course, + courses = this.get('courses'), + length = courses.length; + for (i = 0; i < length; i++) { + if (courses.hasOwnProperty(i)) { + course = courses[i]; + if (course.get('node').one('input[name="bc[]"]').get('checked')) { + selected = true; + break; + } + } + } + } + return selected; + }, + + /** + * Check if any category is selected. + * + * @method isCategorySelected + * @param {Node} checkboxnode Checkbox node on which action happened. + * @return bool + */ + isCategorySelected : function(checkboxnode) { + var selected = false; + + // If any category selected then show move to category select box. + if (checkboxnode && checkboxnode.get('checked')) { + selected = true; + } else { + var i, + category, + categories = this.get('categories'), + length = categories.length; + for (i = 0; i < length; i++) { + if (categories.hasOwnProperty(i)) { + category = categories[i]; + if (category.get('node').one('input[name="bcat[]"]').get('checked')) { + selected = true; + break; + } + } + } + } + return selected; + }, + + /** + * Handle bulk sort action. + * + * @method handleBulkSortByaction + * @protected + * @param {EventFacade} e + */ + handleBulkSortByaction : function(e) { + var sortcategoryby = this.get('categorylisting').one('#menuresortcategoriesby'), + sortcourseby = this.get('categorylisting').one('#menuresortcoursesby'), + sortbybutton = this.get('categorylisting').one('input[name="bulksort"]'); + sortby = e; + + if (!sortby) { + sortby = this.get('categorylisting').one('#menuselectsortby'); + } else { + if (e && e.currentTarget) { + sortby = e.currentTarget; + } + } + + // If no sortby select found then return as we can't do anything. + if (!sortby) { + return; + } + + if ((this.get('categories').length <= 1) || (!this.isCategorySelected() && + (sortby.get("options").item(sortby.get('selectedIndex')).getAttribute('value') === 'selectedcategories'))) { + if (sortcategoryby) { + sortcategoryby.setAttribute('disabled', true); + } + if (sortcourseby) { + sortcourseby.setAttribute('disabled', true); + } + if (sortbybutton) { + sortbybutton.setAttribute('disabled', true); + } + } else { + if (sortcategoryby) { + sortcategoryby.removeAttribute('disabled'); + } + if (sortcourseby) { + sortcourseby.removeAttribute('disabled'); + } + if (sortbybutton) { + sortbybutton.removeAttribute('disabled'); + } + } + }, + /** * Returns the category with the given ID. * @method getCategoryById @@ -1168,6 +1305,20 @@ Category.prototype = { e.preventDefault(); this.collapse(); break; + case 'select': + var c = this.get('console'), + movecategoryto = c.get('categorylisting').one('#menumovecategoriesto'); + // If any category is selected and there are more then one categories. + if (movecategoryto) { + if (c.isCategorySelected(e.currentTarget) && + c.get('categories').length > 1) { + movecategoryto.removeAttribute('disabled'); + } else { + movecategoryto.setAttribute('disabled', true); + } + c.handleBulkSortByaction(); + } + break; default: Y.log('Invalid AJAX action requested of managed category.', 'warn', 'moodle-course-management'); return false; @@ -1569,6 +1720,17 @@ Course.prototype = { e.halt(); managementconsole.performAjaxAction('hidecourse', args, this.hide, this); break; + case 'select': + var c = this.get('console'), + movetonode = c.get('courselisting').one('#menumovecoursesto'); + if (movetonode) { + if (c.isCourseSelected(e.currentTarget)) { + movetonode.removeAttribute('disabled'); + } else { + movetonode.setAttribute('disabled', true); + } + } + break; default: Y.log('Invalid AJAX action requested of managed course.', 'warn', 'moodle-course-management'); return false; diff --git a/course/yui/build/moodle-course-management/moodle-course-management-min.js b/course/yui/build/moodle-course-management/moodle-course-management-min.js index 6597c67058d..3db2a2995f8 100644 --- a/course/yui/build/moodle-course-management/moodle-course-management-min.js +++ b/course/yui/build/moodle-course-management/moodle-course-management-min.js @@ -1,3 +1,4 @@ -YUI.add("moodle-course-management",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}function r(e){n.superclass.constructor.apply(this,[e])}function i(){i.superclass.constructor.apply(this,arguments)}function s(){s.superclass.constructor.apply(this,arguments)}function o(){o.superclass.constructor.apply(this,arguments)}n.NAME="moodle-course-management",n.CSS_PREFIX="management",n.ATTRS={element:{setter:function(t){return typeof t=="string"&&(t=e.one("#"+t)),t}},categorylisting:{value:null},courselisting:{value:null},coursedetails:{value:null},activecategoryid:{value:null},activecourseid:{value:null},categories:{setter:function(t,n){if(e.Lang.isArray(t))return t;var r=this.get(n);return r.push(t),r},value:[]},courses:{validator:function(t){return e.Lang.isArray(t)},value:[]},page:{getter:function(e,t){return e===null&&(e=this.get("element").getData(t),this.set(t,e)),e},value:null},totalpages:{getter:function(e,t){return e===null&&(e=this.get("element").getData(t),this.set(t,e)),e},value:null},totalcourses:{getter:function(e,t){return e===null&&(e=this.get("element").getData(t),this.set(t,e)),e},value:null},ajaxurl:{getter:function(e){return e===null&&(e=M.cfg.wwwroot+"/course/ajax/management.php"),e},value:null},dragdrop:{value:null}},n.prototype={categoriesinit:!1,initializer:function(){this.set("element","coursecat-management");var e=this.get("element"),t=e.one("#category-listing"),n=e.one("#course-listing"),i=null,s=null;t&&(i=t.one('.listitem[data-selected="1"]')),n&&(s=n.one('.listitem[data-selected="1"]')),this.set("categorylisting",t),this.set("courselisting",n),this.set("coursedetails",e.one("#course-detail")),i&&this.set("activecategoryid",i.getData("id")),s&&this.set("activecourseid",s.getData("id")),this.initialiseCategories(t),this.initialiseCourses(),n&&this.set("dragdrop",new r({console:this}))},initialiseCategories:function(e){var t=0;if(!e)return!1;e.all(".listitem[data-id]").each(function(e){this.set("categories",new s({node:e,console:this})),t++},this),this.categoriesinit||(this.get("categorylisting").delegate("click",this.handleCategoryDelegation,"a[data-action]",this),this.categoriesinit=!0)},initialiseCourses:function(){var e=this.getCategoryById(this.get("activecategoryid")),t=this.get("courselisting"),n=0;if(!t)return!1;t.all(".listitem[data-id]").each(function(t){this.registerCourse(new o({node:t,console:this,category:e})),n++},this),t.delegate("click",this.handleCourseDelegation,"a[data-action]",this)},registerCourse:function(e){var t=this.get("courses");t.push(e),this.set("courses",t)},handleCourseDelegation:function(e){var t=e.currentTarget,n=t.getData("action"),r=t.ancestor(".listitem").getData("id"),i=this.getCourseById(r);i&&i.handle(n,e)},handleCategoryDelegation:function(e){var t=e.currentTarget,n=t.getData("action"),r=t.ancestor(".listitem").getData("id"),i=this.getCategoryById(r);i&&i.handle(n,e)},getCategoryById:function(e){var t,n,r=this.get("categories"),i=r.length;for(t=0;t .course-listing"),s=r?r.one("ul.ml"):null,o=i?i.one("ul.ml"):null,u=i?i.getData("canmoveoutof"):!1,a=u?n:o;if(!o)return!1;o.all("> li").each(function(e){this.initCourseListing(e,a)},this),o.setData("dd",new e.DD.Drop({node:o})),u&&s&&s.all("li > div").each(function(e){this.initCategoryListitem(e)},this),e.DD.DDM.on("drag:start",this.dragStart,this),e.DD.DDM.on("drag:end",this.dragEnd,this),e.DD.DDM.on("drag:drag",this.dragDrag,this),e.DD.DDM.on("drop:over",this.dropOver,this),e.DD.DDM.on("drop:enter",this.dropEnter,this),e.DD.DDM.on("drop:exit",this.dropExit,this),e.DD.DDM.on("drop:hit",this.dropHit,this)},initCourseListing:function(t,n){t.setData("dd",(new e.DD.Drag({node:t,target:{padding:"0 0 0 20"}})).addHandle(".drag-handle").plug(e.Plugin.DDProxy,{moveOnEnd:!1,borderStyle:!1}).plug(e.Plugin.DDConstrained,{constrain2node:n}))},initCategoryListitem:function(t){t.setData("dd",new e.DD.Drop({node:t}))},dragStart:function(e){var t=e.target,n=t.get("node"),r=t.get("dragNode");n.addClass("course-being-dragged"),r.addClass("course-being-dragged-proxy").set("innerHTML",n.one("a.coursename").get("innerHTML")),this.previoussibling=n.get("previousSibling")},dragEnd:function(e){var t=e.target,n=t.get("node");n.removeClass("course-being-dragged"),this.get("console").get("element").all("#category-listing li.highlight").removeClass("highlight")},dragDrag:function(e){var t=e.target.lastXY[1];t div a.action-moveup"),o=i.one(" > div a.action-movedown");if(!a||!o)s=i.one(" > div a.action-moveup"),f=u.one(" > div a.action-movedown"),!a&&!o?(l=e.Node.create(' '),f.replace(l),s.replace(f),l.replace(s),l.destroy()):o||s.insert(f,"after");s=i.one(" > div a.action-moveup"),s?s.focus():(o=i.one(" > div a.action-movedown"),o&&o.focus()),this.updated(!0)}else window.location.reload()},movedown:function(t,n,r){var i,s,o,u,a,f,l,c=this.checkAjaxResponse(t,n,r);if(c===!1)return!1;i=this.get("node"),s=i.next(".listitem");if(s){i.insert(s,"before"),f=s.one(" > div a.action-movedown"),o=i.one(" > div a.action-moveup");if(!f||!o)a=s.one(" > div a.action-moveup"),u=i.one(" > div a.action-movedown"),!f&&!o?(l=e.Node.create(' '),a.replace(l),u.replace(a),l.replace(u),l.destroy()):o||u.insert(a,"before");u=i.one(" > div a.action-movedown"),u?u.focus():(o=i.one(" > div a.action-moveup"),o&&o.focus()),this.updated(!0)}else window.location.reload()},show:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i;if(r===!1)return!1;this.markVisible(),i=this.get("node").one("a[data-action=hide]"),i&&i.focus(),this.updated()},markVisible:function(){return this.get("node").setAttribute("data-visible","1"),!0},hide:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i;if(r===!1)return!1;this.markHidden(),i=this.get("node").one("a[data-action=show]"),i&&i.focus(),this.updated()},markHidden:function(){return this.get("node").setAttribute("data-visible","0"),!0},updated:function(e){e&&this.highlight()},highlight:function(){var e=this.get("node");e.siblings(".highlight").removeClass("highlight"),e.addClass("highlight"),this.highlighttimeout&&window.clearTimeout(this.highlighttimeout),this.highlighttimeout=window.setTimeout(function(){e.removeClass("highlight")},2500)}},e.extend(i,e.Base,i.prototype),s.NAME="moodle-course-management-category",s.CSS_PREFIX="management-category",s.ATTRS={categoryid:{getter:function(e,t){return e===null&&(e=this.get("node").getData("id"),this.set(t,e)),e},value:null,writeOnce:!0},selected:{getter:function(e,t){return e===null&&(e=this.get("node").getData(t),e===null&&(e=!1),this.set(t,e)),e},value:null},courses:{validator:function(t){return e.Lang.isArray(t)},value:[]}},s.prototype={initializer:function(){this.set("itemname","category")},getName:function(){return this.get("node").one("a.categoryname").get("innerHTML")},registerCourse:function(e){var t=this.get("courses");t.push(e),this.set("courses",t)},handle:function(e,t){var n={categoryid:this.get("categoryid")},r=this.get("console").get("activecategoryid");r&&r!==n.categoryid&&(n.selectedcategory=r);switch(e){case"moveup":t.preventDefault(),this.get("console").performAjaxAction("movecategoryup",n,this.moveup,this);break;case"movedown":t.preventDefault(),this.get("console").performAjaxAction("movecategorydown",n,this.movedown,this);break;case"show":t.preventDefault(),this.get("console").performAjaxAction("showcategory",n,this.show,this);break;case"hide":t.preventDefault(),this.get("console").performAjaxAction("hidecategory",n,this.hide,this);break;case"expand":t.preventDefault(),this.get("node").getData("expanded")==="0"&&(this.get("node").setAttribute("data-expanded","1").setData("expanded","true"),this.get("console").performAjaxAction("getsubcategorieshtml",n,this.loadSubcategories,this)),this.expand();break;case"collapse":t.preventDefault(),this.collapse();break;default:return!1}},expand:function(){var e=this.get("node"),t=e.one("a[data-action=expand]"),n=e.one("ul[role=group]");e.removeClass("collapsed").setAttribute("aria-expanded","true"),t.setAttribute("data-action","collapse").setAttrs({title:M.util.get_string("collapsecategory","moodle",this.getName())}).one("img").setAttrs({src:M.util.image_url("t/switch_minus","moodle"),alt:M.util.get_string("collapse","moodle")}),n&&n.setAttribute("aria-hidden","false"),this.get("console").performAjaxAction("expandcategory",{categoryid:this.get("categoryid")},null,this)},collapse:function(){var e=this.get("node"),t=e.one("a[data-action=collapse]"),n=e.one("ul[role=group]");e.addClass("collapsed").setAttribute("aria-expanded","false"),t.setAttribute("data-action","expand").setAttrs({title:M.util.get_string("expandcategory","moodle",this.getName())}).one("img").setAttrs({src:M.util.image_url("t/switch_plus","moodle"),alt:M.util.get_string("expand","moodle")}),n&&n.setAttribute("aria-hidden","true"),this.get("console").performAjaxAction("collapsecategory",{categoryid:this.get("categoryid")},null,this)},loadSubcategories:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i=this.get("node"),s=this.get("console"),o,u;return r===!1?!1:(i.append(r.html),s.initialiseCategories -(i),M.core&&M.core.actionmenu&&M.core.actionmenu.newDOMNode&&M.core.actionmenu.newDOMNode(i),o=i.one("ul[role=group]"),u=i.one("a[data-action=collapse]"),o&&u&&u.setAttribute("aria-controls",o.generateID()),!0)},moveCourseTo:function(t){var n=this;e.use("moodle-core-notification-confirm",function(){var e=new M.core.confirm({title:M.util.get_string("confirm","moodle"),question:M.util.get_string("confirmcoursemove","moodle",{course:t.getName(),category:n.getName()}),yesLabel:M.util.get_string("move","moodle"),noLabel:M.util.get_string("cancel","moodle")});e.on("complete-yes",function(){e.hide(),e.destroy(),this.get("console").performAjaxAction("movecourseintocategory",{categoryid:this.get("categoryid"),courseid:t.get("courseid")},this.completeMoveCourse,this)},n),e.show()})},completeMoveCourse:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i=this.get("console"),s,o,u;return r===!1?!1:(o=i.getCourseById(n.courseid),o?(this.highlight(),o&&(r.paginationtotals&&(u=i.get("courselisting").one(".listing-pagination-totals"),u&&u.set("innerHTML",r.paginationtotals)),r.totalcatcourses!=="undefined"&&(u=this.get("node").one(".course-count span"),u&&u.set("innerHTML",u.get("innerHTML").replace(/^\d+/,r.totalcatcourses))),typeof r.fromcatcoursecount!="undefined"&&(s=i.get("activecategoryid"),s=i.getCategoryById(s),s&&(u=s.get("node").one(".course-count span"),u&&u.set("innerHTML",u.get("innerHTML").replace(/^\d+/,r.fromcatcoursecount)))),o.remove()),!0):!1)},show:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i;if(r===!1)return!1;this.markVisible(),i=this.get("node").one("a[data-action=hide]"),i&&i.focus(),r.categoryvisibility&&this.updateChildVisibility(r.categoryvisibility),r.coursevisibility&&this.updateCourseVisiblity(r.coursevisibility),this.updated()},hide:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i;if(r===!1)return!1;this.markHidden(),i=this.get("node").one("a[data-action=show]"),i&&i.focus(),r.categoryvisibility&&this.updateChildVisibility(r.categoryvisibility),r.coursevisibility&&this.updateCourseVisiblity(r.coursevisibility),this.updated()},updateCourseVisiblity:function(e){var t=this.get("console"),n,r;try{for(n in e)typeof e[n]=="object"&&(r=t.getCourseById(e[n].id),r&&(e[n].visible==="1"?r.markVisible():r.markHidden()))}catch(i){}return this},updateChildVisibility:function(e){var t=this.get("console"),n,r;try{for(n in e)typeof e[n]=="object"&&(r=t.getCategoryById(e[n].id),r&&(e[n].visible==="1"?r.markVisible():r.markHidden()))}catch(i){}return this}},e.extend(s,i,s.prototype),o.NAME="moodle-course-management-course",o.CSS_PREFIX="management-course",o.ATTRS={courseid:{},selected:{getter:function(e,t){return e===null&&(e=this.get("node").getData(t),this.set(t,e)),e},value:null},node:{},console:{writeOnce:"initOnly"},category:{writeOnce:"initOnly"}},o.prototype={initializer:function(){var e=this.get("node"),t=this.get("category");this.set("courseid",e.getData("id")),t&&t.registerCourse&&t.registerCourse(this),this.set("itemname","course")},getName:function(){return this.get("node").one("a.coursename").get("innerHTML")},handle:function(e,t){var n=this.get("console"),r={courseid:this.get("courseid")};switch(e){case"moveup":t.halt(),n.performAjaxAction("movecourseup",r,this.moveup,this);break;case"movedown":t.halt(),n.performAjaxAction("movecoursedown",r,this.movedown,this);break;case"show":t.halt(),n.performAjaxAction("showcourse",r,this.show,this);break;case"hide":t.halt(),n.performAjaxAction("hidecourse",r,this.hide,this);break;default:return!1}},remove:function(){this.get("console").removeCourseById(this.get("courseid")),this.get("node").remove()},moveAfter:function(e,t){var n=this.get("console"),r={courseid:this.get("courseid"),moveafter:e,previous:t};n.performAjaxAction("movecourseafter",r,this.moveAfterResponse,this)},moveAfterResponse:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i=this.get("node"),s;if(r===!1)return s=i.ancestor("ul").one("li[data-id="+n.previous+"]"),s?s.insertAfter(i,"after"):i.ancestor("ul").one("li").insert(i,"before"),!1;this.highlight()}},e.extend(o,i,o.prototype)},"@VERSION@",{requires:["base","node","io-base","moodle-core-notification-exception","json-parse","dd-constrain","dd-proxy","dd-drop","dd-delegate","node-event-delegate"]}); +YUI.add("moodle-course-management",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}function r(e){n.superclass.constructor.apply(this,[e])}function i(){i.superclass.constructor.apply(this,arguments)}function s(){s.superclass.constructor.apply(this,arguments)}function o(){o.superclass.constructor.apply(this,arguments)}n.NAME="moodle-course-management",n.CSS_PREFIX="management",n.ATTRS={element:{setter:function(t){return typeof t=="string"&&(t=e.one("#"+t)),t}},categorylisting:{value:null},courselisting:{value:null},coursedetails:{value:null},activecategoryid:{value:null},activecourseid:{value:null},categories:{setter:function(t,n){if(e.Lang.isArray(t))return t;var r=this.get(n);return r.push(t),r},value:[]},courses:{validator:function(t){return e.Lang.isArray(t)},value:[]},page:{getter:function(e,t){return e===null&&(e=this.get("element").getData(t),this.set(t,e)),e},value:null},totalpages:{getter:function(e,t){return e===null&&(e=this.get("element").getData(t),this.set(t,e)),e},value:null},totalcourses:{getter:function(e,t){return e===null&&(e=this.get("element").getData(t),this.set(t,e)),e},value:null},ajaxurl:{getter:function(e){return e===null&&(e=M.cfg.wwwroot+"/course/ajax/management.php"),e},value:null},dragdrop:{value:null}},n.prototype={categoriesinit:!1,initializer:function(){this.set("element","coursecat-management");var e=this.get("element"),t=e.one("#category-listing"),n=e.one("#course-listing"),i=null,s=null;t&&(i=t.one('.listitem[data-selected="1"]')),n&&(s=n.one('.listitem[data-selected="1"]')),this.set("categorylisting",t),this.set("courselisting",n),this.set("coursedetails",e.one("#course-detail")),i&&this.set("activecategoryid",i.getData("id")),s&&this.set("activecourseid",s.getData("id")),this.initialiseCategories(t),this.initialiseCourses(),n&&this.set("dragdrop",new r({console:this}))},initialiseCategories:function(e){var t=0;if(!e)return!1;var n=e.one("#menumovecategoriesto");n&&n.setAttribute("disabled",!0);var r=e.one("#menuresortcategoriesby");r&&r.setAttribute("disabled",!0);var i=e.one("#menuresortcoursesby");i&&i.setAttribute("disabled",!0),e.all(".listitem[data-id]").each(function(e){this.set("categories",new s({node:e,console:this})),t++},this),this.categoriesinit||(this.get("categorylisting").delegate("click",this.handleCategoryDelegation,"a[data-action]",this),this.get("categorylisting").delegate("click",this.handleCategoryDelegation,'input[name="bcat[]"]',this),this.get("categorylisting").delegate("click",this.handleBulkSortByaction,"#menuselectsortby",this),this.categoriesinit=!0)},initialiseCourses:function(){var e=this.getCategoryById(this.get("activecategoryid")),t=this.get("courselisting"),n=0;if(!t)return!1;var r=t.one("#menumovecoursesto");r&&r.setAttribute("disabled",!0),t.all(".listitem[data-id]").each(function(t){this.registerCourse(new o({node:t,console:this,category:e})),n++},this),t.delegate("click",this.handleCourseDelegation,"a[data-action]",this),t.delegate("click",this.handleCourseDelegation,'input[name="bc[]"]',this)},registerCourse:function(e){var t=this.get("courses");t.push(e),this.set("courses",t)},handleCourseDelegation:function(e){var t=e.currentTarget,n=t.getData("action"),r=t.ancestor(".listitem").getData("id"),i=this.getCourseById(r);i&&i.handle(n,e)},handleCategoryDelegation:function(e){var t=e.currentTarget,n=t.getData("action"),r=t.ancestor(".listitem").getData("id"),i=this.getCategoryById(r);i&&i.handle(n,e)},isCourseSelected:function(e){var t=!1;if(e&&e.get("checked"))t=!0;else{var n,r,i=this.get("courses"),s=i.length;for(n=0;n .course-listing"),s=r?r.one("ul.ml"):null,o=i?i.one("ul.ml"):null,u=i?i.getData("canmoveoutof"):!1,a=u?n:o;if(!o)return!1;o.all("> li").each +(function(e){this.initCourseListing(e,a)},this),o.setData("dd",new e.DD.Drop({node:o})),u&&s&&s.all("li > div").each(function(e){this.initCategoryListitem(e)},this),e.DD.DDM.on("drag:start",this.dragStart,this),e.DD.DDM.on("drag:end",this.dragEnd,this),e.DD.DDM.on("drag:drag",this.dragDrag,this),e.DD.DDM.on("drop:over",this.dropOver,this),e.DD.DDM.on("drop:enter",this.dropEnter,this),e.DD.DDM.on("drop:exit",this.dropExit,this),e.DD.DDM.on("drop:hit",this.dropHit,this)},initCourseListing:function(t,n){t.setData("dd",(new e.DD.Drag({node:t,target:{padding:"0 0 0 20"}})).addHandle(".drag-handle").plug(e.Plugin.DDProxy,{moveOnEnd:!1,borderStyle:!1}).plug(e.Plugin.DDConstrained,{constrain2node:n}))},initCategoryListitem:function(t){t.setData("dd",new e.DD.Drop({node:t}))},dragStart:function(e){var t=e.target,n=t.get("node"),r=t.get("dragNode");n.addClass("course-being-dragged"),r.addClass("course-being-dragged-proxy").set("innerHTML",n.one("a.coursename").get("innerHTML")),this.previoussibling=n.get("previousSibling")},dragEnd:function(e){var t=e.target,n=t.get("node");n.removeClass("course-being-dragged"),this.get("console").get("element").all("#category-listing li.highlight").removeClass("highlight")},dragDrag:function(e){var t=e.target.lastXY[1];t div a.action-moveup"),o=i.one(" > div a.action-movedown");if(!a||!o)s=i.one(" > div a.action-moveup"),f=u.one(" > div a.action-movedown"),!a&&!o?(l=e.Node.create(' '),f.replace(l),s.replace(f),l.replace(s),l.destroy()):o||s.insert(f,"after");s=i.one(" > div a.action-moveup"),s?s.focus():(o=i.one(" > div a.action-movedown"),o&&o.focus()),this.updated(!0)}else window.location.reload()},movedown:function(t,n,r){var i,s,o,u,a,f,l,c=this.checkAjaxResponse(t,n,r);if(c===!1)return!1;i=this.get("node"),s=i.next(".listitem");if(s){i.insert(s,"before"),f=s.one(" > div a.action-movedown"),o=i.one(" > div a.action-moveup");if(!f||!o)a=s.one(" > div a.action-moveup"),u=i.one(" > div a.action-movedown"),!f&&!o?(l=e.Node.create(' '),a.replace(l),u.replace(a),l.replace(u),l.destroy()):o||u.insert(a,"before");u=i.one(" > div a.action-movedown"),u?u.focus():(o=i.one(" > div a.action-moveup"),o&&o.focus()),this.updated(!0)}else window.location.reload()},show:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i;if(r===!1)return!1;this.markVisible(),i=this.get("node").one("a[data-action=hide]"),i&&i.focus(),this.updated()},markVisible:function(){return this.get("node").setAttribute("data-visible","1"),!0},hide:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i;if(r===!1)return!1;this.markHidden(),i=this.get("node").one("a[data-action=show]"),i&&i.focus(),this.updated()},markHidden:function(){return this.get("node").setAttribute("data-visible","0"),!0},updated:function(e){e&&this.highlight()},highlight:function(){var e=this.get("node");e.siblings(".highlight").removeClass("highlight"),e.addClass("highlight"),this.highlighttimeout&&window.clearTimeout(this.highlighttimeout),this.highlighttimeout=window.setTimeout(function(){e.removeClass("highlight")},2500)}},e.extend(i,e.Base,i.prototype),s.NAME="moodle-course-management-category",s.CSS_PREFIX="management-category",s.ATTRS={categoryid:{getter:function(e,t){return e===null&&(e=this.get("node").getData("id"),this.set(t,e)),e},value:null,writeOnce:!0},selected:{getter:function(e,t){return e===null&&(e=this.get("node").getData(t),e===null&&(e=!1),this.set(t,e)),e},value:null},courses:{validator:function(t){return e.Lang.isArray(t)},value:[]}},s.prototype={initializer:function(){this.set("itemname","category")},getName:function(){return this.get("node").one("a.categoryname").get("innerHTML")},registerCourse:function(e){var t=this.get("courses");t.push(e),this.set("courses",t)},handle:function(e,t){var n={categoryid:this.get("categoryid")},r=this.get("console").get("activecategoryid");r&&r!==n.categoryid&&(n.selectedcategory=r);switch(e){case"moveup":t.preventDefault(),this.get("console").performAjaxAction("movecategoryup",n,this.moveup,this);break;case"movedown":t.preventDefault(),this.get("console").performAjaxAction("movecategorydown",n,this.movedown,this);break;case"show":t.preventDefault(), +this.get("console").performAjaxAction("showcategory",n,this.show,this);break;case"hide":t.preventDefault(),this.get("console").performAjaxAction("hidecategory",n,this.hide,this);break;case"expand":t.preventDefault(),this.get("node").getData("expanded")==="0"&&(this.get("node").setAttribute("data-expanded","1").setData("expanded","true"),this.get("console").performAjaxAction("getsubcategorieshtml",n,this.loadSubcategories,this)),this.expand();break;case"collapse":t.preventDefault(),this.collapse();break;case"select":var i=this.get("console"),s=i.get("categorylisting").one("#menumovecategoriesto");s&&(i.isCategorySelected(t.currentTarget)&&i.get("categories").length>1?s.removeAttribute("disabled"):s.setAttribute("disabled",!0),i.handleBulkSortByaction());break;default:return!1}},expand:function(){var e=this.get("node"),t=e.one("a[data-action=expand]"),n=e.one("ul[role=group]");e.removeClass("collapsed").setAttribute("aria-expanded","true"),t.setAttribute("data-action","collapse").setAttrs({title:M.util.get_string("collapsecategory","moodle",this.getName())}).one("img").setAttrs({src:M.util.image_url("t/switch_minus","moodle"),alt:M.util.get_string("collapse","moodle")}),n&&n.setAttribute("aria-hidden","false"),this.get("console").performAjaxAction("expandcategory",{categoryid:this.get("categoryid")},null,this)},collapse:function(){var e=this.get("node"),t=e.one("a[data-action=collapse]"),n=e.one("ul[role=group]");e.addClass("collapsed").setAttribute("aria-expanded","false"),t.setAttribute("data-action","expand").setAttrs({title:M.util.get_string("expandcategory","moodle",this.getName())}).one("img").setAttrs({src:M.util.image_url("t/switch_plus","moodle"),alt:M.util.get_string("expand","moodle")}),n&&n.setAttribute("aria-hidden","true"),this.get("console").performAjaxAction("collapsecategory",{categoryid:this.get("categoryid")},null,this)},loadSubcategories:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i=this.get("node"),s=this.get("console"),o,u;return r===!1?!1:(i.append(r.html),s.initialiseCategories(i),M.core&&M.core.actionmenu&&M.core.actionmenu.newDOMNode&&M.core.actionmenu.newDOMNode(i),o=i.one("ul[role=group]"),u=i.one("a[data-action=collapse]"),o&&u&&u.setAttribute("aria-controls",o.generateID()),!0)},moveCourseTo:function(t){var n=this;e.use("moodle-core-notification-confirm",function(){var e=new M.core.confirm({title:M.util.get_string("confirm","moodle"),question:M.util.get_string("confirmcoursemove","moodle",{course:t.getName(),category:n.getName()}),yesLabel:M.util.get_string("move","moodle"),noLabel:M.util.get_string("cancel","moodle")});e.on("complete-yes",function(){e.hide(),e.destroy(),this.get("console").performAjaxAction("movecourseintocategory",{categoryid:this.get("categoryid"),courseid:t.get("courseid")},this.completeMoveCourse,this)},n),e.show()})},completeMoveCourse:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i=this.get("console"),s,o,u;return r===!1?!1:(o=i.getCourseById(n.courseid),o?(this.highlight(),o&&(r.paginationtotals&&(u=i.get("courselisting").one(".listing-pagination-totals"),u&&u.set("innerHTML",r.paginationtotals)),r.totalcatcourses!=="undefined"&&(u=this.get("node").one(".course-count span"),u&&u.set("innerHTML",u.get("innerHTML").replace(/^\d+/,r.totalcatcourses))),typeof r.fromcatcoursecount!="undefined"&&(s=i.get("activecategoryid"),s=i.getCategoryById(s),s&&(u=s.get("node").one(".course-count span"),u&&u.set("innerHTML",u.get("innerHTML").replace(/^\d+/,r.fromcatcoursecount)))),o.remove()),!0):!1)},show:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i;if(r===!1)return!1;this.markVisible(),i=this.get("node").one("a[data-action=hide]"),i&&i.focus(),r.categoryvisibility&&this.updateChildVisibility(r.categoryvisibility),r.coursevisibility&&this.updateCourseVisiblity(r.coursevisibility),this.updated()},hide:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i;if(r===!1)return!1;this.markHidden(),i=this.get("node").one("a[data-action=show]"),i&&i.focus(),r.categoryvisibility&&this.updateChildVisibility(r.categoryvisibility),r.coursevisibility&&this.updateCourseVisiblity(r.coursevisibility),this.updated()},updateCourseVisiblity:function(e){var t=this.get("console"),n,r;try{for(n in e)typeof e[n]=="object"&&(r=t.getCourseById(e[n].id),r&&(e[n].visible==="1"?r.markVisible():r.markHidden()))}catch(i){}return this},updateChildVisibility:function(e){var t=this.get("console"),n,r;try{for(n in e)typeof e[n]=="object"&&(r=t.getCategoryById(e[n].id),r&&(e[n].visible==="1"?r.markVisible():r.markHidden()))}catch(i){}return this}},e.extend(s,i,s.prototype),o.NAME="moodle-course-management-course",o.CSS_PREFIX="management-course",o.ATTRS={courseid:{},selected:{getter:function(e,t){return e===null&&(e=this.get("node").getData(t),this.set(t,e)),e},value:null},node:{},console:{writeOnce:"initOnly"},category:{writeOnce:"initOnly"}},o.prototype={initializer:function(){var e=this.get("node"),t=this.get("category");this.set("courseid",e.getData("id")),t&&t.registerCourse&&t.registerCourse(this),this.set("itemname","course")},getName:function(){return this.get("node").one("a.coursename").get("innerHTML")},handle:function(e,t){var n=this.get("console"),r={courseid:this.get("courseid")};switch(e){case"moveup":t.halt(),n.performAjaxAction("movecourseup",r,this.moveup,this);break;case"movedown":t.halt(),n.performAjaxAction("movecoursedown",r,this.movedown,this);break;case"show":t.halt(),n.performAjaxAction("showcourse",r,this.show,this);break;case"hide":t.halt(),n.performAjaxAction("hidecourse",r,this.hide,this);break;case"select":var i=this.get("console"),s=i.get("courselisting").one("#menumovecoursesto");s&&(i.isCourseSelected(t.currentTarget)?s.removeAttribute("disabled"):s.setAttribute("disabled",!0));break;default:return!1}},remove:function(){this.get("console").removeCourseById(this.get("courseid")),this.get("node").remove()},moveAfter:function(e,t){var n=this.get("console"),r={courseid:this.get("courseid"),moveafter:e,previous:t};n.performAjaxAction("movecourseafter" +,r,this.moveAfterResponse,this)},moveAfterResponse:function(e,t,n){var r=this.checkAjaxResponse(e,t,n),i=this.get("node"),s;if(r===!1)return s=i.ancestor("ul").one("li[data-id="+n.previous+"]"),s?s.insertAfter(i,"after"):i.ancestor("ul").one("li").insert(i,"before"),!1;this.highlight()}},e.extend(o,i,o.prototype)},"@VERSION@",{requires:["base","node","io-base","moodle-core-notification-exception","json-parse","dd-constrain","dd-proxy","dd-drop","dd-delegate","node-event-delegate"]}); diff --git a/course/yui/build/moodle-course-management/moodle-course-management.js b/course/yui/build/moodle-course-management/moodle-course-management.js index 5d78e2dc5f6..9b29145c33b 100644 --- a/course/yui/build/moodle-course-management/moodle-course-management.js +++ b/course/yui/build/moodle-course-management/moodle-course-management.js @@ -251,6 +251,21 @@ Console.prototype = { if (!listing) { return false; } + + // Disable category bulk actions as nothing will be selected on initialise. + var menumovecatto = listing.one('#menumovecategoriesto'); + if (menumovecatto) { + menumovecatto.setAttribute('disabled', true); + } + var menuresortcategoriesby = listing.one('#menuresortcategoriesby'); + if (menuresortcategoriesby) { + menuresortcategoriesby.setAttribute('disabled', true); + } + var menuresortcoursesby = listing.one('#menuresortcoursesby'); + if (menuresortcoursesby) { + menuresortcoursesby.setAttribute('disabled', true); + } + listing.all('.listitem[data-id]').each(function(node){ this.set('categories', new Category({ node : node, @@ -260,6 +275,8 @@ Console.prototype = { }, this); if (!this.categoriesinit) { this.get('categorylisting').delegate('click', this.handleCategoryDelegation, 'a[data-action]', this); + this.get('categorylisting').delegate('click', this.handleCategoryDelegation, 'input[name="bcat[]"]', this); + this.get('categorylisting').delegate('click', this.handleBulkSortByaction, '#menuselectsortby', this); this.categoriesinit = true; } else { } @@ -278,6 +295,13 @@ Console.prototype = { if (!listing) { return false; } + + // Disable course move to bulk action as nothing will be selected on initialise. + var menumovecoursesto = listing.one('#menumovecoursesto'); + if (menumovecoursesto) { + menumovecoursesto.setAttribute('disabled', true); + } + listing.all('.listitem[data-id]').each(function(node){ this.registerCourse(new Course({ node : node, @@ -287,6 +311,7 @@ Console.prototype = { count++; }, this); listing.delegate('click', this.handleCourseDelegation, 'a[data-action]', this); + listing.delegate('click', this.handleCourseDelegation, 'input[name="bc[]"]', this); }, /** @@ -336,6 +361,118 @@ Console.prototype = { } }, + /** + * Check if any course is selected. + * + * @method isCourseSelected + * @param {Node} checkboxnode Checkbox node on which action happened. + * @return bool + */ + isCourseSelected : function(checkboxnode) { + var selected = false; + + // If any course selected then show move to category select box. + if (checkboxnode && checkboxnode.get('checked')) { + selected = true; + } else { + var i, + course, + courses = this.get('courses'), + length = courses.length; + for (i = 0; i < length; i++) { + if (courses.hasOwnProperty(i)) { + course = courses[i]; + if (course.get('node').one('input[name="bc[]"]').get('checked')) { + selected = true; + break; + } + } + } + } + return selected; + }, + + /** + * Check if any category is selected. + * + * @method isCategorySelected + * @param {Node} checkboxnode Checkbox node on which action happened. + * @return bool + */ + isCategorySelected : function(checkboxnode) { + var selected = false; + + // If any category selected then show move to category select box. + if (checkboxnode && checkboxnode.get('checked')) { + selected = true; + } else { + var i, + category, + categories = this.get('categories'), + length = categories.length; + for (i = 0; i < length; i++) { + if (categories.hasOwnProperty(i)) { + category = categories[i]; + if (category.get('node').one('input[name="bcat[]"]').get('checked')) { + selected = true; + break; + } + } + } + } + return selected; + }, + + /** + * Handle bulk sort action. + * + * @method handleBulkSortByaction + * @protected + * @param {EventFacade} e + */ + handleBulkSortByaction : function(e) { + var sortcategoryby = this.get('categorylisting').one('#menuresortcategoriesby'), + sortcourseby = this.get('categorylisting').one('#menuresortcoursesby'), + sortbybutton = this.get('categorylisting').one('input[name="bulksort"]'); + sortby = e; + + if (!sortby) { + sortby = this.get('categorylisting').one('#menuselectsortby'); + } else { + if (e && e.currentTarget) { + sortby = e.currentTarget; + } + } + + // If no sortby select found then return as we can't do anything. + if (!sortby) { + return; + } + + if ((this.get('categories').length <= 1) || (!this.isCategorySelected() && + (sortby.get("options").item(sortby.get('selectedIndex')).getAttribute('value') === 'selectedcategories'))) { + if (sortcategoryby) { + sortcategoryby.setAttribute('disabled', true); + } + if (sortcourseby) { + sortcourseby.setAttribute('disabled', true); + } + if (sortbybutton) { + sortbybutton.setAttribute('disabled', true); + } + } else { + if (sortcategoryby) { + sortcategoryby.removeAttribute('disabled'); + } + if (sortcourseby) { + sortcourseby.removeAttribute('disabled'); + } + if (sortbybutton) { + sortbybutton.removeAttribute('disabled'); + } + } + }, + /** * Returns the category with the given ID. * @method getCategoryById @@ -1144,6 +1281,20 @@ Category.prototype = { e.preventDefault(); this.collapse(); break; + case 'select': + var c = this.get('console'), + movecategoryto = c.get('categorylisting').one('#menumovecategoriesto'); + // If any category is selected and there are more then one categories. + if (movecategoryto) { + if (c.isCategorySelected(e.currentTarget) && + c.get('categories').length > 1) { + movecategoryto.removeAttribute('disabled'); + } else { + movecategoryto.setAttribute('disabled', true); + } + c.handleBulkSortByaction(); + } + break; default: return false; } @@ -1531,6 +1682,17 @@ Course.prototype = { e.halt(); managementconsole.performAjaxAction('hidecourse', args, this.hide, this); break; + case 'select': + var c = this.get('console'), + movetonode = c.get('courselisting').one('#menumovecoursesto'); + if (movetonode) { + if (c.isCourseSelected(e.currentTarget)) { + movetonode.removeAttribute('disabled'); + } else { + movetonode.setAttribute('disabled', true); + } + } + break; default: return false; } diff --git a/course/yui/src/management/js/category.js b/course/yui/src/management/js/category.js index 2a608c3eaf8..7d564935070 100644 --- a/course/yui/src/management/js/category.js +++ b/course/yui/src/management/js/category.js @@ -136,6 +136,20 @@ Category.prototype = { e.preventDefault(); this.collapse(); break; + case 'select': + var c = this.get('console'), + movecategoryto = c.get('categorylisting').one('#menumovecategoriesto'); + // If any category is selected and there are more then one categories. + if (movecategoryto) { + if (c.isCategorySelected(e.currentTarget) && + c.get('categories').length > 1) { + movecategoryto.removeAttribute('disabled'); + } else { + movecategoryto.setAttribute('disabled', true); + } + c.handleBulkSortByaction(); + } + break; default: Y.log('Invalid AJAX action requested of managed category.', 'warn', 'moodle-course-management'); return false; diff --git a/course/yui/src/management/js/console.js b/course/yui/src/management/js/console.js index 631dfc44d60..b0ff8725272 100644 --- a/course/yui/src/management/js/console.js +++ b/course/yui/src/management/js/console.js @@ -250,6 +250,21 @@ Console.prototype = { if (!listing) { return false; } + + // Disable category bulk actions as nothing will be selected on initialise. + var menumovecatto = listing.one('#menumovecategoriesto'); + if (menumovecatto) { + menumovecatto.setAttribute('disabled', true); + } + var menuresortcategoriesby = listing.one('#menuresortcategoriesby'); + if (menuresortcategoriesby) { + menuresortcategoriesby.setAttribute('disabled', true); + } + var menuresortcoursesby = listing.one('#menuresortcoursesby'); + if (menuresortcoursesby) { + menuresortcoursesby.setAttribute('disabled', true); + } + listing.all('.listitem[data-id]').each(function(node){ this.set('categories', new Category({ node : node, @@ -259,6 +274,8 @@ Console.prototype = { }, this); if (!this.categoriesinit) { this.get('categorylisting').delegate('click', this.handleCategoryDelegation, 'a[data-action]', this); + this.get('categorylisting').delegate('click', this.handleCategoryDelegation, 'input[name="bcat[]"]', this); + this.get('categorylisting').delegate('click', this.handleBulkSortByaction, '#menuselectsortby', this); this.categoriesinit = true; Y.log(count+' categories being managed', 'info', 'moodle-course-management'); } else { @@ -279,6 +296,13 @@ Console.prototype = { if (!listing) { return false; } + + // Disable course move to bulk action as nothing will be selected on initialise. + var menumovecoursesto = listing.one('#menumovecoursesto'); + if (menumovecoursesto) { + menumovecoursesto.setAttribute('disabled', true); + } + listing.all('.listitem[data-id]').each(function(node){ this.registerCourse(new Course({ node : node, @@ -288,6 +312,7 @@ Console.prototype = { count++; }, this); listing.delegate('click', this.handleCourseDelegation, 'a[data-action]', this); + listing.delegate('click', this.handleCourseDelegation, 'input[name="bc[]"]', this); Y.log(count+' courses being managed', 'info', 'moodle-course-management'); }, @@ -340,6 +365,118 @@ Console.prototype = { } }, + /** + * Check if any course is selected. + * + * @method isCourseSelected + * @param {Node} checkboxnode Checkbox node on which action happened. + * @return bool + */ + isCourseSelected : function(checkboxnode) { + var selected = false; + + // If any course selected then show move to category select box. + if (checkboxnode && checkboxnode.get('checked')) { + selected = true; + } else { + var i, + course, + courses = this.get('courses'), + length = courses.length; + for (i = 0; i < length; i++) { + if (courses.hasOwnProperty(i)) { + course = courses[i]; + if (course.get('node').one('input[name="bc[]"]').get('checked')) { + selected = true; + break; + } + } + } + } + return selected; + }, + + /** + * Check if any category is selected. + * + * @method isCategorySelected + * @param {Node} checkboxnode Checkbox node on which action happened. + * @return bool + */ + isCategorySelected : function(checkboxnode) { + var selected = false; + + // If any category selected then show move to category select box. + if (checkboxnode && checkboxnode.get('checked')) { + selected = true; + } else { + var i, + category, + categories = this.get('categories'), + length = categories.length; + for (i = 0; i < length; i++) { + if (categories.hasOwnProperty(i)) { + category = categories[i]; + if (category.get('node').one('input[name="bcat[]"]').get('checked')) { + selected = true; + break; + } + } + } + } + return selected; + }, + + /** + * Handle bulk sort action. + * + * @method handleBulkSortByaction + * @protected + * @param {EventFacade} e + */ + handleBulkSortByaction : function(e) { + var sortcategoryby = this.get('categorylisting').one('#menuresortcategoriesby'), + sortcourseby = this.get('categorylisting').one('#menuresortcoursesby'), + sortbybutton = this.get('categorylisting').one('input[name="bulksort"]'); + sortby = e; + + if (!sortby) { + sortby = this.get('categorylisting').one('#menuselectsortby'); + } else { + if (e && e.currentTarget) { + sortby = e.currentTarget; + } + } + + // If no sortby select found then return as we can't do anything. + if (!sortby) { + return; + } + + if ((this.get('categories').length <= 1) || (!this.isCategorySelected() && + (sortby.get("options").item(sortby.get('selectedIndex')).getAttribute('value') === 'selectedcategories'))) { + if (sortcategoryby) { + sortcategoryby.setAttribute('disabled', true); + } + if (sortcourseby) { + sortcourseby.setAttribute('disabled', true); + } + if (sortbybutton) { + sortbybutton.setAttribute('disabled', true); + } + } else { + if (sortcategoryby) { + sortcategoryby.removeAttribute('disabled'); + } + if (sortcourseby) { + sortcourseby.removeAttribute('disabled'); + } + if (sortbybutton) { + sortbybutton.removeAttribute('disabled'); + } + } + }, + /** * Returns the category with the given ID. * @method getCategoryById diff --git a/course/yui/src/management/js/course.js b/course/yui/src/management/js/course.js index 2b2df343ba3..3e646c64fb7 100644 --- a/course/yui/src/management/js/course.js +++ b/course/yui/src/management/js/course.js @@ -110,6 +110,17 @@ Course.prototype = { e.halt(); managementconsole.performAjaxAction('hidecourse', args, this.hide, this); break; + case 'select': + var c = this.get('console'), + movetonode = c.get('courselisting').one('#menumovecoursesto'); + if (movetonode) { + if (c.isCourseSelected(e.currentTarget)) { + movetonode.removeAttribute('disabled'); + } else { + movetonode.setAttribute('disabled', true); + } + } + break; default: Y.log('Invalid AJAX action requested of managed course.', 'warn', 'moodle-course-management'); return false;