diff --git a/blocks/blocks.js b/blocks/blocks.js
new file mode 100644
index 00000000000..22e2753f70b
--- /dev/null
+++ b/blocks/blocks.js
@@ -0,0 +1,591 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see .
+
+/**
+ * This file contains classes used to manage the navigation structures in Moodle
+ * and was introduced as part of the changes occuring in Moodle 2.0
+ *
+ * @since 2.0
+ * @package javascript
+ * @copyright 2010 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * This namespace will contain all of content (functions, classes, properties)
+ * for the block system
+ * @namespace
+ */
+var blocks = blocks || {};
+blocks.setup_generic_block = function(uid) {
+ Y.use('base','dom','io','node', 'event-custom', function() {
+ var block = new blocks.genericblock(uid);
+ block.init();
+ });
+}
+
+/**
+ * @namespace
+ */
+blocks.dock = {
+ count:0, // The number of dock items through the page life
+ exists:false, // True if the dock exists
+ items:[], // An array of dock items
+ node:null, // The YUI node for the dock itself
+ earlybinds:[],
+ strings:{
+ addtodock : '[[addtodock]]',
+ undockitem : '[[undockitem]]',
+ undockall : '[[undockall]]'
+ },
+ /**
+ * Configuration parameters used during the initialisation and setup
+ * of dock and dock items.
+ * This is here specifically so that themers can override core parameters and
+ * design aspects without having to re-write navigation
+ * @namespace
+ */
+ cfg:{
+ 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:{
+ spacebeforefirstitem: 10 // Space between the top of the dock and the first item
+ },
+ css: {
+ 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
+ },
+ panel: {
+ close:false, // Show a close button on the panel
+ draggable:false, // Make the panel draggable
+ underlay:"none", // Use a special underlay
+ modal:false, // Throws a lightbox if set to true
+ keylisteners:null, // An array of keylisterners to attach
+ visible:false, // Visible by default
+ effect: null, // An effect that should be used with the panel
+ monitorresize:false, // Monitor the resize of the panel
+ context:null, // Sets up contexts for the panel
+ fixedcenter:false, // Always displays the panel in the center of the screen
+ zIndex:null, // Sets a specific z index for the panel
+ constraintoviewport: false, // Constrain the panel to the viewport
+ autofillheight:'body' // Which container element should fill out empty space
+ }
+ },
+ /**
+ * Adds a dock item into the dock
+ * @function
+ */
+ add:function(item) {
+ item.id = this.count;
+ this.count++;
+ this.items[item.id] = item;
+ this.draw();
+ this.items[item.id].draw();
+ this.fire('dock:itemadded', item);
+ },
+ /**
+ * Draws the dock
+ * @function
+ */
+ draw:function() {
+ if (this.node !== null) {
+ return true;
+ }
+ this.fire('dock:drawstarted');
+ 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');
+ }
+
+ var dockcontrol = Y.Node.create('');
+ var removeall = Y.Node.create('
');
+ removeall.on('removeall|click', this.remove_all, this);
+ dockcontrol.appendChild(removeall);
+ this.node.appendChild(dockcontrol);
+
+ Y.one(document.body).appendChild(this.node);
+ Y.one(document.body).addClass(blocks.dock.cfg.css.body);
+ this.fire('dock:drawcompleted');
+ return true;
+ },
+ /**
+ * Removes the node at the given index and puts it back into conventional page sturcture
+ * @function
+ */
+ remove:function(uid) {
+ this.items[uid].remove();
+ this.fire('dock:itemremoved', uid);
+ this.count--;
+ if (this.count===0) {
+ this.fire('dock:toberemoved');
+ this.items = [];
+ this.node.remove();
+ this.node = null;
+ this.fire('dock:removed');
+ }
+ },
+ /**
+ * Removes all nodes and puts them back into conventional page sturcture
+ * @function
+ */
+ remove_all:function() {
+ for (var i in this.items) {
+ this.items[i].remove();
+ this.items[i] = null;
+ }
+ Y.fire('dock:toberemoved');
+ this.items = [];
+ this.node.remove();
+ this.node = null;
+ Y.fire('dock:removed');
+ },
+ /**
+ * Resizes the active item
+ * @function
+ */
+ resize:function(e){
+ for (var i in this.items) {
+ if (this.items[i].active) {
+ this.items[i].resize_panel(e);
+ }
+ }
+ },
+ /**
+ * Hides all (the active) item
+ * @function
+ */
+ hide_all:function() {
+ for (var i in this.items) {
+ this.items[i].hide();
+ }
+ },
+ /**
+ * This smart little function allows developers to attach event listeners before
+ * the dock has been augmented to allows event listeners.
+ * Once the augmentation is complete this function will be replaced with the proper
+ * on method for handling event listeners.
+ * Finally apply_binds needs to be called in order to properly bind events.
+ * @param {string} event
+ * @param {function} callback
+ */
+ on : function(event, callback) {
+ this.earlybinds.push({event:event,callback:callback});
+ },
+ /**
+ * This function takes all early binds and attaches them as listeners properly
+ * This should only be called once augmentation is complete.
+ */
+ apply_binds : function() {
+ for (var i in this.earlybinds) {
+ var bind = this.earlybinds[i];
+ this.on(bind.event, bind.callback);
+ }
+ this.earlybinds = [];
+ },
+ /**
+ * Namespace containing methods and properties that will be prototyped
+ * to the generic block class and possibly overriden by themes
+ * @namespace
+ */
+ abstract_block_class : {
+
+ id : null,
+ cachedcontentnode : null,
+ blockspacewidth : null,
+ skipsetposition : false,
+
+ /**
+ * 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
+ */
+ init : function(node) {
+ if (!node) {
+ node = Y.one('#inst'+this.id);
+ }
+
+ var commands = node.one('.header .title .commands');
+ if (!commands) {
+ commands = Y.Node.create('');
+ if (node.one('.header .title')) {
+ node.one('.header .title').append(commands);
+ }
+ }
+
+ var moveto = Y.Node.create('');
+ moveto.append(Y.Node.create('
'));
+ if (location.href.match(/\?/)) {
+ moveto.set('href', location.href+'&dock='+this.id);
+ } else {
+ moveto.set('href', location.href+'?dock='+this.id);
+ }
+ 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);
+ });
+ }
+
+ if (node.hasClass('dock_on_load')) {
+ node.removeClass('dock_on_load')
+ this.skipsetposition = true;
+ this.move_to_dock();
+ }
+ },
+
+ /**
+ * This function is reponsible for moving a block from the page structure onto the
+ * dock
+ * @param {event}
+ */
+ move_to_dock : function(e) {
+ if (e) {
+ e.halt(true);
+ }
+
+ var node = Y.one('#inst'+this.id);
+ var blockcontent = node.one('.content');
+
+ this.cachedcontentnode = node;
+
+ node.all('a.moveto').each(function(moveto){
+ Y.Event.purgeElement(Y.Node.getDOMNode(moveto), false, 'click');
+ if (moveto.hasClass('customcommand')) {
+ moveto.all('img').each(function(movetoimg){
+ movetoimg.setAttribute('src', get_image_url('t/dock_to_block', 'moodle'));
+ movetoimg.setAttribute('alt', blocks.dock.strings.undockitem);
+ movetoimg.setAttribute('title', blocks.dock.strings.undockitem);
+ }, this);
+ }
+ }, this);
+
+ var placeholder = Y.Node.create('');
+ node.replace(Y.Node.getDOMNode(placeholder));
+ node = null;
+
+ this.resize_block_space(placeholder);
+
+ var blocktitle = Y.Node.getDOMNode(this.cachedcontentnode.one('.title h2')).cloneNode(true);
+ blocktitle.innerHTML = blocktitle.innerHTML.replace(/([a-zA-Z0-9])/g, "$1
");
+
+ var commands = this.cachedcontentnode.all('.title .commands');
+ var blockcommands = Y.Node.create('');
+ if (commands.size() > 0) {
+ blockcommands = commands.item(0);
+ }
+
+ var dockitem = new blocks.dock.item(this.id, blocktitle, blockcontent, blockcommands);
+ dockitem.on('dockeditem:drawcomplete', function(e){
+ // check the contents block [editing=off]
+ this.contents.all('a.moveto').on('returntoblock|click', function(e){
+ e.halt();
+ blocks.dock.remove(this.id)
+ }, this);
+ // check the commands block [editing=on]
+ this.commands.all('a.moveto').on('returntoblock|click', function(e){
+ e.halt();
+ blocks.dock.remove(this.id)
+ }, this);
+ }, dockitem);
+ dockitem.on('dock:itemremoved', this.return_to_block, this, dockitem);
+ blocks.dock.add(dockitem);
+
+ if (!this.skipsetposition) {
+ set_user_preference('docked_block_instance_'+this.id, 1);
+ } else {
+ this.skipsetposition = false;
+ }
+ },
+
+ /**
+ * 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
+ */
+ resize_block_space : function(node) {
+ node = node.ancestor('.block-region');
+ if (node) {
+ if (node.all('.sideblock').size() === 0 && this.blockspacewidth === null) {
+ this.blockspacewidth = node.getStyle('width');
+ node.setStyle('width', '0px');
+ } else if (this.blockspacewidth !== null) {
+ node.setStyle('width', this.blockspacewidth);
+ this.blockspacewidth = null;
+ }
+ }
+ },
+
+ /**
+ * This function removes a block from the dock and puts it back into the page
+ * structure.
+ * @param {blocks.dock.class.item}
+ */
+ return_to_block : function(dockitem) {
+ var placeholder = Y.one('#content_placeholder_'+this.id);
+ this.cachedcontentnode.appendChild(dockitem.contents);
+ placeholder.replace(Y.Node.getDOMNode(this.cachedcontentnode));
+ this.cachedcontentnode = Y.one('#'+this.cachedcontentnode.get('id'));
+
+ this.resize_block_space(this.cachedcontentnode);
+
+ this.cachedcontentnode.all('a.moveto').each(function(moveto){
+ Y.Event.purgeElement(Y.Node.getDOMNode(moveto), false, 'click');
+ moveto.on('movetodock|click', this.move_to_dock, this);
+ if (moveto.hasClass('customcommand')) {
+ moveto.all('img').each(function(movetoimg){
+ movetoimg.setAttribute('src', get_image_url('t/block_to_dock', 'moodle'));
+ movetoimg.setAttribute('alt', blocks.dock.strings.addtodock);
+ movetoimg.setAttribute('title', blocks.dock.strings.addtodock);
+ }, this);
+ }
+ }, this);
+
+ var commands = this.cachedcontentnode.all('.commands');
+ var blocktitle = this.cachedcontentnode.all('.title');
+
+ if (commands.size() === 1 && blocktitle.size() === 1) {
+ commands.item(0).remove();
+ blocktitle.item(0).append(commands.item(0));
+ }
+
+ this.cachedcontentnode = null;
+ set_user_preference('docked_block_instance_'+this.id, 0);
+ return true;
+ }
+ },
+
+ abstract_item_class : {
+ id : null,
+ name : null,
+ title : null,
+ contents : null,
+ commands : null,
+ events : null,
+ active : false,
+ panel : null,
+ preventhide : false,
+ cfg : null,
+
+ init_events : function() {
+ this.publish('dockeditem:drawstart', {prefix:'dockeditem'});
+ this.publish('dockeditem:drawcomplete', {prefix:'dockeditem'});
+ this.publish('dockeditem:showstart', {prefix:'dockeditem'});
+ this.publish('dockeditem:showcomplete', {prefix:'dockeditem'});
+ this.publish('dockeditem:hidestart', {prefix:'dockeditem'});
+ this.publish('dockeditem:hidecomplete', {prefix:'dockeditem'});
+ this.publish('dockeditem:resizestart', {prefix:'dockeditem'});
+ this.publish('dockeditem:resizecomplete', {prefix:'dockeditem'});
+ this.publish('dockeditem:itemremoved', {prefix:'dockeditem'});
+ },
+
+ /**
+ * This function draws the item on the dock
+ */
+ draw : function() {
+ this.fire('dockeditem:drawstart');
+ var dockitemtitle = Y.Node.create('');
+ dockitemtitle.append(this.title);
+ var dockitem = Y.Node.create('');
+ if (blocks.dock.count === 1) {
+ dockitem.addClass('firstdockitem');
+ }
+ dockitem.append(dockitemtitle);
+ if (this.commands.hasChildNodes) {
+ this.contents.appendChild(this.commands);
+ }
+ blocks.dock.node.append(dockitem);
+
+ var position = dockitemtitle.getXY();
+ position[0] += parseInt(dockitemtitle.get('offsetWidth'));
+ if (YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 8) {
+ position[0] -= 2;
+ }
+ this.panel = new YAHOO.widget.Panel('dock_item_panel_'+this.id, {
+ close:this.cfg.panel.close,
+ draggable:this.cfg.panel.draggable,
+ underlay:this.cfg.panel.underlay,
+ modal: this.cfg.panel.modal,
+ keylisteners: this.cfg.panel.keylisteners,
+ visible:this.cfg.panel.visible,
+ effect:this.cfg.panel.effect,
+ monitorresize:this.cfg.panel.monitorresize,
+ context: this.cfg.panel.context,
+ fixedcenter: this.cfg.panel.fixedcenter,
+ zIndex: this.cfg.panel.zIndex,
+ constraintoviewport: this.cfg.panel.constraintoviewport,
+ xy:position,
+ autofillheight:this.cfg.panel.autofillheight});
+ this.panel.showEvent.subscribe(this.resize_panel, this, true);
+ this.panel.setBody(Y.Node.getDOMNode(this.contents));
+ this.panel.render(blocks.dock.node);
+ dockitem.on('showitem|mouseover', this.show, this);
+ this.fire('dockeditem:drawcomplete');
+ },
+ /**
+ * This function removes the node and destroys it's bits
+ */
+ remove : function (e) {
+ this.hide(e);
+ Y.one('#dock_item_'+this.id).remove();
+ this.panel.destroy();
+ this.fire('dock:itemremoved');
+ },
+ /**
+ * This function toggles makes the item active and shows it
+ * @param {event}
+ */
+ show : function(e) {
+ blocks.dock.hide_all();
+ this.fire('dockeditem:showstart');
+ this.panel.show(e, this);
+ this.active = true;
+ Y.one('#dock_item_'+this.id+'_title').addClass(this.cfg.css.activeitem);
+ Y.detach('mouseover', this.show, Y.one('#dock_item_'+this.id));
+ Y.one('#dock_item_panel_'+this.id).on('dockpreventhide|click', function(){this.preventhide=true;}, this);
+ Y.one('#dock_item_'+this.id).on('dockhide|click', this.hide, this);
+ Y.get(window).on('dockresize|resize', this.resize_panel, this);
+ Y.get(document.body).on('dockhide|click', this.hide, this);
+ this.fire('dockeditem:showcomplete');
+ return true;
+ },
+ /**
+ * This function hides the item and makes it inactive
+ * @param {event}
+ */
+ hide : function(e) {
+ if (this.preventhide===true) {
+ this.preventhide = false;
+ } else if (this.active) {
+ this.fire('dockeditem:hidestart');
+ this.active = false;
+ Y.one('#dock_item_'+this.id+'_title').removeClass(this.cfg.css.activeitem);
+ Y.one('#dock_item_'+this.id).on('showitem|mouseover', this.show, this);
+ Y.get(window).detach('dockresize|resize');
+ Y.get(document.body).detach('dockhide|click');
+ this.panel.hide(e, this);
+ this.fire('dockeditem:hidecomplete');
+ }
+ },
+ /**
+ * This function checks the size and position of the panel and moves/resizes if
+ * required to keep it within the bounds of the window.
+ */
+ resize_panel : function() {
+ this.fire('dockeditem:resizestart');
+ var panelbody = Y.one(this.panel.body);
+ var buffer = this.cfg.buffer;
+ var screenheight = parseInt(Y.get(document.body).get('winHeight'));
+ var panelheight = parseInt(panelbody.get('offsetHeight'));
+ var paneltop = parseInt(this.panel.cfg.getProperty('y'));
+ var titletop = parseInt(Y.one('#dock_item_'+this.id+'_title').getY());
+ var scrolltop = window.pageYOffset || document.body.scrollTop || 0;
+
+ // This makes sure that the panel is the same height as the dock title to
+ // begin with
+ if (paneltop > (buffer+scrolltop) && paneltop > (titletop+scrolltop)) {
+ this.panel.cfg.setProperty('y', titletop+scrolltop);
+ }
+
+ // This makes sure that if the panel is big it is moved up to ensure we don't
+ // have wasted space above the panel
+ if ((paneltop+panelheight)>(screenheight+scrolltop) && paneltop > buffer) {
+ paneltop = (screenheight-panelheight-buffer);
+ if (paneltop screenheight || panelbody.hasClass('oversized_content'))) {
+ this.panel.cfg.setProperty('height', screenheight-(buffer*2));
+ panelbody.setStyle('height', (screenheight-(buffer*3))+'px');
+ panelbody.addClass('oversized_content');
+ }
+ this.fire('dockeditem:resizecomplete');
+ }
+ }
+};
+
+/**
+ * This class represents a generic block
+ * @class genericblock
+ * @constructor
+ */
+blocks.genericblock = function(uid){
+ if (uid && this.id==null) {
+ this.id = uid;
+ }
+};
+/** Properties */
+blocks.genericblock.prototype.name = blocks.dock.abstract_block_class.name;
+blocks.genericblock.prototype.cachedcontentnode = blocks.dock.abstract_block_class.cachedcontentnode;
+blocks.genericblock.prototype.blockspacewidth = blocks.dock.abstract_block_class.blockspacewidth;
+blocks.genericblock.prototype.skipsetposition = blocks.dock.abstract_block_class.skipsetposition;
+/** Methods **/
+blocks.genericblock.prototype.init = blocks.dock.abstract_block_class.init;
+blocks.genericblock.prototype.move_to_dock = blocks.dock.abstract_block_class.move_to_dock;
+blocks.genericblock.prototype.resize_block_space = blocks.dock.abstract_block_class.resize_block_space;
+blocks.genericblock.prototype.return_to_block = blocks.dock.abstract_block_class.return_to_block;
+
+/**
+ * This class represents an item in the dock
+ * @class item
+ * @constructor
+ */
+blocks.dock.item = function(uid, title, contents, commands){
+ if (uid && this.id==null) this.id = uid;
+ if (title && this.title==null) this.title = title;
+ if (contents && this.contents==null) this.contents = contents;
+ if (commands && this.commands==null) this.commands = commands;
+ this.init_events();
+}
+/** Properties */
+blocks.dock.item.prototype.id = blocks.dock.abstract_item_class.id;
+blocks.dock.item.prototype.name = blocks.dock.abstract_item_class.name;
+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;
+blocks.dock.item.prototype.cfg = blocks.dock.cfg;
+/** Methods **/
+blocks.dock.item.prototype.init_events = blocks.dock.abstract_item_class.init_events;
+blocks.dock.item.prototype.draw = blocks.dock.abstract_item_class.draw;
+blocks.dock.item.prototype.remove = blocks.dock.abstract_item_class.remove;
+blocks.dock.item.prototype.show = blocks.dock.abstract_item_class.show;
+blocks.dock.item.prototype.hide = blocks.dock.abstract_item_class.hide;
+blocks.dock.item.prototype.resize_panel = blocks.dock.abstract_item_class.resize_panel;
+
+YUI({base: moodle_cfg.yui3loaderBase}).use('event-custom','event', 'node', function(Y){
+ // Give the dock item class the event properties/methods
+ Y.augment(blocks.dock.item, Y.EventTarget);
+ Y.augment(blocks.dock, Y.EventTarget, true);
+ blocks.dock.apply_binds();
+});
\ No newline at end of file
diff --git a/blocks/global_navigation_tree/block_global_navigation_tree.php b/blocks/global_navigation_tree/block_global_navigation_tree.php
index 61d54342bf0..fc790b658a2 100644
--- a/blocks/global_navigation_tree/block_global_navigation_tree.php
+++ b/blocks/global_navigation_tree/block_global_navigation_tree.php
@@ -79,6 +79,12 @@ class block_global_navigation_tree extends block_tree {
return true;
}
+ function get_required_javascript() {
+ $this->_initialise_dock();
+ $this->page->requires->js('blocks/global_navigation_tree/navigation.js');
+ user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT);
+ }
+
/**
* Gets the content for this block by grabbing it from $this->page
*/
@@ -142,21 +148,14 @@ class block_global_navigation_tree extends block_tree {
$this->showmyhistory();
}
- $togglesidetabdisplay = get_string('togglesidetabdisplay', $this->blockname);
- $toggleblockdisplay = get_string('toggleblockdisplay', $this->blockname);
-
-
// Get the expandable items so we can pass them to JS
$expandable = array();
$this->page->navigation->find_expandable($expandable);
- $args = array('expansions'=>$expandable,'instance'=>$this->instance->id);
- $args['togglesidetabdisplay'] = $togglesidetabdisplay;
- $args['toggleblockdisplay'] = $toggleblockdisplay;
- // Give JS some information we will use within the JS tree object
- $this->page->requires->data_for_js('globalnav'.block_global_navigation_tree::$navcount, $args);
+
// Initialise the JS tree object
- $this->id = 'globalnav'.block_global_navigation_tree::$navcount;
- $this->page->requires->js_function_call('setup_new_navtree', array($this->id))->on_dom_ready();
+ $args = array($this->instance->id,array('expansions'=>$expandable,'instance'=>$this->instance->id));
+ $this->page->requires->js_function_call('blocks.navigation.setup_new_tree', $args)->on_dom_ready();
+
// Grab the items to display
$this->content->items = array($this->page->navigation);
@@ -165,21 +164,6 @@ class block_global_navigation_tree extends block_tree {
$this->content->footer .= $OUTPUT->action_icon($reloadlink, get_string('reload'), 't/reload');
- if (empty($this->config->enablesidebarpopout) || $this->config->enablesidebarpopout == 'yes') {
- user_preference_allow_ajax_update('nav_in_tab_panel_globalnav'.block_global_navigation_tree::$navcount, PARAM_INT);
-
- $movelink = new html_link($this->page->url);
- $movelink->add_classes('moveto customcommand requiresjs');
- if ($this->docked) {
- $movelink->url->param('undock', $this->instance->id);
- $moveicon = $OUTPUT->action_icon($movelink, $toggleblockdisplay, 't/movetoblock');
- } else {
- $movelink->url->param('dock', $this->instance->id);
- $moveicon = $OUTPUT->action_icon($movelink, $toggleblockdisplay, 't/movetosidetab');
- }
- $this->content->footer .= $moveicon;
- }
-
// Set content generated to true so that we know it has been done
$this->contentgenerated = true;
return true;
@@ -200,14 +184,14 @@ class block_global_navigation_tree extends block_tree {
$attributes = parent::html_attributes();
if ($this->docked===null) {
- $this->docked = get_user_preferences('nav_in_tab_panel_globalnav'.block_global_navigation_tree::$navcount, 0);
+ $this->docked = get_user_preferences('docked_block_instance_'.$this->instance->id, 0);
}
if (!empty($this->config->enablehoverexpansion) && $this->config->enablehoverexpansion == 'yes') {
- $attributes['class'] .= ' sideblock_js_expansion';
+ $attributes['class'] .= ' block_js_expansion';
}
if ($this->docked) {
- $attributes['class'] .= ' sideblock_js_sidebarpopout';
+ $attributes['class'] .= ' dock_on_load';
}
return $attributes;
}
diff --git a/blocks/global_navigation_tree/navigation.js b/blocks/global_navigation_tree/navigation.js
new file mode 100644
index 00000000000..39bd0f2f0f7
--- /dev/null
+++ b/blocks/global_navigation_tree/navigation.js
@@ -0,0 +1,298 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see .
+
+/**
+ * This file contains classes used to manage the navigation structures in Moodle
+ * and was introduced as part of the changes occuring in Moodle 2.0
+ *
+ * @since 2.0
+ * @package javascript
+ * @copyright 2009 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * @namespace
+ */
+var blocks = blocks || {};
+
+/**
+ * This namespace will contain all of the contents of the navigation blocks
+ * global navigation and settings.
+ * @namespace
+ */
+blocks.navigation = {
+ /** The number of expandable branches in existence */
+ expandablebranchcount:0,
+ /** An array of initialised trees */
+ treecollection:[],
+ /**
+ * @namespace
+ */
+ classes:{},
+ /**
+ * @function
+ * @static
+ * @param {int} uid The id of the block within the page
+ * @param {object} properties
+ */
+ setup_new_tree:function(uid, properties) {
+ Y.use('base','dom','io','node', function() {
+ properties = properties || {'instance':uid};
+ blocks.navigation.treecollection[uid] = new blocks.navigation.classes.tree(uid, uid, properties);
+ });
+ }
+};
+
+/**
+ * @class tree
+ * @constructor
+ * @base blocks.dock.abstractblock
+ * @param {string} id The name of the tree
+ * @param {int} key The internal id within the tree store
+ * @param {object} properties Object containing tree properties
+ */
+blocks.navigation.classes.tree = function(id, key, properties) {
+ this.id = id;
+ this.key = key;
+ this.type = 'blocks.navigation.classes.tree';
+ this.errorlog = [];
+ this.ajaxbranches = 0;
+ this.expansions = [];
+ this.instance = null;
+ this.cachedcontentnode = null;
+ this.cachedfooter = null;
+ this.position = 'block';
+ this.skipsetposition = false;
+ if (properties) {
+ if (properties.expansions) {
+ this.expansions = properties.expansions;
+ }
+ if (properties.instance) {
+ this.instance = properties.instance;
+ }
+ }
+
+ if (Y.one('#inst'+this.id) === null) {
+ return;
+ }
+
+ 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++;
+ }
+
+ var node = Y.one('#inst'+this.id);
+ node.all('.tree_item.branch').on('click', this.toggleexpansion , this);
+
+ this.init(node);
+
+ if (node.hasClass('block_js_expansion')) {
+ node.on('mouseover', function(e){this.toggleClass('mouseover');}, node);
+ node.on('mouseout', function(e){this.toggleClass('mouseover');}, node);
+ }
+}
+
+/**
+ * Loads a branch via AJAX
+ * @param {event} The event object
+ * @param {object} 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:'';
+ 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,
+ on: {
+ complete:this.load_ajax,
+ success:function() {Y.detach('click', this.init_load_ajax, e.target);}
+ },
+ context:this,
+ arguments:{
+ target:e.target
+ }
+ });
+ return true;
+}
+
+/**
+ * Takes an branch provided through ajax and loads it into the tree
+ */
+blocks.navigation.classes.tree.prototype.load_ajax = function(tid, outcome, args) {
+ // Check the status
+ if (outcome.status!=0 && outcome.responseXML!=null) {
+ var branch = outcome.responseXML.documentElement;
+ if (branch!=null && this.add_branch(branch, args.target.ancestor('LI') ,1)) {
+ // If we get here everything worked perfectly
+ blocks.dock.resize();
+ return true;
+ }
+ }
+ args.target.replaceClass('branch', 'emptybranch');
+ return true;
+}
+
+/**
+ * Adds a branch into the tree provided with some XML
+ */
+blocks.navigation.classes.tree.prototype.add_branch = function(branchxml, target, depth) {
+
+ var branch = new blocks.navigation.classes.branch(this);
+ branch.construct_from_xml(branchxml);
+
+ var childrenul = false;
+ if (depth === 1) {
+ if (!branch.haschildren) {
+ return false;
+ }
+ childrenul = Y.Node.create('');
+ target.appendChild(childrenul);
+ } else {
+ childrenul = branch.inject_into_dom(target);
+ }
+
+ if (childrenul) {
+ for (var i=0;i');
+ var branchp = Y.Node.create('');
+
+ if ((this.expandable !== null || this.haschildren) && this.expansionceiling===null) {
+ branchli.addClass('collapsed');
+ branchp.addClass('branch');
+ branchp.on('click', this.tree.toggleexpansion, this.tree);
+ if (this.expandable) {
+ branchp.on('ajaxload|click', this.tree.init_load_ajax, this.tree, {branchid:this.key,id:this.id,type:this.type});
+ }
+ }
+
+ if (this.myclass !== null) {
+ branchp.addClass(this.myclass);
+ }
+ if (this.id !== null) {
+ branchp.setAttribute('id', this.id);
+ }
+
+ var branchicon = false;
+ if (this.icon != null) {
+ branchicon = Y.Node.create('
');
+ this.name = ' '+this.name;
+ }
+ if (this.link === null) {
+ if (branchicon) {
+ branchp.appendChild(branchicon);
+ }
+ branchp.append(this.name.replace(/\n/g, '
'));
+ } else {
+ var branchlink = Y.Node.create(''+this.name.replace(/\n/g, '
')+'');
+ if (branchicon) {
+ branchlink.appendChild(branchicon);
+ }
+ if (this.hidden) {
+ branchlink.addClass('dimmed');
+ }
+ branchp.appendChild(branchlink);
+ }
+
+ branchli.appendChild(branchp);
+ if (this.haschildren) {
+ var childrenul = Y.Node.create('');
+ branchli.appendChild(childrenul);
+ element.appendChild(branchli);
+ return childrenul
+ } else {
+ element.appendChild(branchli);
+ return false;
+ }
+}
+
+YUI({base: moodle_cfg.yui3loaderBase}).use('event-custom', 'node', function(Y){
+ // Give the tree class the dock block properties
+ Y.augment(blocks.navigation.classes.tree, blocks.genericblock);
+});
\ No newline at end of file
diff --git a/blocks/moodleblock.class.php b/blocks/moodleblock.class.php
index 03db833cd23..595405c58fd 100644
--- a/blocks/moodleblock.class.php
+++ b/blocks/moodleblock.class.php
@@ -113,6 +113,8 @@ class block_base {
var $cron = NULL;
+ static $dockinitialised = false;
+
/// Class Functions
/**
@@ -541,10 +543,14 @@ class block_base {
* @return array attribute name => value.
*/
function html_attributes() {
- return array(
+ $attributes = array(
'id' => 'inst' . $this->instance->id,
'class' => 'block_' . $this->name()
);
+ if (get_user_preferences('docked_block_instance_'.$this->instance->id, 0)) {
+ $attributes['class'] .= ' dock_on_load';
+ }
+ return $attributes;
}
/**
@@ -566,6 +572,15 @@ class block_base {
}
$this->page = $page;
$this->specialization();
+ $this->get_required_javascript();
+ }
+
+ function get_required_javascript() {
+ if ($this->instance_can_dock_with_dock()) {
+ $this->_initialise_dock();
+ $this->page->requires->js_function_call('blocks.setup_generic_block', array($this->instance->id))->on_dom_ready();
+ user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT);
+ }
}
/**
@@ -728,6 +743,22 @@ class block_base {
function config_print() {
throw new coding_exception('config_print() can no longer be used. Blocks should use a settings.php file.');
}
+
+ public function instance_can_dock_with_dock() {
+ return true;
+ }
+
+ public function _initialise_dock() {
+ if (!self::$dockinitialised) {
+ $this->page->requires->js('blocks/blocks.js');
+ $this->page->requires->data_for_js('blocks.dock.strings.addtodock', get_string('addtodock', 'block'));
+ $this->page->requires->data_for_js('blocks.dock.strings.undockitem', get_string('undockitem', 'block'));
+ $this->page->requires->data_for_js('blocks.dock.strings.undockall', get_string('undockall', 'block'));
+ self::$dockinitialised = true;
+ }
+
+ }
+
/** @callback callback functions for comments api */
public static function comment_template($options) {
$ret = <<_initialise_dock();
+ $this->page->requires->js('blocks/global_navigation_tree/navigation.js');
+ $this->page->requires->js_function_call('blocks.navigation.setup_new_tree', array($this->instance->id))->on_dom_ready();
+ user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT);
+ }
+
/**
* Gets the content for this block by grabbing it from $this->page
*/
@@ -110,17 +116,6 @@ class block_settings_navigation_tree extends block_tree {
redirect($url);
}
- $togglesidetabdisplay = get_string('togglesidetabdisplay', $this->blockname);
- $toggleblockdisplay = get_string('toggleblockdisplay', $this->blockname);
- $args = array('instance'=>$this->instance->id);
- $args['togglesidetabdisplay'] = $togglesidetabdisplay;
- $args['toggleblockdisplay'] = $toggleblockdisplay;
- // Give JS some information we will use within the JS tree object
- $this->page->requires->data_for_js('settingsnav'.block_settings_navigation_tree::$navcount, $args);
-
-
- $this->id = 'settingsnav'.block_settings_navigation_tree::$navcount;
- $this->page->requires->js_function_call('setup_new_navtree', array($this->id))->on_dom_ready();
// Grab the children from settings nav, we have more than one root node
// and we dont want to show the site node
$this->content->items = $this->page->settingsnav->children;
@@ -147,17 +142,6 @@ class block_settings_navigation_tree extends block_tree {
if (!empty($this->config->enablesidebarpopout) && $this->config->enablesidebarpopout == 'yes') {
user_preference_allow_ajax_update('nav_in_tab_panel_settingsnav'.block_settings_navigation_tree::$navcount, PARAM_INT);
-
- $movelink = new html_link($this->page->url);
- $movelink->add_classes('moveto customcommand requiresjs');
- if ($this->docked) {
- $movelink->url->param('undock', $this->instance->id);
- $moveicon = $OUTPUT->action_icon($movelink, $toggleblockdisplay, 't/movetoblock');
- } else {
- $movelink->url->param('dock', $this->instance->id);
- $moveicon = $OUTPUT->action_icon($movelink, $toggleblockdisplay, 't/movetosidetab');
- }
- $this->content->footer .= $moveicon;
}
}
@@ -170,14 +154,14 @@ class block_settings_navigation_tree extends block_tree {
// Check if this block has been docked
if ($this->docked === null) {
- $this->docked = get_user_preferences('nav_in_tab_panel_settingsnav'.block_settings_navigation_tree::$navcount, 0);
+ $this->docked = get_user_preferences('docked_block_instance_'.$this->instance->id, 0);
}
if (!empty($this->config->enablehoverexpansion) && $this->config->enablehoverexpansion == 'yes') {
- $attributes['class'] .= ' sideblock_js_expansion';
+ $attributes['class'] .= ' block_js_expansion';
}
if ($this->docked) {
- $attributes['class'] .= ' sideblock_js_sidebarpopout';
+ $attributes['class'] .= ' dock_on_load';
}
return $attributes;
}
diff --git a/lang/en_utf8/block.php b/lang/en_utf8/block.php
index 70b576f73e0..e06c51d3dd0 100644
--- a/lang/en_utf8/block.php
+++ b/lang/en_utf8/block.php
@@ -1,6 +1,7 @@
headdone) {
- throw new coding_exception('YUI3 libraries can be preloaded by PHP only from HEAD, please use YUI autoloading instead: ', $stylesheet);
+ throw new coding_exception('YUI3 libraries can be preloaded by PHP only from HEAD, please use YUI autoloading instead: ', $libname);
}
$libnames = (array)$libname;
foreach ($libnames as $lib) {
@@ -591,6 +591,7 @@ class page_requirements_manager {
* @return string the HTML code to to at the end of the page.
*/
public function get_end_code() {
+ global $CFG;
$output = $this->get_yui2lib_code();
$output .= $this->get_linked_resources_code(self::WHEN_AT_END);
@@ -601,9 +602,16 @@ class page_requirements_manager {
$js = $this->get_javascript_code(self::WHEN_AT_END);
$ondomreadyjs = $this->get_javascript_code(self::WHEN_ON_DOM_READY, ' ');
- if ($ondomreadyjs) {
- $js .= "YAHOO.util.Event.onDOMReady(function() {\n" . $ondomreadyjs . "});\n";
- }
+
+ $js .= <<forceopen = true;
$this->action = new moodle_url($CFG->wwwroot);
$this->cache = new navigation_cache(NAVIGATION_CACHE_NAME);
- $PAGE->requires->string_for_js('moveallsidetabstoblock','moodle');
$regenerate = optional_param('regenerate', null, PARAM_TEXT);
if ($regenerate==='navigation') {
$this->cache->clear();
diff --git a/pix/t/block_to_dock.png b/pix/t/block_to_dock.png
new file mode 100644
index 00000000000..d72690c8701
Binary files /dev/null and b/pix/t/block_to_dock.png differ
diff --git a/pix/t/dock_to_block.png b/pix/t/dock_to_block.png
new file mode 100644
index 00000000000..5ace5af1c62
Binary files /dev/null and b/pix/t/dock_to_block.png differ
diff --git a/theme/base/config.php b/theme/base/config.php
index 4b0ef7ca73e..03070d7e5ba 100644
--- a/theme/base/config.php
+++ b/theme/base/config.php
@@ -150,5 +150,5 @@ $THEME->layouts = array(
);
/** List of javascript files that need to included on each page */
-$THEME->javascripts = array('navigation');
-//$THEME->javascripts_footer = array();
\ No newline at end of file
+$THEME->javascripts = array();
+$THEME->javascripts_footer = array('navigation');
\ No newline at end of file
diff --git a/theme/base/javascript/navigation.js b/theme/base/javascript/navigation.js
index e8b872f0562..7e0fbffa335 100644
--- a/theme/base/javascript/navigation.js
+++ b/theme/base/javascript/navigation.js
@@ -1 +1,116 @@
-/* base: javascript needed for navbar manipulations */
+/**
+ * So you want to override the navigation huh ??
+ * Make it look like your own and totally customise it to be way cool !!
+ *
+ * Well now you can by following the instructions in this file.
+ *
+ * It will be essential to have a clear idea about what it is you want to acheive,
+ * whilst it is possible to override nearly all of the navbar settings/methods it's
+ * not nesecarily going to be an easy task.
+ *
+ * To begin you must understand the structure of the blocks and particually the navbar
+ * object. The following outlines the basic structure:
+ *
+ * - Namespace: blocks
+ * - Func: setup_generic_block Creates a new generic block instance
+ * - Class: genericblock Generic block class
+ * - Namespace: navbar
+ * - Var: count The # of items that have EVER existed on the navbar
+ * - Var: exists True if the navbar exists
+ * - Var: items An array of items on the navbar
+ * - Var: node The node that is the navbar
+ * - Var: strings An object containing strings for the navbar
+ * - Namespace: cfg
+ * - Var: buffer The space buffer around panels
+ * - Var: position The position of the navbar
+ * - Var: orientation The orientation of the navbar
+ * - Namespace: display
+ * ............ A series of display parameters
+ * - Namespace: css
+ * ............ A series of CSS class names
+ * - Namespace: panel
+ * ............ A series of conf options for YUI panels
+ * - Func: add Adds an item to the navbar
+ * - Func: draw Creates the navbar and adds it to the page
+ * - Func: remove Removes an item from the navbar
+ * - Func: remove_all Removes all items from the navbar
+ * - Func: resize Calls the navbar to resize its active item
+ * - Func: hide_all Calls the navbar to hide all active items
+ * - Class: item A navbar item class
+ * - Namespace: abstract_block_class A namespace containing all of the properties
+ * ............. and methods that will be used as the default
+ * ............. methods for the generic block class.
+ * - Namespace: abstract_item_class A namespace containing all of the properties
+ * ............. and methods for the navbar item class
+ *
+ * From the structure above you are able to immediatly override any of the vars
+ * that are associated with the navigation by simply assigning them a value as
+ * shown below:
+ *
+ * blocks.navbar.cfg.buffer = 20; // or
+ *
+ * You are also able to override all of the properties and methods of the two
+ * abstract classes that manage all of the interaction for the blocks and navbar
+ * items thanks to the prototyping method that is being used to build the classes.
+ *
+ * To override a method simply copy the following style of coding:
+ *
+ * blocks.genericblock.prototype.init = function(uid) {
+ * // The code for the new init method which will be executed in the
+ * // objects scope and override the old init method.
+ * }
+ *
+ * // OR if the following is easier for you to understand
+ *
+ * function new_init_method(uid) {
+ * // The code for the new init method which will be executed in the
+ * // objects scope and override the old init method.
+ * }
+ * blocks.genericblock.prototype.init = new_init_method()
+ *
+ * Alternativily for the navbar items class the there are a series of actions that
+ * get fired that you may want to listen to. The events defined are as follows:
+ *
+ * navbaritem:drawstart draw is called
+ * navbaritem:drawcomplete draw is complete
+ * navbaritem:showstart show is called
+ * navbaritem:showcomplete show is complete
+ * navbaritem:hidestart hide is called
+ * navbaritem:hidecomplete hide is complete
+ * navbaritem:resizestart resize is called
+ * navbaritem:resizecomplete resize is complete
+ * navbaritem:itemremoved item is removed from the navbar
+ *
+ * You can listen to any of these events by first finding the appropriate item within
+ * the navbar.items array and then calling the following on it:
+ *
+ * var uid = x;
+ * blocks.navbar.items[uid].on('navbaritem:showstart', callback, scope);
+ * function callback(navbaritem) {
+ * // What ever you want to do can go here
+ * }
+ *
+ */
+
+// If this isn't set we don't need an override at all
+if (blocks.genericblock) {
+
+ /**
+ * Override the default resize_block_space method so that we can ensure
+ * it works for this template
+ * @param {Y.Node} blocknode
+ */
+ blocks.genericblock.prototype.resize_block_space = function(blocknode) {
+ var blockregion = blocknode.ancestor('#block-region');
+ if (blockregion) {
+ if (blockregion.all('.sideblock').size() === 0 && this.blockspacewidth === null) {
+ // Some spiffy code to reduce the template sideblock to 0 width
+ this.blockspacewidth = blockregion.getStyle('width');
+ } else if (this.blockspacewidth !== null) {
+ // Some spiffy code to set the sideblock width back to the original width
+ this.blockspacewidth = null;
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/theme/base/style/blocks.css b/theme/base/style/blocks.css
index f37f39bcb4f..7a2646ca6aa 100644
--- a/theme/base/style/blocks.css
+++ b/theme/base/style/blocks.css
@@ -111,7 +111,7 @@
font-weight:bold;
}
-.jsenabled .sideblock_js_sidebarpopout,
+.jsenabled .dock_on_load,
.jsenabled .block_tree .collapsed ul {
display: none;
}
diff --git a/theme/standardold/config.php b/theme/standardold/config.php
index 884fc9d1fc8..80cf7a4277c 100644
--- a/theme/standardold/config.php
+++ b/theme/standardold/config.php
@@ -177,5 +177,5 @@ $THEME->layouts = array(
);
/** List of javascript files that need to included on each page */
-$THEME->javascripts = array('navigation');
-
+$THEME->javascripts = array();
+$THEME->javascripts_footer = array('navigation');
\ No newline at end of file
diff --git a/theme/standardold/javascript/navigation.js b/theme/standardold/javascript/navigation.js
index b23832b0219..e9ee0e4b0ce 100644
--- a/theme/standardold/javascript/navigation.js
+++ b/theme/standardold/javascript/navigation.js
@@ -1,882 +1,48 @@
-/* legacy standard: javascript needed for navbar manipulations */
+// This attaches a shadow to the dock when it has been drawn (added to the page)
+blocks.dock.on('dock:drawcompleted', function() {
+ blocks.dock.node.append(shadow.create(true, true, true, true));
+});
+blocks.dock.on('dock:itemadded', function(item) {
+ item.on('dockeditem:showcomplete', function() {
+ Y.one('#dock_item_panel_'+this.id).append(shadow.create(true, true, true, false));
+ });
+ item.on('dockeditem:hidestart', function() {
+ shadow.remove(Y.one('#dock_item_panel_'+this.id));
+ });
+});
-// content of this file was originally in lib/javascript-naigation.php,
-// it was moved here for two reasons - testing of themes JS and second it may need
-// to use different tricks in other themes with CSS column layouts
-
-
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see .
-
-/**
- * This file contains classes used to manage the navigation structures in Moodle
- * and was introduced as part of the changes occuring in Moodle 2.0
- *
- * @since 2.0
- * @package javascript
- * @copyright 2009 Sam Hemelryk
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-/**
- * Some very important general namespaces to act as containers for the general
- * objects required to manage the navigation.
- *
- * For anyone looking to improve this javascript taking a little time to turn
- * the classes into namespaced classes, and giving the class structure in this file
- * a similar structure to YUI on a moodle namespace would be AWESOME
- */
-YAHOO.namespace('moodle.navigation');
-YAHOO.namespace('moodle.navigation.sideblockwidth');
-YAHOO.namespace('moodle.navigation.tabpanel');
-YAHOO.namespace('moodle.navigation.treecollection');
-
-/**
- * Instatiate some very important variables that allow us to manage the navigaiton
- * objects without having to hit my arch enemy `undefined`
- */
-YAHOO.moodle.navigation.sideblockwidth = null;
-YAHOO.moodle.navigation.tabpanel = null;
-YAHOO.moodle.navigation.treecollection = Array();
-YAHOO.moodle.navigation.expandablebranchcount = 0;
-
-/**
- * Navigation Tree object (function) used to control a global navigation tree
- * handling things such as collapse, expand, and AJAX requests for more branches
- *
- * You should never call this directly.. you should use {@link start_new_navtree()}
- * which will create the class and make it accessible in a smart way
- *
- * @class navigation_tree
- * @constructor
- * @param {string} treename
- * @param {string} key
- */
-function navigation_tree (treename, key) {
- this.name = treename;
- this.key = key;
- this.errorlog = '';
- this.ajaxbranches = 0;
- this.expansions = Array();
- this.instance = null
- this.cachedcontent = null;
- this.cachedfooter = null;
- this.position = 'block';
- this.skipsetposition = false;
- this.togglesidetabdisplay = '[[togglesidetabdisplay]]';
- this.toggleblockdisplay = '[[toggleblockdisplay]]';
- this.sideblockwidth = null;
- if (window[this.name]) {
- if (window[this.name].expansions) {
- this.expansions = window[this.name].expansions;
+var shadow = {
+ /**
+ * This function create a series of DIV's appended to an element to give it a
+ * shadow
+ * @param {bool} top Displays a top shadow if true
+ * @param {bool} right Displays a right shadow if true
+ * @param {bool} bottom Displays a bottom shadow if true
+ * @param {bool} left Displays a left shadow if true
+ * @return {Y.Node}
+ */
+ create : function(top, right, bottom, left) {
+ var shadow = Y.Node.create('');
+ if (Y.UA.ie > 0 && Y.UA.ie < 7) {
+ // IE 6 doesn't like this shadow method
+ return shadow;
}
- if (window[this.name].instance) {
- this.instance = window[this.name].instance;
- }
- if (window[this.name].togglesidetabdisplay) {
- this.togglesidetabdisplay = window[this.name].togglesidetabdisplay;
- }
- if (window[this.name].toggleblockdisplay) {
- this.toggleblockdisplay = window[this.name].toggleblockdisplay;
- }
- }
-}
-/**
- * Initialise function used to attach the initial events to the navigation tree
- * This function attachs toggles and ajax calls
- */
-navigation_tree.prototype.initialise = function() {
- if (!document.getElementById(this.name)) {
- return;
- }
- var e = document.getElementById(this.name);
- var i = 0;
- while (!YAHOO.util.Dom.hasClass(e, 'sideblock') && e.nodeName.toUpperCase()!='BODY') {
- e = e.parentNode;
- }
- var movetos = YAHOO.util.Dom.getElementsByClassName('moveto', 'a', e);
- if (movetos !== null && movetos.length > 0) {
- for (i = 0;i0) {
- for (i = 0; i 0) {
- for (i = 0; i < customcommands.length; i++) {
- customcommands[i].parentNode.removeChild(customcommands[i]);
- commands[0].appendChild(customcommands[i]);
- }
- }
-
- if (YAHOO.util.Dom.hasClass(e, 'sideblock_js_sidebarpopout')) {
- YAHOO.util.Dom.removeClass(e, 'sideblock_js_sidebarpopout');
- this.skipsetposition = true;
- this.toggle_block_display(e, this);
- } else if (YAHOO.util.Dom.hasClass(e, 'sideblock_js_expansion')) {
- YAHOO.util.Event.addListener(e, 'mouseover', this.togglesize, e, this);
- YAHOO.util.Event.addListener(e, 'mouseout', this.togglesize, e, this);
- }
-}
-/**
- * Toogle a branch either collapsed or expanded... CSS styled
- * @param {object} e Event object
- */
-navigation_tree.prototype.toggleexpansion = function(e) {
- YAHOO.util.Event.stopPropagation(e);
- var target = YAHOO.util.Event.getTarget(e);
- var parent = target.parentNode;
- while (parent.nodeName.toUpperCase()!='LI') {
- parent = parent.parentNode;
- }
- if (YAHOO.util.Dom.hasClass(parent, 'collapsed')) {
- YAHOO.util.Dom.removeClass(parent, 'collapsed');
- } else {
- YAHOO.util.Dom.addClass(parent, 'collapsed');
- }
- if (this.position === 'sidebar') {
- YAHOO.moodle.navigation.tabpanel.resize_tab();
- }
-}
-/**
- * Toggles the size on an element by adding/removing the mouseover class
- * @param {object} e Event object
- * @param {element} element The element to add/remove the class from
- */
-navigation_tree.prototype.togglesize = function(e, element) {
- if (e.type == 'mouseout') {
- var mp = YAHOO.util.Event.getXY(e);
- if (mp[0] == -1) {
- return true;
- }
- var ep = YAHOO.util.Dom.getXY(element);
- ep[2] = ep[0]+element.offsetWidth;
- ep[3] = ep[1]+element.offsetHeight;
- var withinrealm = (mp[0] > ep[0] && mp[0] < ep[2] && mp[1] > ep[1] && mp[1] < ep[3]);
- if (!withinrealm) {
- YAHOO.util.Event.stopEvent(e);
- YAHOO.util.Dom.removeClass(element, 'mouseover');
- }
- } else {
- YAHOO.util.Event.stopEvent(e);
- element.style.width = element.offsetWidth +'px';
- YAHOO.util.Dom.addClass(element, 'mouseover');
- }
- return true;
-}
-/**
- * This function makes the initial call to load a branch of the navigation
- * tree by AJAX
- * @param {object} e Event object
- * @param {object} branch The branch object from navigation_tree::expansions
- * @return {bool}
- */
-navigation_tree.prototype.init_load_ajax = function(e, branch) {
- YAHOO.util.Event.stopPropagation(e);
- if (YAHOO.util.Event.getTarget(e).nodeName.toUpperCase() != 'P') {
- return true;
- }
- var postargs = 'elementid='+branch.id+'&id='+branch.branchid+'&type='+branch.type+'&sesskey='+moodle_cfg.sesskey;
- if (this.instance != null) {
- postargs += '&instance='+this.instance;
- }
- YAHOO.util.Connect.asyncRequest('POST', moodle_cfg.wwwroot+'/lib/ajax/getnavbranch.php', callback={
- success:function(o) {this.load_ajax(o);},
- failure:function(o) {this.load_ajax(o);},
- argument: {gntinstance:this,branch:branch,event:e, target:YAHOO.util.Event.getTarget(e)},
- scope: this
- }, postargs);
- return true;
-}
-/**
- * This function loads a branch returned by AJAX into the XHTML tree structure
- * @param {object} outcome The AJAX response
- * @return {bool}
- */
-navigation_tree.prototype.load_ajax = function(outcome) {
- // Check the status
- if (outcome.status!=0 && outcome.responseXML!=null) {
- var branch = outcome.responseXML.documentElement;
- if (branch!=null && this.add_branch(branch,outcome.argument.target ,1)) {
- // If we get here everything worked perfectly
- YAHOO.util.Event.removeListener(outcome.argument.branch.element, 'click', navigation_tree.prototype.init_load_ajax);
- if (this.position === 'sidebar') {
- YAHOO.moodle.navigation.tabpanel.resize_tab();
- }
- return true;
- }
- }
- // Something went wrong or there simply wasn't anything more to display
- // add the emptybranch css class so we can flag it
- YAHOO.util.Dom.replaceClass(outcome.argument.target, 'branch', 'emptybranch');
- return false;
-}
-/**
- * This recursive function takes an XML branch and includes it in the tree
- * @param {xmlnode} branchxml The XML node for the branch
- * @param {element} target The target node to add to
- * @param {int} depth The depth we have delved (recusive counter)
- * @return {bool}
- */
-navigation_tree.prototype.add_branch = function(branchxml, target, depth) {
- var branch = new navigation_tree_branch(this.name);
- branch.load_from_xml_node(branchxml);
- if (depth>1) {
- target = branch.inject_into_dom(target,this);
- }
- var dropcount = 5;
- while (target.nodeName.toUpperCase() !== 'LI') {
- target = target.parentNode;
- if (dropcount==0 && moodle_cfg.developerdebug) {
- return alert("dropped because of exceeding dropcount");
- }
- dropcount--;
- }
- if (branch.haschildren && branch.mychildren && branch.mychildren.childNodes) {
- for (var i=0;i 0) {
- for (var i=0;i0) {
- for (var j=0;j");
- var commands = YAHOO.util.Dom.getElementsByClassName('commands', 'div', this.cachedcontent);
- var tabcommands = null;
- if (commands.length > 0) {
- tabcommands = commands[0];
- } else {
- tabcommands = document.createElement('div');
- YAHOO.util.Dom.addClass(tabcommands, 'commands');
- }
-
- if (YAHOO.util.Dom.hasClass(sideblocknode, 'block-region')) {
- var blocks = YAHOO.util.Dom.getElementsByClassName('sideblock', 'div', sideblocknode);
- if (blocks.length === 0) {
- YAHOO.moodle.navigation.sideblockwidth = YAHOO.util.Dom.getStyle(sideblocknode, 'width');
- YAHOO.util.Dom.setStyle(sideblocknode, 'width', '0px');
- }
- }
-
- if (YAHOO.moodle.navigation.tabpanel === null) {
- YAHOO.moodle.navigation.tabpanel = new navigation_tab_panel();
- }
- YAHOO.moodle.navigation.tabpanel.add_to_tab_panel(this.name, tabtitle, tabcontent, tabcommands);
- if (!this.skipsetposition) {
- set_user_preference('nav_in_tab_panel_'+this.name, 1);
- } else {
- this.skipsetposition = false;
- }
- return true;
-}
-/**
- * This function gets called from {@link navigation_tree.toggle_block_display()}
- * and is responsible for moving the block from the sidebar to the block position
- * @return {bool}
- */
-navigation_tree.prototype.move_to_block_position = function(e) {
-
- YAHOO.util.Event.stopEvent(e);
-
- if (this.sideblockwidth !== null) {
- YAHOO.util.Dom.setStyle(sideblocknode, 'width', this.sideblockwidth);
- this.sideblockwidth = null;
- }
-
- var placeholder = document.getElementById(this.name+'_content_placeholder');
- if (!placeholder || YAHOO.moodle.navigation.tabpanel == null) {
- return false;
- }
-
- if (YAHOO.moodle.navigation.tabpanel.showntab !== null) {
- YAHOO.moodle.navigation.tabpanel.hide_tab(e, YAHOO.moodle.navigation.tabpanel.showntab.tabname);
- }
-
- var tabcontent = YAHOO.moodle.navigation.tabpanel.get_tab_panel_contents(this.name);
- this.cachedcontent.appendChild(tabcontent);
- placeholder.parentNode.replaceChild(this.cachedcontent, placeholder);
-
- if (YAHOO.moodle.navigation.sideblockwidth !== null) {
- var sideblocknode = this.cachedcontent;
- while (sideblocknode && !YAHOO.util.Dom.hasClass(sideblocknode, 'block-region')) {
- sideblocknode = sideblocknode.parentNode;
- }
- if (YAHOO.util.Dom.hasClass(sideblocknode, 'block-region')) {
- YAHOO.util.Dom.setStyle(sideblocknode, 'width', YAHOO.moodle.navigation.sideblockwidth);
- }
- }
-
- var moveto = YAHOO.util.Dom.getElementsByClassName('moveto customcommand', 'a', this.cachedcontent);
- if (moveto.length > 0) {
- for (var i=0;i0) {
- for (var j=0;j 0 && YAHOO.env.ua.ie < 7) {
- YAHOO.util.Dom.setStyle(navbar, 'height', YAHOO.util.Dom.getViewportHeight()+'px');
- }
-
- var navbarcontrol = document.createElement('div');
- YAHOO.util.Dom.addClass(navbarcontrol, 'controls');
- var removeall = document.createElement('img');
- removeall.setAttribute('src', get_image_url('t/movetoblock', 'moodle'));
- removeall.setAttribute('title', mstr.moodle.moveallsidetabstoblock);
- removeall.setAttribute('alt', mstr.moodle.moveallsidetabstoblock);
- navbarcontrol.appendChild(removeall);
- navbar.appendChild(navbarcontrol);
-
- document.getElementsByTagName('body')[0].appendChild(navbar);
- navbar.appendChild(create_shadow(false, true, true, false));
- YAHOO.util.Dom.addClass(document.getElementsByTagName('body')[0], 'has_navigation_bar');
- this.navigationpanel = navbar;
- this.tabpanelexists = true;
- navbar.style.display = 'block';
-
- YAHOO.util.Event.addListener(removeall, 'click', move_all_sidetabs_to_block_position);
-
- return true;
-}
-/**
- * This removes the tab panel element from the page
- * @method remove_tab_panel
- * @return {bool}
- */
-navigation_tab_panel.prototype.remove_tab_panel = function () {
- var panel = document.getElementById('sidebarpopup');
- if (!panel) {
- return false;
- }
- this.tabpanel = null;
- panel.parentNode.removeChild(panel);
- this.tabpanelexists = false;
- this.navigationpanel = null;
- if (YAHOO.util.Dom.hasClass(document.getElementsByTagName('body')[0], 'has_navigation_bar')) {
- YAHOO.util.Dom.removeClass(document.getElementsByTagName('body')[0], 'has_navigation_bar')
- }
- return true;
-}
-/**
- * This function retrieves the content of a tab in the navigation tab panel
- * @method get_tab_panel_contents
- * @param {string} tabname The name of the tab
- * @return {element} The content element
- */
-navigation_tab_panel.prototype.get_tab_panel_contents = function(tabname) {
- remove_shadow(this.tabpanelelementcontents[tabname]);
- return this.tabpanelelementcontents[tabname];
-}
-/**
- * This function adds a tab to the navigation tab panel
- *
- * If you find that it takes a long time to make the initial transaction then I
- * would first check the time that set_user_preference is taking, during development
- * the code needed to be re-jigged because it was taking a very long time to execute
- *
- * @method add_to_tab_panel
- * @param {string} tabname The string name of the tab
- * @param {element} tabtitle The title of the tab
- * @param {element} tabcontent The content for the tab
- * @param {element} tabcommands The commands for the tab
- */
-navigation_tab_panel.prototype.add_to_tab_panel = function (tabname, tabtitle, tabcontent, tabcommands) {
- if (!this.tabpanelexists) {
- this.create_tab_panel();
- }
-
- var firsttab = (this.tabcount==0);
-
- var sidetab = document.createElement('div');
- sidetab.setAttribute('id', tabname+'_sidebarpopup');
- YAHOO.util.Dom.addClass(sidetab, 'sideblock_tab');
-
- if (firsttab) {
- YAHOO.util.Dom.addClass(sidetab, 'firsttab');
- }
- var sidetabtitle = document.createElement('div');
- sidetabtitle.appendChild(tabtitle);
- sidetabtitle.setAttribute('id', tabname+'_title');
- YAHOO.util.Dom.addClass(sidetabtitle, 'title');
- tabcontent.appendChild(create_shadow(true, true, true, false));
- sidetab.appendChild(sidetabtitle);
-
- if (tabcommands.childNodes.length>0) {
- tabcontent.appendChild(tabcommands);
- }
-
- this.navigationpanel.appendChild(sidetab);
-
- var position = YAHOO.util.Dom.getXY(sidetabtitle);
- position[0] += sidetabtitle.offsetWidth;
- if (YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 8) {
- position[0] -= 2;
- }
-
- this.tabpanels[tabname] = new YAHOO.widget.Panel('navigation_tab_panel_'+tabname, {
- close:false,
- draggable:false,
- constraintoviewport: false,
- underlay:"none",
- visible:false,
- monitorresize:false,
- /*context:[tabname+'_title','tl','tr',['configChanged','beforeShow','changeBody']],*/
- xy:position,
- autofillheight:'body'});
- this.tabpanels[tabname].showEvent.subscribe(this.resize_tab, this, true);
- this.tabpanels[tabname].setBody(tabcontent);
- this.tabpanels[tabname].render(this.navigationpanel);
-
- this.tabpanelelementnames[this.tabpanelelementnames.length] = tabname;
- this.tabpanelelementcontents[tabname] = tabcontent;
- this.tabcount++;
-
- YAHOO.util.Event.addListener(sidetab, "mouseover", this.show_tab, tabname, this);
-}
-/**
- * This function handles checking the size, and positioning of the navigaiton
- * panel when expansion events occur, or when the panel is shown, or if the window
- * is resized
- *
- * There are undoubtably some bugs in this little bit of code. For one it relies
- * on the padding set in CSS by the YUI:sam skin, if you are hitting a problem
- * whereby the navigation extends beyond its border, or doesn't fill to its own
- * border check the value assigned to padding for the panel body `.yui_panel .bd`
- *
- * @return {bool}
- */
-navigation_tab_panel.prototype.resize_tab = function () {
- var screenheight = YAHOO.util.Dom.getViewportHeight();
- var tabheight = parseInt(this.tabpanels[this.showntab.tabname].body.offsetHeight);
- var tabtop = parseInt(this.tabpanels[this.showntab.tabname].cfg.getProperty('y'));
- var titletop = YAHOO.util.Dom.getY(this.showntab.tabname+'_title');
- var scrolltop = (document.all)?document.body.scrollTop:window.pageYOffset;
- // This makes sure that the panel is the same height as the tab title to
- // begin with
- if (tabtop > (10+scrolltop) && tabtop > (titletop+scrolltop)) {
- this.tabpanels[this.showntab.tabname].cfg.setProperty('y', titletop+scrolltop);
- }
-
- // This makes sure that if the panel is big it is moved up to ensure we don't
- // have wasted space above the panel
- if ((tabtop+tabheight)>(screenheight+scrolltop) && tabtop > 10) {
- tabtop = (screenheight-tabheight-10);
- if (tabtop<10) {
- tabtop = 10;
- }
- this.tabpanels[this.showntab.tabname].cfg.setProperty('y', tabtop+scrolltop);
- }
-
- // This makes the panel constrain to the screen's height if the panel is big
- if (tabtop <= 10 && ((tabheight+tabtop*2) > screenheight || YAHOO.util.Dom.hasClass(this.tabpanels[this.showntab.tabname].body, 'oversized_content'))) {
- this.tabpanels[this.showntab.tabname].cfg.setProperty('height', (screenheight-39));
- YAHOO.util.Dom.setStyle(this.tabpanels[this.showntab.tabname].body, 'height', (screenheight-59)+'px');
- YAHOO.util.Dom.addClass(this.tabpanels[this.showntab.tabname].body, 'oversized_content');
- }
-}
-/**
- * This function sets everything up for the show even and then calls the panel's
- * show event once we are happy.
- *
- * This function is responsible for closing any open panels, removing show events
- * so we don't refresh unnessecarily and adding events to trap closing, and resizing
- * events
- *
- * @param {event} e The event that fired to get us here
- * @param {string} tabname The tabname to open
- * @return {bool}
- */
-navigation_tab_panel.prototype.show_tab = function (e, tabname) {
- if (this.showntab !== null) {
- this.hide_tab(e, this.showntab.tabname);
- }
- this.showntab = {event:e, tabname:tabname};
- this.tabpanels[tabname].show(e, this.tabpanel);
- YAHOO.util.Dom.addClass(tabname+'_title', 'active_tab');
- YAHOO.util.Event.removeListener(tabname+'_sidebarpopup', "mouseover", this.show_tab);
- YAHOO.util.Event.addListener('navigation_tab_panel_'+tabname, "click", function (e){this.preventhide = true}, this, true);
- YAHOO.util.Event.addListener(tabname+'_sidebarpopup', "click", this.hide_tab, tabname, this);
- YAHOO.util.Event.addListener(window, 'resize', this.resize_tab, this, true);
- YAHOO.util.Event.addListener(document.body, "click", this.hide_tab, tabname, this);
- return true;
-}
-/**
- * This function closes the open tab and sets the listeners up to handle the show
- * event again
- *
- * @param {event} e The event that fired to get us here
- * @param {string} tabname The tabname to close
- * @return {bool}
- */
-navigation_tab_panel.prototype.hide_tab = function(e, tabname) {
- if (this.preventhide===true) {
- this.preventhide = false;
- } else {
- this.showntab = null;
- YAHOO.util.Event.addListener(tabname+'_sidebarpopup', "mouseover", this.show_tab, tabname, this);
- YAHOO.util.Event.removeListener(window, 'resize', this.resize_tab);
- YAHOO.util.Event.removeListener(document.body, "click", this.hide_tab);
- YAHOO.util.Dom.removeClass(tabname+'_title', 'active_tab');
- this.tabpanels[tabname].hide(e, this.tabpanel);
- }
-}
-/**
- * This function removes a tab from the navigation tab panel
- * @param {string} tabname
- * @return {bool}
- */
-navigation_tab_panel.prototype.remove_from_tab_panel = function(tabname) {
- var tab = document.getElementById(tabname+'_sidebarpopup');
- if (!tab) {
- return false;
- }
- tab.parentNode.removeChild(tab);
- this.tabpanels[tabname].destroy();
- this.tabpanels[tabname] = null;
- this.tabcount--;
- if (this.tabcount === 0) {
- this.remove_tab_panel();
- }
- return true;
-}
-
-/**
- * Global navigation tree branch object used to parse an XML branch
- * into a usable object, and then to inject it into the DOM
- * @class navigation_tree_branch
- * @constructor
- */
-function navigation_tree_branch(treename) {
- this.treename = treename;
- this.myname = null;
- this.mytitle = null;
- this.myclass = null;
- this.myid = null;
- this.mykey = null;
- this.mytype = null;
- this.mylink = null;
- this.myicon = null;
- this.myexpandable = null;
- this.expansionceiling = null;
- this.myhidden = false;
- this.haschildren = false;
- this.mychildren = false;
-}
-/**
- * This function populates the object from an XML branch
- * @param {xmlnode} branch The XML branch to turn into an object
- */
-navigation_tree_branch.prototype.load_from_xml_node = function (branch) {
- this.myname = null;
- this.mytitle = branch.getAttribute('title');
- this.myclass = branch.getAttribute('class');
- this.myid = branch.getAttribute('id');
- this.mylink = branch.getAttribute('link');
- this.myicon = branch.getAttribute('icon');
- this.mykey = branch.getAttribute('key');
- this.mytype = branch.getAttribute('type');
- this.myexpandable = branch.getAttribute('expandable');
- this.expansionceiling = branch.getAttribute('expansionceiling');
- this.myhidden = (branch.getAttribute('hidden')=='true');
- this.haschildren = (branch.getAttribute('haschildren')=='true');
-
- if (this.myid && this.myid.match(/^expandable_branch_\d+$/)) {
- YAHOO.moodle.navigation.expandablebranchcount++;
- this.myid = 'expandable_branch_'+YAHOO.moodle.navigation.expandablebranchcount;
- }
-
- for (var i=0; i')));
- } else {
- var branchlink = document.createElement('a');
- branchlink.setAttribute('title', this.mytitle);
- branchlink.setAttribute('href', this.mylink);
- if (branchicon !== false) {
- branchlink.appendChild(branchicon);
- }
- branchlink.appendChild(document.createTextNode(this.myname.replace(/\n/g, '
')));
- if (this.myhidden) {
- YAHOO.util.Dom.addClass(branchlink, 'dimmed');
- }
- branchp.appendChild(branchlink);
- }
- branchli.appendChild(branchp);
- element.appendChild(branchli);
- return branchli;
-}
-
-/**
- * Creates a new JS instance of a global navigation tree and kicks it into gear
- * @param {string} treename The name of the tree
- */
-function setup_new_navtree(treename) {
- var key = YAHOO.moodle.navigation.treecollection.length;
- YAHOO.moodle.navigation.treecollection[key] = new navigation_tree(treename, key);
- YAHOO.moodle.navigation.treecollection[key].initialise();
-}
-
-/**
- * This function moves all navigation tree instances that are currently
- * displayed in the sidebar back into their block positions
- */
-function move_all_sidetabs_to_block_position(e) {
- for (var i=0; i 0 && YAHOO.env.ua.ie < 7) {
- // IE6 just doest like my shadow...
+ if (top) shadow.append(Y.Node.create(''));
+ if (right) shadow.append(Y.Node.create(''));
+ if (bottom) shadow.append(Y.Node.create(''));
+ if (left) shadow.append(Y.Node.create(''));
+ if (top && left) shadow.append(Y.Node.create(''));
+ if (top && right) shadow.append(Y.Node.create(''));
+ if (bottom && left) shadow.append(Y.Node.create(''));
+ if (bottom && right) shadow.append(Y.Node.create(''));
return shadow;
+ },
+ /**
+ * This function removes any shadows that a node and its children may have
+ * @param {Y.Node} node The element to remove the shadow from
+ * @return {bool}
+ */
+ remove : function(node) {
+ node.all('.divshadow').remove();
}
- var createShadowDiv = function(cname) {
- var shadowdiv = document.createElement('div');
- YAHOO.util.Dom.addClass(shadowdiv, cname);
- if (YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 7) {
- // IE version less than 7 doesnt support alpha
- YAHOO.util.Dom.setStyle(shadowdiv, 'opacity', 0.3);
- }
- return shadowdiv;
- }
- if (top) shadow.appendChild(createShadowDiv('shadow_top'));
- if (right) shadow.appendChild(createShadowDiv('shadow_right'));
- if (bottom) shadow.appendChild(createShadowDiv('shadow_bottom'));
- if (left) shadow.appendChild(createShadowDiv('shadow_left'));
- if (top && left) shadow.appendChild(createShadowDiv('shadow_top_left'));
- if (bottom && left) shadow.appendChild(createShadowDiv('shadow_bottom_left'));
- if (top && right) shadow.appendChild(createShadowDiv('shadow_top_right'));
- if (bottom && right) shadow.appendChild(createShadowDiv('shadow_bottom_right'));
- return shadow;
-}
-/**
- * This function removes any shadows that a node and its children may have
- * @param {element} el The element to remove the shadow from
- * @return {bool}
- */
-function remove_shadow(el) {
- var shadows = YAHOO.util.Dom.getElementsByClassName('divshadow', 'div', el);
- if (shadows == null || shadows.length == 0) return true;
- for (var i=0;i