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