| 1 | efrain | 1 | YUI.add('moodle-course-management', function (Y, NAME) {
 | 
        
           |  |  | 2 |   | 
        
           |  |  | 3 | var Category;
 | 
        
           |  |  | 4 | var Console;
 | 
        
           |  |  | 5 | var Course;
 | 
        
           |  |  | 6 | var DragDrop;
 | 
        
           |  |  | 7 | var Item;
 | 
        
           |  |  | 8 | /**
 | 
        
           |  |  | 9 |  * Provides drop down menus for list of action links.
 | 
        
           |  |  | 10 |  *
 | 
        
           |  |  | 11 |  * @module moodle-course-management
 | 
        
           |  |  | 12 |  */
 | 
        
           |  |  | 13 |   | 
        
           |  |  | 14 | /**
 | 
        
           |  |  | 15 |  * Management JS console.
 | 
        
           |  |  | 16 |  *
 | 
        
           |  |  | 17 |  * Provides the organisation for course and category management JS.
 | 
        
           |  |  | 18 |  *
 | 
        
           |  |  | 19 |  * @namespace M.course.management
 | 
        
           |  |  | 20 |  * @class Console
 | 
        
           |  |  | 21 |  * @constructor
 | 
        
           |  |  | 22 |  * @extends Base
 | 
        
           |  |  | 23 |  */
 | 
        
           |  |  | 24 | Console = function() {
 | 
        
           |  |  | 25 |     Console.superclass.constructor.apply(this, arguments);
 | 
        
           |  |  | 26 | };
 | 
        
           |  |  | 27 | Console.NAME = 'moodle-course-management';
 | 
        
           |  |  | 28 | Console.CSS_PREFIX = 'management';
 | 
        
           |  |  | 29 | Console.ATTRS = {
 | 
        
           |  |  | 30 |     /**
 | 
        
           |  |  | 31 |      * The HTML element containing the management interface.
 | 
        
           |  |  | 32 |      * @attribute element
 | 
        
           |  |  | 33 |      * @type Node
 | 
        
           |  |  | 34 |      */
 | 
        
           |  |  | 35 |     element: {
 | 
        
           |  |  | 36 |         setter: function(node) {
 | 
        
           |  |  | 37 |             if (typeof node === 'string') {
 | 
        
           |  |  | 38 |                 node = Y.one('#' + node);
 | 
        
           |  |  | 39 |             }
 | 
        
           |  |  | 40 |             return node;
 | 
        
           |  |  | 41 |         }
 | 
        
           |  |  | 42 |     },
 | 
        
           |  |  | 43 |   | 
        
           |  |  | 44 |     /**
 | 
        
           |  |  | 45 |      * The category listing container node.
 | 
        
           |  |  | 46 |      * @attribute categorylisting
 | 
        
           |  |  | 47 |      * @type Node
 | 
        
           |  |  | 48 |      * @default null
 | 
        
           |  |  | 49 |      */
 | 
        
           |  |  | 50 |     categorylisting: {
 | 
        
           |  |  | 51 |         value: null
 | 
        
           |  |  | 52 |     },
 | 
        
           |  |  | 53 |   | 
        
           |  |  | 54 |     /**
 | 
        
           |  |  | 55 |      * The course listing container node.
 | 
        
           |  |  | 56 |      * @attribute courselisting
 | 
        
           |  |  | 57 |      * @type Node
 | 
        
           |  |  | 58 |      * @default null
 | 
        
           |  |  | 59 |      */
 | 
        
           |  |  | 60 |     courselisting: {
 | 
        
           |  |  | 61 |         value: null
 | 
        
           |  |  | 62 |     },
 | 
        
           |  |  | 63 |   | 
        
           |  |  | 64 |     /**
 | 
        
           |  |  | 65 |      * The course details container node.
 | 
        
           |  |  | 66 |      * @attribute coursedetails
 | 
        
           |  |  | 67 |      * @type Node|null
 | 
        
           |  |  | 68 |      * @default null
 | 
        
           |  |  | 69 |      */
 | 
        
           |  |  | 70 |     coursedetails: {
 | 
        
           |  |  | 71 |         value: null
 | 
        
           |  |  | 72 |     },
 | 
        
           |  |  | 73 |   | 
        
           |  |  | 74 |     /**
 | 
        
           |  |  | 75 |      * The id of the currently active category.
 | 
        
           |  |  | 76 |      * @attribute activecategoryid
 | 
        
           |  |  | 77 |      * @type Number
 | 
        
           |  |  | 78 |      * @default null
 | 
        
           |  |  | 79 |      */
 | 
        
           |  |  | 80 |     activecategoryid: {
 | 
        
           |  |  | 81 |         value: null
 | 
        
           |  |  | 82 |     },
 | 
        
           |  |  | 83 |   | 
        
           |  |  | 84 |     /**
 | 
        
           |  |  | 85 |      * The id of the currently active course.
 | 
        
           |  |  | 86 |      * @attribute activecourseid
 | 
        
           |  |  | 87 |      * @type Number
 | 
        
           |  |  | 88 |      * @default Null
 | 
        
           |  |  | 89 |      */
 | 
        
           |  |  | 90 |     activecourseid: {
 | 
        
           |  |  | 91 |         value: null
 | 
        
           |  |  | 92 |     },
 | 
        
           |  |  | 93 |   | 
        
           |  |  | 94 |     /**
 | 
        
           |  |  | 95 |      * The categories that are currently available through the management interface.
 | 
        
           |  |  | 96 |      * @attribute categories
 | 
        
           |  |  | 97 |      * @type Array
 | 
        
           |  |  | 98 |      * @default []
 | 
        
           |  |  | 99 |      */
 | 
        
           |  |  | 100 |     categories: {
 | 
        
           |  |  | 101 |         setter: function(item, name) {
 | 
        
           |  |  | 102 |             if (Y.Lang.isArray(item)) {
 | 
        
           |  |  | 103 |                 return item;
 | 
        
           |  |  | 104 |             }
 | 
        
           |  |  | 105 |             var items = this.get(name);
 | 
        
           |  |  | 106 |             items.push(item);
 | 
        
           |  |  | 107 |             return items;
 | 
        
           |  |  | 108 |         },
 | 
        
           |  |  | 109 |         value: []
 | 
        
           |  |  | 110 |     },
 | 
        
           |  |  | 111 |   | 
        
           |  |  | 112 |     /**
 | 
        
           |  |  | 113 |      * The courses that are currently available through the management interface.
 | 
        
           |  |  | 114 |      * @attribute courses
 | 
        
           |  |  | 115 |      * @type Course[]
 | 
        
           |  |  | 116 |      * @default Array
 | 
        
           |  |  | 117 |      */
 | 
        
           |  |  | 118 |     courses: {
 | 
        
           |  |  | 119 |         validator: function(val) {
 | 
        
           |  |  | 120 |             return Y.Lang.isArray(val);
 | 
        
           |  |  | 121 |         },
 | 
        
           |  |  | 122 |         value: []
 | 
        
           |  |  | 123 |     },
 | 
        
           |  |  | 124 |   | 
        
           |  |  | 125 |     /**
 | 
        
           |  |  | 126 |      * The currently displayed page of courses.
 | 
        
           |  |  | 127 |      * @attribute page
 | 
        
           |  |  | 128 |      * @type Number
 | 
        
           |  |  | 129 |      * @default null
 | 
        
           |  |  | 130 |      */
 | 
        
           |  |  | 131 |     page: {
 | 
        
           |  |  | 132 |         getter: function(value, name) {
 | 
        
           |  |  | 133 |             if (value === null) {
 | 
        
           |  |  | 134 |                 value = this.get('element').getData(name);
 | 
        
           |  |  | 135 |                 this.set(name, value);
 | 
        
           |  |  | 136 |             }
 | 
        
           |  |  | 137 |             return value;
 | 
        
           |  |  | 138 |         },
 | 
        
           |  |  | 139 |         value: null
 | 
        
           |  |  | 140 |     },
 | 
        
           |  |  | 141 |   | 
        
           |  |  | 142 |     /**
 | 
        
           |  |  | 143 |      * The total pages of courses that can be shown for this category.
 | 
        
           |  |  | 144 |      * @attribute totalpages
 | 
        
           |  |  | 145 |      * @type Number
 | 
        
           |  |  | 146 |      * @default null
 | 
        
           |  |  | 147 |      */
 | 
        
           |  |  | 148 |     totalpages: {
 | 
        
           |  |  | 149 |         getter: function(value, name) {
 | 
        
           |  |  | 150 |             if (value === null) {
 | 
        
           |  |  | 151 |                 value = this.get('element').getData(name);
 | 
        
           |  |  | 152 |                 this.set(name, value);
 | 
        
           |  |  | 153 |             }
 | 
        
           |  |  | 154 |             return value;
 | 
        
           |  |  | 155 |         },
 | 
        
           |  |  | 156 |         value: null
 | 
        
           |  |  | 157 |     },
 | 
        
           |  |  | 158 |   | 
        
           |  |  | 159 |     /**
 | 
        
           |  |  | 160 |      * The total number of courses belonging to this category.
 | 
        
           |  |  | 161 |      * @attribute totalcourses
 | 
        
           |  |  | 162 |      * @type Number
 | 
        
           |  |  | 163 |      * @default null
 | 
        
           |  |  | 164 |      */
 | 
        
           |  |  | 165 |     totalcourses: {
 | 
        
           |  |  | 166 |         getter: function(value, name) {
 | 
        
           |  |  | 167 |             if (value === null) {
 | 
        
           |  |  | 168 |                 value = this.get('element').getData(name);
 | 
        
           |  |  | 169 |                 this.set(name, value);
 | 
        
           |  |  | 170 |             }
 | 
        
           |  |  | 171 |             return value;
 | 
        
           |  |  | 172 |         },
 | 
        
           |  |  | 173 |         value: null
 | 
        
           |  |  | 174 |     },
 | 
        
           |  |  | 175 |   | 
        
           |  |  | 176 |     /**
 | 
        
           |  |  | 177 |      * The URL to use for AJAX actions/requests.
 | 
        
           |  |  | 178 |      * @attribute ajaxurl
 | 
        
           |  |  | 179 |      * @type String
 | 
        
           |  |  | 180 |      * @default /course/ajax/management.php
 | 
        
           |  |  | 181 |      */
 | 
        
           |  |  | 182 |     ajaxurl: {
 | 
        
           |  |  | 183 |         getter: function(value) {
 | 
        
           |  |  | 184 |             if (value === null) {
 | 
        
           |  |  | 185 |                 value = M.cfg.wwwroot + '/course/ajax/management.php';
 | 
        
           |  |  | 186 |             }
 | 
        
           |  |  | 187 |             return value;
 | 
        
           |  |  | 188 |         },
 | 
        
           |  |  | 189 |         value: null
 | 
        
           |  |  | 190 |     },
 | 
        
           |  |  | 191 |   | 
        
           |  |  | 192 |     /**
 | 
        
           |  |  | 193 |      * The drag drop handler
 | 
        
           |  |  | 194 |      * @attribute dragdrop
 | 
        
           |  |  | 195 |      * @type DragDrop
 | 
        
           |  |  | 196 |      * @default null
 | 
        
           |  |  | 197 |      */
 | 
        
           |  |  | 198 |     dragdrop: {
 | 
        
           |  |  | 199 |         value: null
 | 
        
           |  |  | 200 |     }
 | 
        
           |  |  | 201 | };
 | 
        
           |  |  | 202 | Console.prototype = {
 | 
        
           |  |  | 203 |   | 
        
           |  |  | 204 |     /**
 | 
        
           |  |  | 205 |      * Gets set to true once the first categories have been initialised.
 | 
        
           |  |  | 206 |      * @property categoriesinit
 | 
        
           |  |  | 207 |      * @private
 | 
        
           |  |  | 208 |      * @type {boolean}
 | 
        
           |  |  | 209 |      */
 | 
        
           |  |  | 210 |     categoriesinit: false,
 | 
        
           |  |  | 211 |   | 
        
           |  |  | 212 |     /**
 | 
        
           |  |  | 213 |      * Initialises a new instance of the Console.
 | 
        
           |  |  | 214 |      * @method initializer
 | 
        
           |  |  | 215 |      */
 | 
        
           |  |  | 216 |     initializer: function() {
 | 
        
           |  |  | 217 |         Y.log('Initialising course category management console', 'info', 'moodle-course-management');
 | 
        
           |  |  | 218 |         this.set('element', 'coursecat-management');
 | 
        
           |  |  | 219 |         var element = this.get('element'),
 | 
        
           |  |  | 220 |             categorylisting = element.one('#category-listing'),
 | 
        
           |  |  | 221 |             courselisting = element.one('#course-listing'),
 | 
        
           |  |  | 222 |             selectedcategory = null,
 | 
        
           |  |  | 223 |             selectedcourse = null;
 | 
        
           |  |  | 224 |   | 
        
           |  |  | 225 |         if (categorylisting) {
 | 
        
           |  |  | 226 |             selectedcategory = categorylisting.one('.listitem[data-selected="1"]');
 | 
        
           |  |  | 227 |         }
 | 
        
           |  |  | 228 |         if (courselisting) {
 | 
        
           |  |  | 229 |             selectedcourse = courselisting.one('.listitem[data-selected="1"]');
 | 
        
           |  |  | 230 |         }
 | 
        
           |  |  | 231 |         this.set('categorylisting', categorylisting);
 | 
        
           |  |  | 232 |         this.set('courselisting', courselisting);
 | 
        
           |  |  | 233 |         this.set('coursedetails', element.one('#course-detail'));
 | 
        
           |  |  | 234 |         if (selectedcategory) {
 | 
        
           |  |  | 235 |             this.set('activecategoryid', selectedcategory.getData('id'));
 | 
        
           |  |  | 236 |         }
 | 
        
           |  |  | 237 |         if (selectedcourse) {
 | 
        
           |  |  | 238 |             this.set('activecourseid', selectedcourse.getData('id'));
 | 
        
           |  |  | 239 |         }
 | 
        
           |  |  | 240 |         this.initialiseCategories(categorylisting);
 | 
        
           |  |  | 241 |         this.initialiseCourses();
 | 
        
           |  |  | 242 |   | 
        
           |  |  | 243 |         if (courselisting) {
 | 
        
           |  |  | 244 |             // No need for dragdrop if we don't have a course listing.
 | 
        
           |  |  | 245 |             this.set('dragdrop', new DragDrop({console: this}));
 | 
        
           |  |  | 246 |         }
 | 
        
           |  |  | 247 |     },
 | 
        
           |  |  | 248 |   | 
        
           |  |  | 249 |     /**
 | 
        
           |  |  | 250 |      * Initialises all the categories being shown.
 | 
        
           |  |  | 251 |      * @method initialiseCategories
 | 
        
           |  |  | 252 |      * @private
 | 
        
           |  |  | 253 |      * @return {boolean}
 | 
        
           |  |  | 254 |      */
 | 
        
           |  |  | 255 |     initialiseCategories: function(listing) {
 | 
        
           |  |  | 256 |         var count = 0;
 | 
        
           |  |  | 257 |         if (!listing) {
 | 
        
           |  |  | 258 |             return false;
 | 
        
           |  |  | 259 |         }
 | 
        
           |  |  | 260 |   | 
        
           |  |  | 261 |         // Disable category bulk actions as nothing will be selected on initialise.
 | 
        
           |  |  | 262 |         var menumovecatto = listing.one('#menumovecategoriesto');
 | 
        
           |  |  | 263 |         if (menumovecatto) {
 | 
        
           |  |  | 264 |             menumovecatto.setAttribute('disabled', true);
 | 
        
           |  |  | 265 |         }
 | 
        
           |  |  | 266 |         var menuresortcategoriesby = listing.one('#menuresortcategoriesby');
 | 
        
           |  |  | 267 |         if (menuresortcategoriesby) {
 | 
        
           |  |  | 268 |             menuresortcategoriesby.setAttribute('disabled', true);
 | 
        
           |  |  | 269 |         }
 | 
        
           |  |  | 270 |         var menuresortcoursesby = listing.one('#menuresortcoursesby');
 | 
        
           |  |  | 271 |         if (menuresortcoursesby) {
 | 
        
           |  |  | 272 |             menuresortcoursesby.setAttribute('disabled', true);
 | 
        
           |  |  | 273 |         }
 | 
        
           |  |  | 274 |   | 
        
           |  |  | 275 |         listing.all('.listitem[data-id]').each(function(node) {
 | 
        
           |  |  | 276 |             this.set('categories', new Category({
 | 
        
           |  |  | 277 |                 node: node,
 | 
        
           |  |  | 278 |                 console: this
 | 
        
           |  |  | 279 |             }));
 | 
        
           |  |  | 280 |             count++;
 | 
        
           |  |  | 281 |         }, this);
 | 
        
           |  |  | 282 |         if (!this.categoriesinit) {
 | 
        
           |  |  | 283 |             this.get('categorylisting').delegate('click', this.handleCategoryDelegation, 'a[data-action]', this);
 | 
        
           |  |  | 284 |             this.get('categorylisting').delegate('click', this.handleCategoryDelegation, 'input[name="bcat[]"]', this);
 | 
        
           |  |  | 285 |             this.get('categorylisting').delegate('change', this.handleBulkSortByaction, '#menuselectsortby', this);
 | 
        
           |  |  | 286 |             this.categoriesinit = true;
 | 
        
           |  |  | 287 |             Y.log(count + ' categories being managed', 'info', 'moodle-course-management');
 | 
        
           |  |  | 288 |         } else {
 | 
        
           |  |  | 289 |             Y.log(count + ' new categories being managed', 'info', 'moodle-course-management');
 | 
        
           |  |  | 290 |         }
 | 
        
           |  |  | 291 |     },
 | 
        
           |  |  | 292 |   | 
        
           |  |  | 293 |     /**
 | 
        
           |  |  | 294 |      * Initialises all the categories being shown.
 | 
        
           |  |  | 295 |      * @method initialiseCourses
 | 
        
           |  |  | 296 |      * @private
 | 
        
           |  |  | 297 |      * @return {boolean}
 | 
        
           |  |  | 298 |      */
 | 
        
           |  |  | 299 |     initialiseCourses: function() {
 | 
        
           |  |  | 300 |         var category = this.getCategoryById(this.get('activecategoryid')),
 | 
        
           |  |  | 301 |             listing = this.get('courselisting'),
 | 
        
           |  |  | 302 |             count = 0;
 | 
        
           |  |  | 303 |         if (!listing) {
 | 
        
           |  |  | 304 |             return false;
 | 
        
           |  |  | 305 |         }
 | 
        
           |  |  | 306 |   | 
        
           |  |  | 307 |         // Disable course move to bulk action as nothing will be selected on initialise.
 | 
        
           |  |  | 308 |         var menumovecoursesto = listing.one('#menumovecoursesto');
 | 
        
           |  |  | 309 |         if (menumovecoursesto) {
 | 
        
           |  |  | 310 |             menumovecoursesto.setAttribute('disabled', true);
 | 
        
           |  |  | 311 |         }
 | 
        
           |  |  | 312 |   | 
        
           |  |  | 313 |         listing.all('.listitem[data-id]').each(function(node) {
 | 
        
           |  |  | 314 |             this.registerCourse(new Course({
 | 
        
           |  |  | 315 |                 node: node,
 | 
        
           |  |  | 316 |                 console: this,
 | 
        
           |  |  | 317 |                 category: category
 | 
        
           |  |  | 318 |             }));
 | 
        
           |  |  | 319 |             count++;
 | 
        
           |  |  | 320 |         }, this);
 | 
        
           |  |  | 321 |         listing.delegate('click', this.handleCourseDelegation, 'a[data-action]', this);
 | 
        
           |  |  | 322 |         listing.delegate('click', this.handleCourseDelegation, 'input[name="bc[]"]', this);
 | 
        
           |  |  | 323 |         Y.log(count + ' courses being managed', 'info', 'moodle-course-management');
 | 
        
           |  |  | 324 |     },
 | 
        
           |  |  | 325 |   | 
        
           |  |  | 326 |     /**
 | 
        
           |  |  | 327 |      * Registers a course within the management display.
 | 
        
           |  |  | 328 |      * @method registerCourse
 | 
        
           |  |  | 329 |      * @param {Course} course
 | 
        
           |  |  | 330 |      */
 | 
        
           |  |  | 331 |     registerCourse: function(course) {
 | 
        
           |  |  | 332 |         var courses = this.get('courses');
 | 
        
           |  |  | 333 |         courses.push(course);
 | 
        
           |  |  | 334 |         this.set('courses', courses);
 | 
        
           |  |  | 335 |     },
 | 
        
           |  |  | 336 |   | 
        
           |  |  | 337 |     /**
 | 
        
           |  |  | 338 |      * Handles the event fired by a delegated course listener.
 | 
        
           |  |  | 339 |      *
 | 
        
           |  |  | 340 |      * @method handleCourseDelegation
 | 
        
           |  |  | 341 |      * @protected
 | 
        
           |  |  | 342 |      * @param {EventFacade} e
 | 
        
           |  |  | 343 |      */
 | 
        
           |  |  | 344 |     handleCourseDelegation: function(e) {
 | 
        
           |  |  | 345 |         var target = e.currentTarget,
 | 
        
           |  |  | 346 |             action = target.getData('action'),
 | 
        
           |  |  | 347 |             courseid = target.ancestor('.listitem').getData('id'),
 | 
        
           |  |  | 348 |             course = this.getCourseById(courseid);
 | 
        
           |  |  | 349 |         if (course) {
 | 
        
           |  |  | 350 |             course.handle(action, e);
 | 
        
           |  |  | 351 |         } else {
 | 
        
           |  |  | 352 |             Y.log('Course with ID ' + courseid + ' could not be found for delegation', 'error', 'moodle-course-management');
 | 
        
           |  |  | 353 |         }
 | 
        
           |  |  | 354 |     },
 | 
        
           |  |  | 355 |   | 
        
           |  |  | 356 |     /**
 | 
        
           |  |  | 357 |      * Handles the event fired by a delegated course listener.
 | 
        
           |  |  | 358 |      *
 | 
        
           |  |  | 359 |      * @method handleCategoryDelegation
 | 
        
           |  |  | 360 |      * @protected
 | 
        
           |  |  | 361 |      * @param {EventFacade} e
 | 
        
           |  |  | 362 |      */
 | 
        
           |  |  | 363 |     handleCategoryDelegation: function(e) {
 | 
        
           |  |  | 364 |         var target = e.currentTarget,
 | 
        
           |  |  | 365 |             action = target.getData('action'),
 | 
        
           |  |  | 366 |             categoryid = target.ancestor('.listitem').getData('id'),
 | 
        
           |  |  | 367 |             category = this.getCategoryById(categoryid);
 | 
        
           |  |  | 368 |         if (category) {
 | 
        
           |  |  | 369 |             category.handle(action, e);
 | 
        
           |  |  | 370 |         } else {
 | 
        
           |  |  | 371 |             Y.log('Could not find category to delegate to.', 'error', 'moodle-course-management');
 | 
        
           |  |  | 372 |         }
 | 
        
           |  |  | 373 |     },
 | 
        
           |  |  | 374 |   | 
        
           |  |  | 375 |     /**
 | 
        
           |  |  | 376 |      * Check if any course is selected.
 | 
        
           |  |  | 377 |      *
 | 
        
           |  |  | 378 |      * @method isCourseSelected
 | 
        
           |  |  | 379 |      * @param {Node} checkboxnode Checkbox node on which action happened.
 | 
        
           |  |  | 380 |      * @return bool
 | 
        
           |  |  | 381 |      */
 | 
        
           |  |  | 382 |     isCourseSelected: function(checkboxnode) {
 | 
        
           |  |  | 383 |         var selected = false;
 | 
        
           |  |  | 384 |   | 
        
           |  |  | 385 |         // If any course selected then show move to category select box.
 | 
        
           |  |  | 386 |         if (checkboxnode && checkboxnode.get('checked')) {
 | 
        
           |  |  | 387 |             selected = true;
 | 
        
           |  |  | 388 |         } else {
 | 
        
           |  |  | 389 |             var i,
 | 
        
           |  |  | 390 |                 course,
 | 
        
           |  |  | 391 |                 courses = this.get('courses'),
 | 
        
           |  |  | 392 |                 length = courses.length;
 | 
        
           |  |  | 393 |             for (i = 0; i < length; i++) {
 | 
        
           |  |  | 394 |                 if (courses.hasOwnProperty(i)) {
 | 
        
           |  |  | 395 |                     course = courses[i];
 | 
        
           |  |  | 396 |                     if (course.get('node').one('input[name="bc[]"]').get('checked')) {
 | 
        
           |  |  | 397 |                         selected = true;
 | 
        
           |  |  | 398 |                         break;
 | 
        
           |  |  | 399 |                     }
 | 
        
           |  |  | 400 |                 }
 | 
        
           |  |  | 401 |             }
 | 
        
           |  |  | 402 |         }
 | 
        
           |  |  | 403 |         return selected;
 | 
        
           |  |  | 404 |     },
 | 
        
           |  |  | 405 |   | 
        
           |  |  | 406 |     /**
 | 
        
           |  |  | 407 |      * Check if any category is selected.
 | 
        
           |  |  | 408 |      *
 | 
        
           |  |  | 409 |      * @method isCategorySelected
 | 
        
           |  |  | 410 |      * @param {Node} checkboxnode Checkbox node on which action happened.
 | 
        
           |  |  | 411 |      * @return bool
 | 
        
           |  |  | 412 |      */
 | 
        
           |  |  | 413 |     isCategorySelected: function(checkboxnode) {
 | 
        
           |  |  | 414 |         var selected = false;
 | 
        
           |  |  | 415 |   | 
        
           |  |  | 416 |         // If any category selected then show move to category select box.
 | 
        
           |  |  | 417 |         if (checkboxnode && checkboxnode.get('checked')) {
 | 
        
           |  |  | 418 |             selected = true;
 | 
        
           |  |  | 419 |         } else {
 | 
        
           |  |  | 420 |             var i,
 | 
        
           |  |  | 421 |                 category,
 | 
        
           |  |  | 422 |                 categories = this.get('categories'),
 | 
        
           |  |  | 423 |                 length = categories.length;
 | 
        
           |  |  | 424 |             for (i = 0; i < length; i++) {
 | 
        
           |  |  | 425 |                 if (categories.hasOwnProperty(i)) {
 | 
        
           |  |  | 426 |                     category = categories[i];
 | 
        
           |  |  | 427 |                     if (category.get('node').one('input[name="bcat[]"]').get('checked')) {
 | 
        
           |  |  | 428 |                         selected = true;
 | 
        
           |  |  | 429 |                         break;
 | 
        
           |  |  | 430 |                     }
 | 
        
           |  |  | 431 |                 }
 | 
        
           |  |  | 432 |             }
 | 
        
           |  |  | 433 |         }
 | 
        
           |  |  | 434 |         return selected;
 | 
        
           |  |  | 435 |     },
 | 
        
           |  |  | 436 |   | 
        
           |  |  | 437 |     /**
 | 
        
           |  |  | 438 |      * Handle bulk sort action.
 | 
        
           |  |  | 439 |      *
 | 
        
           |  |  | 440 |      * @method handleBulkSortByaction
 | 
        
           |  |  | 441 |      * @protected
 | 
        
           |  |  | 442 |      * @param {EventFacade} e
 | 
        
           |  |  | 443 |      */
 | 
        
           |  |  | 444 |     handleBulkSortByaction: function(e) {
 | 
        
           |  |  | 445 |         var sortcategoryby = this.get('categorylisting').one('#menuresortcategoriesby'),
 | 
        
           |  |  | 446 |             sortcourseby = this.get('categorylisting').one('#menuresortcoursesby'),
 | 
        
           |  |  | 447 |             sortbybutton = this.get('categorylisting').one('input[name="bulksort"]'),
 | 
        
           |  |  | 448 |             sortby = e;
 | 
        
           |  |  | 449 |   | 
        
           |  |  | 450 |         if (!sortby) {
 | 
        
           |  |  | 451 |             sortby = this.get('categorylisting').one('#menuselectsortby');
 | 
        
           |  |  | 452 |         } else {
 | 
        
           |  |  | 453 |             if (e && e.currentTarget) {
 | 
        
           |  |  | 454 |                 sortby = e.currentTarget;
 | 
        
           |  |  | 455 |             }
 | 
        
           |  |  | 456 |         }
 | 
        
           |  |  | 457 |   | 
        
           |  |  | 458 |         // If no sortby select found then return as we can't do anything.
 | 
        
           |  |  | 459 |         if (!sortby) {
 | 
        
           |  |  | 460 |             return;
 | 
        
           |  |  | 461 |         }
 | 
        
           |  |  | 462 |   | 
        
           |  |  | 463 |         if ((this.get('categories').length <= 1) || (!this.isCategorySelected() &&
 | 
        
           |  |  | 464 |                 (sortby.get("options").item(sortby.get('selectedIndex')).getAttribute('value') === 'selectedcategories'))) {
 | 
        
           |  |  | 465 |             if (sortcategoryby) {
 | 
        
           |  |  | 466 |                 sortcategoryby.setAttribute('disabled', true);
 | 
        
           |  |  | 467 |             }
 | 
        
           |  |  | 468 |             if (sortcourseby) {
 | 
        
           |  |  | 469 |                 sortcourseby.setAttribute('disabled', true);
 | 
        
           |  |  | 470 |             }
 | 
        
           |  |  | 471 |             if (sortbybutton) {
 | 
        
           |  |  | 472 |                 sortbybutton.setAttribute('disabled', true);
 | 
        
           |  |  | 473 |             }
 | 
        
           |  |  | 474 |         } else {
 | 
        
           |  |  | 475 |             if (sortcategoryby) {
 | 
        
           |  |  | 476 |                 sortcategoryby.removeAttribute('disabled');
 | 
        
           |  |  | 477 |             }
 | 
        
           |  |  | 478 |             if (sortcourseby) {
 | 
        
           |  |  | 479 |                 sortcourseby.removeAttribute('disabled');
 | 
        
           |  |  | 480 |             }
 | 
        
           |  |  | 481 |             if (sortbybutton) {
 | 
        
           |  |  | 482 |                 sortbybutton.removeAttribute('disabled');
 | 
        
           |  |  | 483 |             }
 | 
        
           |  |  | 484 |         }
 | 
        
           |  |  | 485 |     },
 | 
        
           |  |  | 486 |   | 
        
           |  |  | 487 |     /**
 | 
        
           |  |  | 488 |      * Returns the category with the given ID.
 | 
        
           |  |  | 489 |      * @method getCategoryById
 | 
        
           |  |  | 490 |      * @param {Number} id
 | 
        
           |  |  | 491 |      * @return {Category|Boolean} The category or false if it can't be found.
 | 
        
           |  |  | 492 |      */
 | 
        
           |  |  | 493 |     getCategoryById: function(id) {
 | 
        
           |  |  | 494 |         var i,
 | 
        
           |  |  | 495 |             category,
 | 
        
           |  |  | 496 |             categories = this.get('categories'),
 | 
        
           |  |  | 497 |             length = categories.length;
 | 
        
           |  |  | 498 |         for (i = 0; i < length; i++) {
 | 
        
           |  |  | 499 |             if (categories.hasOwnProperty(i)) {
 | 
        
           |  |  | 500 |                 category = categories[i];
 | 
        
           |  |  | 501 |                 if (category.get('categoryid') === id) {
 | 
        
           |  |  | 502 |                     return category;
 | 
        
           |  |  | 503 |                 }
 | 
        
           |  |  | 504 |             }
 | 
        
           |  |  | 505 |         }
 | 
        
           |  |  | 506 |         return false;
 | 
        
           |  |  | 507 |     },
 | 
        
           |  |  | 508 |   | 
        
           |  |  | 509 |     /**
 | 
        
           |  |  | 510 |      * Returns the course with the given id.
 | 
        
           |  |  | 511 |      * @method getCourseById
 | 
        
           |  |  | 512 |      * @param {Number} id
 | 
        
           |  |  | 513 |      * @return {Course|Boolean} The course or false if not found/
 | 
        
           |  |  | 514 |      */
 | 
        
           |  |  | 515 |     getCourseById: function(id) {
 | 
        
           |  |  | 516 |         var i,
 | 
        
           |  |  | 517 |             course,
 | 
        
           |  |  | 518 |             courses = this.get('courses'),
 | 
        
           |  |  | 519 |             length = courses.length;
 | 
        
           |  |  | 520 |         for (i = 0; i < length; i++) {
 | 
        
           |  |  | 521 |             if (courses.hasOwnProperty(i)) {
 | 
        
           |  |  | 522 |                 course = courses[i];
 | 
        
           |  |  | 523 |                 if (course.get('courseid') === id) {
 | 
        
           |  |  | 524 |                     return course;
 | 
        
           |  |  | 525 |                 }
 | 
        
           |  |  | 526 |             }
 | 
        
           |  |  | 527 |         }
 | 
        
           |  |  | 528 |         return false;
 | 
        
           |  |  | 529 |     },
 | 
        
           |  |  | 530 |   | 
        
           |  |  | 531 |     /**
 | 
        
           |  |  | 532 |      * Removes the course with the given ID.
 | 
        
           |  |  | 533 |      * @method removeCourseById
 | 
        
           |  |  | 534 |      * @param {Number} id
 | 
        
           |  |  | 535 |      */
 | 
        
           |  |  | 536 |     removeCourseById: function(id) {
 | 
        
           |  |  | 537 |         var courses = this.get('courses'),
 | 
        
           |  |  | 538 |             length = courses.length,
 | 
        
           |  |  | 539 |             course,
 | 
        
           |  |  | 540 |             i;
 | 
        
           |  |  | 541 |         for (i = 0; i < length; i++) {
 | 
        
           |  |  | 542 |             course = courses[i];
 | 
        
           |  |  | 543 |             if (course.get('courseid') === id) {
 | 
        
           |  |  | 544 |                 courses.splice(i, 1);
 | 
        
           |  |  | 545 |                 break;
 | 
        
           |  |  | 546 |             }
 | 
        
           |  |  | 547 |         }
 | 
        
           |  |  | 548 |     },
 | 
        
           |  |  | 549 |   | 
        
           |  |  | 550 |     /**
 | 
        
           |  |  | 551 |      * Performs an AJAX action.
 | 
        
           |  |  | 552 |      *
 | 
        
           |  |  | 553 |      * @method performAjaxAction
 | 
        
           |  |  | 554 |      * @param {String} action The action to perform.
 | 
        
           |  |  | 555 |      * @param {Object} args The arguments to pass through with teh request.
 | 
        
           |  |  | 556 |      * @param {Function} callback The function to call when all is done.
 | 
        
           |  |  | 557 |      * @param {Object} context The object to use as the context for the callback.
 | 
        
           |  |  | 558 |      */
 | 
        
           |  |  | 559 |     performAjaxAction: function(action, args, callback, context) {
 | 
        
           |  |  | 560 |         var io = new Y.IO();
 | 
        
           |  |  | 561 |         args.action = action;
 | 
        
           |  |  | 562 |         args.ajax = '1';
 | 
        
           |  |  | 563 |         args.sesskey = M.cfg.sesskey;
 | 
        
           |  |  | 564 |         if (callback === null) {
 | 
        
           |  |  | 565 |             callback = function() {
 | 
        
           |  |  | 566 |                 Y.log("'Action '" + action + "' completed", 'debug', 'moodle-course-management');
 | 
        
           |  |  | 567 |             };
 | 
        
           |  |  | 568 |         }
 | 
        
           |  |  | 569 |         io.send(this.get('ajaxurl'), {
 | 
        
           |  |  | 570 |             method: 'POST',
 | 
        
           |  |  | 571 |             on: {
 | 
        
           |  |  | 572 |                 complete: callback
 | 
        
           |  |  | 573 |             },
 | 
        
           |  |  | 574 |             context: context,
 | 
        
           |  |  | 575 |             data: args,
 | 
        
           |  |  | 576 |             'arguments': args
 | 
        
           |  |  | 577 |         });
 | 
        
           |  |  | 578 |     }
 | 
        
           |  |  | 579 | };
 | 
        
           |  |  | 580 | Y.extend(Console, Y.Base, Console.prototype);
 | 
        
           |  |  | 581 |   | 
        
           |  |  | 582 | M.course = M.course || {};
 | 
        
           |  |  | 583 | M.course.management = M.course.management || {};
 | 
        
           |  |  | 584 | M.course.management.console = null;
 | 
        
           |  |  | 585 |   | 
        
           |  |  | 586 | /**
 | 
        
           |  |  | 587 |  * Initalises the course management console.
 | 
        
           |  |  | 588 |  *
 | 
        
           |  |  | 589 |  * @method M.course.management.init
 | 
        
           |  |  | 590 |  * @static
 | 
        
           |  |  | 591 |  * @param {Object} config
 | 
        
           |  |  | 592 |  */
 | 
        
           |  |  | 593 | M.course.management.init = function(config) {
 | 
        
           |  |  | 594 |     M.course.management.console = new Console(config);
 | 
        
           |  |  | 595 | };
 | 
        
           |  |  | 596 | /**
 | 
        
           |  |  | 597 |  * Drag and Drop handler
 | 
        
           |  |  | 598 |  *
 | 
        
           |  |  | 599 |  * @namespace M.course.management
 | 
        
           |  |  | 600 |  * @class DragDrop
 | 
        
           |  |  | 601 |  * @constructor
 | 
        
           |  |  | 602 |  * @extends Base
 | 
        
           |  |  | 603 |  */
 | 
        
           |  |  | 604 | DragDrop = function(config) {
 | 
        
           |  |  | 605 |     Console.superclass.constructor.apply(this, [config]);
 | 
        
           |  |  | 606 | };
 | 
        
           |  |  | 607 | DragDrop.NAME = 'moodle-course-management-dd';
 | 
        
           |  |  | 608 | DragDrop.CSS_PREFIX = 'management-dd';
 | 
        
           |  |  | 609 | DragDrop.ATTRS = {
 | 
        
           |  |  | 610 |     /**
 | 
        
           |  |  | 611 |      * The management console this drag and drop has been set up for.
 | 
        
           |  |  | 612 |      * @attribute console
 | 
        
           |  |  | 613 |      * @type Console
 | 
        
           |  |  | 614 |      * @writeOnce
 | 
        
           |  |  | 615 |      */
 | 
        
           |  |  | 616 |     console: {
 | 
        
           |  |  | 617 |         writeOnce: 'initOnly'
 | 
        
           |  |  | 618 |     }
 | 
        
           |  |  | 619 | };
 | 
        
           |  |  | 620 | DragDrop.prototype = {
 | 
        
           |  |  | 621 |     /**
 | 
        
           |  |  | 622 |      * True if the user is dragging a course upwards.
 | 
        
           |  |  | 623 |      * @property goingup
 | 
        
           |  |  | 624 |      * @protected
 | 
        
           |  |  | 625 |      * @default false
 | 
        
           |  |  | 626 |      */
 | 
        
           |  |  | 627 |     goingup: false,
 | 
        
           |  |  | 628 |   | 
        
           |  |  | 629 |     /**
 | 
        
           |  |  | 630 |      * The last Y position of the course being dragged
 | 
        
           |  |  | 631 |      * @property lasty
 | 
        
           |  |  | 632 |      * @protected
 | 
        
           |  |  | 633 |      * @default null
 | 
        
           |  |  | 634 |      */
 | 
        
           |  |  | 635 |     lasty: null,
 | 
        
           |  |  | 636 |   | 
        
           |  |  | 637 |     /**
 | 
        
           |  |  | 638 |      * The sibling above the course being dragged currently (tracking its original position).
 | 
        
           |  |  | 639 |      *
 | 
        
           |  |  | 640 |      * @property previoussibling
 | 
        
           |  |  | 641 |      * @protected
 | 
        
           |  |  | 642 |      * @default false
 | 
        
           |  |  | 643 |      */
 | 
        
           |  |  | 644 |     previoussibling: null,
 | 
        
           |  |  | 645 |   | 
        
           |  |  | 646 |     /**
 | 
        
           |  |  | 647 |      * Initialises the DragDrop instance.
 | 
        
           |  |  | 648 |      * @method initializer
 | 
        
           |  |  | 649 |      */
 | 
        
           |  |  | 650 |     initializer: function() {
 | 
        
           |  |  | 651 |         var managementconsole = this.get('console'),
 | 
        
           |  |  | 652 |             container = managementconsole.get('element'),
 | 
        
           |  |  | 653 |             categorylisting = container.one('#category-listing'),
 | 
        
           |  |  | 654 |             courselisting = container.one('#course-listing > .course-listing'),
 | 
        
           | 1441 | ariadna | 655 |             categoryul = (categorylisting) ? categorylisting.one('ul.category-list') : null,
 | 
        
           |  |  | 656 |             courseul = (courselisting) ? courselisting.one('ul.course-list') : null,
 | 
        
           | 1 | efrain | 657 |             canmoveoutof = (courselisting) ? courselisting.getData('canmoveoutof') : false,
 | 
        
           |  |  | 658 |             contstraint = (canmoveoutof) ? container : courseul;
 | 
        
           |  |  | 659 |   | 
        
           |  |  | 660 |         if (!courseul) {
 | 
        
           |  |  | 661 |             // No course listings found.
 | 
        
           |  |  | 662 |             return false;
 | 
        
           |  |  | 663 |         }
 | 
        
           |  |  | 664 |   | 
        
           |  |  | 665 |         while (contstraint.get('scrollHeight') === 0 && !contstraint.compareTo(window.document.body)) {
 | 
        
           |  |  | 666 |             contstraint = contstraint.get('parentNode');
 | 
        
           |  |  | 667 |         }
 | 
        
           |  |  | 668 |   | 
        
           |  |  | 669 |         courseul.all('> li').each(function(li) {
 | 
        
           |  |  | 670 |             this.initCourseListing(li, contstraint);
 | 
        
           |  |  | 671 |         }, this);
 | 
        
           |  |  | 672 |         courseul.setData('dd', new Y.DD.Drop({
 | 
        
           |  |  | 673 |             node: courseul
 | 
        
           |  |  | 674 |         }));
 | 
        
           |  |  | 675 |         if (canmoveoutof && categoryul) {
 | 
        
           |  |  | 676 |             // Category UL may not be there if viewmode is just courses.
 | 
        
           |  |  | 677 |             categoryul.all('li > div').each(function(div) {
 | 
        
           |  |  | 678 |                 this.initCategoryListitem(div);
 | 
        
           |  |  | 679 |             }, this);
 | 
        
           |  |  | 680 |         }
 | 
        
           |  |  | 681 |         Y.DD.DDM.on('drag:start', this.dragStart, this);
 | 
        
           |  |  | 682 |         Y.DD.DDM.on('drag:end', this.dragEnd, this);
 | 
        
           |  |  | 683 |         Y.DD.DDM.on('drag:drag', this.dragDrag, this);
 | 
        
           |  |  | 684 |         Y.DD.DDM.on('drop:over', this.dropOver, this);
 | 
        
           |  |  | 685 |         Y.DD.DDM.on('drop:enter', this.dropEnter, this);
 | 
        
           |  |  | 686 |         Y.DD.DDM.on('drop:exit', this.dropExit, this);
 | 
        
           |  |  | 687 |         Y.DD.DDM.on('drop:hit', this.dropHit, this);
 | 
        
           |  |  | 688 |   | 
        
           |  |  | 689 |     },
 | 
        
           |  |  | 690 |   | 
        
           |  |  | 691 |     /**
 | 
        
           |  |  | 692 |      * Initialises a course listing.
 | 
        
           |  |  | 693 |      * @method initCourseListing
 | 
        
           |  |  | 694 |      * @param Node
 | 
        
           |  |  | 695 |      */
 | 
        
           |  |  | 696 |     initCourseListing: function(node, contstraint) {
 | 
        
           |  |  | 697 |         node.setData('dd', new Y.DD.Drag({
 | 
        
           |  |  | 698 |             node: node,
 | 
        
           |  |  | 699 |             target: {
 | 
        
           |  |  | 700 |                 padding: '0 0 0 20'
 | 
        
           |  |  | 701 |             }
 | 
        
           |  |  | 702 |         }).addHandle(
 | 
        
           |  |  | 703 |             '.drag-handle'
 | 
        
           |  |  | 704 |         ).plug(Y.Plugin.DDProxy, {
 | 
        
           |  |  | 705 |             moveOnEnd: false,
 | 
        
           |  |  | 706 |             borderStyle: false
 | 
        
           |  |  | 707 |         }).plug(Y.Plugin.DDConstrained, {
 | 
        
           |  |  | 708 |             constrain2node: contstraint
 | 
        
           |  |  | 709 |         }));
 | 
        
           |  |  | 710 |     },
 | 
        
           |  |  | 711 |   | 
        
           |  |  | 712 |     /**
 | 
        
           |  |  | 713 |      * Initialises a category listing.
 | 
        
           |  |  | 714 |      * @method initCategoryListitem
 | 
        
           |  |  | 715 |      * @param Node
 | 
        
           |  |  | 716 |      */
 | 
        
           |  |  | 717 |     initCategoryListitem: function(node) {
 | 
        
           |  |  | 718 |         node.setData('dd', new Y.DD.Drop({
 | 
        
           |  |  | 719 |             node: node
 | 
        
           |  |  | 720 |         }));
 | 
        
           |  |  | 721 |     },
 | 
        
           |  |  | 722 |   | 
        
           |  |  | 723 |     /**
 | 
        
           |  |  | 724 |      * Dragging has started.
 | 
        
           |  |  | 725 |      * @method dragStart
 | 
        
           |  |  | 726 |      * @private
 | 
        
           |  |  | 727 |      * @param {EventFacade} e
 | 
        
           |  |  | 728 |      */
 | 
        
           |  |  | 729 |     dragStart: function(e) {
 | 
        
           |  |  | 730 |         var drag = e.target,
 | 
        
           |  |  | 731 |             node = drag.get('node'),
 | 
        
           |  |  | 732 |             dragnode = drag.get('dragNode');
 | 
        
           |  |  | 733 |         node.addClass('course-being-dragged');
 | 
        
           |  |  | 734 |         dragnode.addClass('course-being-dragged-proxy').set('innerHTML', node.one('a.coursename').get('innerHTML'));
 | 
        
           |  |  | 735 |         this.previoussibling = node.get('previousSibling');
 | 
        
           |  |  | 736 |     },
 | 
        
           |  |  | 737 |   | 
        
           |  |  | 738 |     /**
 | 
        
           |  |  | 739 |      * Dragging has ended.
 | 
        
           |  |  | 740 |      * @method dragEnd
 | 
        
           |  |  | 741 |      * @private
 | 
        
           |  |  | 742 |      * @param {EventFacade} e
 | 
        
           |  |  | 743 |      */
 | 
        
           |  |  | 744 |     dragEnd: function(e) {
 | 
        
           |  |  | 745 |         var drag = e.target,
 | 
        
           |  |  | 746 |             node = drag.get('node');
 | 
        
           |  |  | 747 |         node.removeClass('course-being-dragged');
 | 
        
           |  |  | 748 |         this.get('console').get('element').all('#category-listing li.highlight').removeClass('highlight');
 | 
        
           |  |  | 749 |     },
 | 
        
           |  |  | 750 |   | 
        
           |  |  | 751 |     /**
 | 
        
           |  |  | 752 |      * Dragging in progress.
 | 
        
           |  |  | 753 |      * @method dragDrag
 | 
        
           |  |  | 754 |      * @private
 | 
        
           |  |  | 755 |      * @param {EventFacade} e
 | 
        
           |  |  | 756 |      */
 | 
        
           |  |  | 757 |     dragDrag: function(e) {
 | 
        
           |  |  | 758 |         var y = e.target.lastXY[1];
 | 
        
           |  |  | 759 |         if (y < this.lasty) {
 | 
        
           |  |  | 760 |             this.goingup = true;
 | 
        
           |  |  | 761 |         } else {
 | 
        
           |  |  | 762 |             this.goingup = false;
 | 
        
           |  |  | 763 |         }
 | 
        
           |  |  | 764 |         this.lasty = y;
 | 
        
           |  |  | 765 |     },
 | 
        
           |  |  | 766 |   | 
        
           |  |  | 767 |     /**
 | 
        
           |  |  | 768 |      * The course has been dragged over a drop target.
 | 
        
           |  |  | 769 |      * @method dropOver
 | 
        
           |  |  | 770 |      * @private
 | 
        
           |  |  | 771 |      * @param {EventFacade} e
 | 
        
           |  |  | 772 |      */
 | 
        
           |  |  | 773 |     dropOver: function(e) {
 | 
        
           |  |  | 774 |         // Get a reference to our drag and drop nodes
 | 
        
           |  |  | 775 |         var drag = e.drag.get('node'),
 | 
        
           |  |  | 776 |             drop = e.drop.get('node'),
 | 
        
           |  |  | 777 |             tag = drop.get('tagName').toLowerCase();
 | 
        
           |  |  | 778 |         if (tag === 'li' && drop.hasClass('listitem-course')) {
 | 
        
           |  |  | 779 |             if (!this.goingup) {
 | 
        
           |  |  | 780 |                 drop = drop.get('nextSibling');
 | 
        
           |  |  | 781 |                 if (!drop) {
 | 
        
           |  |  | 782 |                     drop = e.drop.get('node');
 | 
        
           |  |  | 783 |                     drop.get('parentNode').append(drag);
 | 
        
           |  |  | 784 |                     return false;
 | 
        
           |  |  | 785 |                 }
 | 
        
           |  |  | 786 |             }
 | 
        
           |  |  | 787 |             drop.get('parentNode').insertBefore(drag, drop);
 | 
        
           |  |  | 788 |             e.drop.sizeShim();
 | 
        
           |  |  | 789 |         }
 | 
        
           |  |  | 790 |     },
 | 
        
           |  |  | 791 |   | 
        
           |  |  | 792 |     /**
 | 
        
           |  |  | 793 |      * The course has been dragged over a drop target.
 | 
        
           |  |  | 794 |      * @method dropEnter
 | 
        
           |  |  | 795 |      * @private
 | 
        
           |  |  | 796 |      * @param {EventFacade} e
 | 
        
           |  |  | 797 |      */
 | 
        
           |  |  | 798 |     dropEnter: function(e) {
 | 
        
           |  |  | 799 |         var drop = e.drop.get('node'),
 | 
        
           |  |  | 800 |             tag = drop.get('tagName').toLowerCase();
 | 
        
           |  |  | 801 |         if (tag === 'div') {
 | 
        
           |  |  | 802 |             drop.ancestor('li.listitem-category').addClass('highlight');
 | 
        
           |  |  | 803 |         }
 | 
        
           |  |  | 804 |     },
 | 
        
           |  |  | 805 |   | 
        
           |  |  | 806 |     /**
 | 
        
           |  |  | 807 |      * The course has been dragged off a drop target.
 | 
        
           |  |  | 808 |      * @method dropExit
 | 
        
           |  |  | 809 |      * @private
 | 
        
           |  |  | 810 |      * @param {EventFacade} e
 | 
        
           |  |  | 811 |      */
 | 
        
           |  |  | 812 |     dropExit: function(e) {
 | 
        
           |  |  | 813 |         var drop = e.drop.get('node'),
 | 
        
           |  |  | 814 |             tag = drop.get('tagName').toLowerCase();
 | 
        
           |  |  | 815 |         if (tag === 'div') {
 | 
        
           |  |  | 816 |             drop.ancestor('li.listitem-category').removeClass('highlight');
 | 
        
           |  |  | 817 |         }
 | 
        
           |  |  | 818 |     },
 | 
        
           |  |  | 819 |   | 
        
           |  |  | 820 |     /**
 | 
        
           |  |  | 821 |      * The course has been dropped on a target.
 | 
        
           |  |  | 822 |      * @method dropHit
 | 
        
           |  |  | 823 |      * @private
 | 
        
           |  |  | 824 |      * @param {EventFacade} e
 | 
        
           |  |  | 825 |      */
 | 
        
           |  |  | 826 |     dropHit: function(e) {
 | 
        
           |  |  | 827 |         var drag = e.drag.get('node'),
 | 
        
           |  |  | 828 |             drop = e.drop.get('node'),
 | 
        
           |  |  | 829 |             iscategory = (drop.ancestor('.listitem-category') !== null),
 | 
        
           |  |  | 830 |             iscourse = !iscategory && (drop.test('.listitem-course')),
 | 
        
           |  |  | 831 |             managementconsole = this.get('console'),
 | 
        
           |  |  | 832 |             categoryid,
 | 
        
           |  |  | 833 |             category,
 | 
        
           |  |  | 834 |             courseid,
 | 
        
           |  |  | 835 |             course,
 | 
        
           |  |  | 836 |             aftercourseid,
 | 
        
           |  |  | 837 |             previoussibling,
 | 
        
           |  |  | 838 |             previousid;
 | 
        
           |  |  | 839 |   | 
        
           |  |  | 840 |         if (!drag.test('.listitem-course')) {
 | 
        
           |  |  | 841 |             Y.log('It was not a course being dragged.', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 842 |             return false;
 | 
        
           |  |  | 843 |         }
 | 
        
           |  |  | 844 |         courseid = drag.getData('id');
 | 
        
           |  |  | 845 |         if (iscategory) {
 | 
        
           |  |  | 846 |             categoryid = drop.ancestor('.listitem-category').getData('id');
 | 
        
           |  |  | 847 |             Y.log('Course ' + courseid + ' dragged into category ' + categoryid);
 | 
        
           |  |  | 848 |             category = managementconsole.getCategoryById(categoryid);
 | 
        
           |  |  | 849 |             if (category) {
 | 
        
           |  |  | 850 |                 course = managementconsole.getCourseById(courseid);
 | 
        
           |  |  | 851 |                 if (course) {
 | 
        
           |  |  | 852 |                     category.moveCourseTo(course);
 | 
        
           |  |  | 853 |                 }
 | 
        
           |  |  | 854 |             }
 | 
        
           |  |  | 855 |         } else if (iscourse || drop.ancestor('#course-listing')) {
 | 
        
           |  |  | 856 |             course = managementconsole.getCourseById(courseid);
 | 
        
           |  |  | 857 |             previoussibling = drag.get('previousSibling');
 | 
        
           |  |  | 858 |             aftercourseid = (previoussibling) ? previoussibling.getData('id') || 0 : 0;
 | 
        
           |  |  | 859 |             previousid = (this.previoussibling) ? this.previoussibling.getData('id') : 0;
 | 
        
           |  |  | 860 |             if (aftercourseid !== previousid) {
 | 
        
           |  |  | 861 |                 course.moveAfter(aftercourseid, previousid);
 | 
        
           |  |  | 862 |             }
 | 
        
           |  |  | 863 |         } else {
 | 
        
           |  |  | 864 |             Y.log('Course dropped over unhandled target.', 'info', 'moodle-course-management');
 | 
        
           |  |  | 865 |         }
 | 
        
           |  |  | 866 |     }
 | 
        
           |  |  | 867 | };
 | 
        
           |  |  | 868 | Y.extend(DragDrop, Y.Base, DragDrop.prototype);
 | 
        
           |  |  | 869 | /**
 | 
        
           |  |  | 870 |  * A managed course.
 | 
        
           |  |  | 871 |  *
 | 
        
           |  |  | 872 |  * @namespace M.course.management
 | 
        
           |  |  | 873 |  * @class Item
 | 
        
           |  |  | 874 |  * @constructor
 | 
        
           |  |  | 875 |  * @extends Base
 | 
        
           |  |  | 876 |  */
 | 
        
           |  |  | 877 | Item = function() {
 | 
        
           |  |  | 878 |     Item.superclass.constructor.apply(this, arguments);
 | 
        
           |  |  | 879 | };
 | 
        
           |  |  | 880 | Item.NAME = 'moodle-course-management-item';
 | 
        
           |  |  | 881 | Item.CSS_PREFIX = 'management-item';
 | 
        
           |  |  | 882 | Item.ATTRS = {
 | 
        
           |  |  | 883 |     /**
 | 
        
           |  |  | 884 |      * The node for this item.
 | 
        
           |  |  | 885 |      * @attribute node
 | 
        
           |  |  | 886 |      * @type Node
 | 
        
           |  |  | 887 |      */
 | 
        
           |  |  | 888 |     node: {},
 | 
        
           |  |  | 889 |   | 
        
           |  |  | 890 |     /**
 | 
        
           |  |  | 891 |      * The management console.
 | 
        
           |  |  | 892 |      * @attribute console
 | 
        
           |  |  | 893 |      * @type Console
 | 
        
           |  |  | 894 |      */
 | 
        
           |  |  | 895 |     console: {},
 | 
        
           |  |  | 896 |   | 
        
           |  |  | 897 |     /**
 | 
        
           |  |  | 898 |      * Describes the type of this item. Should be set by the extending class.
 | 
        
           |  |  | 899 |      * @attribute itemname
 | 
        
           |  |  | 900 |      * @type {String}
 | 
        
           |  |  | 901 |      * @default item
 | 
        
           |  |  | 902 |      */
 | 
        
           |  |  | 903 |     itemname: {
 | 
        
           |  |  | 904 |         value: 'item'
 | 
        
           |  |  | 905 |     }
 | 
        
           |  |  | 906 | };
 | 
        
           |  |  | 907 | Item.prototype = {
 | 
        
           |  |  | 908 |     /**
 | 
        
           |  |  | 909 |      * The highlight timeout for this item if there is one.
 | 
        
           |  |  | 910 |      * @property highlighttimeout
 | 
        
           |  |  | 911 |      * @protected
 | 
        
           |  |  | 912 |      * @type Timeout
 | 
        
           |  |  | 913 |      * @default null
 | 
        
           |  |  | 914 |      */
 | 
        
           |  |  | 915 |     highlighttimeout: null,
 | 
        
           |  |  | 916 |   | 
        
           |  |  | 917 |     /**
 | 
        
           |  |  | 918 |      * Checks and parses an AJAX response for an item.
 | 
        
           |  |  | 919 |      *
 | 
        
           |  |  | 920 |      * @method checkAjaxResponse
 | 
        
           |  |  | 921 |      * @protected
 | 
        
           |  |  | 922 |      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
 | 
        
           |  |  | 923 |      * @param {Object} response The response from the AJAX request.
 | 
        
           |  |  | 924 |      * @param {Object} args The arguments given to the request.
 | 
        
           |  |  | 925 |      * @return {Object|Boolean}
 | 
        
           |  |  | 926 |      */
 | 
        
           |  |  | 927 |     checkAjaxResponse: function(transactionid, response, args) {
 | 
        
           |  |  | 928 |         if (response.status !== 200) {
 | 
        
           |  |  | 929 |             Y.log('Error: AJAX response resulted in non 200 status.', 'error', 'Item.checkAjaxResponse');
 | 
        
           |  |  | 930 |             return false;
 | 
        
           |  |  | 931 |         }
 | 
        
           |  |  | 932 |         if (transactionid === null || args === null) {
 | 
        
           |  |  | 933 |             Y.log('Error: Invalid AJAX response details provided.', 'error', 'Item.checkAjaxResponse');
 | 
        
           |  |  | 934 |             return false;
 | 
        
           |  |  | 935 |         }
 | 
        
           |  |  | 936 |         var outcome = Y.JSON.parse(response.responseText);
 | 
        
           |  |  | 937 |         if (outcome.error !== false) {
 | 
        
           |  |  | 938 |             new M.core.exception(outcome);
 | 
        
           |  |  | 939 |         }
 | 
        
           |  |  | 940 |         if (outcome.outcome === false) {
 | 
        
           |  |  | 941 |             return false;
 | 
        
           |  |  | 942 |         }
 | 
        
           |  |  | 943 |         return outcome;
 | 
        
           |  |  | 944 |     },
 | 
        
           |  |  | 945 |   | 
        
           |  |  | 946 |     /**
 | 
        
           |  |  | 947 |      * Moves an item up by one.
 | 
        
           |  |  | 948 |      *
 | 
        
           |  |  | 949 |      * @method moveup
 | 
        
           |  |  | 950 |      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
 | 
        
           |  |  | 951 |      * @param {Object} response The response from the AJAX request.
 | 
        
           |  |  | 952 |      * @param {Object} args The arguments given to the request.
 | 
        
           |  |  | 953 |      * @return {Boolean}
 | 
        
           |  |  | 954 |      */
 | 
        
           |  |  | 955 |     moveup: function(transactionid, response, args) {
 | 
        
           |  |  | 956 |         var node,
 | 
        
           |  |  | 957 |             nodeup,
 | 
        
           |  |  | 958 |             nodedown,
 | 
        
           |  |  | 959 |             previous,
 | 
        
           |  |  | 960 |             previousup,
 | 
        
           |  |  | 961 |             previousdown,
 | 
        
           |  |  | 962 |             tmpnode,
 | 
        
           |  |  | 963 |             outcome = this.checkAjaxResponse(transactionid, response, args);
 | 
        
           |  |  | 964 |         if (outcome === false) {
 | 
        
           |  |  | 965 |             Y.log('AJAX request to move ' + this.get('itemname') + ' up failed by outcome.', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 966 |             return false;
 | 
        
           |  |  | 967 |         }
 | 
        
           |  |  | 968 |         node = this.get('node');
 | 
        
           |  |  | 969 |         previous = node.previous('.listitem');
 | 
        
           |  |  | 970 |         if (previous) {
 | 
        
           |  |  | 971 |             previous.insert(node, 'before');
 | 
        
           |  |  | 972 |             previousup = previous.one(' > div a.action-moveup');
 | 
        
           |  |  | 973 |             nodedown = node.one(' > div a.action-movedown');
 | 
        
           |  |  | 974 |             if (!previousup || !nodedown) {
 | 
        
           |  |  | 975 |                 // We can have two situations here:
 | 
        
           |  |  | 976 |                 //   1. previousup is not set and nodedown is not set. This happens when there are only two courses.
 | 
        
           |  |  | 977 |                 //   2. nodedown is not set. This happens when they are moving the bottom course up.
 | 
        
           |  |  | 978 |                 // node up and previous down should always be there. They would be required to trigger the action.
 | 
        
           |  |  | 979 |                 nodeup = node.one(' > div a.action-moveup');
 | 
        
           |  |  | 980 |                 previousdown = previous.one(' > div a.action-movedown');
 | 
        
           |  |  | 981 |                 if (!previousup && !nodedown) {
 | 
        
           |  |  | 982 |                     // Ok, must be two courses. We need to switch the up and down icons.
 | 
        
           |  |  | 983 |                     tmpnode = Y.Node.create('<a style="visibility:hidden;"> </a>');
 | 
        
           |  |  | 984 |                     previousdown.replace(tmpnode);
 | 
        
           |  |  | 985 |                     nodeup.replace(previousdown);
 | 
        
           |  |  | 986 |                     tmpnode.replace(nodeup);
 | 
        
           |  |  | 987 |                     tmpnode.destroy();
 | 
        
           |  |  | 988 |                 } else if (!nodedown) {
 | 
        
           |  |  | 989 |                     // previous down needs to be given to node.
 | 
        
           |  |  | 990 |                     nodeup.insert(previousdown, 'after');
 | 
        
           |  |  | 991 |                 }
 | 
        
           |  |  | 992 |             }
 | 
        
           |  |  | 993 |             nodeup = node.one(' > div a.action-moveup');
 | 
        
           |  |  | 994 |             if (nodeup) {
 | 
        
           |  |  | 995 |                 // Try to re-focus on up.
 | 
        
           |  |  | 996 |                 nodeup.focus();
 | 
        
           |  |  | 997 |             } else {
 | 
        
           |  |  | 998 |                 // If we can't focus up we're at the bottom, try to focus on up.
 | 
        
           |  |  | 999 |                 nodedown = node.one(' > div a.action-movedown');
 | 
        
           |  |  | 1000 |                 if (nodedown) {
 | 
        
           |  |  | 1001 |                     nodedown.focus();
 | 
        
           |  |  | 1002 |                 }
 | 
        
           |  |  | 1003 |             }
 | 
        
           |  |  | 1004 |             this.updated(true);
 | 
        
           |  |  | 1005 |             Y.log('Success: ' + this.get('itemname') + ' moved up by AJAX.', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1006 |         } else {
 | 
        
           |  |  | 1007 |             // Aha it succeeded but this is the top item in the list. Pagination is in play!
 | 
        
           |  |  | 1008 |             // Refresh to update the state of things.
 | 
        
           |  |  | 1009 |             Y.log(this.get('itemname') + ' cannot be moved up as its the top item on this page.',
 | 
        
           |  |  | 1010 |                     'info', 'moodle-course-management');
 | 
        
           |  |  | 1011 |             window.location.reload();
 | 
        
           |  |  | 1012 |         }
 | 
        
           |  |  | 1013 |     },
 | 
        
           |  |  | 1014 |   | 
        
           |  |  | 1015 |     /**
 | 
        
           |  |  | 1016 |      * Moves an item down by one.
 | 
        
           |  |  | 1017 |      *
 | 
        
           |  |  | 1018 |      * @method movedown
 | 
        
           |  |  | 1019 |      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
 | 
        
           |  |  | 1020 |      * @param {Object} response The response from the AJAX request.
 | 
        
           |  |  | 1021 |      * @param {Object} args The arguments given to the request.
 | 
        
           |  |  | 1022 |      * @return {Boolean}
 | 
        
           |  |  | 1023 |      */
 | 
        
           |  |  | 1024 |     movedown: function(transactionid, response, args) {
 | 
        
           |  |  | 1025 |         var node,
 | 
        
           |  |  | 1026 |             next,
 | 
        
           |  |  | 1027 |             nodeup,
 | 
        
           |  |  | 1028 |             nodedown,
 | 
        
           |  |  | 1029 |             nextup,
 | 
        
           |  |  | 1030 |             nextdown,
 | 
        
           |  |  | 1031 |             tmpnode,
 | 
        
           |  |  | 1032 |             outcome = this.checkAjaxResponse(transactionid, response, args);
 | 
        
           |  |  | 1033 |         if (outcome === false) {
 | 
        
           |  |  | 1034 |             Y.log('AJAX request to move ' + this.get('itemname') + ' down failed by outcome.', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1035 |             return false;
 | 
        
           |  |  | 1036 |         }
 | 
        
           |  |  | 1037 |         node = this.get('node');
 | 
        
           |  |  | 1038 |         next = node.next('.listitem');
 | 
        
           |  |  | 1039 |         if (next) {
 | 
        
           |  |  | 1040 |             node.insert(next, 'before');
 | 
        
           |  |  | 1041 |             nextdown = next.one(' > div a.action-movedown');
 | 
        
           |  |  | 1042 |             nodeup = node.one(' > div a.action-moveup');
 | 
        
           |  |  | 1043 |             if (!nextdown || !nodeup) {
 | 
        
           |  |  | 1044 |                 // next up and node down should always be there. They would be required to trigger the action.
 | 
        
           |  |  | 1045 |                 nextup = next.one(' > div a.action-moveup');
 | 
        
           |  |  | 1046 |                 nodedown = node.one(' > div a.action-movedown');
 | 
        
           |  |  | 1047 |                 if (!nextdown && !nodeup) {
 | 
        
           |  |  | 1048 |                     // We can have two situations here:
 | 
        
           |  |  | 1049 |                     //   1. nextdown is not set and nodeup is not set. This happens when there are only two courses.
 | 
        
           |  |  | 1050 |                     //   2. nodeup is not set. This happens when we are moving the first course down.
 | 
        
           |  |  | 1051 |                     // Ok, must be two courses. We need to switch the up and down icons.
 | 
        
           |  |  | 1052 |                     tmpnode = Y.Node.create('<a style="visibility:hidden;"> </a>');
 | 
        
           |  |  | 1053 |                     nextup.replace(tmpnode);
 | 
        
           |  |  | 1054 |                     nodedown.replace(nextup);
 | 
        
           |  |  | 1055 |                     tmpnode.replace(nodedown);
 | 
        
           |  |  | 1056 |                     tmpnode.destroy();
 | 
        
           |  |  | 1057 |                 } else if (!nodeup) {
 | 
        
           |  |  | 1058 |                     // next up needs to be given to node.
 | 
        
           |  |  | 1059 |                     nodedown.insert(nextup, 'before');
 | 
        
           |  |  | 1060 |                 }
 | 
        
           |  |  | 1061 |             }
 | 
        
           |  |  | 1062 |             nodedown = node.one(' > div a.action-movedown');
 | 
        
           |  |  | 1063 |             if (nodedown) {
 | 
        
           |  |  | 1064 |                 // Try to ensure the up is focused again.
 | 
        
           |  |  | 1065 |                 nodedown.focus();
 | 
        
           |  |  | 1066 |             } else {
 | 
        
           |  |  | 1067 |                 // If we can't focus up we're at the top, try to focus on down.
 | 
        
           |  |  | 1068 |                 nodeup = node.one(' > div a.action-moveup');
 | 
        
           |  |  | 1069 |                 if (nodeup) {
 | 
        
           |  |  | 1070 |                     nodeup.focus();
 | 
        
           |  |  | 1071 |                 }
 | 
        
           |  |  | 1072 |             }
 | 
        
           |  |  | 1073 |             this.updated(true);
 | 
        
           |  |  | 1074 |             Y.log('Success: ' + this.get('itemname') + ' moved down by AJAX.', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1075 |         } else {
 | 
        
           |  |  | 1076 |             // Aha it succeeded but this is the bottom item in the list. Pagination is in play!
 | 
        
           |  |  | 1077 |             // Refresh to update the state of things.
 | 
        
           |  |  | 1078 |             Y.log(this.get('itemname') + ' cannot be moved down as its the top item on this page.',
 | 
        
           |  |  | 1079 |                     'info', 'moodle-course-management');
 | 
        
           |  |  | 1080 |             window.location.reload();
 | 
        
           |  |  | 1081 |         }
 | 
        
           |  |  | 1082 |     },
 | 
        
           |  |  | 1083 |   | 
        
           |  |  | 1084 |     /**
 | 
        
           |  |  | 1085 |      * Makes an item visible.
 | 
        
           |  |  | 1086 |      *
 | 
        
           |  |  | 1087 |      * @method show
 | 
        
           |  |  | 1088 |      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
 | 
        
           |  |  | 1089 |      * @param {Object} response The response from the AJAX request.
 | 
        
           |  |  | 1090 |      * @param {Object} args The arguments given to the request.
 | 
        
           |  |  | 1091 |      * @return {Boolean}
 | 
        
           |  |  | 1092 |      */
 | 
        
           |  |  | 1093 |     show: function(transactionid, response, args) {
 | 
        
           |  |  | 1094 |         var outcome = this.checkAjaxResponse(transactionid, response, args),
 | 
        
           |  |  | 1095 |             hidebtn;
 | 
        
           |  |  | 1096 |         if (outcome === false) {
 | 
        
           |  |  | 1097 |             Y.log('AJAX request to show ' + this.get('itemname') + ' by outcome.', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1098 |             return false;
 | 
        
           |  |  | 1099 |         }
 | 
        
           |  |  | 1100 |   | 
        
           |  |  | 1101 |         this.markVisible();
 | 
        
           |  |  | 1102 |         hidebtn = this.get('node').one('a[data-action=hide]');
 | 
        
           |  |  | 1103 |         if (hidebtn) {
 | 
        
           |  |  | 1104 |             hidebtn.focus();
 | 
        
           |  |  | 1105 |         }
 | 
        
           |  |  | 1106 |         this.updated();
 | 
        
           |  |  | 1107 |         Y.log('Success: ' + this.get('itemname') + ' made visible by AJAX.', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1108 |     },
 | 
        
           |  |  | 1109 |   | 
        
           |  |  | 1110 |     /**
 | 
        
           |  |  | 1111 |      * Marks the item as visible
 | 
        
           |  |  | 1112 |      * @method markVisible
 | 
        
           |  |  | 1113 |      */
 | 
        
           |  |  | 1114 |     markVisible: function() {
 | 
        
           |  |  | 1115 |         this.get('node').setAttribute('data-visible', '1');
 | 
        
           |  |  | 1116 |         Y.log('Marked ' + this.get('itemname') + ' as visible', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1117 |         return true;
 | 
        
           |  |  | 1118 |     },
 | 
        
           |  |  | 1119 |   | 
        
           |  |  | 1120 |     /**
 | 
        
           |  |  | 1121 |      * Hides an item.
 | 
        
           |  |  | 1122 |      *
 | 
        
           |  |  | 1123 |      * @method hide
 | 
        
           |  |  | 1124 |      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
 | 
        
           |  |  | 1125 |      * @param {Object} response The response from the AJAX request.
 | 
        
           |  |  | 1126 |      * @param {Object} args The arguments given to the request.
 | 
        
           |  |  | 1127 |      * @return {Boolean}
 | 
        
           |  |  | 1128 |      */
 | 
        
           |  |  | 1129 |     hide: function(transactionid, response, args) {
 | 
        
           |  |  | 1130 |         var outcome = this.checkAjaxResponse(transactionid, response, args),
 | 
        
           |  |  | 1131 |             showbtn;
 | 
        
           |  |  | 1132 |         if (outcome === false) {
 | 
        
           |  |  | 1133 |             Y.log('AJAX request to hide ' + this.get('itemname') + ' by outcome.', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1134 |             return false;
 | 
        
           |  |  | 1135 |         }
 | 
        
           |  |  | 1136 |         this.markHidden();
 | 
        
           |  |  | 1137 |         showbtn = this.get('node').one('a[data-action=show]');
 | 
        
           |  |  | 1138 |         if (showbtn) {
 | 
        
           |  |  | 1139 |             showbtn.focus();
 | 
        
           |  |  | 1140 |         }
 | 
        
           |  |  | 1141 |         this.updated();
 | 
        
           |  |  | 1142 |         Y.log('Success: ' + this.get('itemname') + ' made hidden by AJAX.', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1143 |     },
 | 
        
           |  |  | 1144 |   | 
        
           |  |  | 1145 |     /**
 | 
        
           |  |  | 1146 |      * Marks the item as hidden.
 | 
        
           |  |  | 1147 |      * @method makeHidden
 | 
        
           |  |  | 1148 |      */
 | 
        
           |  |  | 1149 |     markHidden: function() {
 | 
        
           |  |  | 1150 |         this.get('node').setAttribute('data-visible', '0');
 | 
        
           |  |  | 1151 |         Y.log('Marked ' + this.get('itemname') + ' as hidden', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1152 |         return true;
 | 
        
           |  |  | 1153 |     },
 | 
        
           |  |  | 1154 |   | 
        
           |  |  | 1155 |     /**
 | 
        
           |  |  | 1156 |      * Called when ever a node is updated.
 | 
        
           |  |  | 1157 |      *
 | 
        
           |  |  | 1158 |      * @method updated
 | 
        
           |  |  | 1159 |      * @param {Boolean} moved True if this item was moved.
 | 
        
           |  |  | 1160 |      */
 | 
        
           |  |  | 1161 |     updated: function(moved) {
 | 
        
           |  |  | 1162 |         if (moved) {
 | 
        
           |  |  | 1163 |             this.highlight();
 | 
        
           |  |  | 1164 |         }
 | 
        
           |  |  | 1165 |     },
 | 
        
           |  |  | 1166 |   | 
        
           |  |  | 1167 |     /**
 | 
        
           |  |  | 1168 |      * Highlights this option for a breif time.
 | 
        
           |  |  | 1169 |      *
 | 
        
           |  |  | 1170 |      * @method highlight
 | 
        
           |  |  | 1171 |      */
 | 
        
           |  |  | 1172 |     highlight: function() {
 | 
        
           |  |  | 1173 |         var node = this.get('node');
 | 
        
           |  |  | 1174 |         node.siblings('.highlight').removeClass('highlight');
 | 
        
           |  |  | 1175 |         node.addClass('highlight');
 | 
        
           |  |  | 1176 |         if (this.highlighttimeout) {
 | 
        
           |  |  | 1177 |             window.clearTimeout(this.highlighttimeout);
 | 
        
           |  |  | 1178 |         }
 | 
        
           |  |  | 1179 |         this.highlighttimeout = window.setTimeout(function() {
 | 
        
           |  |  | 1180 |             node.removeClass('highlight');
 | 
        
           |  |  | 1181 |         }, 2500);
 | 
        
           |  |  | 1182 |     }
 | 
        
           |  |  | 1183 | };
 | 
        
           |  |  | 1184 | Y.extend(Item, Y.Base, Item.prototype);
 | 
        
           |  |  | 1185 | /**
 | 
        
           |  |  | 1186 |  * A managed category.
 | 
        
           |  |  | 1187 |  *
 | 
        
           |  |  | 1188 |  * @namespace M.course.management
 | 
        
           |  |  | 1189 |  * @class Category
 | 
        
           |  |  | 1190 |  * @constructor
 | 
        
           |  |  | 1191 |  * @extends Item
 | 
        
           |  |  | 1192 |  */
 | 
        
           |  |  | 1193 | Category = function() {
 | 
        
           |  |  | 1194 |     Category.superclass.constructor.apply(this, arguments);
 | 
        
           |  |  | 1195 | };
 | 
        
           |  |  | 1196 | Category.NAME = 'moodle-course-management-category';
 | 
        
           |  |  | 1197 | Category.CSS_PREFIX = 'management-category';
 | 
        
           |  |  | 1198 | Category.ATTRS = {
 | 
        
           |  |  | 1199 |     /**
 | 
        
           |  |  | 1200 |      * The category ID relating to this category.
 | 
        
           |  |  | 1201 |      * @attribute categoryid
 | 
        
           |  |  | 1202 |      * @type Number
 | 
        
           |  |  | 1203 |      * @writeOnce
 | 
        
           |  |  | 1204 |      * @default null
 | 
        
           |  |  | 1205 |      */
 | 
        
           |  |  | 1206 |     categoryid: {
 | 
        
           |  |  | 1207 |         getter: function(value, name) {
 | 
        
           |  |  | 1208 |             if (value === null) {
 | 
        
           |  |  | 1209 |                 value = this.get('node').getData('id');
 | 
        
           |  |  | 1210 |                 this.set(name, value);
 | 
        
           |  |  | 1211 |             }
 | 
        
           |  |  | 1212 |             return value;
 | 
        
           |  |  | 1213 |         },
 | 
        
           |  |  | 1214 |         value: null,
 | 
        
           |  |  | 1215 |         writeOnce: true
 | 
        
           |  |  | 1216 |     },
 | 
        
           |  |  | 1217 |   | 
        
           |  |  | 1218 |     /**
 | 
        
           |  |  | 1219 |      * True if this category is the currently selected category.
 | 
        
           |  |  | 1220 |      * @attribute selected
 | 
        
           |  |  | 1221 |      * @type Boolean
 | 
        
           |  |  | 1222 |      * @default null
 | 
        
           |  |  | 1223 |      */
 | 
        
           |  |  | 1224 |     selected: {
 | 
        
           |  |  | 1225 |         getter: function(value, name) {
 | 
        
           |  |  | 1226 |             if (value === null) {
 | 
        
           |  |  | 1227 |                 value = this.get('node').getData(name);
 | 
        
           |  |  | 1228 |                 if (value === null) {
 | 
        
           |  |  | 1229 |                     value = false;
 | 
        
           |  |  | 1230 |                 }
 | 
        
           |  |  | 1231 |                 this.set(name, value);
 | 
        
           |  |  | 1232 |             }
 | 
        
           |  |  | 1233 |             return value;
 | 
        
           |  |  | 1234 |         },
 | 
        
           |  |  | 1235 |         value: null
 | 
        
           |  |  | 1236 |     },
 | 
        
           |  |  | 1237 |   | 
        
           |  |  | 1238 |     /**
 | 
        
           |  |  | 1239 |      * An array of courses belonging to this category.
 | 
        
           |  |  | 1240 |      * @attribute courses
 | 
        
           |  |  | 1241 |      * @type Course[]
 | 
        
           |  |  | 1242 |      * @default Array
 | 
        
           |  |  | 1243 |      */
 | 
        
           |  |  | 1244 |     courses: {
 | 
        
           |  |  | 1245 |         validator: function(val) {
 | 
        
           |  |  | 1246 |             return Y.Lang.isArray(val);
 | 
        
           |  |  | 1247 |         },
 | 
        
           |  |  | 1248 |         value: []
 | 
        
           |  |  | 1249 |     }
 | 
        
           |  |  | 1250 | };
 | 
        
           |  |  | 1251 | Category.prototype = {
 | 
        
           |  |  | 1252 |     /**
 | 
        
           |  |  | 1253 |      * Initialises an instance of a Category.
 | 
        
           |  |  | 1254 |      * @method initializer
 | 
        
           |  |  | 1255 |      */
 | 
        
           |  |  | 1256 |     initializer: function() {
 | 
        
           |  |  | 1257 |         this.set('itemname', 'category');
 | 
        
           |  |  | 1258 |     },
 | 
        
           |  |  | 1259 |   | 
        
           |  |  | 1260 |     /**
 | 
        
           |  |  | 1261 |      * Returns the name of the category.
 | 
        
           |  |  | 1262 |      * @method getName
 | 
        
           |  |  | 1263 |      * @return {String}
 | 
        
           |  |  | 1264 |      */
 | 
        
           |  |  | 1265 |     getName: function() {
 | 
        
           |  |  | 1266 |         return this.get('node').one('a.categoryname').get('innerHTML');
 | 
        
           |  |  | 1267 |     },
 | 
        
           |  |  | 1268 |   | 
        
           |  |  | 1269 |     /**
 | 
        
           |  |  | 1270 |      * Registers a course as belonging to this category.
 | 
        
           |  |  | 1271 |      * @method registerCourse
 | 
        
           |  |  | 1272 |      * @param {Course} course
 | 
        
           |  |  | 1273 |      */
 | 
        
           |  |  | 1274 |     registerCourse: function(course) {
 | 
        
           |  |  | 1275 |         var courses = this.get('courses');
 | 
        
           |  |  | 1276 |         courses.push(course);
 | 
        
           |  |  | 1277 |         this.set('courses', courses);
 | 
        
           |  |  | 1278 |     },
 | 
        
           |  |  | 1279 |   | 
        
           |  |  | 1280 |     /**
 | 
        
           |  |  | 1281 |      * Handles a category related event.
 | 
        
           |  |  | 1282 |      *
 | 
        
           |  |  | 1283 |      * @method handle
 | 
        
           |  |  | 1284 |      * @param {String} action
 | 
        
           |  |  | 1285 |      * @param {EventFacade} e
 | 
        
           |  |  | 1286 |      * @return {Boolean}
 | 
        
           |  |  | 1287 |      */
 | 
        
           |  |  | 1288 |     handle: function(action, e) {
 | 
        
           |  |  | 1289 |         var catarg = {categoryid: this.get('categoryid')},
 | 
        
           |  |  | 1290 |             selected = this.get('console').get('activecategoryid');
 | 
        
           |  |  | 1291 |         if (selected && selected !== catarg.categoryid) {
 | 
        
           |  |  | 1292 |             catarg.selectedcategory = selected;
 | 
        
           |  |  | 1293 |         }
 | 
        
           |  |  | 1294 |         switch (action) {
 | 
        
           |  |  | 1295 |             case 'moveup':
 | 
        
           |  |  | 1296 |                 e.preventDefault();
 | 
        
           |  |  | 1297 |                 this.get('console').performAjaxAction('movecategoryup', catarg, this.moveup, this);
 | 
        
           |  |  | 1298 |                 break;
 | 
        
           |  |  | 1299 |             case 'movedown':
 | 
        
           |  |  | 1300 |                 e.preventDefault();
 | 
        
           |  |  | 1301 |                 this.get('console').performAjaxAction('movecategorydown', catarg, this.movedown, this);
 | 
        
           |  |  | 1302 |                 break;
 | 
        
           |  |  | 1303 |             case 'show':
 | 
        
           |  |  | 1304 |                 e.preventDefault();
 | 
        
           |  |  | 1305 |                 this.get('console').performAjaxAction('showcategory', catarg, this.show, this);
 | 
        
           |  |  | 1306 |                 break;
 | 
        
           |  |  | 1307 |             case 'hide':
 | 
        
           |  |  | 1308 |                 e.preventDefault();
 | 
        
           | 1441 | ariadna | 1309 |                 var courseCount = this.get('node').getData('course-count');
 | 
        
           |  |  | 1310 |                 if (courseCount === '0') {
 | 
        
           |  |  | 1311 |                     this.get('console').performAjaxAction('hidecategory', catarg, this.hide, this);
 | 
        
           |  |  | 1312 |                     break;
 | 
        
           |  |  | 1313 |                 }
 | 
        
           |  |  | 1314 |                 var warningStr = courseCount === '1' ? 'hidecategoryone' : 'hidecategorymany';
 | 
        
           |  |  | 1315 |                 var warningParams = {
 | 
        
           |  |  | 1316 |                     category: this.get('node').getData('category-name'),
 | 
        
           |  |  | 1317 |                     coursecount: courseCount,
 | 
        
           |  |  | 1318 |                 };
 | 
        
           |  |  | 1319 |                 require(['core/notification', 'core/str'], function(Notification, Str) {
 | 
        
           |  |  | 1320 |                     Notification.saveCancelPromise(
 | 
        
           |  |  | 1321 |                         Str.get_string('hidecategory'),
 | 
        
           |  |  | 1322 |                         Str.get_string(warningStr, 'core', warningParams),
 | 
        
           |  |  | 1323 |                         Str.get_string('hide')
 | 
        
           |  |  | 1324 |                     ).then(function() {
 | 
        
           |  |  | 1325 |                         this.get('console').performAjaxAction('hidecategory', catarg, this.hide, this);
 | 
        
           |  |  | 1326 |                     }.bind(this)
 | 
        
           |  |  | 1327 |                     ).catch(function() {
 | 
        
           |  |  | 1328 |                         // User cancelled, no action needed.
 | 
        
           |  |  | 1329 |                     });
 | 
        
           |  |  | 1330 |                 }.bind(this));
 | 
        
           | 1 | efrain | 1331 |                 break;
 | 
        
           |  |  | 1332 |             case 'expand':
 | 
        
           |  |  | 1333 |                 e.preventDefault();
 | 
        
           |  |  | 1334 |                 if (this.get('node').getData('expanded') === '0') {
 | 
        
           |  |  | 1335 |                     this.get('node').setAttribute('data-expanded', '1').setData('expanded', 'true');
 | 
        
           |  |  | 1336 |                     this.get('console').performAjaxAction('getsubcategorieshtml', catarg, this.loadSubcategories, this);
 | 
        
           |  |  | 1337 |                 }
 | 
        
           |  |  | 1338 |                 this.expand();
 | 
        
           |  |  | 1339 |                 break;
 | 
        
           |  |  | 1340 |             case 'collapse':
 | 
        
           |  |  | 1341 |                 e.preventDefault();
 | 
        
           |  |  | 1342 |                 this.collapse();
 | 
        
           |  |  | 1343 |                 break;
 | 
        
           |  |  | 1344 |             case 'select':
 | 
        
           |  |  | 1345 |                 var c = this.get('console'),
 | 
        
           |  |  | 1346 |                     movecategoryto = c.get('categorylisting').one('#menumovecategoriesto');
 | 
        
           |  |  | 1347 |                 // If any category is selected and there are more then one categories.
 | 
        
           |  |  | 1348 |                 if (movecategoryto) {
 | 
        
           |  |  | 1349 |                     if (c.isCategorySelected(e.currentTarget) &&
 | 
        
           |  |  | 1350 |                             c.get('categories').length > 1) {
 | 
        
           |  |  | 1351 |                         movecategoryto.removeAttribute('disabled');
 | 
        
           |  |  | 1352 |                     } else {
 | 
        
           |  |  | 1353 |                         movecategoryto.setAttribute('disabled', true);
 | 
        
           |  |  | 1354 |                     }
 | 
        
           |  |  | 1355 |                     c.handleBulkSortByaction();
 | 
        
           |  |  | 1356 |                 }
 | 
        
           |  |  | 1357 |                 break;
 | 
        
           |  |  | 1358 |             default:
 | 
        
           |  |  | 1359 |                 Y.log('Invalid AJAX action requested of managed category.', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1360 |                 return false;
 | 
        
           |  |  | 1361 |         }
 | 
        
           |  |  | 1362 |     },
 | 
        
           |  |  | 1363 |   | 
        
           |  |  | 1364 |     /**
 | 
        
           |  |  | 1365 |      * Expands the category making its sub categories visible.
 | 
        
           |  |  | 1366 |      * @method expand
 | 
        
           |  |  | 1367 |      */
 | 
        
           |  |  | 1368 |     expand: function() {
 | 
        
           |  |  | 1369 |         var node = this.get('node'),
 | 
        
           |  |  | 1370 |             action = node.one('a[data-action=expand]'),
 | 
        
           |  |  | 1371 |             ul = node.one('ul[role=group]');
 | 
        
           |  |  | 1372 |         node.removeClass('collapsed').setAttribute('aria-expanded', 'true');
 | 
        
           |  |  | 1373 |         action.setAttribute('data-action', 'collapse').setAttrs({
 | 
        
           |  |  | 1374 |             title: M.util.get_string('collapsecategory', 'moodle', this.getName())
 | 
        
           |  |  | 1375 |         });
 | 
        
           |  |  | 1376 |   | 
        
           |  |  | 1377 |         require(['core/str', 'core/templates', 'core/notification'], function(Str, Templates, Notification) {
 | 
        
           |  |  | 1378 |             Str.get_string('collapse', 'core')
 | 
        
           |  |  | 1379 |                 .then(function(string) {
 | 
        
           |  |  | 1380 |                     return Templates.renderPix('t/switch_minus', 'core', string);
 | 
        
           |  |  | 1381 |                 })
 | 
        
           |  |  | 1382 |                 .then(function(html) {
 | 
        
           |  |  | 1383 |                     html = Y.Node.create(html).addClass('tree-icon').getDOMNode().outerHTML;
 | 
        
           |  |  | 1384 |                     return action.set('innerHTML', html);
 | 
        
           |  |  | 1385 |                 }).fail(Notification.exception);
 | 
        
           |  |  | 1386 |         });
 | 
        
           |  |  | 1387 |   | 
        
           |  |  | 1388 |         if (ul) {
 | 
        
           |  |  | 1389 |             ul.setAttribute('aria-hidden', 'false');
 | 
        
           |  |  | 1390 |         }
 | 
        
           |  |  | 1391 |         this.get('console').performAjaxAction('expandcategory', {categoryid: this.get('categoryid')}, null, this);
 | 
        
           |  |  | 1392 |     },
 | 
        
           |  |  | 1393 |   | 
        
           |  |  | 1394 |     /**
 | 
        
           |  |  | 1395 |      * Collapses the category making its sub categories hidden.
 | 
        
           |  |  | 1396 |      * @method collapse
 | 
        
           |  |  | 1397 |      */
 | 
        
           |  |  | 1398 |     collapse: function() {
 | 
        
           |  |  | 1399 |         var node = this.get('node'),
 | 
        
           |  |  | 1400 |             action = node.one('a[data-action=collapse]'),
 | 
        
           |  |  | 1401 |             ul = node.one('ul[role=group]');
 | 
        
           |  |  | 1402 |         node.addClass('collapsed').setAttribute('aria-expanded', 'false');
 | 
        
           |  |  | 1403 |         action.setAttribute('data-action', 'expand').setAttrs({
 | 
        
           |  |  | 1404 |             title: M.util.get_string('expandcategory', 'moodle', this.getName())
 | 
        
           |  |  | 1405 |         });
 | 
        
           |  |  | 1406 |   | 
        
           |  |  | 1407 |         require(['core/str', 'core/templates', 'core/notification'], function(Str, Templates, Notification) {
 | 
        
           |  |  | 1408 |             Str.get_string('expand', 'core')
 | 
        
           |  |  | 1409 |                 .then(function(string) {
 | 
        
           |  |  | 1410 |                     return Templates.renderPix('t/switch_plus', 'core', string);
 | 
        
           |  |  | 1411 |                 })
 | 
        
           |  |  | 1412 |                 .then(function(html) {
 | 
        
           |  |  | 1413 |                     html = Y.Node.create(html).addClass('tree-icon').getDOMNode().outerHTML;
 | 
        
           |  |  | 1414 |                     return action.set('innerHTML', html);
 | 
        
           |  |  | 1415 |                 }).fail(Notification.exception);
 | 
        
           |  |  | 1416 |         });
 | 
        
           |  |  | 1417 |   | 
        
           |  |  | 1418 |         if (ul) {
 | 
        
           |  |  | 1419 |             ul.setAttribute('aria-hidden', 'true');
 | 
        
           |  |  | 1420 |         }
 | 
        
           |  |  | 1421 |         this.get('console').performAjaxAction('collapsecategory', {categoryid: this.get('categoryid')}, null, this);
 | 
        
           |  |  | 1422 |     },
 | 
        
           |  |  | 1423 |   | 
        
           |  |  | 1424 |     /**
 | 
        
           |  |  | 1425 |      * Loads sub categories provided by an AJAX request..
 | 
        
           |  |  | 1426 |      *
 | 
        
           |  |  | 1427 |      * @method loadSubcategories
 | 
        
           |  |  | 1428 |      * @protected
 | 
        
           |  |  | 1429 |      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
 | 
        
           |  |  | 1430 |      * @param {Object} response The response from the AJAX request.
 | 
        
           |  |  | 1431 |      * @param {Object} args The arguments given to the request.
 | 
        
           |  |  | 1432 |      * @return {Boolean} Returns true on success - false otherwise.
 | 
        
           |  |  | 1433 |      */
 | 
        
           |  |  | 1434 |     loadSubcategories: function(transactionid, response, args) {
 | 
        
           |  |  | 1435 |         var outcome = this.checkAjaxResponse(transactionid, response, args),
 | 
        
           |  |  | 1436 |             node = this.get('node'),
 | 
        
           |  |  | 1437 |             managementconsole = this.get('console'),
 | 
        
           |  |  | 1438 |             ul,
 | 
        
           |  |  | 1439 |             actionnode;
 | 
        
           |  |  | 1440 |         if (outcome === false) {
 | 
        
           |  |  | 1441 |             Y.log('AJAX failed to load sub categories for ' + this.get('itemname'), 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1442 |             return false;
 | 
        
           |  |  | 1443 |         }
 | 
        
           |  |  | 1444 |         Y.log('AJAX loaded subcategories for ' + this.get('itemname'), 'info', 'moodle-course-management');
 | 
        
           |  |  | 1445 |         node.append(outcome.html);
 | 
        
           |  |  | 1446 |         managementconsole.initialiseCategories(node);
 | 
        
           |  |  | 1447 |         if (M.core && M.core.actionmenu && M.core.actionmenu.newDOMNode) {
 | 
        
           |  |  | 1448 |             M.core.actionmenu.newDOMNode(node);
 | 
        
           |  |  | 1449 |         }
 | 
        
           |  |  | 1450 |         ul = node.one('ul[role=group]');
 | 
        
           |  |  | 1451 |         actionnode = node.one('a[data-action=collapse]');
 | 
        
           |  |  | 1452 |         if (ul && actionnode) {
 | 
        
           |  |  | 1453 |             actionnode.setAttribute('aria-controls', ul.generateID());
 | 
        
           |  |  | 1454 |         }
 | 
        
           |  |  | 1455 |         return true;
 | 
        
           |  |  | 1456 |     },
 | 
        
           |  |  | 1457 |   | 
        
           |  |  | 1458 |     /**
 | 
        
           |  |  | 1459 |      * Moves the course to this category.
 | 
        
           |  |  | 1460 |      *
 | 
        
           |  |  | 1461 |      * @method moveCourseTo
 | 
        
           |  |  | 1462 |      * @param {Course} course
 | 
        
           |  |  | 1463 |      */
 | 
        
           |  |  | 1464 |     moveCourseTo: function(course) {
 | 
        
           |  |  | 1465 |         require(['core/notification'], function(Notification) {
 | 
        
           |  |  | 1466 |             Notification.saveCancelPromise(
 | 
        
           |  |  | 1467 |                 M.util.get_string('confirmation', 'admin'),
 | 
        
           |  |  | 1468 |                 M.util.get_string('confirmcoursemove', 'moodle',
 | 
        
           |  |  | 1469 |                 {
 | 
        
           |  |  | 1470 |                     course: course.getName(),
 | 
        
           |  |  | 1471 |                     category: this.getName(),
 | 
        
           |  |  | 1472 |                 }),
 | 
        
           |  |  | 1473 |                 M.util.get_string('move', 'moodle')
 | 
        
           |  |  | 1474 |             ).then(function() {
 | 
        
           |  |  | 1475 |                 this.get('console').performAjaxAction('movecourseintocategory', {
 | 
        
           |  |  | 1476 |                     courseid: course.get('courseid'),
 | 
        
           |  |  | 1477 |                     categoryid: this.get('categoryid'),
 | 
        
           |  |  | 1478 |                 }, this.completeMoveCourse, this);
 | 
        
           |  |  | 1479 |                 return;
 | 
        
           |  |  | 1480 |             }.bind(this)).catch(function() {
 | 
        
           |  |  | 1481 |                 // User cancelled.
 | 
        
           |  |  | 1482 |             });
 | 
        
           |  |  | 1483 |         }.bind(this));
 | 
        
           |  |  | 1484 |     },
 | 
        
           |  |  | 1485 |   | 
        
           |  |  | 1486 |     /**
 | 
        
           |  |  | 1487 |      * Completes moving a course to this category.
 | 
        
           |  |  | 1488 |      * @method completeMoveCourse
 | 
        
           |  |  | 1489 |      * @protected
 | 
        
           |  |  | 1490 |      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
 | 
        
           |  |  | 1491 |      * @param {Object} response The response from the AJAX request.
 | 
        
           |  |  | 1492 |      * @param {Object} args The arguments given to the request.
 | 
        
           |  |  | 1493 |      * @return {Boolean}
 | 
        
           |  |  | 1494 |      */
 | 
        
           |  |  | 1495 |     completeMoveCourse: function(transactionid, response, args) {
 | 
        
           |  |  | 1496 |         var outcome = this.checkAjaxResponse(transactionid, response, args),
 | 
        
           |  |  | 1497 |             managementconsole = this.get('console'),
 | 
        
           |  |  | 1498 |             category,
 | 
        
           |  |  | 1499 |             course,
 | 
        
           |  |  | 1500 |             totals;
 | 
        
           |  |  | 1501 |         if (outcome === false) {
 | 
        
           |  |  | 1502 |             Y.log('AJAX failed to move courses into this category: ' + this.get('itemname'), 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1503 |             return false;
 | 
        
           |  |  | 1504 |         }
 | 
        
           |  |  | 1505 |         course = managementconsole.getCourseById(args.courseid);
 | 
        
           |  |  | 1506 |         if (!course) {
 | 
        
           |  |  | 1507 |             Y.log('Course was moved but the course listing could not be found to reflect this', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1508 |             return false;
 | 
        
           |  |  | 1509 |         }
 | 
        
           |  |  | 1510 |         Y.log('Moved the course (' + course.getName() + ') into this category (' + this.getName() + ')',
 | 
        
           |  |  | 1511 |             'debug', 'moodle-course-management');
 | 
        
           |  |  | 1512 |         this.highlight();
 | 
        
           |  |  | 1513 |         if (course) {
 | 
        
           |  |  | 1514 |             if (outcome.paginationtotals) {
 | 
        
           |  |  | 1515 |                 totals = managementconsole.get('courselisting').one('.listing-pagination-totals');
 | 
        
           |  |  | 1516 |                 if (totals) {
 | 
        
           |  |  | 1517 |                     totals.set('innerHTML', outcome.paginationtotals);
 | 
        
           |  |  | 1518 |                 }
 | 
        
           |  |  | 1519 |             }
 | 
        
           |  |  | 1520 |             if (outcome.totalcatcourses !== 'undefined') {
 | 
        
           |  |  | 1521 |                 totals = this.get('node').one('.course-count span');
 | 
        
           |  |  | 1522 |                 if (totals) {
 | 
        
           |  |  | 1523 |                     totals.set('innerHTML', totals.get('innerHTML').replace(/^\d+/, outcome.totalcatcourses));
 | 
        
           |  |  | 1524 |                 }
 | 
        
           |  |  | 1525 |             }
 | 
        
           |  |  | 1526 |             if (typeof outcome.fromcatcoursecount !== 'undefined') {
 | 
        
           |  |  | 1527 |                 category = managementconsole.get('activecategoryid');
 | 
        
           |  |  | 1528 |                 category = managementconsole.getCategoryById(category);
 | 
        
           |  |  | 1529 |                 if (category) {
 | 
        
           |  |  | 1530 |                     totals = category.get('node').one('.course-count span');
 | 
        
           |  |  | 1531 |                     if (totals) {
 | 
        
           |  |  | 1532 |                         totals.set('innerHTML', totals.get('innerHTML').replace(/^\d+/, outcome.fromcatcoursecount));
 | 
        
           |  |  | 1533 |                     }
 | 
        
           |  |  | 1534 |                 }
 | 
        
           |  |  | 1535 |             }
 | 
        
           |  |  | 1536 |             course.remove();
 | 
        
           |  |  | 1537 |         }
 | 
        
           |  |  | 1538 |         return true;
 | 
        
           |  |  | 1539 |     },
 | 
        
           |  |  | 1540 |   | 
        
           |  |  | 1541 |     /**
 | 
        
           |  |  | 1542 |      * Makes an item visible.
 | 
        
           |  |  | 1543 |      *
 | 
        
           |  |  | 1544 |      * @method show
 | 
        
           |  |  | 1545 |      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
 | 
        
           |  |  | 1546 |      * @param {Object} response The response from the AJAX request.
 | 
        
           |  |  | 1547 |      * @param {Object} args The arguments given to the request.
 | 
        
           |  |  | 1548 |      * @return {Boolean}
 | 
        
           |  |  | 1549 |      */
 | 
        
           |  |  | 1550 |     show: function(transactionid, response, args) {
 | 
        
           |  |  | 1551 |         var outcome = this.checkAjaxResponse(transactionid, response, args),
 | 
        
           |  |  | 1552 |             hidebtn;
 | 
        
           |  |  | 1553 |         if (outcome === false) {
 | 
        
           |  |  | 1554 |             Y.log('AJAX request to show ' + this.get('itemname') + ' by outcome.', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1555 |             return false;
 | 
        
           |  |  | 1556 |         }
 | 
        
           |  |  | 1557 |   | 
        
           |  |  | 1558 |         this.markVisible();
 | 
        
           |  |  | 1559 |         hidebtn = this.get('node').one('a[data-action=hide]');
 | 
        
           |  |  | 1560 |         if (hidebtn) {
 | 
        
           |  |  | 1561 |             hidebtn.focus();
 | 
        
           |  |  | 1562 |         }
 | 
        
           |  |  | 1563 |         if (outcome.categoryvisibility) {
 | 
        
           |  |  | 1564 |             this.updateChildVisibility(outcome.categoryvisibility);
 | 
        
           |  |  | 1565 |         }
 | 
        
           |  |  | 1566 |         if (outcome.coursevisibility) {
 | 
        
           |  |  | 1567 |             this.updateCourseVisiblity(outcome.coursevisibility);
 | 
        
           |  |  | 1568 |         }
 | 
        
           |  |  | 1569 |         this.updated();
 | 
        
           |  |  | 1570 |         Y.log('Success: category made visible by AJAX.', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1571 |     },
 | 
        
           |  |  | 1572 |   | 
        
           |  |  | 1573 |     /**
 | 
        
           |  |  | 1574 |      * Hides an item.
 | 
        
           |  |  | 1575 |      *
 | 
        
           |  |  | 1576 |      * @method hide
 | 
        
           |  |  | 1577 |      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
 | 
        
           |  |  | 1578 |      * @param {Object} response The response from the AJAX request.
 | 
        
           |  |  | 1579 |      * @param {Object} args The arguments given to the request.
 | 
        
           |  |  | 1580 |      * @return {Boolean}
 | 
        
           |  |  | 1581 |      */
 | 
        
           |  |  | 1582 |     hide: function(transactionid, response, args) {
 | 
        
           |  |  | 1583 |         var outcome = this.checkAjaxResponse(transactionid, response, args),
 | 
        
           |  |  | 1584 |             showbtn;
 | 
        
           |  |  | 1585 |         if (outcome === false) {
 | 
        
           |  |  | 1586 |             Y.log('AJAX request to hide ' + this.get('itemname') + ' by outcome.', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1587 |             return false;
 | 
        
           |  |  | 1588 |         }
 | 
        
           |  |  | 1589 |         this.markHidden();
 | 
        
           |  |  | 1590 |         showbtn = this.get('node').one('a[data-action=show]');
 | 
        
           |  |  | 1591 |         if (showbtn) {
 | 
        
           |  |  | 1592 |             showbtn.focus();
 | 
        
           |  |  | 1593 |         }
 | 
        
           |  |  | 1594 |         if (outcome.categoryvisibility) {
 | 
        
           |  |  | 1595 |             this.updateChildVisibility(outcome.categoryvisibility);
 | 
        
           |  |  | 1596 |         }
 | 
        
           |  |  | 1597 |         if (outcome.coursevisibility) {
 | 
        
           |  |  | 1598 |             this.updateCourseVisiblity(outcome.coursevisibility);
 | 
        
           |  |  | 1599 |         }
 | 
        
           |  |  | 1600 |         this.updated();
 | 
        
           |  |  | 1601 |         Y.log('Success: ' + this.get('itemname') + ' made hidden by AJAX.', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1602 |     },
 | 
        
           |  |  | 1603 |   | 
        
           |  |  | 1604 |     /**
 | 
        
           |  |  | 1605 |      * Updates the visibility of child courses if required.
 | 
        
           |  |  | 1606 |      * @method updateCourseVisiblity
 | 
        
           |  |  | 1607 |      * @chainable
 | 
        
           |  |  | 1608 |      * @param courses
 | 
        
           |  |  | 1609 |      */
 | 
        
           |  |  | 1610 |     updateCourseVisiblity: function(courses) {
 | 
        
           |  |  | 1611 |         var managementconsole = this.get('console'),
 | 
        
           |  |  | 1612 |             key,
 | 
        
           |  |  | 1613 |             course;
 | 
        
           |  |  | 1614 |         Y.log('Changing categories course visibility', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1615 |         try {
 | 
        
           |  |  | 1616 |             for (key in courses) {
 | 
        
           |  |  | 1617 |                 if (typeof courses[key] === 'object') {
 | 
        
           |  |  | 1618 |                     course = managementconsole.getCourseById(courses[key].id);
 | 
        
           |  |  | 1619 |                     if (course) {
 | 
        
           |  |  | 1620 |                         if (courses[key].visible === "1") {
 | 
        
           |  |  | 1621 |                             course.markVisible();
 | 
        
           |  |  | 1622 |                         } else {
 | 
        
           |  |  | 1623 |                             course.markHidden();
 | 
        
           |  |  | 1624 |                         }
 | 
        
           |  |  | 1625 |                     }
 | 
        
           |  |  | 1626 |                 }
 | 
        
           |  |  | 1627 |             }
 | 
        
           |  |  | 1628 |         } catch (err) {
 | 
        
           |  |  | 1629 |             Y.log('Error trying to update course visibility: ' + err.message, 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1630 |         }
 | 
        
           |  |  | 1631 |         return this;
 | 
        
           |  |  | 1632 |     },
 | 
        
           |  |  | 1633 |   | 
        
           |  |  | 1634 |     /**
 | 
        
           |  |  | 1635 |      * Updates the visibility of subcategories if required.
 | 
        
           |  |  | 1636 |      * @method updateChildVisibility
 | 
        
           |  |  | 1637 |      * @chainable
 | 
        
           |  |  | 1638 |      * @param categories
 | 
        
           |  |  | 1639 |      */
 | 
        
           |  |  | 1640 |     updateChildVisibility: function(categories) {
 | 
        
           |  |  | 1641 |         var managementconsole = this.get('console'),
 | 
        
           |  |  | 1642 |             key,
 | 
        
           |  |  | 1643 |             category;
 | 
        
           |  |  | 1644 |         Y.log('Changing categories subcategory visibility', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1645 |         try {
 | 
        
           |  |  | 1646 |             for (key in categories) {
 | 
        
           |  |  | 1647 |                 if (typeof categories[key] === 'object') {
 | 
        
           |  |  | 1648 |                     category = managementconsole.getCategoryById(categories[key].id);
 | 
        
           |  |  | 1649 |                     if (category) {
 | 
        
           |  |  | 1650 |                         if (categories[key].visible === "1") {
 | 
        
           |  |  | 1651 |                             category.markVisible();
 | 
        
           |  |  | 1652 |                         } else {
 | 
        
           |  |  | 1653 |                             category.markHidden();
 | 
        
           |  |  | 1654 |                         }
 | 
        
           |  |  | 1655 |                     }
 | 
        
           |  |  | 1656 |                 }
 | 
        
           |  |  | 1657 |             }
 | 
        
           |  |  | 1658 |         } catch (err) {
 | 
        
           |  |  | 1659 |             Y.log('Error trying to update category visibility: ' + err.message, 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1660 |         }
 | 
        
           |  |  | 1661 |         return this;
 | 
        
           |  |  | 1662 |     }
 | 
        
           |  |  | 1663 | };
 | 
        
           |  |  | 1664 | Y.extend(Category, Item, Category.prototype);
 | 
        
           |  |  | 1665 | /**
 | 
        
           |  |  | 1666 |  * A managed course.
 | 
        
           |  |  | 1667 |  *
 | 
        
           |  |  | 1668 |  * @namespace M.course.management
 | 
        
           |  |  | 1669 |  * @class Course
 | 
        
           |  |  | 1670 |  * @constructor
 | 
        
           |  |  | 1671 |  * @extends Item
 | 
        
           |  |  | 1672 |  */
 | 
        
           |  |  | 1673 | Course = function() {
 | 
        
           |  |  | 1674 |     Course.superclass.constructor.apply(this, arguments);
 | 
        
           |  |  | 1675 | };
 | 
        
           |  |  | 1676 | Course.NAME = 'moodle-course-management-course';
 | 
        
           |  |  | 1677 | Course.CSS_PREFIX = 'management-course';
 | 
        
           |  |  | 1678 | Course.ATTRS = {
 | 
        
           |  |  | 1679 |   | 
        
           |  |  | 1680 |     /**
 | 
        
           |  |  | 1681 |      * The course ID of this course.
 | 
        
           |  |  | 1682 |      * @attribute courseid
 | 
        
           |  |  | 1683 |      * @type Number
 | 
        
           |  |  | 1684 |      */
 | 
        
           |  |  | 1685 |     courseid: {},
 | 
        
           |  |  | 1686 |   | 
        
           |  |  | 1687 |     /**
 | 
        
           |  |  | 1688 |      * True if this is the selected course.
 | 
        
           |  |  | 1689 |      * @attribute selected
 | 
        
           |  |  | 1690 |      * @type Boolean
 | 
        
           |  |  | 1691 |      * @default null
 | 
        
           |  |  | 1692 |      */
 | 
        
           |  |  | 1693 |     selected: {
 | 
        
           |  |  | 1694 |         getter: function(value, name) {
 | 
        
           |  |  | 1695 |             if (value === null) {
 | 
        
           |  |  | 1696 |                 value = this.get('node').getData(name);
 | 
        
           |  |  | 1697 |                 this.set(name, value);
 | 
        
           |  |  | 1698 |             }
 | 
        
           |  |  | 1699 |             return value;
 | 
        
           |  |  | 1700 |         },
 | 
        
           |  |  | 1701 |         value: null
 | 
        
           |  |  | 1702 |     },
 | 
        
           |  |  | 1703 |     node: {
 | 
        
           |  |  | 1704 |   | 
        
           |  |  | 1705 |     },
 | 
        
           |  |  | 1706 |     /**
 | 
        
           |  |  | 1707 |      * The management console tracking this course.
 | 
        
           |  |  | 1708 |      * @attribute console
 | 
        
           |  |  | 1709 |      * @type Console
 | 
        
           |  |  | 1710 |      * @writeOnce
 | 
        
           |  |  | 1711 |      */
 | 
        
           |  |  | 1712 |     console: {
 | 
        
           |  |  | 1713 |         writeOnce: 'initOnly'
 | 
        
           |  |  | 1714 |     },
 | 
        
           |  |  | 1715 |   | 
        
           |  |  | 1716 |     /**
 | 
        
           |  |  | 1717 |      * The category this course belongs to.
 | 
        
           |  |  | 1718 |      * @attribute category
 | 
        
           |  |  | 1719 |      * @type Category
 | 
        
           |  |  | 1720 |      * @writeOnce
 | 
        
           |  |  | 1721 |      */
 | 
        
           |  |  | 1722 |     category: {
 | 
        
           |  |  | 1723 |         writeOnce: 'initOnly'
 | 
        
           |  |  | 1724 |     }
 | 
        
           |  |  | 1725 | };
 | 
        
           |  |  | 1726 | Course.prototype = {
 | 
        
           |  |  | 1727 |     /**
 | 
        
           |  |  | 1728 |      * Initialises the new course instance.
 | 
        
           |  |  | 1729 |      * @method initializer
 | 
        
           |  |  | 1730 |      */
 | 
        
           |  |  | 1731 |     initializer: function() {
 | 
        
           |  |  | 1732 |         var node = this.get('node'),
 | 
        
           |  |  | 1733 |             category = this.get('category');
 | 
        
           |  |  | 1734 |         this.set('courseid', node.getData('id'));
 | 
        
           |  |  | 1735 |         if (category && category.registerCourse) {
 | 
        
           |  |  | 1736 |             category.registerCourse(this);
 | 
        
           |  |  | 1737 |         }
 | 
        
           |  |  | 1738 |         this.set('itemname', 'course');
 | 
        
           |  |  | 1739 |     },
 | 
        
           |  |  | 1740 |   | 
        
           |  |  | 1741 |     /**
 | 
        
           |  |  | 1742 |      * Returns the name of the course.
 | 
        
           |  |  | 1743 |      * @method getName
 | 
        
           |  |  | 1744 |      * @return {String}
 | 
        
           |  |  | 1745 |      */
 | 
        
           |  |  | 1746 |     getName: function() {
 | 
        
           |  |  | 1747 |         return this.get('node').one('a.coursename').get('innerHTML');
 | 
        
           |  |  | 1748 |     },
 | 
        
           |  |  | 1749 |   | 
        
           |  |  | 1750 |     /**
 | 
        
           |  |  | 1751 |      * Handles an event relating to this course.
 | 
        
           |  |  | 1752 |      * @method handle
 | 
        
           |  |  | 1753 |      * @param {String} action
 | 
        
           |  |  | 1754 |      * @param {EventFacade} e
 | 
        
           |  |  | 1755 |      * @return {Boolean}
 | 
        
           |  |  | 1756 |      */
 | 
        
           |  |  | 1757 |     handle: function(action, e) {
 | 
        
           |  |  | 1758 |         var managementconsole = this.get('console'),
 | 
        
           |  |  | 1759 |             args = {courseid: this.get('courseid')};
 | 
        
           |  |  | 1760 |         switch (action) {
 | 
        
           |  |  | 1761 |             case 'moveup':
 | 
        
           |  |  | 1762 |                 e.halt();
 | 
        
           |  |  | 1763 |                 managementconsole.performAjaxAction('movecourseup', args, this.moveup, this);
 | 
        
           |  |  | 1764 |                 break;
 | 
        
           |  |  | 1765 |             case 'movedown':
 | 
        
           |  |  | 1766 |                 e.halt();
 | 
        
           |  |  | 1767 |                 managementconsole.performAjaxAction('movecoursedown', args, this.movedown, this);
 | 
        
           |  |  | 1768 |                 break;
 | 
        
           |  |  | 1769 |             case 'show':
 | 
        
           |  |  | 1770 |                 e.halt();
 | 
        
           |  |  | 1771 |                 managementconsole.performAjaxAction('showcourse', args, this.show, this);
 | 
        
           |  |  | 1772 |                 break;
 | 
        
           |  |  | 1773 |             case 'hide':
 | 
        
           |  |  | 1774 |                 e.halt();
 | 
        
           |  |  | 1775 |                 managementconsole.performAjaxAction('hidecourse', args, this.hide, this);
 | 
        
           |  |  | 1776 |                 break;
 | 
        
           |  |  | 1777 |             case 'select':
 | 
        
           |  |  | 1778 |                 var c = this.get('console'),
 | 
        
           |  |  | 1779 |                     movetonode = c.get('courselisting').one('#menumovecoursesto');
 | 
        
           |  |  | 1780 |                 if (movetonode) {
 | 
        
           |  |  | 1781 |                     if (c.isCourseSelected(e.currentTarget)) {
 | 
        
           |  |  | 1782 |                         movetonode.removeAttribute('disabled');
 | 
        
           |  |  | 1783 |                     } else {
 | 
        
           |  |  | 1784 |                         movetonode.setAttribute('disabled', true);
 | 
        
           |  |  | 1785 |                     }
 | 
        
           |  |  | 1786 |                 }
 | 
        
           |  |  | 1787 |                 break;
 | 
        
           |  |  | 1788 |             default:
 | 
        
           |  |  | 1789 |                 Y.log('Invalid AJAX action requested of managed course.', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1790 |                 return false;
 | 
        
           |  |  | 1791 |         }
 | 
        
           |  |  | 1792 |     },
 | 
        
           |  |  | 1793 |   | 
        
           |  |  | 1794 |     /**
 | 
        
           |  |  | 1795 |      * Removes this course.
 | 
        
           |  |  | 1796 |      * @method remove
 | 
        
           |  |  | 1797 |      */
 | 
        
           |  |  | 1798 |     remove: function() {
 | 
        
           |  |  | 1799 |         this.get('console').removeCourseById(this.get('courseid'));
 | 
        
           |  |  | 1800 |         this.get('node').remove();
 | 
        
           |  |  | 1801 |     },
 | 
        
           |  |  | 1802 |   | 
        
           |  |  | 1803 |     /**
 | 
        
           |  |  | 1804 |      * Moves this course after another course.
 | 
        
           |  |  | 1805 |      *
 | 
        
           |  |  | 1806 |      * @method moveAfter
 | 
        
           |  |  | 1807 |      * @param {Number} moveaftercourse The course to move after or 0 to put it at the top.
 | 
        
           |  |  | 1808 |      * @param {Number} previousid the course it was previously after in case we need to revert.
 | 
        
           |  |  | 1809 |      */
 | 
        
           |  |  | 1810 |     moveAfter: function(moveaftercourse, previousid) {
 | 
        
           |  |  | 1811 |         var managementconsole = this.get('console'),
 | 
        
           |  |  | 1812 |             args = {
 | 
        
           |  |  | 1813 |                 courseid: this.get('courseid'),
 | 
        
           |  |  | 1814 |                 moveafter: moveaftercourse,
 | 
        
           |  |  | 1815 |                 previous: previousid
 | 
        
           |  |  | 1816 |             };
 | 
        
           |  |  | 1817 |         managementconsole.performAjaxAction('movecourseafter', args, this.moveAfterResponse, this);
 | 
        
           |  |  | 1818 |     },
 | 
        
           |  |  | 1819 |   | 
        
           |  |  | 1820 |     /**
 | 
        
           |  |  | 1821 |      * Performs the actual move.
 | 
        
           |  |  | 1822 |      *
 | 
        
           |  |  | 1823 |      * @method moveAfterResponse
 | 
        
           |  |  | 1824 |      * @protected
 | 
        
           |  |  | 1825 |      * @param {Number} transactionid The transaction ID for the request.
 | 
        
           |  |  | 1826 |      * @param {Object} response The response to the request.
 | 
        
           |  |  | 1827 |      * @param {Objects} args The arguments that were given with the request.
 | 
        
           |  |  | 1828 |      * @return {Boolean}
 | 
        
           |  |  | 1829 |      */
 | 
        
           |  |  | 1830 |     moveAfterResponse: function(transactionid, response, args) {
 | 
        
           |  |  | 1831 |         var outcome = this.checkAjaxResponse(transactionid, response, args),
 | 
        
           |  |  | 1832 |             node = this.get('node'),
 | 
        
           |  |  | 1833 |             previous;
 | 
        
           |  |  | 1834 |         if (outcome === false) {
 | 
        
           |  |  | 1835 |             previous = node.ancestor('ul').one('li[data-id=' + args.previous + ']');
 | 
        
           |  |  | 1836 |             Y.log('AJAX failed to move this course after the requested course', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 1837 |             if (previous) {
 | 
        
           |  |  | 1838 |                 // After the last previous.
 | 
        
           |  |  | 1839 |                 previous.insertAfter(node, 'after');
 | 
        
           |  |  | 1840 |             } else {
 | 
        
           |  |  | 1841 |                 // Start of the list.
 | 
        
           |  |  | 1842 |                 node.ancestor('ul').one('li').insert(node, 'before');
 | 
        
           |  |  | 1843 |             }
 | 
        
           |  |  | 1844 |             return false;
 | 
        
           |  |  | 1845 |         }
 | 
        
           |  |  | 1846 |         Y.log('AJAX successfully moved course (' + this.getName() + ')', 'info', 'moodle-course-management');
 | 
        
           |  |  | 1847 |         this.highlight();
 | 
        
           |  |  | 1848 |     }
 | 
        
           |  |  | 1849 | };
 | 
        
           |  |  | 1850 | Y.extend(Course, Item, Course.prototype);
 | 
        
           |  |  | 1851 |   | 
        
           |  |  | 1852 |   | 
        
           |  |  | 1853 | }, '@VERSION@', {
 | 
        
           |  |  | 1854 |     "requires": [
 | 
        
           |  |  | 1855 |         "base",
 | 
        
           |  |  | 1856 |         "node",
 | 
        
           |  |  | 1857 |         "io-base",
 | 
        
           |  |  | 1858 |         "moodle-core-notification-exception",
 | 
        
           |  |  | 1859 |         "json-parse",
 | 
        
           |  |  | 1860 |         "dd-constrain",
 | 
        
           |  |  | 1861 |         "dd-proxy",
 | 
        
           |  |  | 1862 |         "dd-drop",
 | 
        
           |  |  | 1863 |         "dd-delegate",
 | 
        
           |  |  | 1864 |         "node-event-delegate"
 | 
        
           |  |  | 1865 |     ]
 | 
        
           |  |  | 1866 | });
 |