[ Index ]

PHP Cross Reference of moodle-2.8

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


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