[ Index ]

PHP Cross Reference of moodle-2.8

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  /**
   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              Y.log('Both core_renderer::blocks and core_renderer::blocks_for_region have been used.', 'warn', 'moodle-core_blocks');
 356          }
 357      }
 358      return this._isusingnewblocksmethod;
 359  };
 360  
 361  /**
 362   * Initialises a drag and drop manager.
 363   * This should only ever be called once for a page.
 364   * @static
 365   * @method M.core.blockdraganddrop.init
 366   * @param {Object} params
 367   * @return Manager
 368   */
 369  M.core.blockdraganddrop.init = function(params) {
 370      if (this.is_using_blocks_render_method()) {
 371          Y.log('Block drag and drop initialised for the blocks method.', 'info', 'moodle-core_blocks');
 372          new MANAGER(params);
 373      } else {
 374          Y.log('Block drag and drop initialised with the legacy manager (blocks_for_region used).', 'info', 'moodle-core_blocks');
 375          new DRAGBLOCK(params);
 376      }
 377  };
 378  
 379  /*
 380   * Legacy code to keep things working.
 381   */
 382  M.core_blocks = M.core_blocks || {};
 383  M.core_blocks.init_dragdrop = function(params) {
 384      M.core.blockdraganddrop.init(params);
 385  };
 386  /**
 387   * This file contains the drag and drop manager class.
 388   *
 389   * Provides drag and drop functionality for blocks.
 390   *
 391   * @module moodle-core-blockdraganddrop
 392   */
 393  
 394  /**
 395   * Constructs a new Block drag and drop manager.
 396   *
 397   * @namespace M.core.blockdraganddrop
 398   * @class Manager
 399   * @constructor
 400   * @extends M.core.dragdrop
 401   */
 402  var MANAGER = function() {
 403      MANAGER.superclass.constructor.apply(this, arguments);
 404  };
 405  MANAGER.prototype = {
 406  
 407      /**
 408       * The skip block link from above the block being dragged while a drag is in progress.
 409       * Required by the M.core.dragdrop from whom this class extends.
 410       * @private
 411       * @property skipnodetop
 412       * @type Node
 413       * @default null
 414       */
 415      skipnodetop : null,
 416  
 417      /**
 418       * The skip block link from below the block being dragged while a drag is in progress.
 419       * Required by the M.core.dragdrop from whom this class extends.
 420       * @private
 421       * @property skipnodebottom
 422       * @type Node
 423       * @default null
 424       */
 425      skipnodebottom : null,
 426  
 427      /**
 428       * An associative object of regions and the
 429       * @property regionobjects
 430       * @type {Object} Primitive object mocking an associative array.
 431       * @type {BLOCKREGION} [regionname]* Each item uses the region name as the key with the value being
 432       *      an instance of the BLOCKREGION class.
 433       */
 434      regionobjects : {},
 435  
 436      /**
 437       * Called during the initialisation process of the object.
 438       * @method initializer
 439       */
 440      initializer : function() {
 441          Y.log('Initialising drag and drop for blocks.', 'info');
 442          var regionnames = this.get('regions'),
 443              i = 0,
 444              region,
 445              regionname,
 446              dragdelegation;
 447  
 448          // Evil required by M.core.dragdrop.
 449          this.groups = ['block'];
 450          this.samenodeclass = CSS.BLOCK;
 451          this.parentnodeclass = CSS.BLOCKREGION;
 452  
 453          // Add relevant classes and ID to 'content' block region on My Home page.
 454          var myhomecontent = Y.Node.all('body#'+CSS.MYINDEX+' #'+CSS.REGIONMAIN+' > .'+CSS.REGIONCONTENT);
 455          if (myhomecontent.size() > 0) {
 456              var contentregion = myhomecontent.item(0);
 457              contentregion.addClass(CSS.BLOCKREGION);
 458              contentregion.set('id', CSS.REGIONCONTENT);
 459              contentregion.one('div').addClass(CSS.REGIONCONTENT);
 460          }
 461  
 462          for (i in regionnames) {
 463              regionname = regionnames[i];
 464              region = new BLOCKREGION({
 465                  manager : this,
 466                  region : regionname,
 467                  node : Y.one('#block-region-'+regionname)
 468              });
 469              this.regionobjects[regionname] = region;
 470  
 471              // Setting blockregion as droptarget (the case when it is empty)
 472              // The region-post (the right one)
 473              // is very narrow, so add extra padding on the left to drop block on it.
 474              new Y.DD.Drop({
 475                  node: region.get_droptarget(),
 476                  groups: this.groups,
 477                  padding: '40 240 40 240'
 478              });
 479  
 480              // Make each div element in the list of blocks draggable
 481              dragdelegation = new Y.DD.Delegate({
 482                  container: region.get_droptarget(),
 483                  nodes: '.'+CSS.BLOCK,
 484                  target: true,
 485                  handles: [SELECTOR.DRAGHANDLE],
 486                  invalid: '.block-hider-hide, .block-hider-show, .moveto, .block_fake',
 487                  dragConfig: {groups: this.groups}
 488              });
 489              dragdelegation.dd.plug(Y.Plugin.DDProxy, {
 490                  // Don't move the node at the end of the drag
 491                  moveOnEnd: false
 492              });
 493              dragdelegation.dd.plug(Y.Plugin.DDWinScroll);
 494  
 495              // On the DD Manager start operation, we enable all block regions so that they can be drop targets. This
 496              // must be done *before* drag:start but after dragging has been initialised.
 497              Y.DD.DDM.on('ddm:start', this.enable_all_regions, this);
 498  
 499              region.change_block_move_icons(this);
 500          }
 501          Y.log('Initialisation of drag and drop for blocks complete.', 'info');
 502      },
 503  
 504      /**
 505       * Returns the ID of the block the given node represents.
 506       * @method get_block_id
 507       * @param {Node} node
 508       * @return {int} The blocks ID in the database.
 509       */
 510      get_block_id : function(node) {
 511          return Number(node.get('id').replace(/inst/i, ''));
 512      },
 513  
 514      /**
 515       * Returns the block region that the node is part of or belonging to.
 516       * @method get_block_region
 517       * @param {Y.Node} node
 518       * @return {string} The region name.
 519       */
 520      get_block_region : function(node) {
 521          if (!node.test('[data-blockregion]')) {
 522              node = node.ancestor('[data-blockregion]');
 523          }
 524          return node.getData('blockregion');
 525      },
 526  
 527      /**
 528       * Returns the BLOCKREGION instance that represents the block region the given node is part of.
 529       * @method get_region_object
 530       * @param {Y.Node} node
 531       * @return {BLOCKREGION}
 532       */
 533      get_region_object : function(node) {
 534          return this.regionobjects[this.get_block_region(node)];
 535      },
 536  
 537      /**
 538       * Enables all fo the regions so that they are all visible while dragging is occuring.
 539       *
 540       * @method enable_all_regions
 541       */
 542      enable_all_regions : function() {
 543          var groups = Y.DD.DDM.activeDrag.get('groups');
 544  
 545          // As we're called by Y.DD.DDM, we can't be certain that the call
 546          // relates specifically to a block drag/drop operation. Test
 547          // whether the relevant group applies here.
 548          if (!groups || Y.Array.indexOf(groups, 'block') === -1) {
 549              return;
 550          }
 551  
 552          var i;
 553          for (i in this.regionobjects) {
 554              if (!this.regionobjects.hasOwnProperty(i)) {
 555                  continue;
 556              }
 557              this.regionobjects[i].enable();
 558          }
 559      },
 560  
 561      /**
 562       * Disables enabled regions if they contain no blocks.
 563       * @method disable_regions_if_required
 564       */
 565      disable_regions_if_required : function() {
 566          var i = 0;
 567          for (i in this.regionobjects) {
 568              this.regionobjects[i].disable_if_required();
 569          }
 570      },
 571  
 572      /**
 573       * Called by M.core.dragdrop.global_drag_start when dragging starts.
 574       * @method drag_start
 575       * @param {Event} e
 576       */
 577      drag_start : function(e) {
 578          // Get our drag object
 579          var drag = e.target;
 580  
 581          // Store the parent node of original drag node (block)
 582          // we will need it later for show/hide empty regions
 583  
 584          // Determine skipnodes and store them
 585          if (drag.get('node').previous() && drag.get('node').previous().hasClass(CSS.SKIPBLOCK)) {
 586              this.skipnodetop = drag.get('node').previous();
 587          }
 588          if (drag.get('node').next() && drag.get('node').next().hasClass(CSS.SKIPBLOCKTO)) {
 589              this.skipnodebottom = drag.get('node').next();
 590          }
 591      },
 592  
 593      /**
 594       * Called by M.core.dragdrop.global_drop_over when something is dragged over a drop target.
 595       * @method drop_over
 596       * @param {Event} e
 597       */
 598      drop_over : function(e) {
 599          // Get a reference to our drag and drop nodes
 600          var drag = e.drag.get('node');
 601          var drop = e.drop.get('node');
 602  
 603          // We need to fix the case when parent drop over event has determined
 604          // 'goingup' and appended the drag node after admin-block.
 605          if (drop.hasClass(CSS.REGIONCONTENT) && drop.one('.'+CSS.BLOCKADMINBLOCK) && drop.one('.'+CSS.BLOCKADMINBLOCK).next('.'+CSS.BLOCK)) {
 606              drop.prepend(drag);
 607          }
 608      },
 609  
 610      /**
 611       * Called by M.core.dragdrop.global_drop_end when a drop has been completed.
 612       * @method drop_end
 613       */
 614      drop_end : function() {
 615          // Clear variables.
 616          this.skipnodetop = null;
 617          this.skipnodebottom = null;
 618          this.disable_regions_if_required();
 619      },
 620  
 621      /**
 622       * Called by M.core.dragdrop.global_drag_dropmiss when something has been dropped on a node that isn't contained by a drop target.
 623       * @method drag_dropmiss
 624       * @param {Event} e
 625       */
 626      drag_dropmiss : function(e) {
 627          // Missed the target, but we assume the user intended to drop it
 628          // on the last ghost node location, e.drag and e.drop should be
 629          // prepared by global_drag_dropmiss parent so simulate drop_hit(e).
 630          this.drop_hit(e);
 631      },
 632  
 633      /**
 634       * Called by M.core.dragdrop.global_drag_hit when something has been dropped on a drop target.
 635       * @method drop_hit
 636       * @param {Event} e
 637       */
 638      drop_hit : function(e) {
 639          // Get a reference to our drag node
 640          var dragnode = e.drag.get('node');
 641          var dropnode = e.drop.get('node');
 642  
 643          // Amend existing skipnodes
 644          if (dragnode.previous() && dragnode.previous().hasClass(CSS.SKIPBLOCK)) {
 645              // the one that belongs to block below move below
 646              dragnode.insert(dragnode.previous(), 'after');
 647          }
 648          // Move original skipnodes
 649          if (this.skipnodetop) {
 650              dragnode.insert(this.skipnodetop, 'before');
 651          }
 652          if (this.skipnodebottom) {
 653              dragnode.insert(this.skipnodebottom, 'after');
 654          }
 655  
 656          // Add lightbox if it not there
 657          var lightbox = M.util.add_lightbox(Y, dragnode);
 658  
 659          // Prepare request parameters
 660          var params = {
 661              sesskey : M.cfg.sesskey,
 662              courseid : this.get('courseid'),
 663              pagelayout : this.get('pagelayout'),
 664              pagetype : this.get('pagetype'),
 665              subpage : this.get('subpage'),
 666              contextid : this.get('contextid'),
 667              action : 'move',
 668              bui_moveid : this.get_block_id(dragnode),
 669              bui_newregion : this.get_block_region(dropnode)
 670          };
 671  
 672          if (this.get('cmid')) {
 673              params.cmid = this.get('cmid');
 674          }
 675  
 676          if (dragnode.next('.'+CSS.BLOCK) && !dragnode.next('.'+CSS.BLOCK).hasClass(CSS.BLOCKADMINBLOCK)) {
 677              params.bui_beforeid = this.get_block_id(dragnode.next('.'+CSS.BLOCK));
 678          }
 679  
 680          // Do AJAX request
 681          Y.io(M.cfg.wwwroot+AJAXURL, {
 682              method: 'POST',
 683              data: params,
 684              on: {
 685                  start : function() {
 686                      lightbox.show();
 687                  },
 688                  success: function(tid, response) {
 689                      window.setTimeout(function() {
 690                          lightbox.hide();
 691                      }, 250);
 692                      try {
 693                          var responsetext = Y.JSON.parse(response.responseText);
 694                          if (responsetext.error) {
 695                              new M.core.ajaxException(responsetext);
 696                          }
 697                      } catch (e) {}
 698                  },
 699                  failure: function(tid, response) {
 700                      this.ajax_failure(response);
 701                      lightbox.hide();
 702                  },
 703                  complete : function() {
 704                      this.disable_regions_if_required();
 705                  }
 706              },
 707              context:this
 708          });
 709      }
 710  };
 711  Y.extend(MANAGER, M.core.dragdrop, MANAGER.prototype, {
 712      NAME : 'core-blocks-dragdrop-manager',
 713      ATTRS : {
 714          /**
 715           * The Course ID if there is one.
 716           * @attribute courseid
 717           * @type int|null
 718           * @default null
 719           */
 720          courseid : {
 721              value : null
 722          },
 723  
 724          /**
 725           * The Course Module ID if there is one.
 726           * @attribute cmid
 727           * @type int|null
 728           * @default null
 729           */
 730          cmid : {
 731              value : null
 732          },
 733  
 734          /**
 735           * The Context ID.
 736           * @attribute contextid
 737           * @type int|null
 738           * @default null
 739           */
 740          contextid : {
 741              value : null
 742          },
 743  
 744          /**
 745           * The current page layout.
 746           * @attribute pagelayout
 747           * @type string|null
 748           * @default null
 749           */
 750          pagelayout : {
 751              value : null
 752          },
 753  
 754          /**
 755           * The page type string, should be used as the id for the body tag in the theme.
 756           * @attribute pagetype
 757           * @type string|null
 758           * @default null
 759           */
 760          pagetype : {
 761              value : null
 762          },
 763  
 764          /**
 765           * The subpage identifier, if any.
 766           * @attribute subpage
 767           * @type string|null
 768           * @default null
 769           */
 770          subpage : {
 771              value : null
 772          },
 773  
 774          /**
 775           * An array of block regions that are present on the page.
 776           * @attribute regions
 777           * @type array|null
 778           * @default Array[]
 779           */
 780          regions : {
 781              value : []
 782          }
 783      }
 784  });
 785  /**
 786   * This file contains the Block Region class used by the drag and drop manager.
 787   *
 788   * Provides drag and drop functionality for blocks.
 789   *
 790   * @module moodle-core-blockdraganddrop
 791   */
 792  
 793  /**
 794   * Constructs a new block region object.
 795   *
 796   * @namespace M.core.blockdraganddrop
 797   * @class BlockRegion
 798   * @constructor
 799   * @extends Base
 800   */
 801  var BLOCKREGION = function() {
 802      BLOCKREGION.superclass.constructor.apply(this, arguments);
 803  };
 804  BLOCKREGION.prototype = {
 805      /**
 806       * Called during the initialisation process of the object.
 807       * @method initializer
 808       */
 809      initializer : function() {
 810          var node = this.get('node');
 811          Y.log('Block region `'+this.get('region')+'` initialising', 'info');
 812          if (!node) {
 813              Y.log('block region known about but no HTML structure found for it. Guessing structure.', 'warn');
 814              node = this.create_and_add_node();
 815          }
 816          var body = Y.one('body'),
 817              hasblocks = node.all('.'+CSS.BLOCK).size() > 0,
 818              hasregionclass = this.get_has_region_class();
 819          this.set('hasblocks', hasblocks);
 820          if (!body.hasClass(hasregionclass)) {
 821              body.addClass(hasregionclass);
 822          }
 823          body.addClass((hasblocks) ? this.get_used_region_class() : this.get_empty_region_class());
 824          body.removeClass((hasblocks) ? this.get_empty_region_class() : this.get_used_region_class());
 825      },
 826      /**
 827       * Creates a generic block region node and adds it to the DOM at the best guess location.
 828       * Any calling of this method is an unfortunate circumstance.
 829       * @method create_and_add_node
 830       * @return Node The newly created Node
 831       */
 832      create_and_add_node : function() {
 833          var c = Y.Node.create,
 834              region = this.get('region'),
 835              node = c('<div id="block-region-'+region+'" data-droptarget="1"></div>')
 836                  .addClass(CSS.BLOCKREGION)
 837                  .setData('blockregion', region),
 838              regions = this.get('manager').get('regions'),
 839              i,
 840              haspre = false,
 841              haspost = false,
 842              added = false,
 843              pre,
 844              post;
 845  
 846          for (i in regions) {
 847              if (regions[i].match(/(pre|left)/)) {
 848                  haspre = regions[i];
 849              } else if (regions[i].match(/(post|right)/)) {
 850                  haspost = regions[i];
 851              }
 852          }
 853  
 854          if (haspre !== false && haspost !== false) {
 855              if (region === haspre) {
 856                  post = Y.one('#block-region-'+haspost);
 857                  if (post) {
 858                      post.insert(node, 'before');
 859                      added = true;
 860                  }
 861              } else {
 862                  pre = Y.one('#block-region-'+haspre);
 863                  if (pre) {
 864                      pre.insert(node, 'after');
 865                      added = true;
 866                  }
 867              }
 868          }
 869          if (added === false) {
 870              Y.one('body').append(node);
 871          }
 872          this.set('node', node);
 873  
 874          return node;
 875      },
 876  
 877      /**
 878       * Change the move icons to enhanced drag handles and changes the cursor to a move icon when over the header.
 879       * @param M.core.dragdrop the block manager
 880       * @method change_block_move_icons
 881       */
 882      change_block_move_icons : function(manager) {
 883          var handle, icon;
 884          this.get('node').all('.'+CSS.BLOCK+' a.'+CSS.EDITINGMOVE).each(function(moveicon){
 885              moveicon.setStyle('cursor', 'move');
 886              handle = manager.get_drag_handle(moveicon.getAttribute('title'), '', 'icon', true);
 887              icon = handle.one('img');
 888              icon.addClass('iconsmall');
 889              icon.removeClass('icon');
 890              moveicon.replace(handle);
 891          });
 892      },
 893  
 894      /**
 895       * Returns the class name on the body that signifies the document knows about this region.
 896       * @method get_has_region_class
 897       * @return String
 898       */
 899      get_has_region_class : function() {
 900          return 'has-region-'+this.get('region');
 901      },
 902  
 903      /**
 904       * Returns the class name to use on the body if the region contains no blocks.
 905       * @method get_empty_region_class
 906       * @return String
 907       */
 908      get_empty_region_class : function() {
 909          return 'empty-region-'+this.get('region');
 910      },
 911  
 912      /**
 913       * Returns the class name to use on the body if the region contains blocks.
 914       * @method get_used_region_class
 915       * @return String
 916       */
 917      get_used_region_class : function() {
 918          return 'used-region-'+this.get('region');
 919      },
 920  
 921      /**
 922       * Returns the node to use as the drop target for this region.
 923       * @method get_droptarget
 924       * @return Node
 925       */
 926      get_droptarget : function() {
 927          var node = this.get('node');
 928          if (node.test('[data-droptarget="1"]')) {
 929              return node;
 930          }
 931          return node.one('[data-droptarget="1"]');
 932      },
 933  
 934      /**
 935       * Enables the block region so that we can be sure the user can see it.
 936       * This is done even if it is empty.
 937       * @method enable
 938       */
 939      enable : function() {
 940          Y.one('body').addClass(this.get_used_region_class()).removeClass(this.get_empty_region_class());
 941      },
 942  
 943      /**
 944       * Disables the region if it contains no blocks, essentially hiding it from the user.
 945       * @method disable_if_required
 946       */
 947      disable_if_required : function() {
 948          if (this.get('node').all('.'+CSS.BLOCK).size() === 0) {
 949              Y.one('body').addClass(this.get_empty_region_class()).removeClass(this.get_used_region_class());
 950          }
 951      }
 952  };
 953  Y.extend(BLOCKREGION, Y.Base, BLOCKREGION.prototype, {
 954      NAME : 'core-blocks-dragdrop-blockregion',
 955      ATTRS : {
 956  
 957          /**
 958           * The drag and drop manager that created this block region instance.
 959           * @attribute manager
 960           * @type M.core.blockdraganddrop.Manager
 961           * @writeOnce
 962           */
 963          manager : {
 964              // Can only be set during initialisation and must be set then.
 965              writeOnce : 'initOnly',
 966              validator : function (value) {
 967                  return Y.Lang.isObject(value) && value instanceof MANAGER;
 968              }
 969          },
 970  
 971          /**
 972           * The name of the block region this object represents.
 973           * @attribute region
 974           * @type String
 975           * @writeOnce
 976           */
 977          region : {
 978              // Can only be set during initialisation and must be set then.
 979              writeOnce : 'initOnly',
 980              validator : function (value) {
 981                  return Y.Lang.isString(value);
 982              }
 983          },
 984  
 985          /**
 986           * The node the block region HTML starts at.s
 987           * @attribute region
 988           * @type Y.Node
 989           */
 990          node : {
 991              validator : function (value) {
 992                  return Y.Lang.isObject(value) || Y.Lang.isNull(value);
 993              }
 994          },
 995  
 996          /**
 997           * True if the block region currently contains blocks.
 998           * @attribute hasblocks
 999           * @type Boolean
1000           * @default false
1001           */
1002          hasblocks : {
1003              value : false,
1004              validator : function (value) {
1005                  return Y.Lang.isBoolean(value);
1006              }
1007          }
1008      }
1009  });
1010  
1011  
1012  }, '@VERSION@', {
1013      "requires": [
1014          "base",
1015          "node",
1016          "io",
1017          "dom",
1018          "dd",
1019          "dd-scroll",
1020          "moodle-core-dragdrop",
1021          "moodle-core-notification"
1022      ]
1023  });


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