[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

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

   1  YUI.add('moodle-course-dragdrop', function (Y, NAME) {
   2  
   3  /* eslint-disable no-unused-vars */
   4  /**
   5   * Drag and Drop for course sections and course modules.
   6   *
   7   * @module moodle-course-dragdrop
   8   */
   9  
  10  var CSS = {
  11      ACTIONAREA: '.actions',
  12      ACTIVITY: 'activity',
  13      ACTIVITYINSTANCE: 'activityinstance',
  14      CONTENT: 'content',
  15      COURSECONTENT: 'course-content',
  16      EDITINGMOVE: 'editing_move',
  17      ICONCLASS: 'iconsmall',
  18      JUMPMENU: 'jumpmenu',
  19      LEFT: 'left',
  20      LIGHTBOX: 'lightbox',
  21      MOVEDOWN: 'movedown',
  22      MOVEUP: 'moveup',
  23      PAGECONTENT: 'page-content',
  24      RIGHT: 'right',
  25      SECTION: 'section',
  26      SECTIONADDMENUS: 'section_add_menus',
  27      SECTIONHANDLE: 'section-handle',
  28      SUMMARY: 'summary',
  29      SECTIONDRAGGABLE: 'sectiondraggable'
  30  };
  31  
  32  M.course = M.course || {};
  33  /**
  34   * Section drag and drop.
  35   *
  36   * @class M.course.dragdrop.section
  37   * @constructor
  38   * @extends M.core.dragdrop
  39   */
  40  var DRAGSECTION = function() {
  41      DRAGSECTION.superclass.constructor.apply(this, arguments);
  42  };
  43  Y.extend(DRAGSECTION, M.core.dragdrop, {
  44      sectionlistselector: null,
  45  
  46      initializer: function() {
  47          // Set group for parent class
  48          this.groups = [CSS.SECTIONDRAGGABLE];
  49          this.samenodeclass = M.course.format.get_sectionwrapperclass();
  50          this.parentnodeclass = M.course.format.get_containerclass();
  51  
  52          // Check if we are in single section mode
  53          if (Y.Node.one('.' + CSS.JUMPMENU)) {
  54              return false;
  55          }
  56          // Initialise sections dragging
  57          this.sectionlistselector = M.course.format.get_section_wrapper(Y);
  58          if (this.sectionlistselector) {
  59              this.sectionlistselector = '.' + CSS.COURSECONTENT + ' ' + this.sectionlistselector;
  60  
  61              this.setup_for_section(this.sectionlistselector);
  62  
  63              // Make each li element in the lists of sections draggable
  64              var del = new Y.DD.Delegate({
  65                  container: '.' + CSS.COURSECONTENT,
  66                  nodes: '.' + CSS.SECTIONDRAGGABLE,
  67                  target: true,
  68                  handles: ['.' + CSS.LEFT],
  69                  dragConfig: {groups: this.groups}
  70              });
  71              del.dd.plug(Y.Plugin.DDProxy, {
  72                  // Don't move the node at the end of the drag
  73                  moveOnEnd: false
  74              });
  75              del.dd.plug(Y.Plugin.DDConstrained, {
  76                  // Keep it inside the .course-content
  77                  constrain: '#' + CSS.PAGECONTENT,
  78                  stickY: true
  79              });
  80              del.dd.plug(Y.Plugin.DDWinScroll);
  81          }
  82      },
  83  
  84       /**
  85       * Apply dragdrop features to the specified selector or node that refers to section(s)
  86       *
  87       * @method setup_for_section
  88       * @param {String} baseselector The CSS selector or node to limit scope to
  89       */
  90      setup_for_section: function(baseselector) {
  91          Y.Node.all(baseselector).each(function(sectionnode) {
  92              // Determine the section ID
  93              var sectionid = Y.Moodle.core_course.util.section.getId(sectionnode);
  94  
  95              // We skip the top section as it is not draggable
  96              if (sectionid > 0) {
  97                  // Remove move icons
  98                  var movedown = sectionnode.one('.' + CSS.RIGHT + ' a.' + CSS.MOVEDOWN);
  99                  var moveup = sectionnode.one('.' + CSS.RIGHT + ' a.' + CSS.MOVEUP);
 100  
 101                  // Add dragger icon
 102                  var title = M.util.get_string('movesection', 'moodle', sectionid);
 103                  var cssleft = sectionnode.one('.' + CSS.LEFT);
 104  
 105                  if ((movedown || moveup) && cssleft) {
 106                      cssleft.setStyle('cursor', 'move');
 107                      cssleft.appendChild(this.get_drag_handle(title, CSS.SECTIONHANDLE, 'icon', true));
 108  
 109                      if (moveup) {
 110                          if (moveup.previous('br')) {
 111                              moveup.previous('br').remove();
 112                          } else if (moveup.next('br')) {
 113                              moveup.next('br').remove();
 114                          }
 115  
 116                          if (moveup.ancestor('.section_action_menu')) {
 117                              moveup.ancestor('li').remove();
 118                          } else {
 119                              moveup.remove();
 120                          }
 121                      }
 122                      if (movedown) {
 123                          if (movedown.previous('br')) {
 124                              movedown.previous('br').remove();
 125                          } else if (movedown.next('br')) {
 126                              movedown.next('br').remove();
 127                          }
 128  
 129                          if (movedown.ancestor('.section_action_menu')) {
 130                              movedown.ancestor('li').remove();
 131                          } else {
 132                              movedown.remove();
 133                          }
 134                      }
 135  
 136                      // This section can be moved - add the class to indicate this to Y.DD.
 137                      sectionnode.addClass(CSS.SECTIONDRAGGABLE);
 138                  }
 139              }
 140          }, this);
 141      },
 142  
 143      /*
 144       * Drag-dropping related functions
 145       */
 146      drag_start: function(e) {
 147          // Get our drag object
 148          var drag = e.target;
 149          // Creat a dummy structure of the outer elemnents for clean styles application
 150          var containernode = Y.Node.create('<' + M.course.format.get_containernode() +
 151                  '></' + M.course.format.get_containernode() + '>');
 152          containernode.addClass(M.course.format.get_containerclass());
 153          var sectionnode = Y.Node.create('<' + M.course.format.get_sectionwrappernode() +
 154                  '></' + M.course.format.get_sectionwrappernode() + '>');
 155          sectionnode.addClass(M.course.format.get_sectionwrapperclass());
 156          sectionnode.setStyle('margin', 0);
 157          sectionnode.setContent(drag.get('node').get('innerHTML'));
 158          containernode.appendChild(sectionnode);
 159          drag.get('dragNode').setContent(containernode);
 160          drag.get('dragNode').addClass(CSS.COURSECONTENT);
 161      },
 162  
 163      drag_dropmiss: function(e) {
 164          // Missed the target, but we assume the user intended to drop it
 165          // on the last last ghost node location, e.drag and e.drop should be
 166          // prepared by global_drag_dropmiss parent so simulate drop_hit(e).
 167          this.drop_hit(e);
 168      },
 169  
 170      get_section_index: function(node) {
 171          var sectionlistselector = '.' + CSS.COURSECONTENT + ' ' + M.course.format.get_section_selector(Y),
 172              sectionList = Y.all(sectionlistselector),
 173              nodeIndex = sectionList.indexOf(node),
 174              zeroIndex = sectionList.indexOf(Y.one('#section-0'));
 175  
 176          return (nodeIndex - zeroIndex);
 177      },
 178  
 179      drop_hit: function(e) {
 180          var drag = e.drag;
 181  
 182          // Get references to our nodes and their IDs.
 183          var dragnode = drag.get('node'),
 184              dragnodeid = Y.Moodle.core_course.util.section.getId(dragnode),
 185              loopstart = dragnodeid,
 186  
 187              dropnodeindex = this.get_section_index(dragnode),
 188              loopend = dropnodeindex;
 189  
 190          if (dragnodeid === dropnodeindex) {
 191              Y.log("Skipping move - same location moving " + dragnodeid + " to " + dropnodeindex, 'debug', 'moodle-course-dragdrop');
 192              return;
 193          }
 194  
 195          Y.log("Moving from position " + dragnodeid + " to position " + dropnodeindex, 'debug', 'moodle-course-dragdrop');
 196  
 197          if (loopstart > loopend) {
 198              // If we're going up, we need to swap the loop order
 199              // because loops can't go backwards.
 200              loopstart = dropnodeindex;
 201              loopend = dragnodeid;
 202          }
 203  
 204          // Get the list of nodes.
 205          drag.get('dragNode').removeClass(CSS.COURSECONTENT);
 206          var sectionlist = Y.Node.all(this.sectionlistselector);
 207  
 208          // Add a lightbox if it's not there.
 209          var lightbox = M.util.add_lightbox(Y, dragnode);
 210  
 211          // Handle any variables which we must pass via AJAX.
 212          var params = {},
 213              pageparams = this.get('config').pageparams,
 214              varname;
 215  
 216          for (varname in pageparams) {
 217              if (!pageparams.hasOwnProperty(varname)) {
 218                  continue;
 219              }
 220              params[varname] = pageparams[varname];
 221          }
 222  
 223          // Prepare request parameters
 224          params.sesskey = M.cfg.sesskey;
 225          params.courseId = this.get('courseid');
 226          params['class'] = 'section';
 227          params.field = 'move';
 228          params.id = dragnodeid;
 229          params.value = dropnodeindex;
 230  
 231          // Perform the AJAX request.
 232          var uri = M.cfg.wwwroot + this.get('ajaxurl');
 233          Y.io(uri, {
 234              method: 'POST',
 235              data: params,
 236              on: {
 237                  start: function() {
 238                      lightbox.show();
 239                  },
 240                  success: function(tid, response) {
 241                      // Update section titles, we can't simply swap them as
 242                      // they might have custom title
 243                      try {
 244                          var responsetext = Y.JSON.parse(response.responseText);
 245                          if (responsetext.error) {
 246                              new M.core.ajaxException(responsetext);
 247                          }
 248                          M.course.format.process_sections(Y, sectionlist, responsetext, loopstart, loopend);
 249                      } catch (e) {
 250                          // Ignore.
 251                      }
 252  
 253                      // Update all of the section IDs - first unset them, then set them
 254                      // to avoid duplicates in the DOM.
 255                      var index;
 256  
 257                      // Classic bubble sort algorithm is applied to the section
 258                      // nodes between original drag node location and the new one.
 259                      var swapped = false;
 260                      do {
 261                          swapped = false;
 262                          for (index = loopstart; index <= loopend; index++) {
 263                              if (Y.Moodle.core_course.util.section.getId(sectionlist.item(index - 1)) >
 264                                          Y.Moodle.core_course.util.section.getId(sectionlist.item(index))) {
 265                                  Y.log("Swapping " + Y.Moodle.core_course.util.section.getId(sectionlist.item(index - 1)) +
 266                                          " with " + Y.Moodle.core_course.util.section.getId(sectionlist.item(index)));
 267                                  // Swap section id.
 268                                  var sectionid = sectionlist.item(index - 1).get('id');
 269                                  sectionlist.item(index - 1).set('id', sectionlist.item(index).get('id'));
 270                                  sectionlist.item(index).set('id', sectionid);
 271  
 272                                  // See what format needs to swap.
 273                                  M.course.format.swap_sections(Y, index - 1, index);
 274  
 275                                  // Update flag.
 276                                  swapped = true;
 277                              }
 278                          }
 279                          loopend = loopend - 1;
 280                      } while (swapped);
 281  
 282                      window.setTimeout(function() {
 283                          lightbox.hide();
 284                      }, 250);
 285                  },
 286  
 287                  failure: function(tid, response) {
 288                      this.ajax_failure(response);
 289                      lightbox.hide();
 290                  }
 291              },
 292              context: this
 293          });
 294      }
 295  
 296  }, {
 297      NAME: 'course-dragdrop-section',
 298      ATTRS: {
 299          courseid: {
 300              value: null
 301          },
 302          ajaxurl: {
 303              value: 0
 304          },
 305          config: {
 306              value: 0
 307          }
 308      }
 309  });
 310  
 311  M.course = M.course || {};
 312  M.course.init_section_dragdrop = function(params) {
 313      new DRAGSECTION(params);
 314  };
 315  /**
 316   * Resource drag and drop.
 317   *
 318   * @class M.course.dragdrop.resource
 319   * @constructor
 320   * @extends M.core.dragdrop
 321   */
 322  var DRAGRESOURCE = function() {
 323      DRAGRESOURCE.superclass.constructor.apply(this, arguments);
 324  };
 325  Y.extend(DRAGRESOURCE, M.core.dragdrop, {
 326      initializer: function() {
 327          // Set group for parent class
 328          this.groups = ['resource'];
 329          this.samenodeclass = CSS.ACTIVITY;
 330          this.parentnodeclass = CSS.SECTION;
 331          this.resourcedraghandle = this.get_drag_handle(M.util.get_string('movecoursemodule', 'moodle'),
 332                  CSS.EDITINGMOVE, CSS.ICONCLASS, true);
 333  
 334          this.samenodelabel = {
 335              identifier: 'afterresource',
 336              component: 'moodle'
 337          };
 338          this.parentnodelabel = {
 339              identifier: 'totopofsection',
 340              component: 'moodle'
 341          };
 342  
 343          // Go through all sections
 344          var sectionlistselector = M.course.format.get_section_selector(Y);
 345          if (sectionlistselector) {
 346              sectionlistselector = '.' + CSS.COURSECONTENT + ' ' + sectionlistselector;
 347              this.setup_for_section(sectionlistselector);
 348  
 349              // Initialise drag & drop for all resources/activities
 350              var nodeselector = sectionlistselector.slice(CSS.COURSECONTENT.length + 2) + ' li.' + CSS.ACTIVITY;
 351              var del = new Y.DD.Delegate({
 352                  container: '.' + CSS.COURSECONTENT,
 353                  nodes: nodeselector,
 354                  target: true,
 355                  handles: ['.' + CSS.EDITINGMOVE],
 356                  dragConfig: {groups: this.groups}
 357              });
 358              del.dd.plug(Y.Plugin.DDProxy, {
 359                  // Don't move the node at the end of the drag
 360                  moveOnEnd: false,
 361                  cloneNode: true
 362              });
 363              del.dd.plug(Y.Plugin.DDConstrained, {
 364                  // Keep it inside the .course-content
 365                  constrain: '#' + CSS.PAGECONTENT
 366              });
 367              del.dd.plug(Y.Plugin.DDWinScroll);
 368  
 369              M.course.coursebase.register_module(this);
 370              M.course.dragres = this;
 371          }
 372      },
 373  
 374      /**
 375       * Apply dragdrop features to the specified selector or node that refers to section(s)
 376       *
 377       * @method setup_for_section
 378       * @param {String} baseselector The CSS selector or node to limit scope to
 379       */
 380      setup_for_section: function(baseselector) {
 381          Y.Node.all(baseselector).each(function(sectionnode) {
 382              var resources = sectionnode.one('.' + CSS.CONTENT + ' ul.' + CSS.SECTION);
 383              // See if resources ul exists, if not create one
 384              if (!resources) {
 385                  resources = Y.Node.create('<ul></ul>');
 386                  resources.addClass(CSS.SECTION);
 387                  sectionnode.one('.' + CSS.CONTENT + ' div.' + CSS.SUMMARY).insert(resources, 'after');
 388              }
 389              resources.setAttribute('data-draggroups', this.groups.join(' '));
 390              // Define empty ul as droptarget, so that item could be moved to empty list
 391              new Y.DD.Drop({
 392                  node: resources,
 393                  groups: this.groups,
 394                  padding: '20 0 20 0'
 395              });
 396  
 397              // Initialise each resource/activity in this section
 398              this.setup_for_resource('#' + sectionnode.get('id') + ' li.' + CSS.ACTIVITY);
 399          }, this);
 400      },
 401  
 402      /**
 403       * Apply dragdrop features to the specified selector or node that refers to resource(s)
 404       *
 405       * @method setup_for_resource
 406       * @param {String} baseselector The CSS selector or node to limit scope to
 407       */
 408      setup_for_resource: function(baseselector) {
 409          Y.Node.all(baseselector).each(function(resourcesnode) {
 410              var draggroups = resourcesnode.getData('draggroups');
 411              if (!draggroups) {
 412                  // This Drop Node has not been set up. Configure it now.
 413                  resourcesnode.setAttribute('data-draggroups', this.groups.join(' '));
 414                  // Define empty ul as droptarget, so that item could be moved to empty list
 415                  new Y.DD.Drop({
 416                      node: resourcesnode,
 417                      groups: this.groups,
 418                      padding: '20 0 20 0'
 419                  });
 420              }
 421  
 422              // Replace move icons
 423              var move = resourcesnode.one('a.' + CSS.EDITINGMOVE);
 424              if (move) {
 425                  move.replace(this.resourcedraghandle.cloneNode(true));
 426              }
 427          }, this);
 428      },
 429  
 430      drag_start: function(e) {
 431          // Get our drag object
 432          var drag = e.target;
 433          drag.get('dragNode').setContent(drag.get('node').get('innerHTML'));
 434          drag.get('dragNode').all('img.iconsmall').setStyle('vertical-align', 'baseline');
 435      },
 436  
 437      drag_dropmiss: function(e) {
 438          // Missed the target, but we assume the user intended to drop it
 439          // on the last last ghost node location, e.drag and e.drop should be
 440          // prepared by global_drag_dropmiss parent so simulate drop_hit(e).
 441          this.drop_hit(e);
 442      },
 443  
 444      drop_hit: function(e) {
 445          var drag = e.drag;
 446          // Get a reference to our drag node
 447          var dragnode = drag.get('node');
 448          var dropnode = e.drop.get('node');
 449  
 450          // Add spinner if it not there
 451          var actionarea = dragnode.one(CSS.ACTIONAREA);
 452          var spinner = M.util.add_spinner(Y, actionarea);
 453  
 454          var params = {};
 455  
 456          // Handle any variables which we must pass back through to
 457          var pageparams = this.get('config').pageparams;
 458          var varname;
 459          for (varname in pageparams) {
 460              params[varname] = pageparams[varname];
 461          }
 462  
 463          // Prepare request parameters
 464          params.sesskey = M.cfg.sesskey;
 465          params.courseId = this.get('courseid');
 466          params['class'] = 'resource';
 467          params.field = 'move';
 468          params.id = Number(Y.Moodle.core_course.util.cm.getId(dragnode));
 469          params.sectionId = Y.Moodle.core_course.util.section.getId(dropnode.ancestor(M.course.format.get_section_wrapper(Y), true));
 470  
 471          if (dragnode.next()) {
 472              params.beforeId = Number(Y.Moodle.core_course.util.cm.getId(dragnode.next()));
 473          }
 474  
 475          // Do AJAX request
 476          var uri = M.cfg.wwwroot + this.get('ajaxurl');
 477  
 478          Y.io(uri, {
 479              method: 'POST',
 480              data: params,
 481              on: {
 482                  start: function() {
 483                      this.lock_drag_handle(drag, CSS.EDITINGMOVE);
 484                      spinner.show();
 485                  },
 486                  success: function(tid, response) {
 487                      var responsetext = Y.JSON.parse(response.responseText);
 488                      var params = {element: dragnode, visible: responsetext.visible};
 489                      M.course.coursebase.invoke_function('set_visibility_resource_ui', params);
 490                      this.unlock_drag_handle(drag, CSS.EDITINGMOVE);
 491                      window.setTimeout(function() {
 492                          spinner.hide();
 493                      }, 250);
 494                  },
 495                  failure: function(tid, response) {
 496                      this.ajax_failure(response);
 497                      this.unlock_drag_handle(drag, CSS.SECTIONHANDLE);
 498                      spinner.hide();
 499                      // TODO: revert nodes location
 500                  }
 501              },
 502              context: this
 503          });
 504      }
 505  }, {
 506      NAME: 'course-dragdrop-resource',
 507      ATTRS: {
 508          courseid: {
 509              value: null
 510          },
 511          ajaxurl: {
 512              value: 0
 513          },
 514          config: {
 515              value: 0
 516          }
 517      }
 518  });
 519  
 520  M.course = M.course || {};
 521  M.course.init_resource_dragdrop = function(params) {
 522      new DRAGRESOURCE(params);
 523  };
 524  
 525  
 526  }, '@VERSION@', {
 527      "requires": [
 528          "base",
 529          "node",
 530          "io",
 531          "dom",
 532          "dd",
 533          "dd-scroll",
 534          "moodle-core-dragdrop",
 535          "moodle-core-notification",
 536          "moodle-course-coursebase",
 537          "moodle-course-util"
 538      ]
 539  });


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