# This patch file was generated by NetBeans IDE
# This patch can be applied using context Tools: Apply Diff Patch action on respective folder.
# It uses platform neutral UTF-8 encoding.
# Above lines and this line are ignored by the patching process.
Index: moodle/blocks/blocks.js
--- moodle/blocks/blocks.js No Base Revision
+++ moodle/blocks/blocks.js Locally New
@@ -0,0 +1,549 @@
+// 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 <http://www.gnu.org/licenses/>.
+
+/**
+ * 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', function() {
+        var block = new blocks.genericblock(uid);
+        block.init();
+    });
+}
+
+/**
+ * @namespace
+ */
+blocks.navbar = {
+    count:0,        // The number of navbar items through the page life
+    exists:false,   // True if the navbar exists
+    items:[],       // An array of navbar items
+    node:null,      // The YUI node for the navbar itself
+    strings:{
+        togglesidetabdisplay : '[[togglesidetabdisplay]]',
+        toggleblockdisplay : '[[toggleblockdisplay]]'
+    },
+    /**
+     * Configuration parameters used during the initialisation and setup
+     * of navbar and navbar 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 navbar
+        orientation:'vertical',             // vertical || horizontal determines if we change the title
+        display:{
+            spacebeforefirsttab: 10         // Space between the top of the navbar and the first tab
+        },
+        css: {
+            navbar:'navigation_bar',        // CSS Class applied to the navbar box
+            navbarspacer:'navbarspacer',    // CSS class applied to the navbarspacer
+            controls:'controls',            // CSS class applied to the controls box
+            body:'has_navigation_bar',      // CSS class added to the body when there is a navbar
+            tabbox:'sideblock_tab',         // CSS class added to each tab in the navbar
+            tabtitle:'title',               // CSS class added to the tabtitle in each navbar
+            tabactive:'active_tab'          // CSS class added to the active tab
+        },
+        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 navbar item into the navbar
+     * @function
+     */
+    add:function(item) {
+        item.id = this.count;
+        this.count++;
+        this.items[item.id] = item;
+        this.draw();
+        this.items[item.id].draw();
+    },
+    /**
+     * Draws the navbar
+     * @function
+     */
+    draw:function() {
+        if (this.node !== null) {
+            return true;
+        }
+        this.node = Y.Node.create('<div id="navbar" class="'+blocks.navbar.cfg.css.navbar+'"></div>');
+
+        this.node.appendChild(Y.Node.create('<div class="'+blocks.navbar.cfg.css.navbarspacer+'" style="height:'+blocks.navbar.cfg.display.spacebeforefirsttab+'px"></div>'));
+        if (Y.UA.ie > 0 && Y.UA.ie < 7) {
+            this.node.setStyle('height', this.node.get('winHeight')+'px');
+        }
+
+        var navbarcontrol = Y.Node.create('<div class="'+blocks.navbar.cfg.css.controls+'"></div>');
+        var removeall = Y.Node.create('<img src="'+get_image_url('t/movetoblock', 'moodle')+'" alt="'+mstr.moodle.moveallsidetabstoblock+'" title="'+mstr.moodle.moveallsidetabstoblock+'" />');
+        removeall.on('removeall|click', this.remove_all, this);
+        navbarcontrol.appendChild(removeall);
+        this.node.appendChild(navbarcontrol);
+
+        Y.one(document.body).appendChild(this.node);
+        Y.one(document.body).addClass(blocks.navbar.cfg.css.body);
+        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.count--;
+        if (this.count===0) {
+            this.items = [];
+            this.node.remove();
+            this.node = null;
+        }
+    },
+    /**
+     * 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;
+        }
+        this.items = [];
+        this.node.remove();
+        this.node = null;
+    },
+    /**
+     * 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();
+        }
+    },
+    /**
+     * 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('<div class="commands"></div>');
+                if (node.one('.header .title')) {
+                    node.one('.header .title').append(commands);
+                }
+            }
+            commands.append(Y.Node.create('<a class="moveto customcommand requiresjs" href="http://sam.moodle.local/m20dev1/?dock=5"><img class="action-icon" alt="Move to block position" src="http://sam.moodle.local/m20dev1/theme/image.php?theme=anomaly&image=t/movetosidetab"/></a>'));
+            commands.all('a.moveto').on('movetonavbar|click', this.move_to_navbar, this);
+
+            var customcommands = node.all('.customcommand');
+            if (customcommands.size() > 0) {
+                customcommands.each(function(){
+                    this.remove();
+                    commands.appendChild(this);
+                });
+            }
+
+            if (node.hasClass('sideblock_js_sidebarpopout')) {
+                node.removeClass('sideblock_js_sidebarpopout')
+                this.skipsetposition = true;
+                this.move_to_navbar();
+            }
+        },
+
+        /**
+         * This function is reponsible for moving a block from the page structure onto the
+         * navbar
+         * @param {event}
+         */
+        move_to_navbar : function(e) {
+            if (e) {
+                e.halt(true);
+            }
+
+            var node = Y.one('#inst'+this.id);
+            var navcontent = 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/movetoblock', 'moodle'));
+                        movetoimg.setAttribute('alt', blocks.navbar.strings.toggleblockdisplay);
+                        movetoimg.setAttribute('title', blocks.navbar.strings.toggleblockdisplay);
+                    }, this);
+                }
+            }, this);
+
+            var placeholder = Y.Node.create('<div id="content_placeholder_'+this.id+'"></div>');
+            node.replace(Y.Node.getDOMNode(placeholder));
+            node = null;
+
+            this.resize_block_space(placeholder);
+
+            var navtitle = Y.Node.getDOMNode(this.cachedcontentnode.one('.title h2')).cloneNode(true);
+            navtitle.innerHTML = navtitle.innerHTML.replace(/([a-zA-Z0-9])/g, "$1<br />");
+
+            var commands = this.cachedcontentnode.all('.title .commands');
+            var navcommands = Y.Node.create('<div class="commands"></div>');
+            if (commands.size() > 0) {
+                navcommands = commands.item(0);
+            }
+
+            var navbaritem = new blocks.navbar.item(this.id, navtitle, navcontent, navcommands);
+            navbaritem.on('navbaritem:drawcomplete', function(e){
+                // check the contents block [editing=off]
+                this.contents.all('a.moveto').on('returntoblock|click', function(e){
+                    e.halt();
+                    blocks.navbar.remove(this.id)
+                }, this);
+                // check the commands block [editing=on]
+                this.commands.all('a.moveto').on('returntoblock|click', function(e){
+                    e.halt();
+                    blocks.navbar.remove(this.id)
+                }, this);
+            }, navbaritem);
+            navbaritem.on('navbar:itemremoved', this.return_to_block, this, navbaritem);
+            blocks.navbar.add(navbaritem);
+
+            if (!this.skipsetposition) {
+                set_user_preference('block_in_navbar_'+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 navbar
+         */
+        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 navbar and puts it back into the page
+         * structure.
+         * @param {blocks.navbar.class.item}
+         */
+        return_to_block : function(navbaritem) {
+            var placeholder = Y.one('#content_placeholder_'+this.id);
+            this.cachedcontentnode.appendChild(navbaritem.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('movetonavbar|click', this.move_to_navbar, this);
+                if (moveto.hasClass('customcommand')) {
+                    moveto.all('img').each(function(movetoimg){
+                        movetoimg.setAttribute('src', get_image_url('t/movetosidetab', 'moodle'));
+                        movetoimg.setAttribute('alt', blocks.navbar.strings.togglesidetabdisplay);
+                        movetoimg.setAttribute('title', blocks.navbar.strings.togglesidetabdisplay);
+                    }, 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('block_in_navbar_'+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('navbaritem:drawstart', {prefix:'navbaritem'});
+            this.publish('navbaritem:drawcomplete', {prefix:'navbaritem'});
+            this.publish('navbaritem:showstart', {prefix:'navbaritem'});
+            this.publish('navbaritem:showcomplete', {prefix:'navbaritem'});
+            this.publish('navbaritem:hidestart', {prefix:'navbaritem'});
+            this.publish('navbaritem:hidecomplete', {prefix:'navbaritem'});
+            this.publish('navbaritem:resizestart', {prefix:'navbaritem'});
+            this.publish('navbaritem:resizecomplete', {prefix:'navbaritem'});
+            this.publish('navbaritem:itemremoved', {prefix:'navbaritem'});
+        },
+
+        /**
+         * This function draws the item on the navbar
+         */
+        draw : function() {
+            this.fire('navbaritem:drawstart');
+            var navtabtitle = Y.Node.create('<div id="navbar_item_'+this.id+'_title" class="'+this.cfg.css.tabtitle+'"></div>');
+            navtabtitle.append(this.title);
+            var navtab = Y.Node.create('<div id="navbar_item_'+this.id+'_sidebarpopup" class="'+this.cfg.css.tabbox+'"></div>');
+            if (blocks.navbar.count === 1) {
+                navtab.addClass('firsttab');
+            }
+            navtab.append(navtabtitle);
+            if (this.commands.hasChildNodes) {
+                this.contents.appendChild(this.commands);
+            }
+            blocks.navbar.node.append(navtab);
+
+            var position = navtabtitle.getXY();
+            position[0] += parseInt(navtabtitle.get('offsetWidth'));
+            if (YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 8) {
+                position[0] -= 2;
+            }
+            this.panel = new YAHOO.widget.Panel('navigation_tab_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.navbar.node);
+            navtab.on('showtab|mouseover', this.show, this);
+            this.fire('navbaritem:drawcomplete');
+        },
+        /**
+         * This function removes the node and destroys it's bits
+         */
+        remove : function (e) {
+            this.hide(e);
+            Y.one('#navbar_item_'+this.id+'_sidebarpopup').remove();
+            this.panel.destroy();
+            this.fire('navbar:itemremoved');
+        },
+        /**
+         * This function toggles makes the item active and shows it
+         * @param {event}
+         */
+        show : function(e) {
+            blocks.navbar.hide_all();
+            this.fire('navbaritem:showstart');
+            this.panel.show(e, this);
+            this.active = true;
+            Y.one('#navbar_item_'+this.id+'_title').addClass(this.cfg.css.tabactive);
+            Y.detach('mouseover', this.show, Y.one('#navbar_item_'+this.id+'_sidebarpopup'));
+            Y.one('#navigation_tab_panel_'+this.id).on('navbarpreventhide|click', function(){this.preventhide=true;}, this);
+            Y.one('#navbar_item_'+this.id+'_sidebarpopup').on('navbarhide|click', this.hide, this);
+            Y.get(window).on('navbarresize|resize', this.resize_panel, this);
+            Y.get(document.body).on('navbarhide|click', this.hide, this);
+            this.fire('navbaritem: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('navbaritem:hidestart');
+                this.active = false;
+                Y.one('#navbar_item_'+this.id+'_title').removeClass(this.cfg.css.tabactive);
+                Y.one('#navbar_item_'+this.id+'_sidebarpopup').on('showtab|mouseover', this.show, this);
+                Y.get(window).detach('navbarresize|resize');
+                Y.get(document.body).detach('navbarhide|click');
+                this.panel.hide(e, this);
+                this.fire('navbaritem: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('navbaritem: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('#navbar_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 tab 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<buffer) {
+                    paneltop = buffer;
+                }
+                this.panel.cfg.setProperty('y', paneltop+scrolltop);
+            }
+
+            // This makes the panel constrain to the screen's height if the panel is big
+            if (paneltop <= buffer && ((panelheight+paneltop*2) > 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('navbaritem: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.navbar.abstract_block_class.name;
+blocks.genericblock.prototype.cachedcontentnode =       blocks.navbar.abstract_block_class.cachedcontentnode;
+blocks.genericblock.prototype.blockspacewidth =         blocks.navbar.abstract_block_class.blockspacewidth;
+blocks.genericblock.prototype.skipsetposition =         blocks.navbar.abstract_block_class.skipsetposition;
+/** Methods **/
+blocks.genericblock.prototype.init =                    blocks.navbar.abstract_block_class.init;
+blocks.genericblock.prototype.move_to_navbar =          blocks.navbar.abstract_block_class.move_to_navbar;
+blocks.genericblock.prototype.resize_block_space =      blocks.navbar.abstract_block_class.resize_block_space;
+blocks.genericblock.prototype.return_to_block =         blocks.navbar.abstract_block_class.return_to_block;
+
+/**
+ * This class represents an item in the navbar
+ * @class item
+ * @constructor
+ */
+blocks.navbar.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.navbar.item.prototype.id = blocks.navbar.item.prototype.id;
+blocks.navbar.item.prototype.name = blocks.navbar.item.prototype.name;
+blocks.navbar.item.prototype.title = blocks.navbar.item.prototype.title;
+blocks.navbar.item.prototype.contents = blocks.navbar.item.prototype.contents;
+blocks.navbar.item.prototype.commands = blocks.navbar.item.prototype.commands;
+blocks.navbar.item.prototype.events = blocks.navbar.item.prototype.events;
+blocks.navbar.item.prototype.active = blocks.navbar.item.prototype.active;
+blocks.navbar.item.prototype.panel = blocks.navbar.item.prototype.panel;
+blocks.navbar.item.prototype.preventhide = blocks.navbar.item.prototype.preventhide;
+blocks.navbar.item.prototype.cfg = blocks.navbar.cfg;
+/** Methods **/
+blocks.navbar.item.prototype.init_events =             blocks.navbar.abstract_item_class.init_events;
+blocks.navbar.item.prototype.draw =             blocks.navbar.abstract_item_class.draw;
+blocks.navbar.item.prototype.remove =           blocks.navbar.abstract_item_class.remove;
+blocks.navbar.item.prototype.show =             blocks.navbar.abstract_item_class.show;
+blocks.navbar.item.prototype.hide =             blocks.navbar.abstract_item_class.hide;
+blocks.navbar.item.prototype.resize_panel =     blocks.navbar.abstract_item_class.resize_panel;
+
+YUI({base: moodle_cfg.yui3loaderBase}).use('event-custom', 'node', function(Y){
+    // Give the navbar item class the event properties/methods
+    Y.augment(blocks.navbar.item, Y.EventTarget);
+});
Index: moodle/blocks/global_navigation_tree/block_global_navigation_tree.php
--- moodle/blocks/global_navigation_tree/block_global_navigation_tree.php Base (1.17)
+++ moodle/blocks/global_navigation_tree/block_global_navigation_tree.php Locally Modified (Based On 1.17)
@@ -79,6 +79,12 @@
         return true;
     }
 
+    function get_required_javascript() {
+        $this->_initialise_navbar();
+        $this->page->requires->js('blocks/global_navigation_tree/navigation.js');
+        user_preference_allow_ajax_update('block_in_navbar_'.$this->instance->id, PARAM_INT);
+    }
+
     /**
      * Gets the content for this block by grabbing it from $this->page
      */
@@ -149,14 +155,11 @@
         // 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 +168,6 @@
 
         $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,7 +188,7 @@
         $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('block_in_navbar_'.$this->instance->id, 0);
         }
 
         if (!empty($this->config->enablehoverexpansion) && $this->config->enablehoverexpansion == 'yes') {
Index: moodle/blocks/global_navigation_tree/navigation.js
--- moodle/blocks/global_navigation_tree/navigation.js No Base Revision
+++ moodle/blocks/global_navigation_tree/navigation.js Locally New
@@ -0,0 +1,310 @@
+// 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 <http://www.gnu.org/licenses/>.
+
+/**
+ * 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:[],
+    /** The width of the sideblock */
+    blockspacewidth:null,
+    /**
+     * @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() {
+            var key = blocks.navigation.treecollection.length;
+            properties = properties || {'instance':uid};
+            //var properties = window[treename] || null;
+            blocks.navigation.treecollection[key] = new blocks.navigation.classes.tree(uid, key, properties);
+        });
+    }
+};
+
+/**
+ * @class tree
+ * @constructor
+ * @base blocks.navbar.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;
+    this.togglesidetabdisplay = '[[togglesidetabdisplay]]';
+    this.toggleblockdisplay = '[[toggleblockdisplay]]';
+    if (properties) {
+        if (properties.expansions) {
+            this.expansions = properties.expansions;
+        }
+        if (properties.instance) {
+            this.instance = properties.instance;
+        }
+        if (properties.togglesidetabdisplay) {
+            this.togglesidetabdisplay = properties.togglesidetabdisplay;
+        }
+        if (properties.toggleblockdisplay) {
+            this.toggleblockdisplay = properties.toggleblockdisplay;
+        }
+    }
+
+    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('sideblock_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.navbar.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('<ul></ul>');
+        target.appendChild(childrenul);
+    } else {
+        childrenul = branch.inject_into_dom(target);
+    }
+
+    if (childrenul) {
+        for (var i=0;i<branch.children.childNodes.length;i++) {
+            this.add_branch(branch.children.childNodes[i], childrenul, depth+1);
+        }
+    }
+    return true;
+}
+/**
+ * Toggle a branch as expanded or collapsed
+ */
+blocks.navigation.classes.tree.prototype.toggleexpansion = function(e) {
+    e.target.ancestor('LI').toggleClass('collapsed');
+    blocks.navbar.resize();
+}
+
+/**
+ * This class represents a branch for a tree
+ * @class tree
+ * @constructor
+ */
+blocks.navigation.classes.branch = function(tree) {
+    this.tree = tree;
+    this.name = null;
+    this.title = null;
+    this.classname = null;
+    this.id = null;
+    this.key = null;
+    this.type = null;
+    this.link = null;
+    this.icon = null;
+    this.expandable = null;
+    this.expansionceiling = null;
+    this.hidden = false;
+    this.haschildren = false;
+    this.children = false;
+}
+/**
+ * Constructs a branch from XML
+ */
+blocks.navigation.classes.branch.prototype.construct_from_xml = function(xml) {
+    this.title = xml.getAttribute('title');
+    this.classname = xml.getAttribute('class');
+    this.id = xml.getAttribute('id');
+    this.link = xml.getAttribute('link');
+    this.icon = xml.getAttribute('icon');
+    this.key = xml.getAttribute('key');
+    this.type = xml.getAttribute('type');
+    this.expandable = xml.getAttribute('expandable');
+    this.expansionceiling = xml.getAttribute('expansionceiling');
+    this.hidden = (xml.getAttribute('hidden')=='true');
+    this.haschildren = (xml.getAttribute('haschildren')=='true');
+
+    if (this.id && this.id.match(/^expandable_branch_\d+$/)) {
+        blocks.navigation.expandablebranchcount++;
+        this.id = 'expandable_branch_'+blocks.navigation.expandablebranchcount;
+    }
+
+    for (var i=0; i<xml.childNodes.length;i++) {
+        var node = xml.childNodes[i];
+        switch (node.nodeName.toLowerCase()) {
+            case 'name':
+                this.name = node.firstChild.nodeValue;
+                break;
+            case 'children':
+                this.children = node;
+        }
+    }
+}
+/**
+ * Injects a branch into the tree at the given location
+ */
+blocks.navigation.classes.branch.prototype.inject_into_dom = function(element) {
+
+    var branchli = Y.Node.create('<li></li>');
+    var branchp = Y.Node.create('<p class="tree_item"></p>');
+
+    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('<img src="'+this.icon+'" alt="" />');
+        this.name = ' '+this.name;
+    }
+    if (this.link === null) {
+        if (branchicon) {
+            branchp.appendChild(branchicon);
+        }
+        branchp.append(this.name.replace(/\n/g, '<br />'));
+    } else {
+        var branchlink = Y.Node.create('<a title="'+this.title+'" href="'+this.link+'">'+this.name.replace(/\n/g, '<br />')+'</a>');
+        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('<ul></ul>');
+        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 navbar block properties
+    Y.augment(blocks.navigation.classes.tree, blocks.genericblock);
+});
Index: moodle/blocks/moodleblock.class.php
--- moodle/blocks/moodleblock.class.php Base (1.139)
+++ moodle/blocks/moodleblock.class.php Locally Modified (Based On 1.139)
@@ -113,6 +113,8 @@
 
     var $cron          = NULL;
 
+    static $navbarinitialised = false;
+
 /// Class Functions
 
     /**
@@ -541,11 +543,15 @@
      * @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('block_in_navbar_'.$this->instance->id, 0)) {
+            $attributes['class'] .= ' sideblock_js_sidebarpopout';
     }
+        return $attributes;
+    }
 
     /**
      * Set up a particular instance of this class given data from the block_insances
@@ -566,8 +572,17 @@
         }
         $this->page = $page;
         $this->specialization();
+        $this->get_required_javascript();
     }
 
+    function get_required_javascript() {
+        if ($this->instance_can_dock_with_navbar()) {
+            $this->_initialise_navbar();
+            $this->page->requires->js_function_call('blocks.setup_generic_block', array($this->instance->id))->on_dom_ready();
+            user_preference_allow_ajax_update('block_in_navbar_'.$this->instance->id, PARAM_INT);
+        }
+    }
+
     /**
      * This function is called on your subclass right after an instance is loaded
      * Use this function to act on instance data just after it's loaded and before anything else is done
@@ -728,6 +743,21 @@
     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_navbar() {
+        return true;
+    }
+
+    public function _initialise_navbar() {
+        if (!self::$navbarinitialised) {
+            $this->page->requires->js('blocks/blocks.js');
+            $this->page->requires->data_for_js('blocks.navbar.strings.togglesidetabdisplay', get_string('togglesidetabdisplay', get_class($this)));
+            $this->page->requires->data_for_js('blocks.navbar.strings.toggleblockdisplay', get_string('togglesidetabdisplay', get_class($this)));
+            self::$navbarinitialised = true;
+        }
+        
+    }
+
     /** @callback callback functions for comments api */
     public static function comment_template($options) {
         $ret = <<<EOD
Index: moodle/blocks/settings_navigation_tree/block_settings_navigation_tree.php
--- moodle/blocks/settings_navigation_tree/block_settings_navigation_tree.php Base (1.13)
+++ moodle/blocks/settings_navigation_tree/block_settings_navigation_tree.php Locally Modified (Based On 1.13)
@@ -39,7 +39,6 @@
     /** @var string */
     public static $navcount;
     public $blockname = null;
-    public $id = null;
     /** @var bool */
     protected $contentgenerated = false;
     /** @var bool|null */
@@ -78,6 +77,13 @@
         return true;
     }
 
+    function get_required_javascript() {
+        $this->_initialise_navbar();
+        $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('block_in_navbar_'.$this->instance->id, PARAM_INT);
+    }
+
     /**
      * Gets the content for this block by grabbing it from $this->page
      */
@@ -110,17 +116,6 @@
             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,19 +142,8 @@
 
             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;
             }
-        }
 
         $this->contentgenerated = true;
         return true;
@@ -170,7 +154,7 @@
 
         // 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('block_in_navbar_'.$this->instance->id, 0);
         }
 
         if (!empty($this->config->enablehoverexpansion) && $this->config->enablehoverexpansion == 'yes') {
Index: moodle/lib/ajax/ajaxlib.php
--- moodle/lib/ajax/ajaxlib.php Base (1.100)
+++ moodle/lib/ajax/ajaxlib.php Locally Modified (Based On 1.100)
@@ -243,7 +243,7 @@
      */
     public function yui3_lib($libname) {
         if ($this->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 @@
      * @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,10 +602,17 @@
         $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 .= <<<EOD
+    Y = YUI({
+        base: moodle_cfg.yui3loaderBase
+    }).use('node-base', function(Y) {
+        Y.on('domready', function() {
+        $ondomreadyjs
+        });
+    });
+EOD;
+
         $output .= ajax_generate_script_tag($js);
 
         return $output;
Index: moodle/theme/base/config.php
--- moodle/theme/base/config.php Base (1.6)
+++ moodle/theme/base/config.php Locally Modified (Based On 1.6)
@@ -150,5 +150,5 @@
 );
 
 /** List of javascript files that need to included on each page */
-$THEME->javascripts = array('navigation');
-//$THEME->javascripts_footer = array();
+$THEME->javascripts = array();
+$THEME->javascripts_footer = array('navigation');
Index: moodle/theme/base/javascript/navigation.js
--- moodle/theme/base/javascript/navigation.js Base (1.1)
+++ moodle/theme/base/javascript/navigation.js Locally Modified (Based On 1.1)
@@ -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;
+            }
+        }
+    }
+    
+}
Index: moodle/theme/experiment/config.php
--- moodle/theme/experiment/config.php Base (1.1)
+++ moodle/theme/experiment/config.php Locally Modified (Based On 1.1)
@@ -39,6 +39,7 @@
 $THEME->sheets = array(
     'core',
     'block_calendar_month',
+    'navigation'
 );
 
 $THEME->editor_sheets = array();
Index: moodle/theme/experiment/style/navigation.css
--- moodle/theme/experiment/style/navigation.css No Base Revision
+++ moodle/theme/experiment/style/navigation.css Locally New
@@ -0,0 +1,70 @@
+/** Core overrides **/
+body.has_navigation_bar {margin-left:30px;}
+
+/** YUI overrides **/
+.yui-skin-sam .yui-panel .bd, .yui-skin-sam .yui-panel .ft {
+    background-color:#F9FBFE;
+}
+
+/** Navbar **/
+.navbar {clear: both;padding: 2px 5px 2px 5px;background-color: #7fa5dd;min-height:1.7em;}
+.navbar .breadcrumb {float:left;}
+.navbar .navbutton {float:right;}
+.navbar .navbutton div, .navbar .navbutton form { display:inline;}
+
+/** Navigation and settings block **/
+.block_tree {list-style: none;padding-left:0px;margin:0px;text-align: left;overflow-x:auto;overflow-y:visible;}
+.block_tree ul {margin-left: 0px;padding-left:16px;}
+.block_tree li {list-style: none;}
+.block_tree .current_branch {background-color:#A9D7FA;}
+.block_tree .tree_item { white-space:nowrap; padding-left: 16px; margin:3px 0px;}
+.block_tree .tree_item.note { white-space:normal; font-size:90%;}
+.block_tree .tree_item.branch, .block_tree .tree_item.emptybranch {background-image: url([[pix:t/expanded]]);background-position: center left;background-repeat: no-repeat;}
+.block_tree .root_node.leaf {padding-left:0px;}
+.jsenabled .sideblock_js_sidebarpopout, .jsenabled .block_tree .collapsed ul {display: none;}
+.jsenabled .block_tree .tree_item.branch {cursor:pointer;}
+.jsenabled .block_tree .collapsed .tree_item.branch {background-image: url([[pix:t/collapsed]]);}
+.jsenabled .block_tree .tree_item.emptybranch {background-image: url([[pix:t/collapsed_empty]]);background-position: center left;background-repeat: no-repeat;}
+.block_tree_box .requiresjs {display:none;}
+.jsenabled .block_tree_box .requiresjs {display:inline;}
+
+/* This CSS is for the side panel */
+.navigation_bar {width:30px;position:fixed;top:0px;left:0px;height:100%;border-right:1px solid #7FA5DD;border-bottom:1px solid #7FA5DD;background-color:#F9FBFE;}
+.navigation_bar .sideblock_tab {background-color:#FFFFFF;}
+.navigation_bar .sideblock_tab .firsttab {margin-top:1em;}
+.navigation_bar .sideblock_tab .title {border-bottom:1px solid #7FA5DD;border-top:1px solid #D5E1F4;cursor:pointer;}
+.navigation_bar .sideblock_tab .title.active_tab {background-color:#D5E1F4;}
+.navigation_bar .sideblock_tab .title h2 {font-size:0.8em;line-height:100%;text-transform:uppercase;text-align:center;margin:12px 0px;}
+.navigation_bar .block_tree .current_branch {background-color:#D5E1F4;}
+.navigation_bar .controls {position:absolute;bottom:1em;width:100%;text-align:center;}
+.navigation_bar .controls img {cursor:pointer;}
+.navigation_bar .bd.oversized_content {overflow-y:auto;overflow-x:visible;height:inherit;}
+.navigation_bar .bd.oversized_content .content {margin:6px 6px 6px 0px;padding-bottom:6px;}
+
+/* Sideblock expansion code */
+.sideblock_js_expansion .block_tree {overflow-x:scroll;}
+.sideblock_js_expansion.mouseover .content {width:200%;z-index:1000;position:relative;}
+.sideblock_js_expansion.mouseover .content .block_tree {width:100%; background-color:#fcfcfc; padding-bottom:0px;}
+
+/* CSS for shadows */
+.divshadow div {position:absolute;width:3px;height:3px;background-color:#333;}
+.divshadow .shadow_top {top:-3px;right:0px;width:100%;}
+.divshadow .shadow_bottom {bottom:-3px;right:0px;width:100%;}
+.divshadow .shadow_left {top:0px;left:-3px;height:100%;}
+.divshadow .shadow_right {bottom:0px;right:-3px;height:100%;}
+.divshadow .shadow_top_right {top:-3px;right:-3px;}
+.divshadow .shadow_bottom_right {bottom:-3px;right:-3px;}
+.divshadow .shadow_top_left {top:-3px;left:-3px;}
+.divshadow .shadow_bottom_left {bottom:-3px;left:-3px;}
+
+/** IE stylings */
+.ie6 .sideblock .block_tree {width:160px;overflow-x:scroll;}
+.ie7 .sideblock .block_tree {overflow-x:scroll;}
+.ie6 .block_tree .tree_item {width:100%;}
+.ie6 .navigation_bar {position:absolute;}
+.ie6 .navigation_bar hr {display:none;margin:0px;height:0px;padding:0px;}
+.ie6 .navigation_bar li p {background-color:inherit;}
+.ie6 .navigation_bar .bd.oversized_content .content, .ie7 .navigation_bar .bd.oversized_content .content {padding-bottom:0px;}
+.ie6 .sideblock_js_expansion.mouseover .content, .ie7 .sideblock_js_expansion.mouseover .content{ padding-bottom:2px;}
+.ie6 .navigation_bar .bd.oversized_content {width:100%;}
+.ie7 .navigation_bar .bd.oversized_content {width:400px;}
Index: moodle/theme/standardold/config.php
--- moodle/theme/standardold/config.php Base (1.1)
+++ moodle/theme/standardold/config.php Locally Modified (Based On 1.1)
@@ -177,5 +177,5 @@
 );
 
 /** List of javascript files that need to included on each page */
-$THEME->javascripts = array('navigation');
-
+$THEME->javascripts = array();
+$THEME->javascripts_footer = array();
Index: moodle/theme/standardold/javascript/navigation.js
--- moodle/theme/standardold/javascript/navigation.js Base (1.1)
+++ moodle/theme/standardold/javascript/navigation.js Locally Deleted
@@ -1,882 +0,0 @@
-/* legacy standard: javascript needed for navbar manipulations */
-
-// 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 <http://www.gnu.org/licenses/>.
-
-/**
- * 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;
-        }
-        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;i<movetos.length;i++) {
-            YAHOO.util.Event.addListener(movetos[i], 'click', this.toggle_block_display, this, true);
-        }
-    }
-    for (i = 0; i<this.expansions.length; i++) {
-        try {
-            this.expansions[i].element = document.getElementById(this.expansions[i].id);
-            YAHOO.util.Event.addListener(this.expansions[i].id, 'click', this.init_load_ajax, this.expansions[i], this);
-            YAHOO.moodle.navigation.expandablebranchcount++;
-        } catch (err) {
-            this.errorlog += "attaching ajax load events: \t"+err+"\n";
-        }
-    }
-    var items = YAHOO.util.Dom.getElementsByClassName('tree_item branch', '', document.getElementById(this.name));
-    if (items != null && items.length>0) {
-        for (i = 0; i<items.length; i++) {
-            try {
-                YAHOO.util.Event.addListener(items[i], 'click', this.toggleexpansion, this, true);
-            } catch (err) {
-                this.errorlog += "attaching toggleexpansion events: \t"+err+"\n";
-            }
-        }
-    }
-
-    var customcommands = YAHOO.util.Dom.getElementsByClassName('customcommand', 'a', e);
-    var commands = YAHOO.util.Dom.getElementsByClassName('commands', 'div', e);
-    if (commands.length === 1 && customcommands.length > 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<branch.mychildren.childNodes.length;i++) {
-            if (branch.haschildren) {
-                var ul = document.createElement('ul');
-                target.appendChild(ul);
-            }
-            var child = branch.mychildren.childNodes[i];
-            this.add_branch(child, ul, depth+1);
-        }
-    } else if(depth==1) {
-        // If we are here then we got a valid response however there are no children
-        // to display for the branch that we are expanding, thus we will return false
-        // so we can add the emptybranch class
-        return false;
-    }
-    return true;
-}
-/**
- * This switches a navigation block between its block position and the sidebar
- *
- * @param {element} e Event object
- */
-navigation_tree.prototype.toggle_block_display = function(e) {
-    if (e !== null) {
-        YAHOO.util.Event.stopPropagation(e);
-    }
-    if (this.position === 'block') {
-        this.move_to_sidebar_popout(e);
-        this.position = 'sidebar';
-    } else {
-        this.move_to_block_position(e);
-        this.position = 'block';
-    }
-}
-/**
- * This function gets called from {@link navigation_tree.toggle_block_display()}
- * and is responsible for moving the block from the block position to the sidebar
- * @return {bool}
- */
-navigation_tree.prototype.move_to_sidebar_popout = function(e) {
-
-    YAHOO.util.Event.stopEvent(e);
-
-    var element = document.getElementById(this.name).parentNode;
-    if (element == null) {
-        return false;
-    }
-    var tabcontent = document.getElementById(this.name).parentNode;
-    while (!YAHOO.util.Dom.hasClass(element, 'sideblock')) {
-        element = element.parentNode;
-    }
-    this.cachedcontent = element;
-
-    var sideblocknode = element;
-    while (sideblocknode && !YAHOO.util.Dom.hasClass(sideblocknode, 'block-region')) {
-        sideblocknode = sideblocknode.parentNode;
-    }
-
-    var moveto = YAHOO.util.Dom.getElementsByClassName('moveto customcommand', 'a', this.cachedcontent);
-    if (moveto.length > 0) {
-        for (var i=0;i<moveto.length;i++) {
-            var moveicon = moveto[i].getElementsByTagName('img');
-            if (moveicon.length>0) {
-                for (var j=0;j<moveicon.length;j++) {
-                    moveicon[j].src = get_image_url('t/movetoblock', 'moodle');
-                    moveicon[j].setAttribute('alt', this.toggleblockdisplay);
-                    moveicon[j].setAttribute('title', this.toggleblockdisplay);
-                }
-            }
-        }
-    }
-
-    var placeholder = document.createElement('div');
-    placeholder.setAttribute('id', this.name+'_content_placeholder');
-    element.parentNode.replaceChild(placeholder, element);
-    element = null;
-    var tabtitle = this.cachedcontent.getElementsByTagName('h2')[0].cloneNode(true);
-    tabtitle.innerHTML = tabtitle.innerHTML.replace(/([a-zA-Z0-9])/g, "$1<br />");
-    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;i<moveto.length;i++) {
-            var moveicon = moveto[i].getElementsByTagName('img');
-            if (moveicon.length>0) {
-                for (var j=0;j<moveicon.length;j++) {
-                    moveicon[j].src = get_image_url('t/movetosidetab', 'moodle');
-                    moveicon[j].setAttribute('alt', this.togglesidetabdisplay);
-                    moveicon[j].setAttribute('title', this.togglesidetabdisplay);
-                }
-            }
-        }
-    }
-
-    var commands = YAHOO.util.Dom.getElementsByClassName('commands', 'div', this.cachedcontent);
-    var blocktitle = YAHOO.util.Dom.getElementsByClassName('title', 'div', this.cachedcontent);
-    if (commands.length === 1 && blocktitle.length === 1) {
-        commands[0].parentNode.removeChild(commands[0]);
-        blocktitle[0].appendChild(commands[0]);
-    }
-
-    YAHOO.moodle.navigation.tabpanel.remove_from_tab_panel(this.name);
-
-    var block = this.cachedcontent;
-    while (!YAHOO.util.Dom.hasClass(block, 'sideblock')) {
-        block = block.parentNode;
-    }
-    set_user_preference('nav_in_tab_panel_'+this.name, 0);
-    return true;
-}
-
-/**
- * This class is used to manage the navigation tab panel
- *
- * Through this class you can add, remove, and manage items from the navigation
- * tab panel.
- * Note you only EVER need one of these
- * @constructor
- * @class navigation_tab_panel
- */
-function navigation_tab_panel() {
-    this.tabpanelexists = false;
-    this.tabpanelelementnames = Array();
-    this.tabpanelelementcontents = Array();
-    this.navigationpanel = null;
-    this.tabpanel = null;
-    this.tabpanels = Array();
-    this.tabcount = 0;
-    this.preventhide = false;
-    this.showntab = null;
-}
-/**
- * This creates a tab panel element and injects it into the DOM
- * @method create_tab_panel
- * @return {bool}
- */
-navigation_tab_panel.prototype.create_tab_panel = function () {
-    var navbar  = document.createElement('div');
-    navbar.style.display = 'none';
-    navbar.setAttribute('id', 'sidebarpopup');
-    var navbarspacer = document.createElement('div');
-    navbarspacer.style.height = '10px';
-    navbar.appendChild(navbarspacer);
-    YAHOO.util.Dom.addClass(navbar, 'navigation_bar');
-    if (YAHOO.env.ua.ie > 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<branch.childNodes.length;i++) {
-        var node = branch.childNodes[i];
-        switch (node.nodeName.toLowerCase()) {
-            case 'name':
-                this.myname = node.firstChild.nodeValue;
-                break;
-            case 'children':
-                this.mychildren = node;
-        }
-    }
-}
-/**
- * This function injects the node into the navigation tree
- * @param {element} element The branch to inject into {element}
- * @param {navigation_tree} gntinstance The instance of the navigaiton_tree that this branch
- *         is associated with
- * @return {element} The now added node
- */
-navigation_tree_branch.prototype.inject_into_dom = function (element, gntinstance) {
-    var branchli = document.createElement('li');
-    var branchp = document.createElement('p');
-    YAHOO.util.Dom.addClass(branchp, 'tree_item');
-    if ((this.myexpandable !==null || this.haschildren) && this.expansionceiling===null) {
-        YAHOO.util.Dom.addClass(branchp, 'branch');
-        YAHOO.util.Dom.addClass(branchli, 'collapsed');
-        YAHOO.util.Event.addListener(branchp, 'click', gntinstance.toggleexpansion, this, gntinstance);
-        if (this.myexpandable) {
-            YAHOO.util.Event.addListener(branchp, 'click', gntinstance.init_load_ajax, {branchid:this.mykey,id:this.myid,type:this.mytype,element:branchp}, gntinstance);
-        }
-    }
-    if (this.myclass != null) {
-        YAHOO.util.Dom.addClass(branchp, this.myclass);
-    }
-    if (this.myid != null) {
-        branchp.setAttribute('id',this.myid);
-    }
-    var branchicon = false;
-    if (this.myicon != null) {
-        branchicon = document.createElement('img');
-        branchicon.setAttribute('src',this.myicon);
-        branchicon.setAttribute('alt','');
-        this.myname = ' '+this.myname;
-    }
-    if (this.mylink === null) {
-        if (branchicon !== false) {
-            branchp.appendChild(branchicon);
-        }
-        branchp.appendChild(document.createTextNode(this.myname.replace(/\n/g, '<br />')));
-    } 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, '<br />')));
-        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<YAHOO.moodle.navigation.treecollection.length;i++) {
-        var navtree = YAHOO.moodle.navigation.treecollection[i];
-        if (navtree.position != 'block') {
-            navtree.move_to_block_position(e);
-        }
-    }
-}
-
-/**
- * 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 {element}
- */
-function create_shadow(top, right, bottom, left) {
-    var shadow = document.createElement('div');
-    YAHOO.util.Dom.addClass(shadow, 'divshadow');
-    if (YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 7) {
-        // IE6 just doest like my shadow...
-        return shadow;
-    }
-    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<shadows.length;i++) {
-        shadows[i].parentNode.removeChild(shadows[i]);
-    }
-    return true;
-}
