[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

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


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