javascript MDL-21329 Tidied up navigation and blocks JS documentation

This commit is contained in:
Sam Hemelryk 2010-01-15 03:34:20 +00:00
parent 8568b24ff4
commit b291933029
2 changed files with 152 additions and 61 deletions

View File

@ -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<branch.children.childNodes.length;i++) {
// Add each branch to the tree
this.add_branch(branch.children.childNodes[i], childrenul, depth+1);
}
}
@ -184,9 +201,16 @@ blocks.navigation.classes.tree.prototype.add_branch = function(branchxml, target
}
/**
* Toggle a branch as expanded or collapsed
* @param {Event} e
*/
blocks.navigation.classes.tree.prototype.toggleexpansion = function(e) {
e.target.ancestor('LI').toggleClass('collapsed');
// First check if they managed to click on the li iteslf, then find the closest
// LI ancestor and use that
if (e.target.get('nodeName').toUpperCase() == 'LI') {
e.target.toggleClass('collapsed');
} else if (e.target.ancestor('LI')) {
e.target.ancestor('LI').toggleClass('collapsed');
}
if (this.candock) {
blocks.dock.resize();
}
@ -194,10 +218,12 @@ blocks.navigation.classes.tree.prototype.toggleexpansion = function(e) {
/**
* This class represents a branch for a tree
* @class tree
* @class branch
* @constructor
* @param {blocks.navigation.classes.tree} tree
* @param {xmldoc|null} xml
*/
blocks.navigation.classes.branch = function(tree) {
blocks.navigation.classes.branch = function(tree, xml) {
this.tree = tree;
this.name = null;
this.title = null;
@ -212,11 +238,17 @@ blocks.navigation.classes.branch = function(tree) {
this.hidden = false;
this.haschildren = false;
this.children = false;
if (xml !== null) {
// Construct from the provided xml
this.construct_from_xml(xml);
}
}
/**
* Constructs a branch from XML
* @param {xmldoc} xml
*/
blocks.navigation.classes.branch.prototype.construct_from_xml = function(xml) {
// Get required attributes
this.title = xml.getAttribute('title');
this.classname = xml.getAttribute('class');
this.id = xml.getAttribute('id');
@ -226,14 +258,17 @@ blocks.navigation.classes.branch.prototype.construct_from_xml = function(xml) {
this.type = xml.getAttribute('type');
this.expandable = xml.getAttribute('expandable');
this.expansionceiling = xml.getAttribute('expansionceiling');
// Boolean attributes
this.hidden = (xml.getAttribute('hidden')=='true');
this.haschildren = (xml.getAttribute('haschildren')=='true');
if (this.id && this.id.match(/^expandable_branch_\d+$/)) {
// Assign a new unique id for this new expandable branch
blocks.navigation.expandablebranchcount++;
this.id = 'expandable_branch_'+blocks.navigation.expandablebranchcount;
}
// Retrieve any additional information
for (var i=0; i<xml.childNodes.length;i++) {
var node = xml.childNodes[i];
switch (node.nodeName.toLowerCase()) {
@ -247,6 +282,7 @@ blocks.navigation.classes.branch.prototype.construct_from_xml = function(xml) {
}
/**
* Injects a branch into the tree at the given location
* @param {element} element
*/
blocks.navigation.classes.branch.prototype.inject_into_dom = function(element) {

View File

@ -1436,6 +1436,7 @@ blocks.setup_generic_block = function(uid) {
}
/**
* The dock namespace: Contains all things dock related
* @namespace
*/
blocks.dock = {
@ -1443,7 +1444,11 @@ blocks.dock = {
exists:false, // True if the dock exists
items:[], // An array of dock items
node:null, // The YUI node for the dock itself
earlybinds:[],
earlybinds:[], // Events added before the dock was augmented to support events
/**
* Strings used by the dock/dockitems
* @namespace
*/
strings:{
addtodock : '[[addtodock]]',
undockitem : '[[undockitem]]',
@ -1460,18 +1465,30 @@ blocks.dock = {
buffer:10, // Buffer used when containing a panel
position:'left', // position of the dock
orientation:'vertical', // vertical || horizontal determines if we change the title
/**
* Display parameters for the dock
* @namespace
*/
display:{
spacebeforefirstitem: 10 // Space between the top of the dock and the first item
spacebeforefirstitem: 10 // Space between the top of the dock and the first item
},
/**
* CSS classes to use with the dock
* @namespace
*/
css: {
dock:'dock', // CSS Class applied to the dock box
dockspacer:'dockspacer', // CSS class applied to the dockspacer
dock:'dock', // CSS Class applied to the dock box
dockspacer:'dockspacer', // CSS class applied to the dockspacer
controls:'controls', // CSS class applied to the controls box
body:'has_dock', // CSS class added to the body when there is a dock
dockeditem:'dockeditem', // CSS class added to each item in the dock
dockedtitle:'dockedtitle', // CSS class added to the item's title in each dock
activeitem:'activeitem' // CSS class added to the active item
dockeditem:'dockeditem', // CSS class added to each item in the dock
dockedtitle:'dockedtitle', // CSS class added to the item's title in each dock
activeitem:'activeitem' // CSS class added to the active item
},
/**
* Configuration options for the panel that items are shown in
* @namespace
*/
panel: {
close:false, // Show a close button on the panel
draggable:false, // Make the panel draggable
@ -1496,12 +1513,14 @@ blocks.dock = {
// Give the dock item class the event properties/methods
Y.augment(blocks.dock.item, Y.EventTarget);
Y.augment(blocks.dock, Y.EventTarget, true);
// Re-apply early bindings properly now that we can
blocks.dock.apply_binds();
});
},
/**
* Adds a dock item into the dock
* @function
* @param {blocks.dock.item} item
*/
add:function(item) {
item.id = this.count;
@ -1514,13 +1533,14 @@ blocks.dock = {
/**
* Draws the dock
* @function
* @return bool
*/
draw:function() {
if (this.node !== null) {
return true;
}
this.fire('dock:drawstarted');
this.node = Y.Node.create('<div id="dock" class="'+blocks.dock.cfg.css.dock+'"></div>');
this.node = Y.Node.create('<div id="dock" class="'+blocks.dock.cfg.css.dock+' '+blocks.dock.cfg.css.dock+'_'+blocks.dock.cfg.position+'_'+blocks.dock.cfg.orientation+'"></div>');
this.node.appendChild(Y.Node.create('<div class="'+blocks.dock.cfg.css.dockspacer+'" style="height:'+blocks.dock.cfg.display.spacebeforefirstitem+'px"></div>'));
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;