[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yui/src/blocks/js/ -> blocks.js (source)

   1  /* global MANAGER */
   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 Dashboard 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 (window.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) &&
 183                  drop.one('.' + CSS.BLOCKADMINBLOCK) &&
 184                  drop.one('.' + CSS.BLOCKADMINBLOCK).next('.' + CSS.BLOCK)) {
 185              drop.prepend(drag);
 186          }
 187  
 188          // Block is moved within the same region
 189          // stop here, no need to modify anything.
 190          if (this.dragsourceregion.contains(drop)) {
 191              return false;
 192          }
 193  
 194          // TODO: Hiding-displaying block region only works for base theme blocks
 195          // (region-pre, region-post) at the moment. It should be improved
 196          // to work with custom block regions as well.
 197  
 198          // TODO: Fix this for the case when user drag block towards empty section,
 199          // then the section appears, then user chnages his mind and moving back to
 200          // original section. The opposite section remains opened and empty.
 201  
 202          var documentbody = Y.one('body');
 203          // Moving block towards hidden region-content, display it
 204          var regionname = this.get_region_id(this.dragsourceregion);
 205          if (documentbody.hasClass('side-' + regionname + '-only')) {
 206              documentbody.removeClass('side-' + regionname + '-only');
 207          }
 208  
 209          // Moving from empty region-content towards the opposite one,
 210          // hide empty one (only for region-pre, region-post areas at the moment).
 211          regionname = this.get_region_id(drop.ancestor('div.' + CSS.BLOCKREGION));
 212          if (this.dragsourceregion.all('.' + CSS.BLOCK).size() === 0 &&
 213                  this.dragsourceregion.get('id').match(/(region-pre|region-post)/i)) {
 214              if (!documentbody.hasClass('side-' + regionname + '-only')) {
 215                  documentbody.addClass('side-' + regionname + '-only');
 216              }
 217          }
 218      },
 219  
 220      drag_end: function() {
 221          // clear variables
 222          this.skipnodetop = null;
 223          this.skipnodebottom = null;
 224          this.dragsourceregion = null;
 225          // Remove the blocks moving class once the drag-drop is over.
 226          Y.one('body').removeClass(CSS.BLOCKSMOVING);
 227      },
 228  
 229      drag_dropmiss: function(e) {
 230          // Missed the target, but we assume the user intended to drop it
 231          // on the last last ghost node location, e.drag and e.drop should be
 232          // prepared by global_drag_dropmiss parent so simulate drop_hit(e).
 233          this.drop_hit(e);
 234      },
 235  
 236      drop_hit: function(e) {
 237          var drag = e.drag;
 238          // Get a reference to our drag node
 239          var dragnode = drag.get('node');
 240          var dropnode = e.drop.get('node');
 241  
 242          // Amend existing skipnodes
 243          if (dragnode.previous() && dragnode.previous().hasClass(CSS.SKIPBLOCK)) {
 244              // the one that belongs to block below move below
 245              dragnode.insert(dragnode.previous(), 'after');
 246          }
 247          // Move original skipnodes
 248          if (this.skipnodetop) {
 249              dragnode.insert(this.skipnodetop, 'before');
 250          }
 251          if (this.skipnodebottom) {
 252              dragnode.insert(this.skipnodebottom, 'after');
 253          }
 254  
 255          // Add lightbox if it not there
 256          var lightbox = M.util.add_lightbox(Y, dragnode);
 257  
 258          // Prepare request parameters
 259          var params = {
 260              sesskey: M.cfg.sesskey,
 261              courseid: this.get('courseid'),
 262              pagelayout: this.get('pagelayout'),
 263              pagetype: this.get('pagetype'),
 264              subpage: this.get('subpage'),
 265              contextid: this.get('contextid'),
 266              action: 'move',
 267              bui_moveid: this.get_block_id(dragnode),
 268              bui_newregion: this.get_block_region(dropnode)
 269          };
 270  
 271          if (this.get('cmid')) {
 272              params.cmid = this.get('cmid');
 273          }
 274  
 275          if (dragnode.next('.' + this.samenodeclass) && !dragnode.next('.' + this.samenodeclass).hasClass(CSS.BLOCKADMINBLOCK)) {
 276              params.bui_beforeid = this.get_block_id(dragnode.next('.' + this.samenodeclass));
 277          }
 278  
 279          // Do AJAX request
 280          Y.io(M.cfg.wwwroot + AJAXURL, {
 281              method: 'POST',
 282              data: params,
 283              on: {
 284                  start: function() {
 285                      lightbox.show();
 286                  },
 287                  success: function(tid, response) {
 288                      window.setTimeout(function() {
 289                          lightbox.hide();
 290                      }, 250);
 291                      try {
 292                          var responsetext = Y.JSON.parse(response.responseText);
 293                          if (responsetext.error) {
 294                              new M.core.ajaxException(responsetext);
 295                          }
 296                      } catch (e) {
 297                          // Ignore.
 298                      }
 299                  },
 300                  failure: function(tid, response) {
 301                      this.ajax_failure(response);
 302                      lightbox.hide();
 303                  }
 304              },
 305              context: this
 306          });
 307      }
 308  }, {
 309      NAME: 'core-blocks-dragdrop',
 310      ATTRS: {
 311          courseid: {
 312              value: null
 313          },
 314          cmid: {
 315              value: null
 316          },
 317          contextid: {
 318              value: null
 319          },
 320          pagelayout: {
 321              value: null
 322          },
 323          pagetype: {
 324              value: null
 325          },
 326          subpage: {
 327              value: null
 328          },
 329          regions: {
 330              value: null
 331          }
 332      }
 333  });
 334  
 335  M.core = M.core || {};
 336  M.core.blockdraganddrop = M.core.blockdraganddrop || {};
 337  
 338  /**
 339   * True if the page is using the new blocks methods.
 340   * @private
 341   * @static
 342   * @property M.core.blockdraganddrop._isusingnewblocksmethod
 343   * @type Boolean
 344   * @default null
 345   */
 346  M.core.blockdraganddrop._isusingnewblocksmethod = null;
 347  
 348  /**
 349   * Returns true if the page is using the new blocks methods.
 350   * @static
 351   * @method M.core.blockdraganddrop.is_using_blocks_render_method
 352   * @return Boolean
 353   */
 354  M.core.blockdraganddrop.is_using_blocks_render_method = function() {
 355      if (this._isusingnewblocksmethod === null) {
 356          var goodregions = Y.all('.block-region[data-blockregion]').size();
 357          var allregions = Y.all('.block-region').size();
 358          this._isusingnewblocksmethod = (allregions === goodregions);
 359          if (goodregions > 0 && allregions > 0 && goodregions !== allregions) {
 360              Y.log('Both core_renderer::blocks and core_renderer::blocks_for_region have been used.', 'warn', 'moodle-core_blocks');
 361          }
 362      }
 363      return this._isusingnewblocksmethod;
 364  };
 365  
 366  /**
 367   * Initialises a drag and drop manager.
 368   * This should only ever be called once for a page.
 369   * @static
 370   * @method M.core.blockdraganddrop.init
 371   * @param {Object} params
 372   * @return Manager
 373   */
 374  M.core.blockdraganddrop.init = function(params) {
 375      if (this.is_using_blocks_render_method()) {
 376          Y.log('Block drag and drop initialised for the blocks method.', 'info', 'moodle-core_blocks');
 377          new MANAGER(params);
 378      } else {
 379          Y.log('Block drag and drop initialised with the legacy manager (blocks_for_region used).', 'info', 'moodle-core_blocks');
 380          new DRAGBLOCK(params);
 381      }
 382  };
 383  
 384  /*
 385   * Legacy code to keep things working.
 386   */
 387  M.core_blocks = M.core_blocks || {};
 388  M.core_blocks.init_dragdrop = function(params) {
 389      M.core.blockdraganddrop.init(params);
 390  };


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