[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yui/build/moodle-core-blocks/ -> moodle-core-blocks-debug.js (source)

   1  YUI.add('moodle-core-blocks', function (Y, NAME) {
   2  
   3  /* global MANAGER */
   4  
   5  /**
   6   * Provides drag and drop functionality for blocks.
   7   *
   8   * @module moodle-core-blockdraganddrop
   9   */
  10  
  11  var AJAXURL = '/lib/ajax/blocks.php',
  12  CSS = {
  13      BLOCK: 'block',
  14      BLOCKREGION: 'block-region',
  15      BLOCKADMINBLOCK: 'block_adminblock',
  16      EDITINGMOVE: 'editing_move',
  17      HEADER: 'header',
  18      LIGHTBOX: 'lightbox',
  19      REGIONCONTENT: 'region-content',
  20      SKIPBLOCK: 'skip-block',
  21      SKIPBLOCKTO: 'skip-block-to',
  22      MYINDEX: 'page-my-index',
  23      REGIONMAIN: 'region-main',
  24      BLOCKSMOVING: 'blocks-moving'
  25  };
  26  
  27  var SELECTOR = {
  28      DRAGHANDLE: '.' + CSS.HEADER + ' .commands .moodle-core-dragdrop-draghandle'
  29  };
  30  
  31  /**
  32   * Legacy drag and drop manager.
  33   * This drag and drop manager is specifically designed for themes using side-pre and side-post
  34   * that do not make use of the block output methods introduced by MDL-39824.
  35   *
  36   * @namespace M.core.blockdraganddrop
  37   * @class LegacyManager
  38   * @constructor
  39   * @extends M.core.dragdrop
  40   */
  41  var DRAGBLOCK = function() {
  42      DRAGBLOCK.superclass.constructor.apply(this, arguments);
  43  };
  44  Y.extend(DRAGBLOCK, M.core.dragdrop, {
  45      skipnodetop: null,
  46      skipnodebottom: null,
  47      dragsourceregion: null,
  48      initializer: function() {
  49          // Set group for parent class
  50          this.groups = ['block'];
  51          this.samenodeclass = CSS.BLOCK;
  52          this.parentnodeclass = CSS.REGIONCONTENT;
  53  
  54          // Add relevant classes and ID to 'content' block region on Dashboard page.
  55          var myhomecontent = Y.Node.all('body#' + CSS.MYINDEX + ' #' + CSS.REGIONMAIN + ' > .' + CSS.REGIONCONTENT);
  56          if (myhomecontent.size() > 0) {
  57              var contentregion = myhomecontent.item(0);
  58              contentregion.addClass(CSS.BLOCKREGION);
  59              contentregion.set('id', CSS.REGIONCONTENT);
  60              contentregion.one('div').addClass(CSS.REGIONCONTENT);
  61          }
  62  
  63          // Initialise blocks dragging
  64          // Find all block regions on the page
  65          var blockregionlist = Y.Node.all('div.' + CSS.BLOCKREGION);
  66  
  67          if (blockregionlist.size() === 0) {
  68              return false;
  69          }
  70  
  71          // See if we are missing either of block regions,
  72          // if yes we need to add an empty one to use as target
  73          if (blockregionlist.size() !== this.get('regions').length) {
  74              var blockregion = Y.Node.create('<div></div>')
  75                  .addClass(CSS.BLOCKREGION);
  76              var regioncontent = Y.Node.create('<div></div>')
  77                  .addClass(CSS.REGIONCONTENT);
  78              blockregion.appendChild(regioncontent);
  79              var pre = blockregionlist.filter('#region-pre');
  80              var post = blockregionlist.filter('#region-post');
  81  
  82              if (pre.size() === 0 && post.size() === 1) {
  83                  // pre block is missing, instert it before post
  84                  blockregion.setAttrs({id: 'region-pre'});
  85                  post.item(0).insert(blockregion, 'before');
  86                  blockregionlist.unshift(blockregion);
  87              } else if (post.size() === 0 && pre.size() === 1) {
  88                  // post block is missing, instert it after pre
  89                  blockregion.setAttrs({id: 'region-post'});
  90                  pre.item(0).insert(blockregion, 'after');
  91                  blockregionlist.push(blockregion);
  92              }
  93          }
  94  
  95          blockregionlist.each(function(blockregionnode) {
  96  
  97              // Setting blockregion as droptarget (the case when it is empty)
  98              // The region-post (the right one)
  99              // is very narrow, so add extra padding on the left to drop block on it.
 100              new Y.DD.Drop({
 101                  node: blockregionnode.one('div.' + CSS.REGIONCONTENT),
 102                  groups: this.groups,
 103                  padding: '40 240 40 240'
 104              });
 105  
 106              // Make each div element in the list of blocks draggable
 107              var del = new Y.DD.Delegate({
 108                  container: blockregionnode,
 109                  nodes: '.' + CSS.BLOCK,
 110                  target: true,
 111                  handles: [SELECTOR.DRAGHANDLE],
 112                  invalid: '.block-hider-hide, .block-hider-show, .moveto',
 113                  dragConfig: {groups: this.groups}
 114              });
 115              del.dd.plug(Y.Plugin.DDProxy, {
 116                  // Don't move the node at the end of the drag
 117                  moveOnEnd: false
 118              });
 119              del.dd.plug(Y.Plugin.DDWinScroll);
 120  
 121              var blocklist = blockregionnode.all('.' + CSS.BLOCK);
 122              blocklist.each(function(blocknode) {
 123                  var move = blocknode.one('a.' + CSS.EDITINGMOVE);
 124                  if (move) {
 125                      move.replace(this.get_drag_handle(move.getAttribute('title'), '', 'iconsmall', true));
 126                      blocknode.one(SELECTOR.DRAGHANDLE).setStyle('cursor', 'move');
 127                  }
 128              }, this);
 129          }, this);
 130      },
 131  
 132      get_block_id: function(node) {
 133          return Number(node.get('id').replace(/inst/i, ''));
 134      },
 135  
 136      get_block_region: function(node) {
 137          var region = node.ancestor('div.' + CSS.BLOCKREGION).get('id').replace(/region-/i, '');
 138          if (Y.Array.indexOf(this.get('regions'), region) === -1) {
 139              // Must be standard side-X
 140              if (window.right_to_left()) {
 141                  if (region === 'post') {
 142                      region = 'pre';
 143                  } else if (region === 'pre') {
 144                      region = 'post';
 145                  }
 146              }
 147              return 'side-' + region;
 148          }
 149          // Perhaps custom region
 150          return region;
 151      },
 152  
 153      get_region_id: function(node) {
 154          return node.get('id').replace(/region-/i, '');
 155      },
 156  
 157      drag_start: function(e) {
 158          // Get our drag object
 159          var drag = e.target;
 160  
 161          // Store the parent node of original drag node (block)
 162          // we will need it later for show/hide empty regions
 163          this.dragsourceregion = drag.get('node').ancestor('div.' + CSS.BLOCKREGION);
 164  
 165          // Determine skipnodes and store them
 166          if (drag.get('node').previous() && drag.get('node').previous().hasClass(CSS.SKIPBLOCK)) {
 167              this.skipnodetop = drag.get('node').previous();
 168          }
 169          if (drag.get('node').next() && drag.get('node').next().hasClass(CSS.SKIPBLOCKTO)) {
 170              this.skipnodebottom = drag.get('node').next();
 171          }
 172  
 173          // Add the blocks-moving class so that the theme can respond if need be.
 174          Y.one('body').addClass(CSS.BLOCKSMOVING);
 175      },
 176  
 177      drop_over: function(e) {
 178          // Get a reference to our drag and drop nodes
 179          var drag = e.drag.get('node');
 180          var drop = e.drop.get('node');
 181  
 182          // We need to fix the case when parent drop over event has determined
 183          // 'goingup' and appended the drag node after admin-block.
 184          if (drop.hasClass(this.parentnodeclass) &&
 185                  drop.one('.' + CSS.BLOCKADMINBLOCK) &&
 186                  drop.one('.' + CSS.BLOCKADMINBLOCK).next('.' + CSS.BLOCK)) {
 187              drop.prepend(drag);
 188          }
 189  
 190          // Block is moved within the same region
 191          // stop here, no need to modify anything.
 192          if (this.dragsourceregion.contains(drop)) {
 193              return false;
 194          }
 195  
 196          // TODO: Hiding-displaying block region only works for base theme blocks
 197          // (region-pre, region-post) at the moment. It should be improved
 198          // to work with custom block regions as well.
 199  
 200          // TODO: Fix this for the case when user drag block towards empty section,
 201          // then the section appears, then user chnages his mind and moving back to
 202          // original section. The opposite section remains opened and empty.
 203  
 204          var documentbody = Y.one('body');
 205          // Moving block towards hidden region-content, display it
 206          var regionname = this.get_region_id(this.dragsourceregion);
 207          if (documentbody.hasClass('side-' + regionname + '-only')) {
 208              documentbody.removeClass('side-' + regionname + '-only');
 209          }
 210  
 211          // Moving from empty region-content towards the opposite one,
 212          // hide empty one (only for region-pre, region-post areas at the moment).
 213          regionname = this.get_region_id(drop.ancestor('div.' + CSS.BLOCKREGION));
 214          if (this.dragsourceregion.all('.' + CSS.BLOCK).size() === 0 &&
 215                  this.dragsourceregion.get('id').match(/(region-pre|region-post)/i)) {
 216              if (!documentbody.hasClass('side-' + regionname + '-only')) {
 217                  documentbody.addClass('side-' + regionname + '-only');
 218              }
 219          }
 220      },
 221  
 222      drag_end: function() {
 223          // clear variables
 224          this.skipnodetop = null;
 225          this.skipnodebottom = null;
 226          this.dragsourceregion = null;
 227          // Remove the blocks moving class once the drag-drop is over.
 228          Y.one('body').removeClass(CSS.BLOCKSMOVING);
 229      },
 230  
 231      drag_dropmiss: function(e) {
 232          // Missed the target, but we assume the user intended to drop it
 233          // on the last last ghost node location, e.drag and e.drop should be
 234          // prepared by global_drag_dropmiss parent so simulate drop_hit(e).
 235          this.drop_hit(e);
 236      },
 237  
 238      drop_hit: function(e) {
 239          var drag = e.drag;
 240          // Get a reference to our drag node
 241          var dragnode = drag.get('node');
 242          var dropnode = e.drop.get('node');
 243  
 244          // Amend existing skipnodes
 245          if (dragnode.previous() && dragnode.previous().hasClass(CSS.SKIPBLOCK)) {
 246              // the one that belongs to block below move below
 247              dragnode.insert(dragnode.previous(), 'after');
 248          }
 249          // Move original skipnodes
 250          if (this.skipnodetop) {
 251              dragnode.insert(this.skipnodetop, 'before');
 252          }
 253          if (this.skipnodebottom) {
 254              dragnode.insert(this.skipnodebottom, 'after');
 255          }
 256  
 257          // Add lightbox if it not there
 258          var lightbox = M.util.add_lightbox(Y, dragnode);
 259  
 260          // Prepare request parameters
 261          var params = {
 262              sesskey: M.cfg.sesskey,
 263              courseid: this.get('courseid'),
 264              pagelayout: this.get('pagelayout'),
 265              pagetype: this.get('pagetype'),
 266              subpage: this.get('subpage'),
 267              contextid: this.get('contextid'),
 268              action: 'move',
 269              bui_moveid: this.get_block_id(dragnode),
 270              bui_newregion: this.get_block_region(dropnode)
 271          };
 272  
 273          if (this.get('cmid')) {
 274              params.cmid = this.get('cmid');
 275          }
 276  
 277          if (dragnode.next('.' + this.samenodeclass) && !dragnode.next('.' + this.samenodeclass).hasClass(CSS.BLOCKADMINBLOCK)) {
 278              params.bui_beforeid = this.get_block_id(dragnode.next('.' + this.samenodeclass));
 279          }
 280  
 281          // Do AJAX request
 282          Y.io(M.cfg.wwwroot + AJAXURL, {
 283              method: 'POST',
 284              data: params,
 285              on: {
 286                  start: function() {
 287                      lightbox.show();
 288                  },
 289                  success: function(tid, response) {
 290                      window.setTimeout(function() {
 291                          lightbox.hide();
 292                      }, 250);
 293                      try {
 294                          var responsetext = Y.JSON.parse(response.responseText);
 295                          if (responsetext.error) {
 296                              new M.core.ajaxException(responsetext);
 297                          }
 298                      } catch (e) {
 299                          // Ignore.
 300                      }
 301                  },
 302                  failure: function(tid, response) {
 303                      this.ajax_failure(response);
 304                      lightbox.hide();
 305                  }
 306              },
 307              context: this
 308          });
 309      }
 310  }, {
 311      NAME: 'core-blocks-dragdrop',
 312      ATTRS: {
 313          courseid: {
 314              value: null
 315          },
 316          cmid: {
 317              value: null
 318          },
 319          contextid: {
 320              value: null
 321          },
 322          pagelayout: {
 323              value: null
 324          },
 325          pagetype: {
 326              value: null
 327          },
 328          subpage: {
 329              value: null
 330          },
 331          regions: {
 332              value: null
 333          }
 334      }
 335  });
 336  
 337  M.core = M.core || {};
 338  M.core.blockdraganddrop = M.core.blockdraganddrop || {};
 339  
 340  /**
 341   * True if the page is using the new blocks methods.
 342   * @private
 343   * @static
 344   * @property M.core.blockdraganddrop._isusingnewblocksmethod
 345   * @type Boolean
 346   * @default null
 347   */
 348  M.core.blockdraganddrop._isusingnewblocksmethod = null;
 349  
 350  /**
 351   * Returns true if the page is using the new blocks methods.
 352   * @static
 353   * @method M.core.blockdraganddrop.is_using_blocks_render_method
 354   * @return Boolean
 355   */
 356  M.core.blockdraganddrop.is_using_blocks_render_method = function() {
 357      if (this._isusingnewblocksmethod === null) {
 358          var goodregions = Y.all('.block-region[data-blockregion]').size();
 359          var allregions = Y.all('.block-region').size();
 360          this._isusingnewblocksmethod = (allregions === goodregions);
 361          if (goodregions > 0 && allregions > 0 && goodregions !== allregions) {
 362              Y.log('Both core_renderer::blocks and core_renderer::blocks_for_region have been used.', 'warn', 'moodle-core_blocks');
 363          }
 364      }
 365      return this._isusingnewblocksmethod;
 366  };
 367  
 368  /**
 369   * Initialises a drag and drop manager.
 370   * This should only ever be called once for a page.
 371   * @static
 372   * @method M.core.blockdraganddrop.init
 373   * @param {Object} params
 374   * @return Manager
 375   */
 376  M.core.blockdraganddrop.init = function(params) {
 377      if (this.is_using_blocks_render_method()) {
 378          Y.log('Block drag and drop initialised for the blocks method.', 'info', 'moodle-core_blocks');
 379          new MANAGER(params);
 380      } else {
 381          Y.log('Block drag and drop initialised with the legacy manager (blocks_for_region used).', 'info', 'moodle-core_blocks');
 382          new DRAGBLOCK(params);
 383      }
 384  };
 385  
 386  /*
 387   * Legacy code to keep things working.
 388   */
 389  M.core_blocks = M.core_blocks || {};
 390  M.core_blocks.init_dragdrop = function(params) {
 391      M.core.blockdraganddrop.init(params);
 392  };
 393  /* global BLOCKREGION, SELECTOR, AJAXURL */
 394  
 395  /**
 396   * This file contains the drag and drop manager class.
 397   *
 398   * Provides drag and drop functionality for blocks.
 399   *
 400   * @module moodle-core-blockdraganddrop
 401   */
 402  
 403  /**
 404   * Constructs a new Block drag and drop manager.
 405   *
 406   * @namespace M.core.blockdraganddrop
 407   * @class Manager
 408   * @constructor
 409   * @extends M.core.dragdrop
 410   */
 411  var MANAGER = function() {
 412      MANAGER.superclass.constructor.apply(this, arguments);
 413  };
 414  MANAGER.prototype = {
 415  
 416      /**
 417       * The skip block link from above the block being dragged while a drag is in progress.
 418       * Required by the M.core.dragdrop from whom this class extends.
 419       * @private
 420       * @property skipnodetop
 421       * @type Node
 422       * @default null
 423       */
 424      skipnodetop: null,
 425  
 426      /**
 427       * The skip block link from below the block being dragged while a drag is in progress.
 428       * Required by the M.core.dragdrop from whom this class extends.
 429       * @private
 430       * @property skipnodebottom
 431       * @type Node
 432       * @default null
 433       */
 434      skipnodebottom: null,
 435  
 436      /**
 437       * An associative object of regions and the
 438       * @property regionobjects
 439       * @type {Object} Primitive object mocking an associative array.
 440       * @type {BLOCKREGION} [regionname]* Each item uses the region name as the key with the value being
 441       *      an instance of the BLOCKREGION class.
 442       */
 443      regionobjects: {},
 444  
 445      /**
 446       * Called during the initialisation process of the object.
 447       * @method initializer
 448       */
 449      initializer: function() {
 450          Y.log('Initialising drag and drop for blocks.', 'info');
 451          var regionnames = this.get('regions'),
 452              i = 0,
 453              region,
 454              regionname,
 455              dragdelegation;
 456  
 457          // Evil required by M.core.dragdrop.
 458          this.groups = ['block'];
 459          this.samenodeclass = CSS.BLOCK;
 460          this.parentnodeclass = CSS.BLOCKREGION;
 461  
 462          // Add relevant classes and ID to 'content' block region on Dashboard page.
 463          var myhomecontent = Y.Node.all('body#' + CSS.MYINDEX + ' #' + CSS.REGIONMAIN + ' > .' + CSS.REGIONCONTENT);
 464          if (myhomecontent.size() > 0) {
 465              var contentregion = myhomecontent.item(0);
 466              contentregion.addClass(CSS.BLOCKREGION);
 467              contentregion.set('id', CSS.REGIONCONTENT);
 468              contentregion.one('div').addClass(CSS.REGIONCONTENT);
 469          }
 470  
 471          for (i in regionnames) {
 472              regionname = regionnames[i];
 473              region = new BLOCKREGION({
 474                  manager: this,
 475                  region: regionname,
 476                  node: Y.one('#block-region-' + regionname)
 477              });
 478              this.regionobjects[regionname] = region;
 479  
 480              // Setting blockregion as droptarget (the case when it is empty)
 481              // The region-post (the right one)
 482              // is very narrow, so add extra padding on the left to drop block on it.
 483              new Y.DD.Drop({
 484                  node: region.get_droptarget(),
 485                  groups: this.groups,
 486                  padding: '40 240 40 240'
 487              });
 488  
 489              // Make each div element in the list of blocks draggable
 490              dragdelegation = new Y.DD.Delegate({
 491                  container: region.get_droptarget(),
 492                  nodes: '.' + CSS.BLOCK,
 493                  target: true,
 494                  handles: [SELECTOR.DRAGHANDLE],
 495                  invalid: '.block-hider-hide, .block-hider-show, .moveto, .block_fake',
 496                  dragConfig: {groups: this.groups}
 497              });
 498              dragdelegation.dd.plug(Y.Plugin.DDProxy, {
 499                  // Don't move the node at the end of the drag
 500                  moveOnEnd: false
 501              });
 502              dragdelegation.dd.plug(Y.Plugin.DDWinScroll);
 503  
 504              // On the DD Manager start operation, we enable all block regions so that they can be drop targets. This
 505              // must be done *before* drag:start but after dragging has been initialised.
 506              Y.DD.DDM.on('ddm:start', this.enable_all_regions, this);
 507  
 508              region.change_block_move_icons(this);
 509          }
 510          Y.log('Initialisation of drag and drop for blocks complete.', 'info');
 511      },
 512  
 513      /**
 514       * Returns the ID of the block the given node represents.
 515       * @method get_block_id
 516       * @param {Node} node
 517       * @return {int} The blocks ID in the database.
 518       */
 519      get_block_id: function(node) {
 520          return Number(node.get('id').replace(/inst/i, ''));
 521      },
 522  
 523      /**
 524       * Returns the block region that the node is part of or belonging to.
 525       * @method get_block_region
 526       * @param {Y.Node} node
 527       * @return {string} The region name.
 528       */
 529      get_block_region: function(node) {
 530          if (!node.test('[data-blockregion]')) {
 531              node = node.ancestor('[data-blockregion]');
 532          }
 533          return node.getData('blockregion');
 534      },
 535  
 536      /**
 537       * Returns the BLOCKREGION instance that represents the block region the given node is part of.
 538       * @method get_region_object
 539       * @param {Y.Node} node
 540       * @return {BLOCKREGION}
 541       */
 542      get_region_object: function(node) {
 543          return this.regionobjects[this.get_block_region(node)];
 544      },
 545  
 546      /**
 547       * Enables all fo the regions so that they are all visible while dragging is occuring.
 548       *
 549       * @method enable_all_regions
 550       */
 551      enable_all_regions: function() {
 552          var groups = Y.DD.DDM.activeDrag.get('groups');
 553  
 554          // As we're called by Y.DD.DDM, we can't be certain that the call
 555          // relates specifically to a block drag/drop operation. Test
 556          // whether the relevant group applies here.
 557          if (!groups || Y.Array.indexOf(groups, 'block') === -1) {
 558              return;
 559          }
 560  
 561          var i;
 562          for (i in this.regionobjects) {
 563              if (!this.regionobjects.hasOwnProperty(i)) {
 564                  continue;
 565              }
 566              this.regionobjects[i].enable();
 567          }
 568      },
 569  
 570      /**
 571       * Disables enabled regions if they contain no blocks.
 572       * @method disable_regions_if_required
 573       */
 574      disable_regions_if_required: function() {
 575          var i = 0;
 576          for (i in this.regionobjects) {
 577              this.regionobjects[i].disable_if_required();
 578          }
 579      },
 580  
 581      /**
 582       * Called by M.core.dragdrop.global_drag_start when dragging starts.
 583       * @method drag_start
 584       * @param {Event} e
 585       */
 586      drag_start: function(e) {
 587          // Get our drag object
 588          var drag = e.target;
 589  
 590          // Store the parent node of original drag node (block)
 591          // we will need it later for show/hide empty regions
 592  
 593          // Determine skipnodes and store them
 594          if (drag.get('node').previous() && drag.get('node').previous().hasClass(CSS.SKIPBLOCK)) {
 595              this.skipnodetop = drag.get('node').previous();
 596          }
 597          if (drag.get('node').next() && drag.get('node').next().hasClass(CSS.SKIPBLOCKTO)) {
 598              this.skipnodebottom = drag.get('node').next();
 599          }
 600      },
 601  
 602      /**
 603       * Called by M.core.dragdrop.global_drop_over when something is dragged over a drop target.
 604       * @method drop_over
 605       * @param {Event} e
 606       */
 607      drop_over: function(e) {
 608          // Get a reference to our drag and drop nodes
 609          var drag = e.drag.get('node');
 610          var drop = e.drop.get('node');
 611  
 612          // We need to fix the case when parent drop over event has determined
 613          // 'goingup' and appended the drag node after admin-block.
 614          if (drop.hasClass(CSS.REGIONCONTENT) &&
 615                  drop.one('.' + CSS.BLOCKADMINBLOCK) &&
 616                  drop.one('.' + CSS.BLOCKADMINBLOCK).next('.' + CSS.BLOCK)) {
 617              drop.prepend(drag);
 618          }
 619      },
 620  
 621      /**
 622       * Called by M.core.dragdrop.global_drop_end when a drop has been completed.
 623       * @method drop_end
 624       */
 625      drop_end: function() {
 626          // Clear variables.
 627          this.skipnodetop = null;
 628          this.skipnodebottom = null;
 629          this.disable_regions_if_required();
 630      },
 631  
 632      /**
 633       * Called by M.core.dragdrop.global_drag_dropmiss when something has been dropped on a node that isn't contained by
 634       * a drop target.
 635       *
 636       * @method drag_dropmiss
 637       * @param {Event} e
 638       */
 639      drag_dropmiss: function(e) {
 640          // Missed the target, but we assume the user intended to drop it
 641          // on the last ghost node location, e.drag and e.drop should be
 642          // prepared by global_drag_dropmiss parent so simulate drop_hit(e).
 643          this.drop_hit(e);
 644      },
 645  
 646      /**
 647       * Called by M.core.dragdrop.global_drag_hit when something has been dropped on a drop target.
 648       * @method drop_hit
 649       * @param {Event} e
 650       */
 651      drop_hit: function(e) {
 652          // Get a reference to our drag node
 653          var dragnode = e.drag.get('node');
 654          var dropnode = e.drop.get('node');
 655  
 656          // Amend existing skipnodes
 657          if (dragnode.previous() && dragnode.previous().hasClass(CSS.SKIPBLOCK)) {
 658              // the one that belongs to block below move below
 659              dragnode.insert(dragnode.previous(), 'after');
 660          }
 661          // Move original skipnodes
 662          if (this.skipnodetop) {
 663              dragnode.insert(this.skipnodetop, 'before');
 664          }
 665          if (this.skipnodebottom) {
 666              dragnode.insert(this.skipnodebottom, 'after');
 667          }
 668  
 669          // Add lightbox if it not there
 670          var lightbox = M.util.add_lightbox(Y, dragnode);
 671  
 672          // Prepare request parameters
 673          var params = {
 674              sesskey: M.cfg.sesskey,
 675              courseid: this.get('courseid'),
 676              pagelayout: this.get('pagelayout'),
 677              pagetype: this.get('pagetype'),
 678              subpage: this.get('subpage'),
 679              contextid: this.get('contextid'),
 680              action: 'move',
 681              bui_moveid: this.get_block_id(dragnode),
 682              bui_newregion: this.get_block_region(dropnode)
 683          };
 684  
 685          if (this.get('cmid')) {
 686              params.cmid = this.get('cmid');
 687          }
 688  
 689          if (dragnode.next('.' + CSS.BLOCK) && !dragnode.next('.' + CSS.BLOCK).hasClass(CSS.BLOCKADMINBLOCK)) {
 690              params.bui_beforeid = this.get_block_id(dragnode.next('.' + CSS.BLOCK));
 691          }
 692  
 693          // Do AJAX request
 694          Y.io(M.cfg.wwwroot + AJAXURL, {
 695              method: 'POST',
 696              data: params,
 697              on: {
 698                  start: function() {
 699                      lightbox.show();
 700                  },
 701                  success: function(tid, response) {
 702                      window.setTimeout(function() {
 703                          lightbox.hide();
 704                      }, 250);
 705                      try {
 706                          var responsetext = Y.JSON.parse(response.responseText);
 707                          if (responsetext.error) {
 708                              new M.core.ajaxException(responsetext);
 709                          }
 710                      } catch (e) {
 711                          // Ignore.
 712                      }
 713                  },
 714                  failure: function(tid, response) {
 715                      this.ajax_failure(response);
 716                      lightbox.hide();
 717                  },
 718                  complete: function() {
 719                      this.disable_regions_if_required();
 720                  }
 721              },
 722              context: this
 723          });
 724      }
 725  };
 726  Y.extend(MANAGER, M.core.dragdrop, MANAGER.prototype, {
 727      NAME: 'core-blocks-dragdrop-manager',
 728      ATTRS: {
 729          /**
 730           * The Course ID if there is one.
 731           * @attribute courseid
 732           * @type int|null
 733           * @default null
 734           */
 735          courseid: {
 736              value: null
 737          },
 738  
 739          /**
 740           * The Course Module ID if there is one.
 741           * @attribute cmid
 742           * @type int|null
 743           * @default null
 744           */
 745          cmid: {
 746              value: null
 747          },
 748  
 749          /**
 750           * The Context ID.
 751           * @attribute contextid
 752           * @type int|null
 753           * @default null
 754           */
 755          contextid: {
 756              value: null
 757          },
 758  
 759          /**
 760           * The current page layout.
 761           * @attribute pagelayout
 762           * @type string|null
 763           * @default null
 764           */
 765          pagelayout: {
 766              value: null
 767          },
 768  
 769          /**
 770           * The page type string, should be used as the id for the body tag in the theme.
 771           * @attribute pagetype
 772           * @type string|null
 773           * @default null
 774           */
 775          pagetype: {
 776              value: null
 777          },
 778  
 779          /**
 780           * The subpage identifier, if any.
 781           * @attribute subpage
 782           * @type string|null
 783           * @default null
 784           */
 785          subpage: {
 786              value: null
 787          },
 788  
 789          /**
 790           * An array of block regions that are present on the page.
 791           * @attribute regions
 792           * @type array|null
 793           * @default Array[]
 794           */
 795          regions: {
 796              value: []
 797          }
 798      }
 799  });
 800  /* global MANAGER */
 801  
 802  /**
 803   * This file contains the Block Region class used by the drag and drop manager.
 804   *
 805   * Provides drag and drop functionality for blocks.
 806   *
 807   * @module moodle-core-blockdraganddrop
 808   */
 809  
 810  /**
 811   * Constructs a new block region object.
 812   *
 813   * @namespace M.core.blockdraganddrop
 814   * @class BlockRegion
 815   * @constructor
 816   * @extends Base
 817   */
 818  var BLOCKREGION = function() {
 819      BLOCKREGION.superclass.constructor.apply(this, arguments);
 820  };
 821  BLOCKREGION.prototype = {
 822      /**
 823       * Called during the initialisation process of the object.
 824       * @method initializer
 825       */
 826      initializer: function() {
 827          var node = this.get('node');
 828          Y.log('Block region `' + this.get('region') + '` initialising', 'info');
 829          if (!node) {
 830              Y.log('block region known about but no HTML structure found for it. Guessing structure.', 'warn');
 831              node = this.create_and_add_node();
 832          }
 833          var body = Y.one('body'),
 834              hasblocks = node.all('.' + CSS.BLOCK).size() > 0,
 835              hasregionclass = this.get_has_region_class();
 836          this.set('hasblocks', hasblocks);
 837          if (!body.hasClass(hasregionclass)) {
 838              body.addClass(hasregionclass);
 839          }
 840          body.addClass((hasblocks) ? this.get_used_region_class() : this.get_empty_region_class());
 841          body.removeClass((hasblocks) ? this.get_empty_region_class() : this.get_used_region_class());
 842      },
 843      /**
 844       * Creates a generic block region node and adds it to the DOM at the best guess location.
 845       * Any calling of this method is an unfortunate circumstance.
 846       * @method create_and_add_node
 847       * @return Node The newly created Node
 848       */
 849      create_and_add_node: function() {
 850          var c = Y.Node.create,
 851              region = this.get('region'),
 852              node = c('<div id="block-region-' + region + '" data-droptarget="1"></div>')
 853                  .addClass(CSS.BLOCKREGION)
 854                  .setData('blockregion', region),
 855              regions = this.get('manager').get('regions'),
 856              i,
 857              haspre = false,
 858              haspost = false,
 859              added = false,
 860              pre,
 861              post;
 862  
 863          for (i in regions) {
 864              if (regions[i].match(/(pre|left)/)) {
 865                  haspre = regions[i];
 866              } else if (regions[i].match(/(post|right)/)) {
 867                  haspost = regions[i];
 868              }
 869          }
 870  
 871          if (haspre !== false && haspost !== false) {
 872              if (region === haspre) {
 873                  post = Y.one('#block-region-' + haspost);
 874                  if (post) {
 875                      post.insert(node, 'before');
 876                      added = true;
 877                  }
 878              } else {
 879                  pre = Y.one('#block-region-' + haspre);
 880                  if (pre) {
 881                      pre.insert(node, 'after');
 882                      added = true;
 883                  }
 884              }
 885          }
 886          if (added === false) {
 887              Y.one('body').append(node);
 888          }
 889          this.set('node', node);
 890  
 891          return node;
 892      },
 893  
 894      /**
 895       * Change the move icons to enhanced drag handles and changes the cursor to a move icon when over the header.
 896       * @param M.core.dragdrop the block manager
 897       * @method change_block_move_icons
 898       */
 899      change_block_move_icons: function(manager) {
 900          var handle, icon;
 901          this.get('node').all('.' + CSS.BLOCK + ' a.' + CSS.EDITINGMOVE).each(function(moveicon) {
 902              moveicon.setStyle('cursor', 'move');
 903              handle = manager.get_drag_handle(moveicon.getAttribute('title'), '', 'icon', true);
 904              icon = handle.one('img');
 905              icon.addClass('iconsmall');
 906              icon.removeClass('icon');
 907              moveicon.replace(handle);
 908          });
 909      },
 910  
 911      /**
 912       * Returns the class name on the body that signifies the document knows about this region.
 913       * @method get_has_region_class
 914       * @return String
 915       */
 916      get_has_region_class: function() {
 917          return 'has-region-' + this.get('region');
 918      },
 919  
 920      /**
 921       * Returns the class name to use on the body if the region contains no blocks.
 922       * @method get_empty_region_class
 923       * @return String
 924       */
 925      get_empty_region_class: function() {
 926          return 'empty-region-' + this.get('region');
 927      },
 928  
 929      /**
 930       * Returns the class name to use on the body if the region contains blocks.
 931       * @method get_used_region_class
 932       * @return String
 933       */
 934      get_used_region_class: function() {
 935          return 'used-region-' + this.get('region');
 936      },
 937  
 938      /**
 939       * Returns the node to use as the drop target for this region.
 940       * @method get_droptarget
 941       * @return Node
 942       */
 943      get_droptarget: function() {
 944          var node = this.get('node');
 945          if (node.test('[data-droptarget="1"]')) {
 946              return node;
 947          }
 948          return node.one('[data-droptarget="1"]');
 949      },
 950  
 951      /**
 952       * Enables the block region so that we can be sure the user can see it.
 953       * This is done even if it is empty.
 954       * @method enable
 955       */
 956      enable: function() {
 957          Y.one('body').addClass(this.get_used_region_class()).removeClass(this.get_empty_region_class());
 958      },
 959  
 960      /**
 961       * Disables the region if it contains no blocks, essentially hiding it from the user.
 962       * @method disable_if_required
 963       */
 964      disable_if_required: function() {
 965          if (this.get('node').all('.' + CSS.BLOCK).size() === 0) {
 966              Y.one('body').addClass(this.get_empty_region_class()).removeClass(this.get_used_region_class());
 967          }
 968      }
 969  };
 970  Y.extend(BLOCKREGION, Y.Base, BLOCKREGION.prototype, {
 971      NAME: 'core-blocks-dragdrop-blockregion',
 972      ATTRS: {
 973  
 974          /**
 975           * The drag and drop manager that created this block region instance.
 976           * @attribute manager
 977           * @type M.core.blockdraganddrop.Manager
 978           * @writeOnce
 979           */
 980          manager: {
 981              // Can only be set during initialisation and must be set then.
 982              writeOnce: 'initOnly',
 983              validator: function(value) {
 984                  return Y.Lang.isObject(value) && value instanceof MANAGER;
 985              }
 986          },
 987  
 988          /**
 989           * The name of the block region this object represents.
 990           * @attribute region
 991           * @type String
 992           * @writeOnce
 993           */
 994          region: {
 995              // Can only be set during initialisation and must be set then.
 996              writeOnce: 'initOnly',
 997              validator: function(value) {
 998                  return Y.Lang.isString(value);
 999              }
1000          },
1001  
1002          /**
1003           * The node the block region HTML starts at.s
1004           * @attribute region
1005           * @type Y.Node
1006           */
1007          node: {
1008              validator: function(value) {
1009                  return Y.Lang.isObject(value) || Y.Lang.isNull(value);
1010              }
1011          },
1012  
1013          /**
1014           * True if the block region currently contains blocks.
1015           * @attribute hasblocks
1016           * @type Boolean
1017           * @default false
1018           */
1019          hasblocks: {
1020              value: false,
1021              validator: function(value) {
1022                  return Y.Lang.isBoolean(value);
1023              }
1024          }
1025      }
1026  });
1027  
1028  
1029  }, '@VERSION@', {
1030      "requires": [
1031          "base",
1032          "node",
1033          "io",
1034          "dom",
1035          "dd",
1036          "dd-scroll",
1037          "moodle-core-dragdrop",
1038          "moodle-core-notification"
1039      ]
1040  });


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