[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/blocks/navigation/yui/build/moodle-block_navigation-navigation/ -> moodle-block_navigation-navigation-debug.js (source)

   1  YUI.add('moodle-block_navigation-navigation', function (Y, NAME) {
   2  
   3  /**
   4   * Navigation block JS.
   5   *
   6   * This file contains the Navigation block JS..
   7   *
   8   * @module moodle-block_navigation-navigation
   9   */
  10  
  11  /**
  12   * This namespace will contain all of the contents of the navigation blocks
  13   * global navigation and settings.
  14   * @class M.block_navigation
  15   * @static
  16   */
  17  M.block_navigation = M.block_navigation || {};
  18  /**
  19   * The number of expandable branches in existence.
  20   *
  21   * @property expandablebranchcount
  22   * @protected
  23   * @static
  24   * @type Number
  25   */
  26  M.block_navigation.expandablebranchcount = 1;
  27  /**
  28   * The maximum number of courses to show as part of a branch.
  29   *
  30   * @property courselimit
  31   * @protected
  32   * @static
  33   * @type Number
  34   */
  35  M.block_navigation.courselimit = 20;
  36  /**
  37   * Add new instance of navigation tree to tree collection
  38   *
  39   * @method init_add_tree
  40   * @static
  41   * @param {Object} properties
  42   */
  43  M.block_navigation.init_add_tree = function(properties) {
  44      if (properties.courselimit) {
  45          this.courselimit = properties.courselimit;
  46      }
  47      new TREE(properties);
  48  };
  49  
  50  /**
  51   * A 'actionkey' Event to help with Y.delegate().
  52   * The event consists of the left arrow, right arrow, enter and space keys.
  53   * More keys can be mapped to action meanings.
  54   * actions: collapse , expand, toggle, enter.
  55   *
  56   * This event is delegated to branches in the navigation tree.
  57   * The on() method to subscribe allows specifying the desired trigger actions as JSON.
  58   *
  59   * @namespace M.block_navigation
  60   * @class ActionKey
  61   */
  62  Y.Event.define("actionkey", {
  63      // Webkit and IE repeat keydown when you hold down arrow keys.
  64      // Opera links keypress to page scroll; others keydown.
  65      // Firefox prevents page scroll via preventDefault() on either
  66      // keydown or keypress.
  67      _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress',
  68  
  69      /**
  70       * The keys to trigger on.
  71       * @method _keys
  72       */
  73      _keys: {
  74          //arrows
  75          '37': 'collapse',
  76          '39': 'expand',
  77          '32': 'toggle',
  78          '13': 'enter'
  79      },
  80  
  81      /**
  82       * Handles key events
  83       * @method _keyHandler
  84       * @param {EventFacade} e
  85       * @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
  86       * @param {Object} args
  87       */
  88      _keyHandler: function (e, notifier, args) {
  89          var actObj;
  90          if (!args.actions) {
  91              actObj = {collapse:true, expand:true, toggle:true, enter:true};
  92          } else {
  93              actObj = args.actions;
  94          }
  95          if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) {
  96              e.action = this._keys[e.keyCode];
  97              notifier.fire(e);
  98          }
  99      },
 100  
 101      /**
 102       * Subscribes to events.
 103       * @method on
 104       * @param {Node} node The node this subscription was applied to.
 105       * @param {Subscription} sub The object tracking this subscription.
 106       * @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
 107       */
 108      on: function (node, sub, notifier) {
 109          // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
 110          if (sub.args === null) {
 111              //no actions given
 112              sub._detacher = node.on(this._event, this._keyHandler,this, notifier, {actions:false});
 113          } else {
 114              sub._detacher = node.on(this._event, this._keyHandler,this, notifier, sub.args[0]);
 115          }
 116      },
 117  
 118      /**
 119       * Detaches an event listener
 120       * @method detach
 121       */
 122      detach: function (node, sub) {
 123          //detach our _detacher handle of the subscription made in on()
 124          sub._detacher.detach();
 125      },
 126  
 127      /**
 128       * Creates a delegated event listener.
 129       * @method delegate
 130       * @param {Node} node The node this subscription was applied to.
 131       * @param {Subscription} sub The object tracking this subscription.
 132       * @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
 133       * @param {String|function} filter Selector string or function that accpets an event object and returns null.
 134       */
 135      delegate: function (node, sub, notifier, filter) {
 136          // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
 137          if (sub.args === null) {
 138              //no actions given
 139              sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, {actions:false});
 140          } else {
 141              sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, sub.args[0]);
 142          }
 143      },
 144  
 145      /**
 146       * Detaches a delegated event listener.
 147       * @method detachDelegate
 148       * @param {Node} node The node this subscription was applied to.
 149       * @param {Subscription} sub The object tracking this subscription.
 150       * @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
 151       * @param {String|function} filter Selector string or function that accpets an event object and returns null.
 152       */
 153      detachDelegate: function (node, sub) {
 154          sub._delegateDetacher.detach();
 155      }
 156  });
 157  
 158  var EXPANSIONLIMIT_EVERYTHING = 0,
 159      EXPANSIONLIMIT_COURSE     = 20,
 160      EXPANSIONLIMIT_SECTION    = 30,
 161      EXPANSIONLIMIT_ACTIVITY   = 40;
 162  
 163  // Mappings for the different types of nodes coming from the navigation.
 164  // Copied from lib/navigationlib.php navigation_node constants.
 165  var NODETYPE = {
 166      // @type int Root node = 0
 167      ROOTNODE : 0,
 168      // @type int System context = 1
 169      SYSTEM : 1,
 170      // @type int Course category = 10
 171      CATEGORY : 10,
 172      // @type int MYCATEGORY = 11
 173      MYCATEGORY : 11,
 174      // @type int Course = 20
 175      COURSE : 20,
 176      // @type int Course section = 30
 177      SECTION : 30,
 178      // @type int Activity (course module) = 40
 179      ACTIVITY : 40,
 180      // @type int Resource (course module = 50
 181      RESOURCE : 50,
 182      // @type int Custom node (could be anything) = 60
 183      CUSTOM : 60,
 184      // @type int Setting = 70
 185      SETTING : 70,
 186      // @type int site administration = 71
 187      SITEADMIN : 71,
 188      // @type int User context = 80
 189      USER : 80,
 190      // @type int Container = 90
 191      CONTAINER : 90
 192  };
 193  
 194  /**
 195   * Navigation tree class.
 196   *
 197   * This class establishes the tree initially, creating expandable branches as
 198   * required, and delegating the expand/collapse event.
 199   *
 200   * @namespace M.block_navigation
 201   * @class Tree
 202   * @constructor
 203   * @extends Base
 204   */
 205  var TREE = function() {
 206      TREE.superclass.constructor.apply(this, arguments);
 207  };
 208  TREE.prototype = {
 209      /**
 210       * The tree's ID, normally its block instance id.
 211       * @property id
 212       * @type Number
 213       * @protected
 214       */
 215      id : null,
 216      /**
 217       * An array of initialised branches.
 218       * @property branches
 219       * @type Array
 220       * @protected
 221       */
 222      branches : [],
 223      /**
 224       * Initialise the tree object when its first created.
 225       * @method initializer
 226       * @param {Object} config
 227       */
 228      initializer : function(config) {
 229          Y.log('Initialising navigation block tree', 'note', 'moodle-block_navigation');
 230  
 231          this.id = parseInt(config.id, 10);
 232  
 233          var node = Y.one('#inst'+config.id);
 234  
 235          // Can't find the block instance within the page
 236          if (node === null) {
 237              return;
 238          }
 239  
 240          // Delegate event to toggle expansion
 241          Y.delegate('click', this.toggleExpansion, node.one('.block_tree'), '.tree_item.branch', this);
 242          Y.delegate('actionkey', this.toggleExpansion, node.one('.block_tree'), '.tree_item.branch', this);
 243  
 244          // Gather the expandable branches ready for initialisation.
 245          var expansions = [];
 246          if (config.expansions) {
 247              expansions = config.expansions;
 248          } else if (window['navtreeexpansions'+config.id]) {
 249              expansions = window['navtreeexpansions'+config.id];
 250          }
 251          // Establish each expandable branch as a tree branch.
 252          for (var i in expansions) {
 253              var branch = new BRANCH({
 254                  tree:this,
 255                  branchobj:expansions[i],
 256                  overrides : {
 257                      expandable : true,
 258                      children : [],
 259                      haschildren : true
 260                  }
 261              }).wire();
 262              M.block_navigation.expandablebranchcount++;
 263              this.branches[branch.get('id')] = branch;
 264          }
 265          // Create siteadmin branch.
 266          if (window.siteadminexpansion) {
 267              var siteadminbranch = new BRANCH({
 268                  tree: this,
 269                  branchobj: window.siteadminexpansion,
 270                  overrides : {
 271                      expandable : true,
 272                      children : [],
 273                      haschildren : true
 274                  }
 275              }).wire();
 276              M.block_navigation.expandablebranchcount++;
 277              this.branches[siteadminbranch.get('id')] = siteadminbranch;
 278              // Remove link on site admin with JS to keep old UI.
 279              if (siteadminbranch.node) {
 280                  var siteadminlinknode = siteadminbranch.node.get('childNodes').item(0);
 281                  if (siteadminlinknode) {
 282                      var siteadminnode = Y.Node.create('<span tabindex="0">'+siteadminlinknode.get('innerHTML')+'</span>');
 283                      siteadminbranch.node.replaceChild(siteadminnode, siteadminlinknode);
 284                  }
 285              }
 286          }
 287          if (M.block_navigation.expandablebranchcount > 0) {
 288              // Delegate some events to handle AJAX loading.
 289              Y.delegate('click', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this);
 290              Y.delegate('actionkey', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this);
 291          }
 292      },
 293      /**
 294       * Fire actions for a branch when an event occurs.
 295       * @method fire_branch_action
 296       * @param {EventFacade} event
 297       */
 298      fire_branch_action : function(event) {
 299          var id = event.currentTarget.getAttribute('id');
 300          var branch = this.branches[id];
 301          branch.ajaxLoad(event);
 302      },
 303      /**
 304       * This is a callback function responsible for expanding and collapsing the
 305       * branches of the tree. It is delegated to rather than multiple event handles.
 306       * @method toggleExpansion
 307       * @param {EventFacade} e
 308       * @return Boolean
 309       */
 310      toggleExpansion : function(e) {
 311          // First check if they managed to click on the li iteslf, then find the closest
 312          // LI ancestor and use that
 313  
 314          if (e.target.test('a') && (e.keyCode === 0 || e.keyCode === 13)) {
 315              // A link has been clicked (or keypress is 'enter') don't fire any more events just do the default.
 316              e.stopPropagation();
 317              return;
 318          }
 319  
 320          // Makes sure we can get to the LI containing the branch.
 321          var target = e.target;
 322          if (!target.test('li')) {
 323              target = target.ancestor('li');
 324          }
 325          if (!target) {
 326              return;
 327          }
 328  
 329          // Toggle expand/collapse providing its not a root level branch.
 330          if (!target.hasClass('depth_1')) {
 331              if (e.type === 'actionkey') {
 332                  switch (e.action) {
 333                      case 'expand' :
 334                          target.removeClass('collapsed');
 335                          target.set('aria-expanded', true);
 336                          break;
 337                      case 'collapse' :
 338                          target.addClass('collapsed');
 339                          target.set('aria-expanded', false);
 340                          break;
 341                      default :
 342                          target.toggleClass('collapsed');
 343                          target.set('aria-expanded', !target.hasClass('collapsed'));
 344                  }
 345                  e.halt();
 346              } else {
 347                  target.toggleClass('collapsed');
 348                  target.set('aria-expanded', !target.hasClass('collapsed'));
 349              }
 350          }
 351  
 352          // If the accordian feature has been enabled collapse all siblings.
 353          if (this.get('accordian')) {
 354              target.siblings('li').each(function(){
 355                  if (this.get('id') !== target.get('id') && !this.hasClass('collapsed')) {
 356                      this.addClass('collapsed');
 357                      this.set('aria-expanded', false);
 358                  }
 359              });
 360          }
 361  
 362          // If this block can dock tell the dock to resize if required and check
 363          // the width on the dock panel in case it is presently in use.
 364          if (this.get('candock') && M.core.dock.notifyBlockChange) {
 365              M.core.dock.notifyBlockChange(this.id);
 366          }
 367          return true;
 368  
 369      }
 370  };
 371  // The tree extends the YUI base foundation.
 372  Y.extend(TREE, Y.Base, TREE.prototype, {
 373      NAME : 'navigation-tree',
 374      ATTRS : {
 375          /**
 376           * True if the block can dock.
 377           * @attribute candock
 378           * @type Boolean
 379           */
 380          candock : {
 381              validator : Y.Lang.isBool,
 382              value : false
 383          },
 384          /**
 385           * If set to true nodes will be opened/closed in an accordian fashion.
 386           * @attribute accordian
 387           * @type Boolean
 388           */
 389          accordian : {
 390              validator : Y.Lang.isBool,
 391              value : false
 392          },
 393          /**
 394           * The nodes that get shown.
 395           * @attribute expansionlimit
 396           * @type Number
 397           */
 398          expansionlimit : {
 399              value : 0,
 400              setter : function(val) {
 401                  val = parseInt(val, 10);
 402                  if (val !== EXPANSIONLIMIT_EVERYTHING &&
 403                      val !== EXPANSIONLIMIT_COURSE &&
 404                      val !== EXPANSIONLIMIT_SECTION &&
 405                      val !== EXPANSIONLIMIT_ACTIVITY) {
 406                      val = EXPANSIONLIMIT_EVERYTHING;
 407                  }
 408                  return val;
 409              }
 410          },
 411          /**
 412           * The navigation tree block instance.
 413           *
 414           * @attribute instance
 415           * @default false
 416           * @type Number
 417           */
 418          instance : {
 419              value : false,
 420              setter : function(val) {
 421                  return parseInt(val, 10);
 422              }
 423          }
 424      }
 425  });
 426  
 427  /**
 428   * The Branch class.
 429   *
 430   * This class is used to manage a tree branch, in particular its ability to load
 431   * its contents by AJAX.
 432   *
 433   * @namespace M.block_navigation
 434   * @class Branch
 435   * @constructor
 436   * @extends Base
 437   */
 438  BRANCH = function() {
 439      BRANCH.superclass.constructor.apply(this, arguments);
 440  };
 441  BRANCH.prototype = {
 442      /**
 443       * The node for this branch (p)
 444       * @property node
 445       * @type Node
 446       * @protected
 447       */
 448      node : null,
 449      /**
 450       * Initialises the branch when it is first created.
 451       * @method initializer
 452       * @param {Object} config
 453       */
 454      initializer : function(config) {
 455          var i,
 456              children;
 457          if (config.branchobj !== null) {
 458              // Construct from the provided xml
 459              for (i in config.branchobj) {
 460                  this.set(i, config.branchobj[i]);
 461              }
 462              children = this.get('children');
 463              this.set('haschildren', (children.length > 0));
 464          }
 465          if (config.overrides !== null) {
 466              // Construct from the provided xml
 467              for (i in config.overrides) {
 468                  this.set(i, config.overrides[i]);
 469              }
 470          }
 471          // Get the node for this branch
 472          this.node = Y.one('#'+this.get('id'));
 473          var expansionlimit = this.get('tree').get('expansionlimit');
 474          var type = this.get('type');
 475          if (expansionlimit !== EXPANSIONLIMIT_EVERYTHING &&  type >= expansionlimit && type <= EXPANSIONLIMIT_ACTIVITY) {
 476              this.set('expandable', false);
 477              this.set('haschildren', false);
 478          }
 479      },
 480      /**
 481       * Draws the branch within the tree.
 482       *
 483       * This function creates a DOM structure for the branch and then injects
 484       * it into the navigation tree at the correct point.
 485       *
 486       * @method draw
 487       * @chainable
 488       * @param {Node} element
 489       * @return Branch
 490       */
 491      draw : function(element) {
 492  
 493          var isbranch = (this.get('expandable') || this.get('haschildren'));
 494          var branchli = Y.Node.create('<li></li>');
 495          var link = this.get('link');
 496          var branchp = Y.Node.create('<p class="tree_item"></p>').setAttribute('id', this.get('id'));
 497          if (!link) {
 498              //add tab focus if not link (so still one focus per menu node).
 499              // it was suggested to have 2 foci. one for the node and one for the link in MDL-27428.
 500              branchp.setAttribute('tabindex', '0');
 501          }
 502          if (isbranch) {
 503              branchli.addClass('collapsed').addClass('contains_branch');
 504              branchli.set('aria-expanded', false);
 505              branchp.addClass('branch');
 506          }
 507  
 508          // Prepare the icon, should be an object representing a pix_icon
 509          var branchicon = false;
 510          var icon = this.get('icon');
 511          if (icon && (!isbranch || this.get('type') === NODETYPE.ACTIVITY)) {
 512              branchicon = Y.Node.create('<img alt="" />');
 513              branchicon.setAttribute('src', M.util.image_url(icon.pix, icon.component));
 514              branchli.addClass('item_with_icon');
 515              if (icon.alt) {
 516                  branchicon.setAttribute('alt', icon.alt);
 517              }
 518              if (icon.title) {
 519                  branchicon.setAttribute('title', icon.title);
 520              }
 521              if (icon.classes) {
 522                  for (var i in icon.classes) {
 523                      branchicon.addClass(icon.classes[i]);
 524                  }
 525              }
 526          }
 527  
 528          if (!link) {
 529              var branchspan = Y.Node.create('<span></span>');
 530              if (branchicon) {
 531                  branchspan.appendChild(branchicon);
 532              }
 533              branchspan.append(this.get('name'));
 534              if (this.get('hidden')) {
 535                  branchspan.addClass('dimmed_text');
 536              }
 537              branchp.appendChild(branchspan);
 538          } else {
 539              var branchlink = Y.Node.create('<a title="'+this.get('title')+'" href="'+link+'"></a>');
 540              if (branchicon) {
 541                  branchlink.appendChild(branchicon);
 542              }
 543              branchlink.append(this.get('name'));
 544              if (this.get('hidden')) {
 545                  branchlink.addClass('dimmed');
 546              }
 547              branchp.appendChild(branchlink);
 548          }
 549  
 550          branchli.appendChild(branchp);
 551          element.appendChild(branchli);
 552          this.node = branchp;
 553          return this;
 554      },
 555      /**
 556       * Attaches required events to the branch structure.
 557       *
 558       * @chainable
 559       * @method wire
 560       * @return {BRANCH} This function is chainable, it always returns itself.
 561       */
 562      wire : function() {
 563          this.node = this.node || Y.one('#'+this.get('id'));
 564          if (!this.node) {
 565              return this;
 566          }
 567          if (this.get('expandable')) {
 568              this.node.setAttribute('data-expandable', '1');
 569              this.node.setAttribute('data-loaded', '0');
 570          }
 571          return this;
 572      },
 573      /**
 574       * Gets the UL element that children for this branch should be inserted into.
 575       * @method getChildrenUL
 576       * @return Node
 577       */
 578      getChildrenUL : function() {
 579          var ul = this.node.next('ul');
 580          if (!ul) {
 581              ul = Y.Node.create('<ul></ul>');
 582              this.node.ancestor().append(ul);
 583          }
 584          return ul;
 585      },
 586      /**
 587       * Load the content of the branch via AJAX.
 588       *
 589       * This function calls ajaxProcessResponse with the result of the AJAX
 590       * request made here.
 591       *
 592       * @method ajaxLoad
 593       * @param {EventFacade} e
 594       * @return Bool
 595       */
 596      ajaxLoad : function(e) {
 597          if (e.type === 'actionkey' && e.action !== 'enter') {
 598              e.halt();
 599          } else {
 600              e.stopPropagation();
 601          }
 602          if ((e.type === 'actionkey' && e.action === 'enter') || e.target.test('a')) {
 603              // No ajaxLoad for enter.
 604              this.node.setAttribute('data-expandable', '0');
 605              this.node.setAttribute('data-loaded', '1');
 606              return true;
 607          }
 608  
 609          if (this.node.hasClass('loadingbranch')) {
 610              // Already loading. Just skip.
 611              return true;
 612          }
 613  
 614          if (this.node.getAttribute('data-loaded') === '1') {
 615              // We've already loaded this stuff.
 616              return true;
 617          }
 618          Y.log('Loading navigation branch via AJAX: '+this.get('key'), 'note', 'moodle-block_navigation');
 619          this.node.addClass('loadingbranch');
 620  
 621          var params = {
 622              elementid : this.get('id'),
 623              id : this.get('key'),
 624              type : this.get('type'),
 625              sesskey : M.cfg.sesskey,
 626              instance : this.get('tree').get('instance')
 627          };
 628  
 629          var ajaxfile = '/lib/ajax/getnavbranch.php';
 630          // For siteadmin navigation get tree from getsiteadminbranch.php.
 631          if (this.get('type') === NODETYPE.SITEADMIN) {
 632              ajaxfile = '/lib/ajax/getsiteadminbranch.php';
 633          }
 634  
 635          Y.io(M.cfg.wwwroot + ajaxfile, {
 636              method:'POST',
 637              data:  build_querystring(params),
 638              on: {
 639                  complete: this.ajaxProcessResponse
 640              },
 641              context:this
 642          });
 643          return true;
 644      },
 645      /**
 646       * Processes an AJAX request to load the content of this branch through
 647       * AJAX.
 648       *
 649       * @method ajaxProcessResponse
 650       * @param {Int} tid The transaction id.
 651       * @param {Object} outcome
 652       * @return Boolean
 653       */
 654      ajaxProcessResponse : function(tid, outcome) {
 655          this.node.removeClass('loadingbranch');
 656          this.node.setAttribute('data-loaded', '1');
 657          try {
 658              var object = Y.JSON.parse(outcome.responseText);
 659              if (object.error) {
 660                  Y.use('moodle-core-notification-ajaxexception', function () {
 661                      return new M.core.ajaxException(object).show();
 662                  });
 663                  return false;
 664              }
 665              if (object.children && object.children.length > 0) {
 666                  var coursecount = 0;
 667                  for (var i in object.children) {
 668                      if (typeof(object.children[i])==='object') {
 669                          if (object.children[i].type === NODETYPE.COURSE) {
 670                              coursecount++;
 671                          }
 672                          this.addChild(object.children[i]);
 673                      }
 674                  }
 675                  if ((this.get('type') === NODETYPE.CATEGORY || this.get('type') === NODETYPE.ROOTNODE || this.get('type') === NODETYPE.MYCATEGORY)
 676                      && coursecount >= M.block_navigation.courselimit) {
 677                      this.addViewAllCoursesChild(this);
 678                  }
 679                  Y.log('AJAX loading complete.', 'note', 'moodle-block_navigation');
 680                  // If this block can dock tell the dock to resize if required and check
 681                  // the width on the dock panel in case it is presently in use.
 682                  if (this.get('tree').get('candock') && M.core.dock.notifyBlockChange) {
 683                      M.core.dock.notifyBlockChange(this.get('tree').id);
 684                  }
 685                  return true;
 686              }
 687              Y.log('AJAX loading complete but there were no children.', 'note', 'moodle-block_navigation');
 688          } catch (error) {
 689              if (outcome && outcome.status && outcome.status > 0) {
 690                  // If we got here then there was an error parsing the result.
 691                  Y.log('Error parsing AJAX response or adding branches to the navigation tree', 'error', 'moodle-block_navigation');
 692                  Y.use('moodle-core-notification-exception', function () {
 693                      return new M.core.exception(error).show();
 694                  });
 695              }
 696  
 697              return false;
 698          }
 699          // The branch is empty so class it accordingly
 700          this.node.replaceClass('branch', 'emptybranch');
 701          return true;
 702      },
 703      /**
 704       * Turns the branch object passed to the method into a proper branch object
 705       * and then adds it as a child of this branch.
 706       *
 707       * @method addChild
 708       * @param {Object} branchobj
 709       * @return Boolean
 710       */
 711      addChild : function(branchobj) {
 712          // Make the new branch into an object
 713          var branch = new BRANCH({tree:this.get('tree'), branchobj:branchobj});
 714          if (branch.draw(this.getChildrenUL())) {
 715              this.get('tree').branches[branch.get('id')] = branch;
 716              branch.wire();
 717              var count = 0, i, children = branch.get('children');
 718              for (i in children) {
 719                  // Add each branch to the tree
 720                  if (children[i].type === NODETYPE.COURSE) {
 721                      count++;
 722                  }
 723                  if (typeof(children[i]) === 'object') {
 724                      branch.addChild(children[i]);
 725                  }
 726              }
 727              if ((branch.get('type') === NODETYPE.CATEGORY || branch.get('type') === NODETYPE.MYCATEGORY)
 728                  && count >= M.block_navigation.courselimit) {
 729                  this.addViewAllCoursesChild(branch);
 730              }
 731          }
 732          return true;
 733      },
 734  
 735      /**
 736       * Add a link to view all courses in a category
 737       *
 738       * @method addViewAllCoursesChild
 739       * @param {BRANCH} branch
 740       */
 741      addViewAllCoursesChild: function(branch) {
 742          var url = null;
 743          if (branch.get('type') === NODETYPE.ROOTNODE) {
 744              if (branch.get('key') === 'mycourses') {
 745                  url = M.cfg.wwwroot + '/my';
 746              } else {
 747                  url = M.cfg.wwwroot + '/course/index.php';
 748              }
 749          } else {
 750              url = M.cfg.wwwroot+'/course/index.php?categoryid=' + branch.get('key');
 751          }
 752          branch.addChild({
 753              name : M.str.moodle.viewallcourses,
 754              title : M.str.moodle.viewallcourses,
 755              link : url,
 756              haschildren : false,
 757              icon : {'pix':"i/navigationitem",'component':'moodle'}
 758          });
 759      }
 760  };
 761  Y.extend(BRANCH, Y.Base, BRANCH.prototype, {
 762      NAME : 'navigation-branch',
 763      ATTRS : {
 764          /**
 765           * The Tree this branch belongs to.
 766           * @attribute tree
 767           * @type TREE
 768           * @required
 769           * @writeOnce
 770           */
 771          tree : {
 772              writeOnce : 'initOnly',
 773              validator : Y.Lang.isObject
 774          },
 775          /**
 776           * The name of this branch.
 777           * @attribute name
 778           * @type String
 779           */
 780          name : {
 781              value : '',
 782              validator : Y.Lang.isString,
 783              setter : function(val) {
 784                  return val.replace(/\n/g, '<br />');
 785              }
 786          },
 787          /**
 788           * The title to use for this branch.
 789           * @attribute title
 790           * @type String
 791           */
 792          title : {
 793              value : '',
 794              validator : Y.Lang.isString
 795          },
 796          /**
 797           * The ID of this branch.
 798           * The ID and Type should always form a unique pair.
 799           * @attribute id
 800           * @type String
 801           */
 802          id : {
 803              value : '',
 804              validator : Y.Lang.isString,
 805              getter : function(val) {
 806                  if (val === '') {
 807                      val = 'expandable_branch_'+M.block_navigation.expandablebranchcount;
 808                      M.block_navigation.expandablebranchcount++;
 809                  }
 810                  return val;
 811              }
 812          },
 813          /**
 814           * The key used to identify this branch easily if there is one.
 815           * @attribute key
 816           * @type String
 817           */
 818          key : {
 819              value : null
 820          },
 821          /**
 822           * The type of this branch.
 823           * @attribute type
 824           * @type Number
 825           */
 826          type : {
 827              value : null,
 828              setter : function(value) {
 829                  return parseInt(value, 10);
 830              }
 831          },
 832          /**
 833           * The link to use for this branch.
 834           * @attribute link
 835           * @type String
 836           */
 837          link : {
 838              value : false
 839          },
 840          /**
 841           * The Icon to add when displaying this branch.
 842           * @attribute icon
 843           * @type Object
 844           */
 845          icon : {
 846              value : false,
 847              validator : Y.Lang.isObject
 848          },
 849          /**
 850           * True if this branch is expandable.
 851           * @attribute expandable
 852           * @type Boolean
 853           */
 854          expandable : {
 855              value : false,
 856              validator : Y.Lang.isBool
 857          },
 858          /**
 859           * True if this branch is hidden and should be displayed greyed out.
 860           * @attribute hidden
 861           * @type Boolean
 862           */
 863          hidden : {
 864              value : false,
 865              validator : Y.Lang.isBool
 866          },
 867          /**
 868           * True if this branch has any children.
 869           * @attribute haschildren
 870           * @type Boolean
 871           */
 872          haschildren : {
 873              value : false,
 874              validator : Y.Lang.isBool
 875          },
 876          /**
 877           * An array of other branches that appear as children of this branch.
 878           * @attribute children
 879           * @type Array
 880           */
 881          children : {
 882              value : [],
 883              validator : Y.Lang.isArray
 884          }
 885      }
 886  });
 887  
 888  
 889  }, '@VERSION@', {"requires": ["base", "io-base", "node", "event-synthetic", "event-delegate", "json-parse"]});


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