# 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/dock.js
--- moodle/blocks/dock.js Base (1.21)
+++ moodle/blocks/dock.js Locally Modified (Based On 1.21)
@@ -3,22 +3,24 @@
  * @namespace
  */
 M.core_dock = {
-    count : 0,        // The number of dock items currently
-    totalcount : 0,   // The number of dock items through the page life
-    exists : false,   // True if the dock exists
-    items : [],       // An array of dock items
-    node : null,      // The YUI node for the dock itself
-    earlybinds : [],  // Events added before the dock was augmented to support events
-    Y : null,         // The YUI instance to use with dock related code
+    count : 0,              // The number of dock items currently
+    totalcount : 0,         // The number of dock items through the page life
+    items : [],             // An array of dock items
+    earlybinds : [],        // Events added before the dock was augmented to support events
+    Y : null,               // The YUI instance to use with dock related code
+    initialised : false,    // True once thedock has been initialised
+    delayedevent : null,    // Will be an object if there is a delayed event in effect
+    preventevent : null     // Will be an eventtype if there is an eventyoe to prevent
+}
     /**
-     * Strings used by the dock/dockitems
+ * Namespace containing the nodes that relate to the dock
      * @namespace
      */
-    strings : {
-        addtodock : '[[addtodock]]',
-        undockitem : '[[undockitem]]',
-        undockall : '[[undockall]]'
-    },
+M.core_dock.nodes = {
+    dock : null, // The dock itself
+    body : null, // The body of the page
+    panel : null // The docks panel
+}
     /**
      * Configuration parameters used during the initialisation and setup
      * of dock and dock items.
@@ -26,134 +28,460 @@
      * design aspects without having to re-write navigation
      * @namespace
      */
