[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

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

   1  YUI.add('moodle-course-toolboxes', function (Y, NAME) {
   2  
   3  /* eslint-disable no-unused-vars */
   4  /**
   5   * Resource and activity toolbox class.
   6   *
   7   * This class is responsible for managing AJAX interactions with activities and resources
   8   * when viewing a course in editing mode.
   9   *
  10   * @module moodle-course-toolboxes
  11   * @namespace M.course.toolboxes
  12   */
  13  
  14  // The CSS classes we use.
  15  var CSS = {
  16          ACTIVITYINSTANCE: 'activityinstance',
  17          AVAILABILITYINFODIV: 'div.availabilityinfo',
  18          CONTENTWITHOUTLINK: 'contentwithoutlink',
  19          CONDITIONALHIDDEN: 'conditionalhidden',
  20          DIMCLASS: 'dimmed',
  21          DIMMEDTEXT: 'dimmed_text',
  22          EDITINSTRUCTIONS: 'editinstructions',
  23          HIDE: 'hide',
  24          MODINDENTCOUNT: 'mod-indent-',
  25          MODINDENTHUGE: 'mod-indent-huge',
  26          MODULEIDPREFIX: 'module-',
  27          SECTIONHIDDENCLASS: 'hidden',
  28          SECTIONIDPREFIX: 'section-',
  29          SHOW: 'editing_show'
  30      },
  31      // The CSS selectors we use.
  32      SELECTOR = {
  33          ACTIONAREA: '.actions',
  34          ACTIONLINKTEXT: '.actionlinktext',
  35          ACTIVITYACTION: 'a.cm-edit-action[data-action]',
  36          ACTIVITYICON: 'img.activityicon',
  37          ACTIVITYINSTANCE: '.' + CSS.ACTIVITYINSTANCE,
  38          ACTIVITYLINK: '.' + CSS.ACTIVITYINSTANCE + ' > a, .' + CSS.ACTIVITYINSTANCE +
  39              ' > span[data-inplaceeditable] > a:not([data-inplaceeditablelink])',
  40          ACTIVITYLI: 'li.activity',
  41          COMMANDSPAN: '.commands',
  42          CONTENTAFTERLINK: 'div.contentafterlink',
  43          CONTENTWITHOUTLINK: 'div.contentwithoutlink',
  44          GROUPINGLABEL: '.' + CSS.ACTIVITYINSTANCE + ' .groupinglabel',
  45          HIDE: 'a.editing_hide',
  46          HIGHLIGHT: 'a.editing_highlight',
  47          INSTANCENAME: 'span.instancename',
  48          MODINDENTDIV: '.mod-indent',
  49          MODINDENTOUTER: '.mod-indent-outer',
  50          PAGECONTENT: 'body',
  51          SECTIONLI: 'li.section',
  52          SHOW: 'a.' + CSS.SHOW,
  53          SHOWHIDE: 'a.editing_showhide'
  54      },
  55      INDENTLIMITS = {
  56          MIN: 0,
  57          MAX: 16
  58      },
  59      BODY = Y.one(document.body);
  60  
  61  // Setup the basic namespace.
  62  M.course = M.course || {};
  63  
  64  /**
  65   * The toolbox class is a generic class which should never be directly
  66   * instantiated. Please extend it instead.
  67   *
  68   * @class toolbox
  69   * @constructor
  70   * @protected
  71   * @extends Base
  72   */
  73  var TOOLBOX = function() {
  74      TOOLBOX.superclass.constructor.apply(this, arguments);
  75  };
  76  
  77  Y.extend(TOOLBOX, Y.Base, {
  78      /**
  79       * Send a request using the REST API
  80       *
  81       * @method send_request
  82       * @param {Object} data The data to submit with the AJAX request
  83       * @param {Node} [statusspinner] A statusspinner which may contain a section loader
  84       * @param {Function} success_callback The callback to use on success
  85       * @param {Object} [optionalconfig] Any additional configuration to submit
  86       * @chainable
  87       */
  88      send_request: function(data, statusspinner, success_callback, optionalconfig) {
  89          // Default data structure
  90          if (!data) {
  91              data = {};
  92          }
  93          // Handle any variables which we must pass back through to
  94          var pageparams = this.get('config').pageparams,
  95              varname;
  96          for (varname in pageparams) {
  97              data[varname] = pageparams[varname];
  98          }
  99  
 100          data.sesskey = M.cfg.sesskey;
 101          data.courseId = this.get('courseid');
 102  
 103          var uri = M.cfg.wwwroot + this.get('ajaxurl');
 104  
 105          // Define the configuration to send with the request
 106          var responsetext = [];
 107          var config = {
 108              method: 'POST',
 109              data: data,
 110              on: {
 111                  success: function(tid, response) {
 112                      try {
 113                          responsetext = Y.JSON.parse(response.responseText);
 114                          if (responsetext.error) {
 115                              new M.core.ajaxException(responsetext);
 116                          }
 117                      } catch (e) {
 118                          // Ignore.
 119                      }
 120  
 121                      // Run the callback if we have one.
 122                      if (success_callback) {
 123                          Y.bind(success_callback, this, responsetext)();
 124                      }
 125  
 126                      if (statusspinner) {
 127                          window.setTimeout(function() {
 128                              statusspinner.hide();
 129                          }, 400);
 130                      }
 131                  },
 132                  failure: function(tid, response) {
 133                      if (statusspinner) {
 134                          statusspinner.hide();
 135                      }
 136                      new M.core.ajaxException(response);
 137                  }
 138              },
 139              context: this
 140          };
 141  
 142          // Apply optional config
 143          if (optionalconfig) {
 144              for (varname in optionalconfig) {
 145                  config[varname] = optionalconfig[varname];
 146              }
 147          }
 148  
 149          if (statusspinner) {
 150              statusspinner.show();
 151          }
 152  
 153          // Send the request
 154          Y.io(uri, config);
 155          return this;
 156      }
 157  },
 158  {
 159      NAME: 'course-toolbox',
 160      ATTRS: {
 161          /**
 162           * The ID of the Moodle Course being edited.
 163           *
 164           * @attribute courseid
 165           * @default 0
 166           * @type Number
 167           */
 168          courseid: {
 169              'value': 0
 170          },
 171  
 172          /**
 173           * The Moodle course format.
 174           *
 175           * @attribute format
 176           * @default 'topics'
 177           * @type String
 178           */
 179          format: {
 180              'value': 'topics'
 181          },
 182          /**
 183           * The URL to use when submitting requests.
 184           * @attribute ajaxurl
 185           * @default null
 186           * @type String
 187           */
 188          ajaxurl: {
 189              'value': null
 190          },
 191          /**
 192           * Any additional configuration passed when creating the instance.
 193           *
 194           * @attribute config
 195           * @default {}
 196           * @type Object
 197           */
 198          config: {
 199              'value': {}
 200          }
 201      }
 202  }
 203  );
 204  /* global TOOLBOX, BODY, SELECTOR, INDENTLIMITS */
 205  
 206  /**
 207   * Resource and activity toolbox class.
 208   *
 209   * This class is responsible for managing AJAX interactions with activities and resources
 210   * when viewing a course in editing mode.
 211   *
 212   * @module moodle-course-toolboxes
 213   * @namespace M.course.toolboxes
 214   */
 215  
 216  /**
 217   * Resource and activity toolbox class.
 218   *
 219   * This is a class extending TOOLBOX containing code specific to resources
 220   *
 221   * This class is responsible for managing AJAX interactions with activities and resources
 222   * when viewing a course in editing mode.
 223   *
 224   * @class resources
 225   * @constructor
 226   * @extends M.course.toolboxes.toolbox
 227   */
 228  var RESOURCETOOLBOX = function() {
 229      RESOURCETOOLBOX.superclass.constructor.apply(this, arguments);
 230  };
 231  
 232  Y.extend(RESOURCETOOLBOX, TOOLBOX, {
 233      /**
 234       * No groups are being used.
 235       *
 236       * @property GROUPS_NONE
 237       * @protected
 238       * @type Number
 239       */
 240      GROUPS_NONE: 0,
 241  
 242      /**
 243       * Separate groups are being used.
 244       *
 245       * @property GROUPS_SEPARATE
 246       * @protected
 247       * @type Number
 248       */
 249      GROUPS_SEPARATE: 1,
 250  
 251      /**
 252       * Visible groups are being used.
 253       *
 254       * @property GROUPS_VISIBLE
 255       * @protected
 256       * @type Number
 257       */
 258      GROUPS_VISIBLE: 2,
 259  
 260      /**
 261       * Initialize the resource toolbox
 262       *
 263       * For each activity the commands are updated and a reference to the activity is attached.
 264       * This way it doesn't matter where the commands are going to called from they have a reference to the
 265       * activity that they relate to.
 266       * This is essential as some of the actions are displayed in an actionmenu which removes them from the
 267       * page flow.
 268       *
 269       * This function also creates a single event delegate to manage all AJAX actions for all activities on
 270       * the page.
 271       *
 272       * @method initializer
 273       * @protected
 274       */
 275      initializer: function() {
 276          M.course.coursebase.register_module(this);
 277          BODY.delegate('key', this.handle_data_action, 'down:enter', SELECTOR.ACTIVITYACTION, this);
 278          Y.delegate('click', this.handle_data_action, BODY, SELECTOR.ACTIVITYACTION, this);
 279      },
 280  
 281      /**
 282       * Handles the delegation event. When this is fired someone has triggered an action.
 283       *
 284       * Note not all actions will result in an AJAX enhancement.
 285       *
 286       * @protected
 287       * @method handle_data_action
 288       * @param {EventFacade} ev The event that was triggered.
 289       * @return {boolean}
 290       */
 291      handle_data_action: function(ev) {
 292          // We need to get the anchor element that triggered this event.
 293          var node = ev.target;
 294          if (!node.test('a')) {
 295              node = node.ancestor(SELECTOR.ACTIVITYACTION);
 296          }
 297  
 298          // From the anchor we can get both the activity (added during initialisation) and the action being
 299          // performed (added by the UI as a data attribute).
 300          var action = node.getData('action'),
 301              activity = node.ancestor(SELECTOR.ACTIVITYLI);
 302  
 303          if (!node.test('a') || !action || !activity) {
 304              // It wasn't a valid action node.
 305              return;
 306          }
 307  
 308          // Switch based upon the action and do the desired thing.
 309          switch (action) {
 310              case 'moveleft':
 311              case 'moveright':
 312                  // The user changing the indent of the activity.
 313                  this.change_indent(ev, node, activity, action);
 314                  break;
 315              case 'delete':
 316                  // The user is deleting the activity.
 317                  this.delete_with_confirmation(ev, node, activity, action);
 318                  break;
 319              case 'duplicate':
 320                  // The user is duplicating the activity.
 321                  this.duplicate(ev, node, activity, action);
 322                  break;
 323              case 'hide':
 324              case 'show':
 325                  // The user is changing the visibility of the activity.
 326                  this.change_visibility(ev, node, activity, action);
 327                  break;
 328              case 'groupsseparate':
 329              case 'groupsvisible':
 330              case 'groupsnone':
 331                  // The user is changing the group mode.
 332                  this.change_groupmode(ev, node, activity, action);
 333                  break;
 334              case 'move':
 335              case 'update':
 336              case 'assignroles':
 337                  break;
 338              default:
 339                  // Nothing to do here!
 340                  break;
 341          }
 342      },
 343  
 344      /**
 345       * Add a loading icon to the specified activity.
 346       *
 347       * The icon is added within the action area.
 348       *
 349       * @method add_spinner
 350       * @param {Node} activity The activity to add a loading icon to
 351       * @return {Node|null} The newly created icon, or null if the action area was not found.
 352       */
 353      add_spinner: function(activity) {
 354          var actionarea = activity.one(SELECTOR.ACTIONAREA);
 355          if (actionarea) {
 356              return M.util.add_spinner(Y, actionarea);
 357          }
 358          return null;
 359      },
 360  
 361      /**
 362       * Change the indent of the activity or resource.
 363       *
 364       * @method change_indent
 365       * @protected
 366       * @param {EventFacade} ev The event that was fired.
 367       * @param {Node} button The button that triggered this action.
 368       * @param {Node} activity The activity node that this action will be performed on.
 369       * @param {String} action The action that has been requested. Will be 'moveleft' or 'moveright'.
 370       */
 371      change_indent: function(ev, button, activity, action) {
 372          // Prevent the default button action
 373          ev.preventDefault();
 374  
 375          var direction = (action === 'moveleft') ? -1 : 1;
 376  
 377          // And we need to determine the current and new indent level
 378          var indentdiv = activity.one(SELECTOR.MODINDENTDIV),
 379              indent = indentdiv.getAttribute('class').match(/mod-indent-(\d{1,})/),
 380              oldindent = 0,
 381              newindent;
 382  
 383          if (indent) {
 384              oldindent = parseInt(indent[1], 10);
 385          }
 386          newindent = oldindent + parseInt(direction, 10);
 387  
 388          if (newindent < INDENTLIMITS.MIN || newindent > INDENTLIMITS.MAX) {
 389              return;
 390          }
 391  
 392          if (indent) {
 393              indentdiv.removeClass(indent[0]);
 394          }
 395  
 396          // Perform the move
 397          indentdiv.addClass(CSS.MODINDENTCOUNT + newindent);
 398          var data = {
 399              'class': 'resource',
 400              'field': 'indent',
 401              'value': newindent,
 402              'id': Y.Moodle.core_course.util.cm.getId(activity)
 403          };
 404          var spinner = this.add_spinner(activity);
 405          this.send_request(data, spinner);
 406  
 407          var remainingmove;
 408  
 409          // Handle removal/addition of the moveleft button.
 410          if (newindent === INDENTLIMITS.MIN) {
 411              button.addClass('hidden');
 412              remainingmove = activity.one('.editing_moveright');
 413          } else if (newindent > INDENTLIMITS.MIN && oldindent === INDENTLIMITS.MIN) {
 414              button.ancestor('.menu').one('[data-action=moveleft]').removeClass('hidden');
 415          }
 416  
 417          if (newindent === INDENTLIMITS.MAX) {
 418              button.addClass('hidden');
 419              remainingmove = activity.one('.editing_moveleft');
 420          } else if (newindent < INDENTLIMITS.MAX && oldindent === INDENTLIMITS.MAX) {
 421              button.ancestor('.menu').one('[data-action=moveright]').removeClass('hidden');
 422          }
 423  
 424          // Handle massive indentation to match non-ajax display
 425          var hashugeclass = indentdiv.hasClass(CSS.MODINDENTHUGE);
 426          if (newindent > 15 && !hashugeclass) {
 427              indentdiv.addClass(CSS.MODINDENTHUGE);
 428          } else if (newindent <= 15 && hashugeclass) {
 429              indentdiv.removeClass(CSS.MODINDENTHUGE);
 430          }
 431  
 432          if (ev.type && ev.type === "key" && remainingmove) {
 433              remainingmove.focus();
 434          }
 435      },
 436  
 437      /**
 438       * Deletes the given activity or resource after confirmation.
 439       *
 440       * @protected
 441       * @method delete_with_confirmation
 442       * @param {EventFacade} ev The event that was fired.
 443       * @param {Node} button The button that triggered this action.
 444       * @param {Node} activity The activity node that this action will be performed on.
 445       * @chainable
 446       */
 447      delete_with_confirmation: function(ev, button, activity) {
 448          // Prevent the default button action
 449          ev.preventDefault();
 450  
 451          // Get the element we're working on
 452          var element = activity,
 453              // Create confirm string (different if element has or does not have name)
 454              confirmstring = '',
 455              plugindata = {
 456                  type: M.util.get_string('pluginname', element.getAttribute('class').match(/modtype_([^\s]*)/)[1])
 457              };
 458          if (Y.Moodle.core_course.util.cm.getName(element) !== null) {
 459              plugindata.name = Y.Moodle.core_course.util.cm.getName(element);
 460              confirmstring = M.util.get_string('deletechecktypename', 'moodle', plugindata);
 461          } else {
 462              confirmstring = M.util.get_string('deletechecktype', 'moodle', plugindata);
 463          }
 464  
 465          // Create the confirmation dialogue.
 466          var confirm = new M.core.confirm({
 467              question: confirmstring,
 468              modal: true,
 469              visible: false
 470          });
 471          confirm.show();
 472  
 473          // If it is confirmed.
 474          confirm.on('complete-yes', function() {
 475  
 476              // Actually remove the element.
 477              element.remove();
 478              var data = {
 479                  'class': 'resource',
 480                  'action': 'DELETE',
 481                  'id': Y.Moodle.core_course.util.cm.getId(element)
 482              };
 483              this.send_request(data);
 484              if (M.core.actionmenu && M.core.actionmenu.instance) {
 485                  M.core.actionmenu.instance.hideMenu(ev);
 486              }
 487  
 488          }, this);
 489  
 490          return this;
 491      },
 492  
 493      /**
 494       * Duplicates the activity.
 495       *
 496       * @method duplicate
 497       * @protected
 498       * @param {EventFacade} ev The event that was fired.
 499       * @param {Node} button The button that triggered this action.
 500       * @param {Node} activity The activity node that this action will be performed on.
 501       * @chainable
 502       */
 503      duplicate: function(ev, button, activity) {
 504          // Prevent the default button action
 505          ev.preventDefault();
 506  
 507          // Get the element we're working on
 508          var element = activity;
 509  
 510          // Add the lightbox.
 511          var section = activity.ancestor(M.course.format.get_section_selector(Y)),
 512              lightbox = M.util.add_lightbox(Y, section).show();
 513  
 514          // Build and send the request.
 515          var data = {
 516              'class': 'resource',
 517              'field': 'duplicate',
 518              'id': Y.Moodle.core_course.util.cm.getId(element),
 519              'sr': button.getData('sr')
 520          };
 521          this.send_request(data, lightbox, function(response) {
 522              var newcm = Y.Node.create(response.fullcontent);
 523  
 524              // Append to the section?
 525              activity.insert(newcm, 'after');
 526              Y.use('moodle-course-coursebase', function() {
 527                  M.course.coursebase.invoke_function('setup_for_resource', newcm);
 528              });
 529              if (M.core.actionmenu && M.core.actionmenu.newDOMNode) {
 530                  M.core.actionmenu.newDOMNode(newcm);
 531              }
 532          });
 533          return this;
 534      },
 535  
 536      /**
 537       * Changes the visibility of this activity or resource.
 538       *
 539       * @method change_visibility
 540       * @protected
 541       * @param {EventFacade} ev The event that was fired.
 542       * @param {Node} button The button that triggered this action.
 543       * @param {Node} activity The activity node that this action will be performed on.
 544       * @param {String} action The action that has been requested.
 545       * @chainable
 546       */
 547      change_visibility: function(ev, button, activity, action) {
 548          // Prevent the default button action
 549          ev.preventDefault();
 550  
 551          // Get the element we're working on
 552          var element = activity;
 553          var value = this.handle_resource_dim(button, activity, action);
 554  
 555          // Send the request
 556          var data = {
 557              'class': 'resource',
 558              'field': 'visible',
 559              'value': value,
 560              'id': Y.Moodle.core_course.util.cm.getId(element)
 561          };
 562          var spinner = this.add_spinner(element);
 563          this.send_request(data, spinner);
 564  
 565          return this;
 566      },
 567  
 568      /**
 569       * Handles the UI aspect of dimming the activity or resource.
 570       *
 571       * @method handle_resource_dim
 572       * @protected
 573       * @param {Node} button The button that triggered the action.
 574       * @param {Node} activity The activity node that this action will be performed on.
 575       * @param {String} action 'show' or 'hide'.
 576       * @return {Number} 1 if we changed to visible, 0 if we were hiding.
 577       */
 578      handle_resource_dim: function(button, activity, action) {
 579          var toggleclass = CSS.DIMCLASS,
 580              dimarea = activity.one([
 581                      SELECTOR.ACTIVITYLINK,
 582                      SELECTOR.CONTENTWITHOUTLINK
 583                  ].join(', ')),
 584              availabilityinfo = activity.one(CSS.AVAILABILITYINFODIV),
 585              nextaction = (action === 'hide') ? 'show' : 'hide',
 586              buttontext = button.one('span'),
 587              newstring = M.util.get_string(nextaction, 'moodle'),
 588              buttonimg = button.one('img');
 589  
 590          // Update button info.
 591          buttonimg.setAttrs({
 592              'src': M.util.image_url('t/' + nextaction)
 593          });
 594  
 595          if (Y.Lang.trim(button.getAttribute('title'))) {
 596              button.setAttribute('title', newstring);
 597          }
 598  
 599          if (Y.Lang.trim(buttonimg.getAttribute('alt'))) {
 600              buttonimg.setAttribute('alt', newstring);
 601          }
 602  
 603          button.replaceClass('editing_' + action, 'editing_' + nextaction);
 604          button.setData('action', nextaction);
 605          if (buttontext) {
 606              buttontext.set('text', newstring);
 607          }
 608  
 609          if (activity.one(SELECTOR.CONTENTWITHOUTLINK)) {
 610              dimarea = activity.one(SELECTOR.CONTENTWITHOUTLINK);
 611              toggleclass = CSS.DIMMEDTEXT;
 612          }
 613  
 614          // If activity is conditionally hidden, then don't toggle.
 615          if (!dimarea.hasClass(CSS.CONDITIONALHIDDEN)) {
 616              if (action === 'hide') {
 617                  // Change the UI.
 618                  dimarea.addClass(toggleclass);
 619                  // We need to toggle dimming on the description too.
 620                  activity.all(SELECTOR.CONTENTAFTERLINK).addClass(CSS.DIMMEDTEXT);
 621                  activity.all(SELECTOR.GROUPINGLABEL).addClass(CSS.DIMMEDTEXT);
 622              } else {
 623                  // Change the UI.
 624                  dimarea.removeClass(toggleclass);
 625                  // We need to toggle dimming on the description too.
 626                  activity.all(SELECTOR.CONTENTAFTERLINK).removeClass(CSS.DIMMEDTEXT);
 627                  activity.all(SELECTOR.GROUPINGLABEL).removeClass(CSS.DIMMEDTEXT);
 628              }
 629          }
 630          // Toggle availablity info for conditional activities.
 631          if (availabilityinfo) {
 632              availabilityinfo.toggleClass(CSS.HIDE);
 633          }
 634          return (action === 'hide') ? 0 : 1;
 635      },
 636  
 637      /**
 638       * Changes the groupmode of the activity to the next groupmode in the sequence.
 639       *
 640       * @method change_groupmode
 641       * @protected
 642       * @param {EventFacade} ev The event that was fired.
 643       * @param {Node} button The button that triggered this action.
 644       * @param {Node} activity The activity node that this action will be performed on.
 645       * @chainable
 646       */
 647      change_groupmode: function(ev, button, activity) {
 648          // Prevent the default button action.
 649          ev.preventDefault();
 650  
 651          // Current Mode
 652          var groupmode = parseInt(button.getData('nextgroupmode'), 10),
 653              newtitle = '',
 654              iconsrc = '',
 655              newtitlestr,
 656              data,
 657              spinner,
 658              nextgroupmode = groupmode + 1,
 659              buttonimg = button.one('img');
 660  
 661          if (nextgroupmode > 2) {
 662              nextgroupmode = 0;
 663          }
 664  
 665          if (groupmode === this.GROUPS_NONE) {
 666              newtitle = 'groupsnone';
 667              iconsrc = M.util.image_url('i/groupn', 'moodle');
 668          } else if (groupmode === this.GROUPS_SEPARATE) {
 669              newtitle = 'groupsseparate';
 670              iconsrc = M.util.image_url('i/groups', 'moodle');
 671          } else if (groupmode === this.GROUPS_VISIBLE) {
 672              newtitle = 'groupsvisible';
 673              iconsrc = M.util.image_url('i/groupv', 'moodle');
 674          }
 675          newtitlestr = M.util.get_string('clicktochangeinbrackets', 'moodle', M.util.get_string(newtitle, 'moodle'));
 676  
 677          // Change the UI
 678          var oldAction = button.getData('action');
 679          button.replaceClass('editing_' + oldAction, 'editing_' + newtitle);
 680          buttonimg.setAttrs({
 681              'src': iconsrc
 682          });
 683          if (Y.Lang.trim(button.getAttribute('title'))) {
 684              button.setAttribute('title', newtitlestr).setData('action', newtitle).setData('nextgroupmode', nextgroupmode);
 685          }
 686  
 687          if (Y.Lang.trim(buttonimg.getAttribute('alt'))) {
 688              buttonimg.setAttribute('alt', newtitlestr);
 689          }
 690  
 691          // And send the request
 692          data = {
 693              'class': 'resource',
 694              'field': 'groupmode',
 695              'value': groupmode,
 696              'id': Y.Moodle.core_course.util.cm.getId(activity)
 697          };
 698  
 699          spinner = this.add_spinner(activity);
 700          this.send_request(data, spinner);
 701          return this;
 702      },
 703  
 704      /**
 705       * Set the visibility of the specified resource to match the visible parameter.
 706       *
 707       * Note: This is not a toggle function and only changes the visibility
 708       * in the browser (no ajax update is performed).
 709       *
 710       * @method set_visibility_resource_ui
 711       * @param {object} args An object containing the required information to trigger a change.
 712       * @param {Node} args.element The resource to toggle
 713       * @param {Boolean} args.visible The target visibility
 714       */
 715      set_visibility_resource_ui: function(args) {
 716          var element = args.element,
 717              buttonnode = element.one(SELECTOR.HIDE),
 718              // By default we assume that the item is visible and we're going to hide it.
 719              currentVisibility = true,
 720              targetVisibility = false;
 721  
 722          if (!buttonnode) {
 723              // If the buttonnode was not found, try to find the HIDE button
 724              // and change the target visibility setting to false.
 725              buttonnode = element.one(SELECTOR.SHOW);
 726              currentVisibility = false;
 727              targetVisibility = true;
 728          }
 729  
 730          if (typeof args.visible !== 'undefined') {
 731              // If we were provided with a visibility argument, use that instead.
 732              targetVisibility = args.visible;
 733          }
 734  
 735          // Only trigger a change if necessary.
 736          if (currentVisibility !== targetVisibility) {
 737              var action = 'hide';
 738              if (targetVisibility) {
 739                  action = 'show';
 740              }
 741  
 742              this.handle_resource_dim(buttonnode, element, action);
 743          }
 744      }
 745  }, {
 746      NAME: 'course-resource-toolbox',
 747      ATTRS: {
 748      }
 749  });
 750  
 751  M.course.resource_toolbox = null;
 752  M.course.init_resource_toolbox = function(config) {
 753      M.course.resource_toolbox = new RESOURCETOOLBOX(config);
 754      return M.course.resource_toolbox;
 755  };
 756  /* global SELECTOR, TOOLBOX */
 757  
 758  /**
 759   * Resource and activity toolbox class.
 760   *
 761   * This class is responsible for managing AJAX interactions with activities and resources
 762   * when viewing a course in editing mode.
 763   *
 764   * @module moodle-course-toolboxes
 765   * @namespace M.course.toolboxes
 766   */
 767  
 768  /**
 769   * Section toolbox class.
 770   *
 771   * This class is responsible for managing AJAX interactions with sections
 772   * when viewing a course in editing mode.
 773   *
 774   * @class section
 775   * @constructor
 776   * @extends M.course.toolboxes.toolbox
 777   */
 778  var SECTIONTOOLBOX = function() {
 779      SECTIONTOOLBOX.superclass.constructor.apply(this, arguments);
 780  };
 781  
 782  Y.extend(SECTIONTOOLBOX, TOOLBOX, {
 783      /**
 784       * Initialize the section toolboxes module.
 785       *
 786       * Updates all span.commands with relevant handlers and other required changes.
 787       *
 788       * @method initializer
 789       * @protected
 790       */
 791      initializer: function() {
 792          M.course.coursebase.register_module(this);
 793  
 794          // Section Highlighting.
 795          Y.delegate('click', this.toggle_highlight, SELECTOR.PAGECONTENT, SELECTOR.SECTIONLI + ' ' + SELECTOR.HIGHLIGHT, this);
 796  
 797          // Section Visibility.
 798          Y.delegate('click', this.toggle_hide_section, SELECTOR.PAGECONTENT, SELECTOR.SECTIONLI + ' ' + SELECTOR.SHOWHIDE, this);
 799      },
 800  
 801      toggle_hide_section: function(e) {
 802          // Prevent the default button action.
 803          e.preventDefault();
 804  
 805          // Get the section we're working on.
 806          var section = e.target.ancestor(M.course.format.get_section_selector(Y)),
 807              button = e.target.ancestor('a', true),
 808              hideicon = button.one('img'),
 809              buttontext = button.one('span'),
 810  
 811          // The value to submit
 812              value,
 813  
 814          // The text for strings and images. Also determines the icon to display.
 815              action,
 816              nextaction;
 817  
 818          if (!section.hasClass(CSS.SECTIONHIDDENCLASS)) {
 819              section.addClass(CSS.SECTIONHIDDENCLASS);
 820              value = 0;
 821              action = 'hide';
 822              nextaction = 'show';
 823          } else {
 824              section.removeClass(CSS.SECTIONHIDDENCLASS);
 825              value = 1;
 826              action = 'show';
 827              nextaction = 'hide';
 828          }
 829  
 830          var newstring = M.util.get_string(nextaction + 'fromothers', 'format_' + this.get('format'));
 831          hideicon.setAttrs({
 832              'alt': newstring,
 833              'src': M.util.image_url('i/' + nextaction)
 834          });
 835          button.set('title', newstring);
 836          if (buttontext) {
 837              buttontext.set('text', newstring);
 838          }
 839  
 840          // Change the show/hide status
 841          var data = {
 842              'class': 'section',
 843              'field': 'visible',
 844              'id': Y.Moodle.core_course.util.section.getId(section.ancestor(M.course.format.get_section_wrapper(Y), true)),
 845              'value': value
 846          };
 847  
 848          var lightbox = M.util.add_lightbox(Y, section);
 849          lightbox.show();
 850  
 851          this.send_request(data, lightbox, function(response) {
 852              var activities = section.all(SELECTOR.ACTIVITYLI);
 853              activities.each(function(node) {
 854                  var button;
 855                  if (node.one(SELECTOR.SHOW)) {
 856                      button = node.one(SELECTOR.SHOW);
 857                  } else {
 858                      button = node.one(SELECTOR.HIDE);
 859                  }
 860                  var activityid = Y.Moodle.core_course.util.cm.getId(node);
 861  
 862                  // NOTE: resourcestotoggle is returned as a string instead
 863                  // of a Number so we must cast our activityid to a String.
 864                  if (Y.Array.indexOf(response.resourcestotoggle, "" + activityid) !== -1) {
 865                      M.course.resource_toolbox.handle_resource_dim(button, node, action);
 866                  }
 867              }, this);
 868          });
 869      },
 870  
 871      /**
 872       * Toggle highlighting the current section.
 873       *
 874       * @method toggle_highlight
 875       * @param {EventFacade} e
 876       */
 877      toggle_highlight: function(e) {
 878          // Prevent the default button action.
 879          e.preventDefault();
 880  
 881          // Get the section we're working on.
 882          var section = e.target.ancestor(M.course.format.get_section_selector(Y));
 883          var button = e.target.ancestor('a', true);
 884          var buttonicon = button.one('img');
 885          var buttontext = button.one('span');
 886  
 887          // Determine whether the marker is currently set.
 888          var togglestatus = section.hasClass('current');
 889          var value = 0;
 890  
 891          // Set the current highlighted item text.
 892          var old_string = M.util.get_string('markthistopic', 'moodle');
 893  
 894          var selectedpage = Y.one(SELECTOR.PAGECONTENT);
 895          selectedpage
 896              .all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT)
 897              .set('title', old_string);
 898          selectedpage
 899              .all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT + ' span')
 900              .set('text', M.util.get_string('highlight', 'moodle'));
 901          selectedpage
 902              .all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT + ' img')
 903              .set('alt', old_string)
 904              .set('src', M.util.image_url('i/marker'));
 905  
 906          // Remove the highlighting from all sections.
 907          selectedpage.all(M.course.format.get_section_selector(Y))
 908              .removeClass('current');
 909  
 910          // Then add it if required to the selected section.
 911          if (!togglestatus) {
 912              section.addClass('current');
 913              value = Y.Moodle.core_course.util.section.getId(section.ancestor(M.course.format.get_section_wrapper(Y), true));
 914              var new_string = M.util.get_string('markedthistopic', 'moodle');
 915              button
 916                  .set('title', new_string);
 917              buttonicon
 918                  .set('alt', new_string)
 919                  .set('src', M.util.image_url('i/marked'));
 920              if (buttontext) {
 921                  buttontext
 922                      .set('text', M.util.get_string('highlightoff', 'moodle'));
 923              }
 924          }
 925  
 926          // Change the highlight status.
 927          var data = {
 928              'class': 'course',
 929              'field': 'marker',
 930              'value': value
 931          };
 932          var lightbox = M.util.add_lightbox(Y, section);
 933          lightbox.show();
 934          this.send_request(data, lightbox);
 935      }
 936  }, {
 937      NAME: 'course-section-toolbox',
 938      ATTRS: {
 939      }
 940  });
 941  
 942  M.course.init_section_toolbox = function(config) {
 943      return new SECTIONTOOLBOX(config);
 944  };
 945  
 946  
 947  }, '@VERSION@', {"requires": ["node", "base", "event-key", "node", "io", "moodle-course-coursebase", "moodle-course-util"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1