[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

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

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


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