diff --git a/blocks/global_navigation_tree/navigation.js b/blocks/global_navigation_tree/navigation.js index 18cd6e633e0..edd2f08932d 100644 --- a/blocks/global_navigation_tree/navigation.js +++ b/blocks/global_navigation_tree/navigation.js @@ -24,6 +24,7 @@ */ /** + * This namespace will contain all of the information fo the blocks * @namespace */ var blocks = blocks || {}; @@ -39,6 +40,7 @@ blocks.navigation = { /** An array of initialised trees */ treecollection:[], /** + * Will contain all of the classes for the navigation blocks * @namespace */ classes:{}, @@ -77,51 +79,57 @@ blocks.navigation.classes.tree = function(id, key, properties) { this.position = 'block'; this.skipsetposition = false; this.candock = false; - if (properties) { - if (properties.expansions) { - this.expansions = properties.expansions; - } - if (properties.instance) { - this.instance = properties.instance; - } - if (properties.candock) { - this.candock = true; - } + + if (properties.expansions) { + this.expansions = properties.expansions; } - - if (Y.one('#inst'+this.id) === null) { - return; + if (properties.instance) { + this.instance = properties.instance; } - - for (var i in this.expansions) { - Y.one('#'+this.expansions[i].id).on('ajaxload|click', this.init_load_ajax, this, this.expansions[i]); - blocks.navigation.expandablebranchcount++; + if (properties.candock) { + this.candock = true; } var node = Y.one('#inst'+this.id); + + // Can't find the block instance within the page + if (node === null) { + return; + } + // Attach event to toggle expansion node.all('.tree_item.branch').on('click', this.toggleexpansion , this); - if (this.candock) { - this.init(node); + // Attache events to expand by AJAX + for (var i in this.expansions) { + Y.one('#'+this.expansions[i].id).on('ajaxload|click', this.init_load_ajax, this, this.expansions[i]); + blocks.navigation.expandablebranchcount++; } if (node.hasClass('block_js_expansion')) { node.on('mouseover', function(e){this.toggleClass('mouseover');}, node); node.on('mouseout', function(e){this.toggleClass('mouseover');}, node); } + + // Call the generic blocks init method to add all the generic stuff + if (this.candock) { + this.init(node); + } } /** * Loads a branch via AJAX - * @param {event} The event object - * @param {object} A branch to load via ajax + * @param {event} e The event object + * @param {object} branch A branch to load via ajax */ blocks.navigation.classes.tree.prototype.init_load_ajax = function(e, branch) { e.stopPropagation(); if (e.target.get('nodeName').toUpperCase() != 'P') { return true; } - var cfginstance = (this.instance != null)?'&instance='+this.instance:''; + var cfginstance = ''; + if (this.instance != null) { + cfginstance = '&instance='+this.instance + } Y.io(moodle_cfg.wwwroot+'/lib/ajax/getnavbranch.php', { method:'POST', data:'elementid='+branch.id+'&id='+branch.branchid+'&type='+branch.type+'&sesskey='+moodle_cfg.sesskey+cfginstance, @@ -139,6 +147,10 @@ blocks.navigation.classes.tree.prototype.init_load_ajax = function(e, branch) { /** * Takes an branch provided through ajax and loads it into the tree + * @param {int} tid The transaction id + * @param {object} outcome + * @param {mixed} args + * @return bool */ blocks.navigation.classes.tree.prototype.load_ajax = function(tid, outcome, args) { // Check the status @@ -152,17 +164,22 @@ blocks.navigation.classes.tree.prototype.load_ajax = function(tid, outcome, args return true; } } + // The branch is empty so class it accordingly args.target.replaceClass('branch', 'emptybranch'); return true; } /** * Adds a branch into the tree provided with some XML + * @param {xmldoc} branchxml + * @param {Y.Node} target + * @param {int} depth + * @return bool */ blocks.navigation.classes.tree.prototype.add_branch = function(branchxml, target, depth) { - var branch = new blocks.navigation.classes.branch(this); - branch.construct_from_xml(branchxml); + // Make the new branch into an object + var branch = new blocks.navigation.classes.branch(this, branchxml); var childrenul = false; if (depth === 1) { @@ -174,9 +191,9 @@ blocks.navigation.classes.tree.prototype.add_branch = function(branchxml, target } else { childrenul = branch.inject_into_dom(target); } - if (childrenul) { for (var i=0;i'); + this.node = Y.Node.create('
'); this.node.appendChild(Y.Node.create('
')); if (Y.UA.ie > 0 && Y.UA.ie < 7) { this.node.setStyle('height', this.node.get('winHeight')+'px'); @@ -1540,8 +1560,13 @@ blocks.dock = { /** * Removes the node at the given index and puts it back into conventional page sturcture * @function + * @param {int} uid Unique identifier for the block + * @return {boolean} */ remove:function(uid) { + if (!this.items[uid]) { + return false; + } this.items[uid].remove(); this.fire('dock:itemremoved', uid); this.count--; @@ -1552,10 +1577,12 @@ blocks.dock = { this.node = null; this.fire('dock:removed'); } + return true; }, /** * Removes all nodes and puts them back into conventional page sturcture * @function + * @return {boolean} */ remove_all:function() { for (var i in this.items) { @@ -1567,10 +1594,12 @@ blocks.dock = { this.node.remove(); this.node = null; Y.fire('dock:removed'); + return true; }, /** * Resizes the active item * @function + * @param {Event} e */ resize:function(e){ for (var i in this.items) { @@ -1580,7 +1609,7 @@ blocks.dock = { } }, /** - * Hides all (the active) item + * Hides all [the active] items * @function */ hide_all:function() { @@ -1618,17 +1647,17 @@ blocks.dock = { */ abstract_block_class : { - id : null, - cachedcontentnode : null, - blockspacewidth : null, - skipsetposition : false, + id : null, // The block instance id + cachedcontentnode : null, // The cached content node for the actual block + blockspacewidth : null, // The width of the block's original container + skipsetposition : false, // If true the user preference isn't updated /** * This function should be called within the block's constructor and is used to * set up the initial controls for swtiching block position as well as an initial * moves that may be required. * - * @param {YUI.Node} The node that contains all of the block's content + * @param {YUI.Node} node The node that contains all of the block's content */ init : function(node) { if (!node) { @@ -1656,14 +1685,12 @@ blocks.dock = { commands.append(moveto); commands.all('a.moveto').on('movetodock|click', this.move_to_dock, this); - var customcommands = node.all('.customcommand'); - if (customcommands.size() > 0) { - customcommands.each(function(){ - this.remove(); - commands.appendChild(this); - }); - } + node.all('.customcommand').each(function(){ + this.remove(); + commands.appendChild(this); + }); + // Move the block straight to the dock if required if (node.hasClass('dock_on_load')) { node.removeClass('dock_on_load') this.skipsetposition = true; @@ -1683,6 +1710,9 @@ blocks.dock = { var node = Y.one('#inst'+this.id); var blockcontent = node.one('.content'); + if (!blockcontent) { + return; + } this.cachedcontentnode = node; @@ -1712,7 +1742,9 @@ blocks.dock = { blockcommands = commands.item(0); } + // Create a new dock item for the block var dockitem = new blocks.dock.item(this.id, blocktitle, blockcontent, blockcommands); + // Wire the draw events to register remove events dockitem.on('dockeditem:drawcomplete', function(e){ // check the contents block [editing=off] this.contents.all('a.moveto').on('returntoblock|click', function(e){ @@ -1725,10 +1757,13 @@ blocks.dock = { blocks.dock.remove(this.id) }, this); }, dockitem); + + // Register an event so that when it is removed we can put it back as a block dockitem.on('dock:itemremoved', this.return_to_block, this, dockitem); blocks.dock.add(dockitem); if (!this.skipsetposition) { + // save the users preference set_user_preference('docked_block_instance_'+this.id, 1); } else { this.skipsetposition = false; @@ -1738,14 +1773,18 @@ blocks.dock = { /** * Resizes the space that contained blocks if there were no blocks left in * it. e.g. if all blocks have been moved to the dock + * @param {Y.Node} node */ resize_block_space : function(node) { node = node.ancestor('.block-region'); if (node) { if (node.all('.sideblock').size() === 0 && this.blockspacewidth === null) { + // If the node has no children then we can shrink it this.blockspacewidth = node.getStyle('width'); node.setStyle('width', '0px'); } else if (this.blockspacewidth !== null) { + // Otherwise if it contains children and we have saved a width + // we can reapply the width node.setStyle('width', this.blockspacewidth); this.blockspacewidth = null; } @@ -1790,19 +1829,28 @@ blocks.dock = { return true; } }, - + /** + * This namespace contains the generic properties, methods and events + * that will be bound to the blocks.dock.item class. + * These can then be overriden to customise the way dock items work/display + * @namespace + */ abstract_item_class : { - id : null, - name : null, - title : null, - contents : null, - commands : null, - events : null, - active : false, - panel : null, - preventhide : false, - cfg : null, + + id : null, // The unique id for the item + name : null, // The name of the item + title : null, // The title of the item + contents : null, // The content of the item + commands : null, // The commands for the item + active : false, // True if the item is being shown + panel : null, // The YUI2 panel the item will be shown in + preventhide : false, // If true the next call to hide will be ignored + cfg : null, // The config options for this item by default blocks.cfg + /** + * Initialises all of the items events + * @function + */ init_events : function() { this.publish('dockeditem:drawstart', {prefix:'dockeditem'}); this.publish('dockeditem:drawcomplete', {prefix:'dockeditem'}); @@ -1860,6 +1908,7 @@ blocks.dock = { }, /** * This function removes the node and destroys it's bits + * @param {Event} e */ remove : function (e) { this.hide(e); @@ -1890,6 +1939,7 @@ blocks.dock = { * @param {event} */ hide : function(e) { + // Ignore this call is preventhide is true if (this.preventhide===true) { this.preventhide = false; } else if (this.active) { @@ -1948,8 +1998,10 @@ blocks.dock = { * This class represents a generic block * @class genericblock * @constructor + * @param {int} uid */ blocks.genericblock = function(uid){ + // Save the unique id as the blocks id if (uid && this.id==null) { this.id = uid; } @@ -1969,6 +2021,10 @@ blocks.genericblock.prototype.return_to_block = blocks.dock.abstract_blo * This class represents an item in the dock * @class item * @constructor + * @param {int} uid The unique ID for the item + * @param {Y.Node} title + * @param {Y.Node} contents + * @param {Y.Node} commands */ blocks.dock.item = function(uid, title, contents, commands){ if (uid && this.id==null) this.id = uid; @@ -1983,7 +2039,6 @@ blocks.dock.item.prototype.name = blocks.dock.abstract_item_class. blocks.dock.item.prototype.title = blocks.dock.abstract_item_class.title; blocks.dock.item.prototype.contents = blocks.dock.abstract_item_class.contents; blocks.dock.item.prototype.commands = blocks.dock.abstract_item_class.commands; -blocks.dock.item.prototype.events = blocks.dock.abstract_item_class.events; blocks.dock.item.prototype.active = blocks.dock.abstract_item_class.active; blocks.dock.item.prototype.panel = blocks.dock.abstract_item_class.panel; blocks.dock.item.prototype.preventhide = blocks.dock.abstract_item_class.preventhide;