[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/course/yui/build/moodle-course-dragdrop/ -> moodle-course-dragdrop.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              return;
 169          }
 170  
 171  
 172          if (loopstart > loopend) {
 173              // If we're going up, we need to swap the loop order
 174              // because loops can't go backwards.
 175              loopstart = dropnodeindex;
 176              loopend = dragnodeid;
 177          }
 178  
 179          // Get the list of nodes.
 180          drag.get('dragNode').removeClass(CSS.COURSECONTENT);
 181          var sectionlist = Y.Node.all(this.sectionlistselector);
 182  
 183          // Add a lightbox if it's not there.
 184          var lightbox = M.util.add_lightbox(Y, dragnode);
 185  
 186          // Handle any variables which we must pass via AJAX.
 187          var params = {},
 188              pageparams = this.get('config').pageparams,
 189              varname;
 190  
 191          for (varname in pageparams) {
 192              if (!pageparams.hasOwnProperty(varname)) {
 193                  continue;
 194              }
 195              params[varname] = pageparams[varname];
 196          }
 197  
 198          // Prepare request parameters
 199          params.sesskey = M.cfg.sesskey;
 200          params.courseId = this.get('courseid');
 201          params['class'] = 'section';
 202          params.field = 'move';
 203          params.id = dragnodeid;
 204          params.value = dropnodeindex;
 205  
 206          // Perform the AJAX request.
 207          var uri = M.cfg.wwwroot + this.get('ajaxurl');
 208          Y.io(uri, {
 209              method: 'POST',
 210              data: params,
 211              on: {
 212                  start: function() {
 213                      lightbox.show();
 214                  },
 215                  success: function(tid, response) {
 216                      // Update section titles, we can't simply swap them as
 217                      // they might have custom title
 218                      try {
 219                          var responsetext = Y.JSON.parse(response.responseText);
 220                          if (responsetext.error) {
 221                              new M.core.ajaxException(responsetext);
 222                          }
 223                          M.course.format.process_sections(Y, sectionlist, responsetext, loopstart, loopend);
 224                      } catch (e) {}
 225  
 226                      // Update all of the section IDs - first unset them, then set them
 227                      // to avoid duplicates in the DOM.
 228                      var index;
 229  
 230                      // Classic bubble sort algorithm is applied to the section
 231                      // nodes between original drag node location and the new one.
 232                      var swapped = false;
 233                      do {
 234                          swapped = false;
 235                          for (index = loopstart; index <= loopend; index++) {
 236                              if (Y.Moodle.core_course.util.section.getId(sectionlist.item(index - 1)) >
 237                                          Y.Moodle.core_course.util.section.getId(sectionlist.item(index))) {
 238                                  // Swap section id.
 239                                  var sectionid = sectionlist.item(index - 1).get('id');
 240                                  sectionlist.item(index - 1).set('id', sectionlist.item(index).get('id'));
 241                                  sectionlist.item(index).set('id', sectionid);
 242  
 243                                  // See what format needs to swap.
 244                                  M.course.format.swap_sections(Y, index - 1, index);
 245  
 246                                  // Update flag.
 247                                  swapped = true;
 248                              }
 249                          }
 250                          loopend = loopend - 1;
 251                      } while (swapped);
 252  
 253                      window.setTimeout(function() {
 254                          lightbox.hide();
 255                      }, 250);
 256                  },
 257  
 258                  failure: function(tid, response) {
 259                      this.ajax_failure(response);
 260                      lightbox.hide();
 261                  }
 262              },
 263              context:this
 264          });
 265      }
 266  
 267  }, {
 268      NAME: 'course-dragdrop-section',
 269      ATTRS: {
 270          courseid: {
 271              value: null
 272          },
 273          ajaxurl: {
 274              value: 0
 275          },
 276          config: {
 277              value: 0
 278          }
 279      }
 280  });
 281  
 282  M.course = M.course || {};
 283  M.course.init_section_dragdrop = function(params) {
 284      new DRAGSECTION(params);
 285  };
 286  /**
 287   * Resource drag and drop.
 288   *
 289   * @class M.course.dragdrop.resource
 290   * @constructor
 291   * @extends M.core.dragdrop
 292   */
 293  var DRAGRESOURCE = function() {
 294      DRAGRESOURCE.superclass.constructor.apply(this, arguments);
 295  };
 296  Y.extend(DRAGRESOURCE, M.core.dragdrop, {
 297      initializer: function() {
 298          // Set group for parent class
 299          this.groups = ['resource'];
 300          this.samenodeclass = CSS.ACTIVITY;
 301          this.parentnodeclass = CSS.SECTION;
 302          this.resourcedraghandle = this.get_drag_handle(M.util.get_string('movecoursemodule', 'moodle'), CSS.EDITINGMOVE, CSS.ICONCLASS, true);
 303  
 304          this.samenodelabel = {
 305              identifier: 'afterresource',
 306              component: 'moodle'
 307          };
 308          this.parentnodelabel = {
 309              identifier: 'totopofsection',
 310              component: 'moodle'
 311          };
 312  
 313          // Go through all sections
 314          var sectionlistselector = M.course.format.get_section_selector(Y);
 315          if (sectionlistselector) {
 316              sectionlistselector = '.' + CSS.COURSECONTENT + ' ' + sectionlistselector;
 317              this.setup_for_section(sectionlistselector);
 318  
 319              // Initialise drag & drop for all resources/activities
 320              var nodeselector = sectionlistselector.slice(CSS.COURSECONTENT.length + 2) + ' li.' + CSS.ACTIVITY;
 321              var del = new Y.DD.Delegate({
 322                  container: '.' + CSS.COURSECONTENT,
 323                  nodes: nodeselector,
 324                  target: true,
 325                  handles: ['.' + CSS.EDITINGMOVE],
 326                  dragConfig: {groups: this.groups}
 327              });
 328              del.dd.plug(Y.Plugin.DDProxy, {
 329                  // Don't move the node at the end of the drag
 330                  moveOnEnd: false,
 331                  cloneNode: true
 332              });
 333              del.dd.plug(Y.Plugin.DDConstrained, {
 334                  // Keep it inside the .course-content
 335                  constrain: '#' + CSS.PAGECONTENT
 336              });
 337              del.dd.plug(Y.Plugin.DDWinScroll);
 338  
 339              M.course.coursebase.register_module(this);
 340              M.course.dragres = this;
 341          }
 342      },
 343  
 344      /**
 345       * Apply dragdrop features to the specified selector or node that refers to section(s)
 346       *
 347       * @method setup_for_section
 348       * @param {String} baseselector The CSS selector or node to limit scope to
 349       */
 350      setup_for_section: function(baseselector) {
 351          Y.Node.all(baseselector).each(function(sectionnode) {
 352              var resources = sectionnode.one('.' + CSS.CONTENT + ' ul.' + CSS.SECTION);
 353              // See if resources ul exists, if not create one
 354              if (!resources) {
 355                  resources = Y.Node.create('<ul></ul>');
 356                  resources.addClass(CSS.SECTION);
 357                  sectionnode.one('.' + CSS.CONTENT + ' div.' + CSS.SUMMARY).insert(resources, 'after');
 358              }
 359              resources.setAttribute('data-draggroups', this.groups.join(' '));
 360              // Define empty ul as droptarget, so that item could be moved to empty list
 361              new Y.DD.Drop({
 362                  node: resources,
 363                  groups: this.groups,
 364                  padding: '20 0 20 0'
 365              });
 366  
 367              // Initialise each resource/activity in this section
 368              this.setup_for_resource('#' + sectionnode.get('id') + ' li.' + CSS.ACTIVITY);
 369          }, this);
 370      },
 371  
 372      /**
 373       * Apply dragdrop features to the specified selector or node that refers to resource(s)
 374       *
 375       * @method setup_for_resource
 376       * @param {String} baseselector The CSS selector or node to limit scope to
 377       */
 378      setup_for_resource: function(baseselector) {
 379          Y.Node.all(baseselector).each(function(resourcesnode) {
 380              // Replace move icons
 381              var move = resourcesnode.one('a.' + CSS.EDITINGMOVE);
 382              if (move) {
 383                  move.replace(this.resourcedraghandle.cloneNode(true));
 384              }
 385          }, this);
 386      },
 387  
 388      drag_start: function(e) {
 389          // Get our drag object
 390          var drag = e.target;
 391          drag.get('dragNode').setContent(drag.get('node').get('innerHTML'));
 392          drag.get('dragNode').all('img.iconsmall').setStyle('vertical-align', 'baseline');
 393      },
 394  
 395      drag_dropmiss: function(e) {
 396          // Missed the target, but we assume the user intended to drop it
 397          // on the last last ghost node location, e.drag and e.drop should be
 398          // prepared by global_drag_dropmiss parent so simulate drop_hit(e).
 399          this.drop_hit(e);
 400      },
 401  
 402      drop_hit: function(e) {
 403          var drag = e.drag;
 404          // Get a reference to our drag node
 405          var dragnode = drag.get('node');
 406          var dropnode = e.drop.get('node');
 407  
 408          // Add spinner if it not there
 409          var actionarea = dragnode.one(CSS.ACTIONAREA);
 410          var spinner = M.util.add_spinner(Y, actionarea);
 411  
 412          var params = {};
 413  
 414          // Handle any variables which we must pass back through to
 415          var pageparams = this.get('config').pageparams;
 416          var varname;
 417          for (varname in pageparams) {
 418              params[varname] = pageparams[varname];
 419          }
 420  
 421          // Prepare request parameters
 422          params.sesskey = M.cfg.sesskey;
 423          params.courseId = this.get('courseid');
 424          params['class'] = 'resource';
 425          params.field = 'move';
 426          params.id = Number(Y.Moodle.core_course.util.cm.getId(dragnode));
 427          params.sectionId = Y.Moodle.core_course.util.section.getId(dropnode.ancestor(M.course.format.get_section_wrapper(Y), true));
 428  
 429          if (dragnode.next()) {
 430              params.beforeId = Number(Y.Moodle.core_course.util.cm.getId(dragnode.next()));
 431          }
 432  
 433          // Do AJAX request
 434          var uri = M.cfg.wwwroot + this.get('ajaxurl');
 435  
 436          Y.io(uri, {
 437              method: 'POST',
 438              data: params,
 439              on: {
 440                  start: function() {
 441                      this.lock_drag_handle(drag, CSS.EDITINGMOVE);
 442                      spinner.show();
 443                  },
 444                  success: function(tid, response) {
 445                      var responsetext = Y.JSON.parse(response.responseText);
 446                      var params = {element: dragnode, visible: responsetext.visible};
 447                      M.course.coursebase.invoke_function('set_visibility_resource_ui', params);
 448                      this.unlock_drag_handle(drag, CSS.EDITINGMOVE);
 449                      window.setTimeout(function() {
 450                          spinner.hide();
 451                      }, 250);
 452                  },
 453                  failure: function(tid, response) {
 454                      this.ajax_failure(response);
 455                      this.unlock_drag_handle(drag, CSS.SECTIONHANDLE);
 456                      spinner.hide();
 457                      // TODO: revert nodes location
 458                  }
 459              },
 460              context:this
 461          });
 462      }
 463  }, {
 464      NAME: 'course-dragdrop-resource',
 465      ATTRS: {
 466          courseid: {
 467              value: null
 468          },
 469          ajaxurl: {
 470              value: 0
 471          },
 472          config: {
 473              value: 0
 474          }
 475      }
 476  });
 477  
 478  M.course = M.course || {};
 479  M.course.init_resource_dragdrop = function(params) {
 480      new DRAGRESOURCE(params);
 481  };
 482  
 483  
 484  }, '@VERSION@', {
 485      "requires": [
 486          "base",
 487          "node",
 488          "io",
 489          "dom",
 490          "dd",
 491          "dd-scroll",
 492          "moodle-core-dragdrop",
 493          "moodle-core-notification",
 494          "moodle-course-coursebase",
 495          "moodle-course-util"
 496      ]
 497  });


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