[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/mod/quiz/yui/build/moodle-mod_quiz-dragdrop/ -> moodle-mod_quiz-dragdrop.js (source)

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


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