[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/course/yui/build/moodle-course-management/ -> moodle-course-management.js (source)

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


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1