-    cfg:{
+M.core_dock.cfg = {
         buffer:10,                          // Buffer used when containing a panel
         position:'left',                    // position of the dock
         orientation:'vertical',             // vertical || horizontal determines if we change the title
-        /**
-         * Display parameters for the dock
-         * @namespace
-         */
-        display:{
-            spacebeforefirstitem: 10,       // Space between the top of the dock and the first item
-            mindisplaywidth: null,          // Minimum width for the display of dock items
+    spacebeforefirstitem: 10,           // Space between the top of the dock and the first item
             removeallicon: M.util.image_url('t/dock_to_block', 'moodle')
-        },
+}
         /**
          * CSS classes to use with the dock
          * @namespace
          */
-        css: {
+M.core_dock.css = {
             dock:'dock',                    // CSS Class applied to the dock box
             dockspacer:'dockspacer',        // CSS class applied to the dockspacer
             controls:'controls',            // CSS class applied to the controls box
             body:'has_dock',                // CSS class added to the body when there is a dock
             dockeditem:'dockeditem',        // CSS class added to each item in the dock
+    dockeditemcontainer:'dockeditem_container',
             dockedtitle:'dockedtitle',      // CSS class added to the item's title in each dock
             activeitem:'activeitem'         // CSS class added to the active item
-        },
-        /**
-         * Configuration options for the panel that items are shown in
-         * @namespace
-         */
-        panel: {
-            close:false,                    // Show a close button on the panel
-            draggable:false,                // Make the panel draggable
-            underlay:"none",                // Use a special underlay
-            modal:false,                    // Throws a lightbox if set to true
-            modalzindex:1000,               // Sets the zIndex for the modal to avoid collisions
-            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:9999999,                 // Sets a specific z index for the panel. Has to be high to avoid MCE and filepicker
-            constraintoviewport: false,     // Constrain the panel to the viewport
-            autofillheight:'body'           // Which container element should fill out empty space
         }
-    },
     /**
      * Augments the classes as required and processes early bindings
      */
-    init:function(Y) {
+M.core_dock.init = function(Y) {
+    if (this.initialised) {
+        return true;
+    }
+    var css = this.css;
+    this.initialised = true;
         this.Y = Y;
+    this.nodes.body = Y.one(document.body);
+
         // Give the dock item class the event properties/methods
-        this.Y.augment(M.core_dock.item, this.Y.EventTarget);
-        this.Y.augment(M.core_dock, this.Y.EventTarget, true);
+    Y.augment(this.item, Y.EventTarget);
+    Y.augment(this, Y.EventTarget, true);
+
+    // Publish the events the dock has
+    this.publish('dock:beforedraw', {prefix:'dock'});
+    this.publish('dock:initialised', {prefix:'dock'});
+    this.publish('dock:itemadded', {prefix:'dock'});
+    this.publish('dock:itemremoved', {prefix:'dock'});
+    this.publish('dock:itemschanged', {prefix:'dock'});
+    this.publish('dock:panelgenerated', {prefix:'dock'});
+    this.publish('dock:panelresizestart', {prefix:'dock'});
+    this.publish('dock:resizepanelcomplete', {prefix:'dock'});
+
         // Re-apply early bindings properly now that we can
-        M.core_dock.apply_binds();
+    this.applyBinds();
         // Check if there is a customisation function
         if (typeof(customise_dock_for_theme) === 'function') {
+        try {
+            // Run the customisation function
             customise_dock_for_theme();
+        } catch (exception) {
+            // Do nothing at the moment
         }
+    }
+
+    // Start the construction of the dock
+    dock = Y.Node.create('<div id="dock" class="'+css.dock+' '+css.dock+'_'+this.cfg.position+'_'+this.cfg.orientation+'"></div>');
+    this.nodes.container = Y.Node.create('<div class="'+css.dockeditemcontainer+'"></div>');
+    dock.append(this.nodes.container);
+    if (Y.all('.block.dock_on_load').size() == 0) {
+        // Nothing on the dock... hide it using CSS
+        dock.addClass('nothingdocked');
+    } else {
+        this.nodes.body.addClass(this.css.body);
+    }
+    // Store the dock
+    this.nodes.dock = dock;
+    this.fire('dock:beforedraw');
+    this.nodes.body.append(dock);
+    if (Y.UA.ie > 0 && Y.UA.ie < 7) {
+        // Adjust for IE 6 (can't handle fixed pos)
+        dock.setStyle('height', dock.get('winHeight')+'px');
+    }
+    // Add a removeall button
+    var removeall = Y.Node.create('<img src="'+this.cfg.removeallicon+'" alt="'+M.str.block.undockall+'" title="'+M.str.block.undockall+'" />');
+    removeall.on('removeall|click', this.remove_all, this);
+    dock.appendChild(Y.Node.create('<div class="'+css.controls+'"></div>').append(removeall));
+
+    // Create a manager for the height of the tabs. Once set this can be forgotten about
+    new (function(Y){
+        return {
+            enabled : false,        // True if the item_sizer is being used, false otherwise
+            /**
+             * Initialises the dock sizer which then attaches itself to the required
+             * events in order to monitor the dock
+             * @param {YUI} Y
+             */
+            init : function() {
+                M.core_dock.on('dock:itemschanged', this.checkSizing, this);
+                Y.on('windowresize', this.checkSizing, this);
     },
     /**
+             * Check if the size dock items needs to be adjusted
+             */
+            checkSizing : function() {
+                var dock = M.core_dock;
+                var possibleheight = dock.nodes.dock.get('offsetHeight') - dock.nodes.dock.one('.controls').get('offsetHeight') - (dock.cfg.buffer*3) - (dock.items.length*2);
+                var totalheight = 0;
+                for (var id in dock.items) {
+                    var dockedtitle = Y.one(dock.items[id].title).ancestor('.'+dock.css.dockedtitle);
+                    if (dockedtitle) {
+                        if (this.enabled) {
+                            dockedtitle.setStyle('height', 'auto');
+                        }
+                        totalheight += dockedtitle.get('offsetHeight') || 0;
+                    }
+                }
+                if (totalheight > possibleheight) {
+                    this.enable(possibleheight);
+                }
+            },
+            /**
+             * Enables the dock sizer and resizes where required.
+             */
+            enable : function(possibleheight) {
+                var dock = M.core_dock;
+                var runningcount = 0;
+                var usedheight = 0;
+                this.enabled = true;
+                for (var id in dock.items) {
+                    var itemtitle = Y.one(dock.items[id].title).ancestor('.'+dock.css.dockedtitle);
+                    if (!itemtitle) {
+                        continue;
+                    }
+                    var itemheight = Math.floor((possibleheight-usedheight) / (dock.count - runningcount));
+                    var offsetheight = itemtitle.get('offsetHeight');
+                    itemtitle.setStyle('overflow', 'hidden');
+                    if (offsetheight > itemheight) {
+                        itemtitle.setStyle('height', itemheight+'px');
+                        usedheight += itemheight;
+                    } else {
+                        usedheight += offsetheight;
+                    }
+                    runningcount++;
+                }
+            }
+        }
+    })(Y).init();
+
+    // Attach the required event listeners
+    // We use delegate here as that way a handful of events are created for the dock
+    // and all items rather than the same number for the dock AND every item individually
+    Y.delegate('click', this.handleEvent, this.nodes.dock, '.'+this.css.dockedtitle, this, {cssselector:'.'+this.css.dockedtitle, delay:0});
+    Y.delegate('mouseenter', this.handleEvent, this.nodes.dock, '.'+this.css.dockedtitle, this, {cssselector:'.'+this.css.dockedtitle, delay:0.5, iscontained:true, preventevent:'click', preventdelay:3});
+    Y.delegate('mouseleave', this.handleEvent, this.nodes.body, '#dock', this,  {cssselector:'#dock', delay:0.5, iscontained:false});
+    this.nodes.body.on('click', this.handleEvent, this,  {cssselector:'body', delay:0});
+    this.on('dock:itemschanged', this.resizeBlockSpace, this);
+    this.on('dock:itemschanged', this.checkDockVisibility, this);
+    // Inform everyone the dock has been initialised
+    this.fire('dock:initialised');
+    return true;
+}
+/**
+ * Get the panel docked blocks will be shown in and initialise it if we havn't already.
+ */
+M.core_dock.getPanel = function() {
+    if (this.nodes.panel === null) {
+        // Initialise the dockpanel .. should only happen once
+        this.nodes.panel = (function(Y, parent){
+            var dockpanel = Y.Node.create('<div id="dockeditempanel" class="dockitempanel_hidden"><div class="dockeditempanel_content"><div class="dockeditempanel_hd"></div><div class="dockeditempanel_bd"></div></div></div>');
+            // Give the dockpanel event target properties and methods
+            Y.augment(dockpanel, Y.EventTarget);
+            // Publish events for the dock panel
+            dockpanel.publish('dockpanel:beforeshow', {prefix:'dockpanel'});
+            dockpanel.publish('dockpanel:shown', {prefix:'dockpanel'});
+            dockpanel.publish('dockpanel:beforehide', {prefix:'dockpanel'});
+            dockpanel.publish('dockpanel:hidden', {prefix:'dockpanel'});
+            dockpanel.publish('dockpanel:visiblechange', {prefix:'dockpanel'});
+            // Cache the content nodes
+            dockpanel.contentNode = dockpanel.one('.dockeditempanel_content');
+            dockpanel.contentHeader = dockpanel.contentNode.one('.dockeditempanel_hd');
+            dockpanel.contentBody = dockpanel.contentNode.one('.dockeditempanel_bd');
+            // Set the x position of the panel
+            dockpanel.setX(parent.get('offsetWidth'));
+            dockpanel.visible = false;
+            // Add a show event
+            dockpanel.show = function() {
+                this.fire('dockpanel:beforeshow');
+                this.visible = true;
+                this.removeClass('dockitempanel_hidden');
+                this.fire('dockpanel:shown');
+                this.fire('dockpanel:visiblechange');
+            }
+            // Add a hide event
+            dockpanel.hide = function() {
+                this.fire('dockpanel:beforehide');
+                this.visible = false;
+                this.addClass('dockitempanel_hidden');
+                this.fire('dockpanel:hidden');
+                this.fire('dockpanel:visiblechange');
+            }
+            // Add a method to set the header content
+            dockpanel.setHeader = function(content) {
+                this.contentHeader.setContent(content);
+                if (arguments.length > 1) {
+                    for (var i=1;i < arguments.length;i++) {
+                        this.contentHeader.append(arguments[i]);
+                    }
+                }
+            }
+            // Add a method to set the body content
+            dockpanel.setBody = function(content) {
+                this.contentBody.setContent(content);
+            }
+            // Add a method to set the top of the panel position
+            dockpanel.setTop = function(newtop) {
+                this.setY(newtop);
+                return;
+                if (Y.UA.ie > 0) {
+                    this.setY(newtop);
+                    return true;
+                }
+                this.setStyle('top', newtop+'px');
+            }
+            // Put the dockpanel in the body
+            parent.append(dockpanel);
+            // Return it
+            return dockpanel;
+        })(this.Y, this.nodes.dock);
+        this.nodes.panel.on('panel:visiblechange', this.resize, this);
+        this.Y.on('windowresize', this.resize, this);
+        this.fire('dock:panelgenerated');
+    }
+    return this.nodes.panel;
+}
+/**
+ * Handles a generic event within the dock
+ * @param {Y.Event} e
+ * @param {object} options Event configuration object
+ */
+M.core_dock.handleEvent = function(e, options) {
+    var item = this.getActiveItem();
+    var target = (e.target.test(options.cssselector))?e.target:e.target.ancestor(options.cssselector);
+    if (options.cssselector == 'body') {
+        if (!this.nodes.dock.contains(e.target)) {
+            if (item) {
+                item.hide();
+            }
+        }
+    } else if (target) {
+        if (this.preventevent !== null && e.type === this.preventevent) {
+            return true;
+        }
+        if (options.preventevent) {
+            this.preventevent = options.preventevent;
+            if (options.preventdelay) {
+                setTimeout(function(){M.core_dock.preventevent = null;}, options.preventdelay*1000);
+            }
+        }
+        if (this.delayedevent && this.delayedevent.timeout) {
+            clearTimeout(this.delayedevent.timeout);
+            this.delayedevent.event.detach();
+            this.delayedevent = null;
+        }
+        if (options.delay > 0) {
+            return this.delayEvent(e, options, target);
+        }
+        var targetid = target.get('id');
+        if (targetid.match(/^dock_item_(\d+)_title$/)) {
+            item = this.items[targetid.replace(/^dock_item_(\d+)_title$/, '$1')];
+            if (item.active) {
+                item.hide();
+            } else {
+                item.show();
+            }
+        } else if (item) {
+            item.hide();
+        }
+    }
+    return true;
+}
+/**
+ * This function delays an event and then fires it providing the cursor if either
+ * within or outside of the original target (options.iscontained=true|false)
+ * @param {Y.Event} event
+ * @param {object} options
+ * @param {Y.Node} target
+ * @return bool
+ */
+M.core_dock.delayEvent = function(event, options, target) {
+    var self = this;
+    self.delayedevent = (function(){
+        return {
+            target : target,
+            event : self.nodes.body.on('mousemove', function(e){
+                self.delayedevent.target = e.target;
+            }),
+            timeout : null
+        }
+    })(self);
+    self.delayedevent.timeout = setTimeout(function(){
+        self.delayedevent.timeout = null;
+        self.delayedevent.event.detach();
+        if (options.iscontained == self.nodes.dock.contains(self.delayedevent.target)) {
+            self.handleEvent(event, {cssselector:options.cssselector, delay:0, iscontained:options.iscontained});
+        }
+    }, options.delay*1000);
+    return true;
+}
+/**
+ * Corrects the orientation of the title, which for the default
+ * dock just means making it vertical
+ * The orientation is determined by M.str.langconfig.thisdirectionvertical:
+ *    ver : Letters are stacked rather than rotated
+ *    ttb : Title is rotated clockwise so the first letter is at the top
+ *    btt : Title is rotated counterclockwise so the first letter is at the bottom.
+ * @param {string} title
+ */
+M.core_dock.fixTitleOrientation = function(title, text) {
+    var Y = this.Y;
+
+    var title = Y.one(title);
+
+    if (Y.UA.ie > 0 && Y.UA.ie < 8) {
+        // IE 6/7 can't rotate text so force ver
+        M.str.langconfig.thisdirectionvertical = 'ver';
+    }
+
+    var clockwise = false;
+    switch (M.str.langconfig.thisdirectionvertical) {
+        case 'ver':
+            // Stacked is easy
+            return title.setContent(text.split('').join('<br />'));
+        case 'ttb':
+            clockwise = true;
+            break;
+        case 'btt':
+            clockwise = false;
+            break;
+    }
+
+    if (Y.UA.ie > 7) {
+        // IE8 can flip the text via CSS but not handle SVG
+        title.setContent(text)
+        title.setAttribute('style', 'writing-mode: tb-rl; filter: flipV flipH;display:inline;');
+        title.addClass('filterrotate');
+        return title;
+    }
+
+    // Cool, we can use SVG!
+    var test = Y.Node.create('<div><span style="font-size:10px;">'+text+'</span></div>');
+    this.nodes.body.append(test);
+    var height = test.one('span').get('offsetWidth')+4;
+    var width = test.one('span').get('offsetHeight')*2;
+    var qwidth = width/4;
+    test.remove();
+
+    // Create the text for the SVG
+    var txt = document.createElementNS('http://www.w3.org/2000/svg', 'text');
+    txt.setAttribute('font-size','10px');
+    if (clockwise) {
+        txt.setAttribute('transform','rotate(90 '+(qwidth/2)+' '+qwidth+')');
+    } else {
+        txt.setAttribute('y', height);
+        txt.setAttribute('transform','rotate(270 '+qwidth+' '+(height-qwidth)+')');
+    }
+    txt.appendChild(document.createTextNode(text));
+
+    var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+    svg.setAttribute('version', '1.1');
+    svg.setAttribute('height', height);
+    svg.setAttribute('width', width);
+    svg.appendChild(txt);
+
+    title.append(svg)
+    return title;
+}
+/**
+ * Resizes the space that contained blocks if there were no blocks left in
+ * it. e.g. if all blocks have been moved to the dock
+ * @param {Y.Node} node
+ */
+M.core_dock.resizeBlockSpace = function(node) {
+
+    if (this.Y.all('.block.dock_on_load').size()>0) {
+        // Do not resize during initial load
+        return;
+    }
+    var blockregions = [];
+    var populatedblockregions = 0;
+    this.Y.all('.block-region').each(function(region){
+        var hasblocks = (region.all('.block').size() > 0);
+        if (hasblocks) {
+            populatedblockregions++;
+        }
+        blockregions[region.get('id')] = {hasblocks: hasblocks, bodyclass: region.get('id').replace(/^region\-/, 'side-')+'-only'};
+    });
+    var bodynode = M.core_dock.nodes.body;
+    var noblocksbodyclass = 'content-only';
+    var i = null;
+    if (populatedblockregions==0) {
+        bodynode.addClass(noblocksbodyclass);
+        for (i in blockregions) {
+            bodynode.removeClass(blockregions[i].bodyclass);
+        }
+    } else if (populatedblockregions==1) {
+        bodynode.removeClass(noblocksbodyclass);
+        for (i in blockregions) {
+            if (!blockregions[i].hasblocks) {
+                bodynode.removeClass(blockregions[i].bodyclass);
+            } else {
+                bodynode.addClass(blockregions[i].bodyclass);
+            }
+        }
+    } else {
+        bodynode.removeClass(noblocksbodyclass);
+        for (i in blockregions) {
+            bodynode.removeClass(blockregions[i].bodyclass);
+        }
+    }
+}
+/**
      * Adds a dock item into the dock
      * @function
      * @param {M.core_dock.item} item
      */
-    add:function(item) {
+M.core_dock.add = function(item) {
         item.id = this.totalcount;
         this.count++;
         this.totalcount++;
         this.items[item.id] = item;
-        this.draw();
         this.items[item.id].draw();
         this.fire('dock:itemadded', item);
-    },
+    this.fire('dock:itemschanged', item);
+}
     /**
      * Appends a dock item to the dock
      * @param {YUI.Node} docknode
      */
-    append : function(docknode) {
-        M.core_dock.node.one('#dock_item_container').append(docknode);
-    },
+M.core_dock.append = function(docknode) {
+    this.nodes.container.append(docknode);
+}
     /**
      * Initialises a generic block object
      * @param {YUI} Y
      * @param {int} id
      */
-    init_genericblock : function(Y, id) {
-        var genericblock = new this.genericblock();
-        genericblock.id = id;
-        genericblock.init(Y, Y.one('#inst'+id));
-    },
-    /**
-     * Draws the dock
-     * @function
-     * @return bool
-     */
-    draw:function() {
-        if (this.node !== null) {
-            return true;
+M.core_dock.init_genericblock = function(Y, id) {
+    if (!this.initialised) {
+        this.init(Y);
         }
-        this.fire('dock:drawstarted');
-        this.item_sizer.init(this.Y);
-        this.node = this.Y.Node.create('<div id="dock" class="'+M.core_dock.cfg.css.dock+' '+this.cfg.css.dock+'_'+this.cfg.position+'_'+this.cfg.orientation+'"></div>');
-        this.node.appendChild(this.Y.Node.create('<div class="'+M.core_dock.cfg.css.dockspacer+'" style="height:'+M.core_dock.cfg.display.spacebeforefirstitem+'px"></div>'));
-        this.node.appendChild(this.Y.Node.create('<div id="dock_item_container"></div>'));
-        if (this.Y.UA.ie > 0 && this.Y.UA.ie < 7) {
-            this.node.setStyle('height', this.node.get('winHeight')+'px');
+    new this.genericblock(id).init(Y, Y.one('#inst'+id));
         }
-        var dockcontrol = this.Y.Node.create('<div class="'+M.core_dock.cfg.css.controls+'"></div>');
-        var removeall = this.Y.Node.create('<img src="'+this.cfg.display.removeallicon+'" alt="'+M.str.block.undockall+'" title="'+M.str.block.undockall+'" />');
-        removeall.on('removeall|click', this.remove_all, this);
-        dockcontrol.appendChild(removeall);
-        this.node.appendChild(dockcontrol);
-
-        this.Y.one(document.body).appendChild(this.node);
-        this.Y.one(document.body).addClass(M.core_dock.cfg.css.body);
-        this.fire('dock:drawcompleted');
-        return true;
-    },
     /**
      * Removes the node at the given index and puts it back into conventional page sturcture
      * @function
      * @param {int} uid Unique identifier for the block
      * @return {boolean}
      */
-    remove:function(uid) {
+M.core_dock.remove = function(uid) {
         if (!this.items[uid]) {
             return false;
         }
@@ -161,155 +489,118 @@
         delete this.items[uid];
         this.count--;
         this.fire('dock:itemremoved', uid);
-        if (this.count===0) {
-            this.fire('dock:toberemoved');
-            this.items = [];
-            this.node.remove();
-            this.node = null;
-            this.Y.one(document.body).removeClass(M.core_dock.cfg.css.body);
-            this.fire('dock:removed');
-        }
+    this.fire('dock:itemschanged', uid);
         return true;
-    },
+}
     /**
      * Removes all nodes and puts them back into conventional page sturcture
      * @function
      * @return {boolean}
      */
-    remove_all:function() {
+M.core_dock.remove_all = function() {
         for (var i in this.items) {
-            this.items[i].remove();
-            this.count--;
-            delete this.items[i];
+        this.remove(i);
         }
-        this.Y.fire('dock:toberemoved');
-        this.items = [];
-        this.node.remove();
-        this.node = null;
-        this.Y.one(document.body).removeClass(M.core_dock.cfg.css.body);
-        this.Y.fire('dock:removed');
         return true;
-    },
+}
     /**
-     * Resizes the active item
-     * @function
-     * @param {Event} e
+ * Hides the active item
      */
-    resize:function(e){
-        for (var i in this.items) {
-            if (this.items[i].active) {
-                this.items[i].resize_panel(e);
+M.core_dock.hideActive = function() {
+    var item = this.getActiveItem();
+    if (item) {
+        item.hide();
             }
         }
-    },
     /**
-     * Hides all [the active] items
-     * @function
+ * Checks wether the dock should be shown or hidden
      */
-    hide_all:function() {
-        for (var i in this.items) {
-            this.items[i].hide(null, true);
+M.core_dock.checkDockVisibility = function() {
+    if (!this.count) {
+        this.nodes.dock.addClass('nothingdocked');
+        this.nodes.body.removeClass(this.css.body);
+        this.Y.fire('dock:hidden');
+    } else {
+        this.Y.fire('dock:beforeshow');
+        this.nodes.dock.removeClass('nothingdocked');
+        this.nodes.body.addClass(this.css.body);
+        this.Y.fire('dock:shown');
         }
-    },
+}
     /**
      * This smart little function allows developers to attach event listeners before
      * the dock has been augmented to allows event listeners.
      * Once the augmentation is complete this function will be replaced with the proper
      * on method for handling event listeners.
-     * Finally apply_binds needs to be called in order to properly bind events.
+ * Finally applyBinds needs to be called in order to properly bind events.
      * @param {string} event
      * @param {function} callback
      */
-    on : function(event, callback) {
+M.core_dock.on = function(event, callback) {
         this.earlybinds.push({event:event,callback:callback});
-    },
+}
     /**
      * This function takes all early binds and attaches them as listeners properly
      * This should only be called once augmentation is complete.
      */
-    apply_binds : function() {
+M.core_dock.applyBinds = function() {
         for (var i in this.earlybinds) {
             var bind = this.earlybinds[i];
             this.on(bind.event, bind.callback);
         }
         this.earlybinds = [];
-    },
+}
     /**
-     * Namespace for the dock sizer which is responsible for ensuring that dock
-     * items are visible at all times, this is required because otherwise when there
-     * were enough dock items to fit on the dock those that ran over the size of
-     * the dock would not be usable
-     * @namespace
+ * This function checks the size and position of the panel and moves/resizes if
+ * required to keep it within the bounds of the window.
      */
-    item_sizer : {
-        enabled : false,        // True if the item_sizer is being used, false otherwise
-        Y : null,               // The YUI instance
-        /**
-         * Initialises the dock sizer which then attaches itself to the required
-         * events in order to monitor the dock
-         * @param {YUI} Y
-         */
-        init : function(Y) {
-            this.Y = Y;
-            M.core_dock.on('dock:itemadded', this.check_if_required, this);
-            M.core_dock.on('dock:itemremoved', this.check_if_required, this);
-            this.Y.on('windowresize', this.check_if_required, this);
-        },
-        /**
-         * Check if the size dock items needs to be adjusted
-         */
-        check_if_required : function() {
-            var possibleheight = M.core_dock.node.get('offsetHeight') - M.core_dock.node.one('.controls').get('offsetHeight') - (M.core_dock.cfg.buffer*3) - (M.core_dock.items.length*2);
-            var totalheight = 0;
-            for (var id in M.core_dock.items) {
-                var dockedtitle = this.Y.get(M.core_dock.items[id].title).ancestor('.'+M.core_dock.cfg.css.dockedtitle);
-                if (dockedtitle) {
-                    if (this.enabled) {
-                        dockedtitle.setStyle('height', 'auto');
+M.core_dock.resize = function() {
+    this.fire('dock:panelresizestart');
+    var panel = this.getPanel();
+    var item = this.getActiveItem();
+    if (!panel.visible || !item) {
+        return;
                     }
-                    totalheight += dockedtitle.get('offsetHeight') || 0;
+    var buffer = this.cfg.buffer;
+    var screenheight = parseInt(this.nodes.body.get('winHeight'))-(buffer*2);
+    var titletop = item.nodes.docktitle.getY() - this.nodes.container.getY();
+    var containerheight = this.nodes.container.getY()-this.nodes.dock.getY()+this.nodes.container.get('offsetHeight');
+    panel.contentBody.setStyle('height', 'auto').removeClass('oversized_content');
+    var panelheight = panel.get('offsetHeight');
+
+    if (panelheight > screenheight) {
+        panel.setStyle('top', (buffer-containerheight)+'px');
+        panel.contentBody.setStyle('height', (screenheight-panel.contentHeader.get('offsetHeight'))+'px').addClass('oversized_content');
+    } else if (panelheight > (screenheight-(titletop-buffer))) {
+        var difference = panelheight - (screenheight-titletop);
+        panel.setStyle('top', (titletop-containerheight-difference+buffer)+'px');
+    } else {
+        panel.setStyle('top', (titletop-containerheight+buffer)+'px');
                 }
+    this.fire('dock:resizepanelcomplete');
+    return;
             }
-            if (totalheight > possibleheight) {
-                this.enable(possibleheight);
-            }
-        },
         /**
-         * Enables the dock sizer and resizes where required.
+ * Returns the currently active dock item or false
          */
-        enable : function(possibleheight) {
-            this.enabled = true;
-            var runningcount = 0;
-            var usedheight = 0;
-            for (var id in M.core_dock.items) {
-                var itemtitle = this.Y.get(M.core_dock.items[id].title).ancestor('.'+M.core_dock.cfg.css.dockedtitle);
-                if (!itemtitle) {
-                    continue;
+M.core_dock.getActiveItem = function() {
+    for (var i in this.items) {
+        if (this.items[i].active) {
+            return this.items[i];
                 }
-                var itemheight = Math.floor((possibleheight-usedheight) / (M.core_dock.count - runningcount));
-                this.Y.log("("+possibleheight+"-"+usedheight+") / ("+M.core_dock.count+" - "+runningcount+") = "+itemheight);
-                var offsetheight = itemtitle.get('offsetHeight');
-                itemtitle.setStyle('overflow', 'hidden');
-                if (offsetheight > itemheight) {
-                    itemtitle.setStyle('height', itemheight+'px');
-                    usedheight += itemheight;
-                } else {
-                    usedheight += offsetheight;
                 }
-                runningcount++;
+    return false;
             }
-            this.Y.log('possible: '+possibleheight+' - used height: '+usedheight);
-        }
-    }
-};
-
 /**
  * This class represents a generic block
- * @class genericblock
+ * @class M.core_dock.genericblock
  * @constructor
  */
-M.core_dock.genericblock = function() {
+M.core_dock.genericblock = function(id) {
     // Nothing to actually do here but it needs a constructor!
+    if (id) {
+        this.id = id;
+    }
 };
 M.core_dock.genericblock.prototype = {
     Y : null,                   // A YUI instance to use with the block
@@ -317,6 +608,7 @@
     cachedcontentnode : null,   // The cached content node for the actual block
     blockspacewidth : null,     // The width of the block's original container
     skipsetposition : false,    // If true the user preference isn't updated
+    isdocked : false,           // True if it is docked
     /**
      * 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
@@ -324,12 +616,14 @@
      *
      * @param {YUI} Y
      * @param {YUI.Node} node The node that contains all of the block's content
+     * @return {M.core_dock.genericblock}
      */
     init : function(Y, node) {
+        M.core_dock.init(Y);
 
         this.Y = Y;
         if (!node) {
-            return;
+            return false;
         }
 
         var commands = node.one('.header .title .commands');
@@ -340,7 +634,7 @@
             }
         }
 
-        var moveto = this.Y.Node.create('<input type="image" class="moveto customcommand requiresjs" src="'+M.util.image_url('t/block_to_dock', 'moodle')+'" alt="'+M.str.block.addtodock+'" title="'+M.str.block.addtodock+'" />');
+        var moveto = Y.Node.create('<input type="image" class="moveto customcommand requiresjs" src="'+M.util.image_url('t/block_to_dock', 'moodle')+'" alt="'+M.str.block.addtodock+'" title="'+M.str.block.addtodock+'" />');
         moveto.on('movetodock|click', this.move_to_dock, this, commands);
 
         var blockaction = node.one('.block_action');
@@ -356,6 +650,7 @@
             this.skipsetposition = true;
             this.move_to_dock(null, commands);
         }
+        return this;
     },
 
     /**
@@ -368,7 +663,10 @@
             e.halt(true);
         }
 
-        var node = this.Y.one('#inst'+this.id);
+        var Y = this.Y;
+        var dock = M.core_dock
+
+        var node = Y.one('#inst'+this.id);
         var blockcontent = node.one('.content');
         if (!blockcontent) {
             return;
@@ -382,22 +680,17 @@
 
         this.cachedcontentnode = node;
 
-        var placeholder = this.Y.Node.create('<div id="content_placeholder_'+this.id+'" class="block_dock_placeholder"></div>');
-        node.replace(this.Y.Node.getDOMNode(placeholder));
+        node.replace(Y.Node.getDOMNode(Y.Node.create('<div id="content_placeholder_'+this.id+'" class="block_dock_placeholder"></div>')));
         node = null;
 
-        var spacewidth = this.resize_block_space(placeholder);
+        var blocktitle = Y.Node.getDOMNode(this.cachedcontentnode.one('.title h2')).cloneNode(true);
 
-        var blocktitle = this.Y.Node.getDOMNode(this.cachedcontentnode.one('.title h2')).cloneNode(true);
-        blocktitle = this.fix_title_orientation(blocktitle);
-
         var blockcommands = this.cachedcontentnode.one('.title .commands');
         if (!blockcommands) {
-            blockcommands = this.Y.Node.create('<div class="commands"></div>');
+            blockcommands = Y.Node.create('<div class="commands"></div>');
             this.cachedcontentnode.one('.title').append(blockcommands);
         }
-        var moveto = this.Y.Node.create('<a class="moveto customcommand requiresjs"></a>');
-        moveto.append(this.Y.Node.create('<img src="'+M.util.image_url('t/dock_to_block', 'moodle')+'" alt="'+M.str.block.undockitem+'" title="'+M.str.block.undockitem+'" />'));
+        var moveto = Y.Node.create('<a class="moveto customcommand requiresjs"></a>').append(Y.Node.create('<img src="'+M.util.image_url('t/dock_to_block', 'moodle')+'" alt="'+M.str.block.undockitem+'" title="'+M.str.block.undockitem+'" />'));
         if (location.href.match(/\?/)) {
             moveto.set('href', location.href+'&dock='+this.id);
         } else {
@@ -406,32 +699,27 @@
         blockcommands.append(moveto);
 
         // Create a new dock item for the block
-        var dockitem = new M.core_dock.item(this.Y, this.id, blocktitle, blockcontent, blockcommands, blockclass);
-        if (spacewidth !== null && M.core_dock.cfg.display.mindisplaywidth == null) {
-            dockitem.cfg.display.mindisplaywidth = spacewidth;
-        }
+        var dockitem = new dock.item(Y, this.id, blocktitle, blockcontent, blockcommands, blockclass);
         // Wire the draw events to register remove events
         dockitem.on('dockeditem:drawcomplete', function(e){
             // check the contents block [editing=off]
             this.contents.all('.moveto').on('returntoblock|click', function(e){
                 e.halt();
-                M.core_dock.remove(this.id)
+                dock.remove(this.id)
             }, this);
             // check the commands block [editing=on]
             this.commands.all('.moveto').on('returntoblock|click', function(e){
                 e.halt();
-                M.core_dock.remove(this.id)
+                dock.remove(this.id)
             }, this);
             // Add a close icon
-            var closeicon = this.Y.Node.create('<span class="hidepanelicon"><img src="'+M.util.image_url('t/dockclose', 'moodle')+'" alt="" style="width:11px;height:11px;cursor:pointer;" /></span>');
-            closeicon.on('forceclose|click', M.core_dock.hide_all, M.core_dock);
-            closeicon.on('forceclose|click', M.core_dock.hide_all, M.core_dock);
+            var closeicon = Y.Node.create('<span class="hidepanelicon"><img src="'+M.util.image_url('t/dockclose', 'moodle')+'" alt="" style="width:11px;height:11px;cursor:pointer;" /></span>');
+            closeicon.on('forceclose|click', this.hide, this);
             this.commands.append(closeicon);
         }, dockitem);
-
         // Register an event so that when it is removed we can put it back as a block
-        dockitem.on('dockitem:itemremoved', this.return_to_block, this, dockitem);
-        M.core_dock.add(dockitem);
+        dockitem.on('dockeditem:itemremoved', this.return_to_block, this, dockitem);
+        dock.add(dockitem);
 
         if (!this.skipsetposition) {
             // save the users preference
@@ -439,109 +727,10 @@
         } else {
             this.skipsetposition = false;
         }
-    },
-    /**
-     * Corrects the orientation of the title, which for the default
-     * dock just means making it vertical
-     * @param {YUI.Node} node
-     */
-    fix_title_orientation : function(node) {
-        var title = node.firstChild.nodeValue;
 
-        if (YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 8) {
-            M.str.langconfig.thisdirectionvertical = 'ver';
-        }
-
-        var clockwise = false;
-        switch (M.str.langconfig.thisdirectionvertical) {
-            case 'ver':
-                title = title.split('').join('<br />');
-                node.innerHTML = title;
-                return node;
-            case 'ttb':
-                clockwise = true;
-                break;
-            case 'btt':
-                clockwise = false;
-                break;
-        }
-
-        if (YAHOO.env.ua.ie > 7) {
-            // IE8 can flip the text via CSS
-            node.setAttribute('style', 'writing-mode: tb-rl; filter: flipV flipH;');
-            return node;
-        }
-
-        // Cool, we can use SVG!
-        var test = M.core_dock.Y.Node.create('<div><span style="font-size:10pt;">'+title+'</span></div>');
-        M.core_dock.Y.one(document.body).append(test);
-        var height = test.one('span').get('offsetWidth');
-        var width = test.one('span').get('offsetHeight')*2;
-        var qwidth = width/4;
-        test.remove();
-
-        var txt = document.createElementNS('http://www.w3.org/2000/svg', 'text');
-        txt.setAttribute('font-size', '10');
-        if (clockwise) {
-            txt.setAttribute('transform','rotate(90 '+(qwidth/2)+' '+qwidth+')');
-        } else {
-            txt.setAttribute('y', height);
-            txt.setAttribute('transform','rotate(270 '+qwidth+' '+(height-qwidth)+')');
-        }
-        txt.appendChild(document.createTextNode(node.firstChild.nodeValue));
-
-        var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
-        svg.setAttribute('version', '1.1');
-        svg.setAttribute('height', height);
-        svg.setAttribute('width', width);
-        svg.appendChild(txt);
-
-        var div = document.createElement(node.nodeName);
-        div.appendChild(svg);
-
-        return div;
+        this.isdocked = true;
     },
     /**
-     * Resizes the space that contained blocks if there were no blocks left in
-     * it. e.g. if all blocks have been moved to the dock
-     * @param {Y.Node} node
-     */
-    resize_block_space : function(node) {
-        var blockregions = [];
-        var populatedblockregions = 0;
-        M.core_dock.Y.all('.block-region').each(function(region){
-            var hasblocks = (region.all('.block').size() > 0);
-            if (hasblocks) {
-                populatedblockregions++;
-            }
-            blockregions[region.get('id')] = {hasblocks: hasblocks, bodyclass: region.get('id').replace(/^region\-/, 'side-')+'-only'};
-        });
-        var bodynode = M.core_dock.Y.one(document.body);
-        var noblocksbodyclass = 'content-only';
-        var i = null;
-        if (populatedblockregions==0) {
-            bodynode.addClass(noblocksbodyclass);
-            for (i in blockregions) {
-                bodynode.removeClass(blockregions[i].bodyclass);
-            }
-        } else if (populatedblockregions==1) {
-            bodynode.removeClass(noblocksbodyclass);
-            for (i in blockregions) {
-                if (!blockregions[i].hasblocks) {
-                    bodynode.removeClass(blockregions[i].bodyclass);
-                } else {
-                    bodynode.addClass(blockregions[i].bodyclass);
-                }
-            }
-        } else {
-            bodynode.removeClass(noblocksbodyclass);
-            for (i in blockregions) {
-                bodynode.removeClass(blockregions[i].bodyclass);
-            }
-        }
-        return '200px';
-    },
-    /**
      * This function removes a block from the dock and puts it back into the page
      * structure.
      * @param {M.core_dock.class.item}
@@ -558,10 +747,7 @@
         placeholder.replace(this.Y.Node.getDOMNode(this.cachedcontentnode));
         this.cachedcontentnode = this.Y.one('#'+this.cachedcontentnode.get('id'));
 
-        this.resize_block_space(this.cachedcontentnode);
-
-
-        var commands = this.cachedcontentnode.one('.commands');
+        var commands = this.cachedcontentnode.one('.title .commands');
         if (commands) {
             commands.all('.hidepanelicon').remove();
             commands.all('.moveto').remove();
@@ -570,13 +756,14 @@
         this.cachedcontentnode.one('.title').append(commands);
         this.cachedcontentnode = null;
         M.util.set_user_preference('docked_block_instance_'+this.id, 0);
+        this.isdocked = false;
         return true;
     }
 }
 
 /**
  * This class represents an item in the dock
- * @class item
+ * @class M.core_dock.item
  * @constructor
  * @param {YUI} Y The YUI instance to use for this item
  * @param {int} uid The unique ID for the item
@@ -591,7 +778,9 @@
         this.id = uid;
     }
     if (title && this.title==null) {
-        this.title = title;
+        this.titlestring = title.cloneNode(true);
+        this.title = document.createElement(title.nodeName);
+        var fixedtitle = M.core_dock.fixTitleOrientation(this.title, this.titlestring.firstChild.nodeValue);
     }
     if (contents && this.contents==null) {
         this.contents = contents;
@@ -602,8 +791,16 @@
     if (blockclass && this.blockclass==null) {
         this.blockclass = blockclass
     }
-    this.cfg = M.core_dock.cfg;
-    this.init_events();
+    this.nodes = (function(){
+        return {docktitle : null, dockitem : null, container: null}
+    })();
+    this.publish('dockeditem:drawstart', {prefix:'dockeditem'});
+    this.publish('dockeditem:drawcomplete', {prefix:'dockeditem'});
+    this.publish('dockeditem:showstart', {prefix:'dockeditem'});
+    this.publish('dockeditem:showcomplete', {prefix:'dockeditem'});
+    this.publish('dockeditem:hidestart', {prefix:'dockeditem'});
+    this.publish('dockeditem:hidecomplete', {prefix:'dockeditem'});
+    this.publish('dockeditem:itemremoved', {prefix:'dockeditem'});
 }
 /**
  *
@@ -613,234 +810,73 @@
     id : null,              // The unique id for the item
     name : null,            // The name of the item
     title : null,           // The title of the item
+    titlestring : null,     // The title as a plain string
     contents : null,        // The content of the item
     commands : null,        // The commands for the item
     active : false,         // True if the item is being shown
-    panel : null,           // The YUI2 panel the item will be shown in
-    preventhide : false,    // If true the next call to hide will be ignored
-    cfg : null,             // The config options for this item by default M.core_dock.cfg
-    blockclass : null,
-    delayhiderunning : false,
-    delayhidetimeout : 1000, // 1 Second
-
+    blockclass : null,      // The class of the block this item relates to
+    nodes : null,
     /**
-     * Initialises all of the items events
-     * @function
-     */
-    init_events : function() {
-        this.publish('dockeditem:drawstart', {prefix:'dockeditem'});
-        this.publish('dockeditem:drawcomplete', {prefix:'dockeditem'});
-        this.publish('dockeditem:showstart', {prefix:'dockeditem'});
-        this.publish('dockeditem:showcomplete', {prefix:'dockeditem'});
-        this.publish('dockeditem:hidestart', {prefix:'dockeditem'});
-        this.publish('dockeditem:hidecomplete', {prefix:'dockeditem'});
-        this.publish('dockeditem:resizestart', {prefix:'dockeditem'});
-        this.publish('dockeditem:resizecomplete', {prefix:'dockeditem'});
-        this.publish('dockeditem:itemremoved', {prefix:'dockeditem'});
-    },
-
-    /**
      * This function draws the item on the dock
      */
     draw : function() {
         this.fire('dockeditem:drawstart');
-        var dockitemtitle = this.Y.Node.create('<div id="dock_item_'+this.id+'_title" class="'+this.cfg.css.dockedtitle+'"></div>');
-        dockitemtitle.append(this.title);
-        var dockitem = this.Y.Node.create('<div id="dock_item_'+this.id+'" class="'+this.cfg.css.dockeditem+'"></div>');
+
+        var Y = this.Y;
+        var css = M.core_dock.css;
+
+        this.nodes.docktitle = Y.Node.create('<div id="dock_item_'+this.id+'_title" class="'+css.dockedtitle+'"></div>');
+        this.nodes.docktitle.append(this.title);
+        this.nodes.dockitem = Y.Node.create('<div id="dock_item_'+this.id+'" class="'+css.dockeditem+'"></div>');
         if (M.core_dock.count === 1) {
-            dockitem.addClass('firstdockitem');
+            this.nodes.dockitem.addClass('firstdockitem');
         }
-        dockitem.append(dockitemtitle);
-        M.core_dock.append(dockitem);
-
-        var position = dockitemtitle.getXY();
-        position[0] += parseInt(dockitemtitle.get('offsetWidth'));
-        if (YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 8) {
-            position[0] -= 2;
-        }
-        this.panel = new YAHOO.widget.Panel('dock_item_panel_'+this.id, {
-            close:this.cfg.panel.close,
-            draggable:this.cfg.panel.draggable,
-            underlay:this.cfg.panel.underlay,
-            modal: this.cfg.panel.modal,
-            keylisteners: this.cfg.panel.keylisteners,
-            visible:this.cfg.panel.visible,
-            effect:this.cfg.panel.effect,
-            monitorresize:this.cfg.panel.monitorresize,
-            context: this.cfg.panel.context,
-            fixedcenter: this.cfg.panel.fixedcenter,
-            zIndex: this.cfg.panel.zIndex,
-            constraintoviewport: this.cfg.panel.constraintoviewport,
-            xy:position,
-            autofillheight:this.cfg.panel.autofillheight});
-        this.panel.showEvent.subscribe(this.resize_panel, this, true);
-        this.panel.showMaskEvent.subscribe(function(){
-            this.Y.one(this.panel.mask).setStyle('zIndex', this.cfg.panel.modalzindex);
-        }, this, true);
-        if (this.commands.hasChildNodes) {
-            this.panel.setHeader(this.Y.Node.getDOMNode(this.commands));
-        }
-        this.panel.setBody(this.Y.Node.getDOMNode(this.contents));
-        this.panel.render(M.core_dock.node);
-        this.Y.one(this.panel.body).addClass(this.blockclass);
-        if (this.cfg.display.mindisplaywidth !== null && this.Y.one(this.panel.body).getStyle('minWidth') == '0px') {
-            this.Y.one(this.panel.body).setStyle('minWidth', this.cfg.display.mindisplaywidth);
-            this.Y.one(this.panel.body).setStyle('minHeight', dockitemtitle.get('offsetHeight')+'px');
-        }
-        dockitem.on('showitem|mouseover', this.show, this);
-        dockitem.on('showitem|click', this.show, this);
+        this.nodes.dockitem.append(this.nodes.docktitle);
+        M.core_dock.append(this.nodes.dockitem);
         this.fire('dockeditem:drawcomplete');
+        return true;
     },
     /**
-     * This function removes the node and destroys it's bits
-     * @param {Event} e
-     */
-    remove : function (e) {
-        this.hide(e);
-        this.Y.one('#dock_item_'+this.id).remove();
-        this.panel.destroy();
-        this.fire('dockitem:itemremoved');
-    },
-    /**
      * This function toggles makes the item active and shows it
-     * @param {event}
      */
-    show : function(e) {
-        M.core_dock.hide_all();
+    show : function() {
+        M.core_dock.hideActive();
+        var Y = this.Y;
+        var css = M.core_dock.css;
+        var panel = M.core_dock.getPanel();
         this.fire('dockeditem:showstart');
-        this.panel.show(e, this);
+        panel.setHeader(this.titlestring, this.commands);
+        panel.setBody(Y.Node.create('<div class="'+this.blockclass+' block_docked"></div>').append(this.contents));
+        panel.show();
+        
         this.active = true;
         // Add active item class first up
-        this.Y.one('#dock_item_'+this.id+'_title').addClass(this.cfg.css.activeitem);
-        // Remove the two show event listeners
-        this.Y.detach('mouseover', this.show, this.Y.one('#dock_item_'+this.id));
-        this.Y.detach('click', this.show, this.Y.one('#dock_item_'+this.id));
-        // Add control events to ensure we don't cause annoyance
-        this.Y.one('#dock_item_panel_'+this.id).on('dockpreventhide|click', function(){this.preventhide=true;}, this);
-        // Add resize event so we keep it viewable
-        this.Y.get(window).on('dockresize|resize', this.resize_panel, this);
-
-        // If the event was fired by mouse over then we also want to hide when
-        // the user moves the mouse out of the area
-        if (e.type == 'mouseover') {
-            this.Y.one(this.panel.element).on('dockhide|mouseleave', this.delay_hide, this);
-            this.preventhide = true;
-            setTimeout(function(obj){
-                if (obj.preventhide) {
-                    obj.preventhide = false;
-                }
-            }, 1000, this);
-        }
-
-        // Attach the default hide events, clicking the heading or the body
-        this.Y.one('#dock_item_'+this.id).on('dockhide|click', this.hide, this);
-        this.Y.get(document.body).on('dockhide|click', this.hide, this);
-
+        this.nodes.docktitle.addClass(css.activeitem);
         this.fire('dockeditem:showcomplete');
+        M.core_dock.resize();
         return true;
     },
     /**
      * This function hides the item and makes it inactive
-     * @param {event} e
-     * @param {boolean} ignorepreventhide If true preventhide is ignored
      */
-    hide : function(e) {
-        // Check whether a second argument has been passed
-        var ignorepreventhide = (arguments.length==2 && arguments[1]);
-        // Ignore this call is preventhide is true
-        if (this.preventhide===true && !ignorepreventhide) {
-            this.preventhide = false;
-            if (e) {
-                // Stop all propagation immediatly or the next element (likely body)
-                // will fire this event again and the item will hide
-                e.stopImmediatePropagation();
-            }
-        } else if (this.active) {
-            // Display any hide delay running, mouseleave-mouseenter-click
-            this.delayhiderunning = false;
+    hide : function() {
+        var css = M.core_dock.css;
             this.fire('dockeditem:hidestart');
             // No longer active
             this.active = false;
             // Remove the active class
-            this.Y.one('#dock_item_'+this.id+'_title').removeClass(this.cfg.css.activeitem);
-            // Add the show event again
-            this.Y.one('#dock_item_'+this.id).on('showitem|mouseover', this.show, this);
-            // Remove the hide events
-            this.Y.detach('mouseleave', this.delayhide, this.Y.one(this.panel.element));
-            this.Y.get(window).detach('dockresize|resize');
-            this.Y.get(document.body).detach('dockhide|click');
+        this.nodes.docktitle.removeClass(css.activeitem);
             // Hide the panel
-            this.panel.hide(e, this);
+        M.core_dock.getPanel().hide();
             this.fire('dockeditem:hidecomplete');
-        }
     },
     /**
-     * This function sets the item to hide after a specific delay, that delay is
-     * this.delayhidetimeout.
+     * This function removes the node and destroys it's bits
      * @param {Event} e
      */
-    delay_hide : function(e) {
-        // The hide delay timeout is running now
-        this.delayhiderunning = true;
-        // Add the re-enter event to cancel the delay timeout
-        var delayhideevent = this.Y.one(this.panel.element).on('delayhide|mouseover', function(){this.delayhiderunning = false;}, this);
-        // Set the timeout + callback and pass the this for scope and the event so
-        // it can be easily detached
-        setTimeout(function(obj, ev){
-            if (obj.delayhiderunning) {
-                ev.detach();
-                obj.hide();
+    remove : function () {
+        this.hide();
+        this.nodes.dockitem.remove();
+        this.fire('dockeditem:itemremoved');
             }
-        }, this.delayhidetimeout, this, delayhideevent);
-    },
-    /**
-     * This function checks the size and position of the panel and moves/resizes if
-     * required to keep it within the bounds of the window.
-     */
-    resize_panel : function() {
-        this.fire('dockeditem:resizestart');
-
-        var panelheader = this.Y.one(this.panel.header);
-        panelheader = (panelheader)?panelheader.get('offsetHeight'):0;
-        var panelbody = this.Y.one(this.panel.body);
-
-        var buffer = this.cfg.buffer;
-        var screenheight = parseInt(this.Y.get(document.body).get('winHeight'));
-        var panelheight = parseInt(panelheader + panelbody.get('offsetHeight'));
-        var paneltop = parseInt(this.panel.cfg.getProperty('y'));
-        var titletop = parseInt(this.Y.one('#dock_item_'+this.id+'_title').getY());
-        var scrolltop = window.pageYOffset || document.body.scrollTop || 0;
-
-        // This makes sure that the panel is the same height as the dock title to
-        // begin with
-        if (paneltop > (buffer+scrolltop) && paneltop > (titletop+scrolltop)) {
-            this.panel.cfg.setProperty('y', titletop+scrolltop);
         }
-
-        // This makes sure that if the panel is big it is moved up to ensure we don't
-        // have wasted space above the panel
-        if ((paneltop+panelheight)>(screenheight+scrolltop) && paneltop > buffer) {
-            paneltop = (screenheight-panelheight-buffer);
-            if (paneltop<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*3));
-            panelbody.setStyle('height', (screenheight-panelheader-(buffer*3)-10)+'px');
-            panelbody.addClass('oversized_content');
-        }
-        this.fire('dockeditem:resizecomplete');
-    }
-}
-
-/**
- * This ensures that the first time the dock module is used it is initiatlised.
- * 
- * NOTE: Never convert the second argument to a function reference...
- * doing so causes scoping issues
- */
-YUI.add('core_dock', function(Y) {M.core_dock.init(Y);}, '0.0.0.1', 'requires', M.yui.loader.modules['core_dock'].requires);
Index: moodle/blocks/navigation/block_navigation.php
--- moodle/blocks/navigation/block_navigation.php Base (1.4)
+++ moodle/blocks/navigation/block_navigation.php Locally Modified (Based On 1.4)
@@ -92,8 +92,6 @@
 
     function get_required_javascript() {
         global $CFG;
-        $this->page->requires->js_module(array('name'=>'core_dock', 'fullpath'=>'/blocks/dock.js', 'requires'=>array('base', 'cookie', 'dom', 'io', 'node', 'event-custom', 'event-mouseenter', 'yui2-container')));
-        $this->page->requires->js_module(array('name'=>'block_navigation', 'fullpath'=>'/blocks/navigation/navigation.js', 'requires'=>array('core_dock', 'io', 'node', 'dom', 'event-custom', 'json-parse')));
         user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT);
     }
 
@@ -162,14 +160,13 @@
         $navigation->find_expandable($expandable);
 
         // Initialise the JS tree object
-        $module = array('name'=>'block_navigation', 'fullpath'=>'/blocks/navigation/navigation.js', 'requires'=>array('core_dock', 'io', 'node', 'dom', 'event-custom', 'json-parse'));
+        $module = array('name'=>'block_navigation', 'fullpath'=>'/blocks/navigation/navigation.js', 'requires'=>array('core_dock', 'io', 'node', 'dom', 'event-custom', 'json-parse'), 'strings'=>array(array('viewallcourses','moodle')));
         $limit = 20;
         if (!empty($CFG->navcourselimit)) {
             $limit = $CFG->navcourselimit;
         }
         $arguments = array($this->instance->id, array('expansions'=>$expandable, 'instance'=>$this->instance->id, 'candock'=>$this->instance_can_be_docked(), 'courselimit'=>$limit));
         $this->page->requires->js_init_call('M.block_navigation.init_add_tree', $arguments, false, $module);
-        $this->page->requires->string_for_js('viewallcourses','moodle');
 
         // Grab the items to display
         $renderer = $this->page->get_renderer('block_navigation');
Index: moodle/blocks/navigation/navigation.js
--- moodle/blocks/navigation/navigation.js Base (1.6)
+++ moodle/blocks/navigation/navigation.js Locally Modified (Based On 1.6)
@@ -47,6 +47,7 @@
      * @function
      */
     init:function(Y) {
+        M.core_dock.init(Y);
         if (M.core_dock.genericblock) {
             // Give the tree class the dock block properties
             Y.augment(M.block_navigation.classes.tree, M.core_dock.genericblock);
Index: moodle/blocks/settings/block_settings.php
--- moodle/blocks/settings/block_settings.php Base (1.1)
+++ moodle/blocks/settings/block_settings.php Locally Modified (Based On 1.1)
@@ -83,7 +83,6 @@
 
     function get_required_javascript() {
         global $CFG;
-        $this->page->requires->js_module(array('name'=>'core_dock', 'fullpath'=>'/blocks/dock.js', 'requires'=>array('base', 'cookie', 'dom', 'io', 'node', 'event-custom', 'event-mouseenter', 'yui2-container')));
         $module = array('name'=>'block_navigation', 'fullpath'=>'/blocks/navigation/navigation.js', 'requires'=>array('core_dock', 'io', 'node', 'dom', 'event-custom', 'json-parse'));
         $arguments = array($this->instance->id, array('instance'=>$this->instance->id, 'candock'=>$this->instance_can_be_docked()));
         $this->page->requires->js_init_call('M.block_navigation.init_add_tree', $arguments, false, $module);
Index: moodle/lib/blocklib.php
--- moodle/lib/blocklib.php Base (1.249)
+++ moodle/lib/blocklib.php Locally Modified (Based On 1.249)
@@ -413,6 +413,26 @@
         $this->extracontent[$region][] = $bc;
     }
 
+    /**
+     * Checks to see whether all of the blocks within the given region are docked
+     *
+     * @param string $region
+     * @return bool True if all of the blocks within that region are docked
+     */
+    public function region_completely_docked($region, $output) {
+        if (!$this->page->theme->enable_dock) {
+            return false;
+        }
+        $this->check_is_loaded();
+        $this->ensure_content_created($region, $output);
+        foreach($this->visibleblockcontent[$region] as $instance) {
+            if (!empty($instance->content) && !get_user_preferences('docked_block_instance_'.$instance->blockinstanceid, 0)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
 /// Actions ====================================================================
 
     /**
Index: moodle/lib/outputrequirementslib.php
--- moodle/lib/outputrequirementslib.php Base (1.32)
+++ moodle/lib/outputrequirementslib.php Locally Modified (Based On 1.32)
@@ -380,7 +380,7 @@
                 case 'core_dock':
                     $module = array('name'     => 'core_dock',
                                     'fullpath' => '/blocks/dock.js',
-                                    'requires' => array('base', 'cookie', 'dom', 'io', 'node', 'event-custom', 'event-mouseenter', 'yui2-container'),
+                                    'requires' => array('base', 'node', 'event-custom', 'event-mouseenter', 'event-resize'),
                                     'strings' => array(array('addtodock', 'block'),array('undockitem', 'block'),array('undockall', 'block'),array('thisdirectionvertical', 'langconfig')));
                     break;
                 case 'core_calendar':
Index: moodle/theme/.cvsignore
--- moodle/theme/.cvsignore No Base Revision
+++ moodle/theme/.cvsignore Locally New
@@ -0,0 +1 @@
+.DS_Store
Index: moodle/theme/base/config.php
--- moodle/theme/base/config.php Base (1.14)
+++ moodle/theme/base/config.php Locally Modified (Based On 1.14)
@@ -44,6 +44,7 @@
     'blocks',
     'calendar',
     'course',
+    'dock',
     'grade',
     'message',
     'question',
Index: moodle/theme/base/layout/frontpage.php
--- moodle/theme/base/layout/frontpage.php Base (1.6)
+++ moodle/theme/base/layout/frontpage.php Locally Modified (Based On 1.6)
@@ -2,16 +2,18 @@
 
 $hassidepre = $PAGE->blocks->region_has_content('side-pre', $OUTPUT);
 $hassidepost = $PAGE->blocks->region_has_content('side-post', $OUTPUT);
+$showsidepre = $hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT);
+$showsidepost = $hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT);
 
 $custommenu = $OUTPUT->custom_menu();
 $hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu));
 
 $bodyclasses = array();
-if ($hassidepre && !$hassidepost) {
+if ($showsidepre && !$showsidepost) {
     $bodyclasses[] = 'side-pre-only';
-} else if ($hassidepost && !$hassidepre) {
+} else if ($showsidepost && !$showsidepre) {
     $bodyclasses[] = 'side-post-only';
-} else if (!$hassidepost && !$hassidepre) {
+} else if (!$showsidepost && !$showsidepre) {
     $bodyclasses[] = 'content-only';
 }
 if ($hascustommenu) {
Index: moodle/theme/base/layout/general.php
--- moodle/theme/base/layout/general.php Base (1.8)
+++ moodle/theme/base/layout/general.php Locally Modified (Based On 1.8)
@@ -6,15 +6,18 @@
 $hassidepre = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-pre', $OUTPUT));
 $hassidepost = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-post', $OUTPUT));
 
+$showsidepre = ($hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT));
+$showsidepost = ($hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT));
+
 $custommenu = $OUTPUT->custom_menu();
 $hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu));
 
 $bodyclasses = array();
-if ($hassidepre && !$hassidepost) {
+if ($showsidepre && !$showsidepost) {
     $bodyclasses[] = 'side-pre-only';
-} else if ($hassidepost && !$hassidepre) {
+} else if ($showsidepost && !$showsidepre) {
     $bodyclasses[] = 'side-post-only';
-} else if (!$hassidepost && !$hassidepre) {
+} else if (!$showsidepost && !$showsidepre) {
     $bodyclasses[] = 'content-only';
 }
 if ($hascustommenu) {
@@ -82,7 +85,6 @@
                     </div>
                 </div>
                 <?php } ?>
-                
             </div>
         </div>
     </div>
Index: moodle/theme/base/style/dock.css
--- moodle/theme/base/style/dock.css No Base Revision
+++ moodle/theme/base/style/dock.css Locally New
@@ -0,0 +1,28 @@
+/**
+ * Whilst the dock isn't supported by the base theme this CSS is here so that those
+ * themes that do want to use the dock will have a starting point at least
+ */
+
+/* Put a margin on the body if the dock is shown */
+body.has_dock {margin-left:30px;}
+
+/** For the dock itself */
+#dock {width:30px;position:fixed;top:0px;left:0px;height:100%;background-color:#FFF;border-right:1px solid #000;z-index:11000;}
+#dock.nothingdocked {visibility: hidden;display:none;}
+#dock .dockeditem .firstdockitem {margin-top:1em;}
+#dock .dockeditem .dockedtitle {border-bottom:1px solid #000;border-top:1px solid #000;cursor:pointer;}
+#dock .dockeditem .dockedtitle h2 {font-size:0.8em;line-height:100%;text-align:center;}
+#dock .dockeditem .dockedtitle .filterrotate {margin-left:8px;}
+#dock .controls {position:absolute;bottom:1em;text-align:center;width:100%;}
+#dock .controls img {cursor:pointer;}
+
+/** For the panel the docked blocks are shown in */
+#dockeditempanel {min-width:200px;position:relative;z-index:12000;left:100%;}
+#dockeditempanel.dockitempanel_hidden {display:none;}
+#dockeditempanel .dockeditempanel_content {background-color:#fff;border:1px solid #000;z-index:12050;}
+#dockeditempanel .dockeditempanel_bd {overflow:auto;width:auto;}
+#dockeditempanel .dockeditempanel_bd .block_docked {margin:10px;}
+#dockeditempanel .dockeditempanel_hd {border-bottom:1px solid #000;text-align:right;}
+#dockeditempanel .dockeditempanel_hd h2 {display:inline;margin:0;padding-right:1em;}
+#dockeditempanel .dockeditempanel_hd .commands {display:inline;}
+#dockeditempanel .dockeditempanel_hd .commands img {margin-right:2px;vertical-align:middle;}
Index: moodle/theme/standard/javascript/navigation.js
--- moodle/theme/standard/javascript/navigation.js Base (1.7)
+++ moodle/theme/standard/javascript/navigation.js Locally Deleted
@@ -1,9 +0,0 @@
-
-function customise_dock_for_theme() {
-    if (!M.core_dock) {
-        return false;
-    }
-    // Throw a lightbox for the navigation boxes
-    M.core_dock.cfg.panel.modal = true;
-    return true;
-}
Index: moodle/theme/standard/style/dock.css
--- moodle/theme/standard/style/dock.css Base (1.3)
+++ moodle/theme/standard/style/dock.css Locally Modified (Based On 1.3)
@@ -1,54 +1,28 @@
-/** Core overrides **/
-body.has_dock {margin-left:30px;margin-right:30px;}
+/* For the dock and items on the dock */
+#dock {background-image:url([[pix:theme|vgradient]]);background-repeat: repeat-y;background-position:100% 0;background-color:#DDD;border-right-color:#AAA;}
+#dock .dockeditem_container {margin-top:10px;}
+#dock .dockeditem {background-color:#DDD;}
+#dock .dockeditem .firstdockitem {margin-top:1em;}
+#dock .dockeditem .dockedtitle {border-color:#AAA;background-image:url([[pix:theme|vgradient]]);background-position:90% 0;background-repeat: repeat-y;}
+#dock .dockeditem .dockedtitle.activeitem {background-position:80% 0;}
+#dock .dockeditem .dockedtitle h2 {margin:12px 0px;}
 
-/* This CSS is for the dock */
-.dock {width:30px;position:fixed;top:0px;left:0px;height:100%;background-image:url([[pix:theme|vgradient]]);background-repeat: repeat-y;background-position:100% 0;background-color:#DDD;border-right:1px solid #AAA;z-index:2002;}
-.dock .dockeditem {background-color:#DDD;}
-.dock .dockeditem .firstdockitem {margin-top:1em;}
-.dock .dockeditem .dockedtitle {border-bottom:1px solid #AAA;border-top:1px solid #CCC;cursor:pointer;background-image:url([[pix:theme|vgradient]]);background-position:90% 0;background-repeat: repeat-y;}
-.dock .dockeditem .dockedtitle.activeitem {background-position:80% 0;}
-.dock .dockeditem .dockedtitle h2 {font-size:0.8em;line-height:100%;text-transform:uppercase;text-align:center;margin:12px 0px;}
-.dock .block_tree .current_branch {}
-.dock .controls {position:absolute;bottom:1em;text-align:center;width:100%;}
-.dock .controls img {cursor:pointer;}
-.dock .bd.oversized_content {overflow-y:auto;overflow-x:visible;height:inherit;}
-.dock .bd.oversized_content .content {margin:6px 6px 6px 0px;padding-bottom:6px;}
-.dock .yui-panel .hd {text-align:right;border-width:0 0 1px 0;padding:3px 5px;}
-.dock .yui-panel .hd .commands img {margin-right:2px;}
+/** For the panel the docked blocks are shown in */
+#dockeditempanel .dockeditempanel_content {border-color:#AAA;margin-left:-1px;}
+#dockeditempanel .dockeditempanel_hd {border-bottom-color:#AAA;padding:3px 5px;background-image:url([[pix:theme|hgradient]]);}
+#dockeditempanel .dockeditempanel_hd h2 {font-size:80%;color:#999;}
 
-/**.dock .bd .content .blockcommands {text-align:right;border:1px solid #AAA;border-width:0 0 1px 1px;background-image:url([[pix:theme|hgradient]]);background-repeat: repeat-x;}**/
-/** YUI overrides **/
-.yui-skin-sam .dock .yui-panel {border-width:1px 2px 1px 1px;border-color:#AAA;min-width:150px;}
-.yui-skin-sam .dock .yui-panel .bd {border-width:0;background-color:#FAFAFA;}
-/** Override the above if the dock is on the right **/
-.dock.dock_right_vertical {left:auto;right:0px;border-width:0px 0px 1px 5px;}
-.dock.dock_right_vertical .commands {text-align:right;}
-.yui-skin-sam .dock.dock_right_vertical .yui-panel {border-width:1px 0 1px 5px;}
-
 /* block expansion code */
 .block_js_expansion .block_tree {overflow-x:scroll;}
 .block_js_expansion.mouseover .content {width:200%;z-index:1000;position:relative;}
 .block_js_expansion.mouseover .content .block_tree {width:100%; background-color:#FAFAFA; 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 .block .block_tree {width:160px;overflow-x:scroll;}
-.ie7 .block .block_tree {overflow-x:scroll;}
 .ie6 .block_tree .tree_item {width:100%;}
-.ie6 .dock {position:absolute;}
-.ie6 .dock hr {display:none;margin:0px;height:0px;padding:0px;}
-.ie6 .dock li p {background-color:inherit;}
-.ie6 .dock .bd.oversized_content .content, .ie7 .dock .bd.oversized_content .content {padding-bottom:0px;}
+.ie6 #dock {position:absolute;}
+.ie6 #dock hr {display:none;margin:0px;height:0px;padding:0px;}
+.ie6 #dock li p {background-color:inherit;}
+.ie6 #dock .bd.oversized_content .content, .ie7 #dock .bd.oversized_content .content {padding-bottom:0px;}
 .ie6 .block_js_expansion.mouseover .content, .ie7 .block_js_expansion.mouseover .content{ padding-bottom:2px;}
-.ie6 .dock .bd.oversized_content {width:100%;}
-.ie7 .dock .bd.oversized_content {width:400px;}
+.ie6 #dock .bd.oversized_content {width:100%;}
