# 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 No Base Revision
+++ moodle/blocks/dock.js Locally New
@@ -0,0 +1,700 @@
+/**
+ * START OF BLOCKS CODE
+ * This code can be included in the footer instead of the header if we ever
+ * have a static JS file that will be loaded in the footer.
+ * Once this is done we will then also be able to remove the blocks.dock.init
+ * function and call
+ */
+
+/**
+ * This namespace will contain all of content (functions, classes, properties)
+ * for the block system
+ * @namespace
+ */
+M.blocks = M.blocks || {};
+
+/**
+ * The dock namespace: Contains all things dock related
+ * @namespace
+ */
+M.blocks.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
+    /**
+     * Strings used by the dock/dockitems
+     * @namespace
+     */
+    strings:{
+        addtodock : '[[addtodock]]',
+        undockitem : '[[undockitem]]',
+        undockall : '[[undockall]]'
+    },
+    /**
+     * Configuration parameters used during the initialisation and setup
+     * of dock and dock items.
+     * This is here specifically so that themers can override core parameters and
+     * design aspects without having to re-write navigation
+     * @namespace
+     */
+    cfg:{
+        buffer:10,                          // Buffer used when containing a panel
+        position:'left',                    // position of the dock
+        orientation:'vertical',             // vertical || horizontal determines if we change the title
+        /**
+         * Display 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
+        },
+        /**
+         * CSS classes to use with the dock
+         * @namespace
+         */
+        css: {
+            dock:'dock',                    // CSS Class applied to the dock box
+            dockspacer:'dockspacer',        // CSS class applied to the dockspacer
+            controls:'controls',            // CSS class applied to the controls box
+            body:'has_dock',                // CSS class added to the body when there is a dock
+            dockeditem:'dockeditem',        // CSS class added to each item in the dock
+            dockedtitle:'dockedtitle',      // CSS class added to the item's title in each dock
+            activeitem:'activeitem'         // CSS class added to the active item
+        },
+        /**
+         * 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
+            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
+        }
+    },
+    /**
+     * Augments the classes as required and processes early bindings
+     */
+    init:function() {
+        // Give the dock item class the event properties/methods
+        Y.augment(M.blocks.dock.item, Y.EventTarget);
+        Y.augment(M.blocks.dock, Y.EventTarget, true);
+        // Re-apply early bindings properly now that we can
+        M.blocks.dock.apply_binds();
+    },
+    /**
+     * Adds a dock item into the dock
+     * @function
+     * @param {M.blocks.dock.item} item
+     */
+    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);
+    },
+    append : function(docknode) {
+        M.blocks.dock.node.one('#dock_item_container').append(docknode);
+    },
+    /**
+     * Draws the dock
+     * @function
+     * @return bool
+     */
+    draw:function() {
+        if (this.node !== null) {
+            return true;
+        }
+        this.fire('dock:drawstarted');
+        this.item_sizer.init();
+        this.node = Y.Node.create('<div id="dock" class="'+M.blocks.dock.cfg.css.dock+' '+M.blocks.dock.cfg.css.dock+'_'+M.blocks.dock.cfg.position+'_'+M.blocks.dock.cfg.orientation+'"></div>');
+        this.node.appendChild(Y.Node.create('<div class="'+M.blocks.dock.cfg.css.dockspacer+'" style="height:'+M.blocks.dock.cfg.display.spacebeforefirstitem+'px"></div>'));
+        this.node.appendChild(Y.Node.create('<div id="dock_item_container"></div>'));
+        if (Y.UA.ie > 0 && Y.UA.ie < 7) {
+            this.node.setStyle('height', this.node.get('winHeight')+'px');
+        }
+
+        var dockcontrol = Y.Node.create('<div class="'+M.blocks.dock.cfg.css.controls+'"></div>');
+        var removeall = Y.Node.create('<img src="'+get_image_url('t/dock_to_block', 'moodle')+'" alt="'+mstr.block.undockall+'" title="'+mstr.block.undockall+'" />');
+        removeall.on('removeall|click', this.remove_all, this);
+        dockcontrol.appendChild(removeall);
+        this.node.appendChild(dockcontrol);
+
+        Y.one(document.body).appendChild(this.node);
+        Y.one(document.body).addClass(M.blocks.dock.cfg.css.body);
+        this.fire('dock:drawcompleted');
+        return true;
+    },
+    /**
+     * Removes the node at the given index and puts it back into conventional page sturcture
+     * @function
+     * @param {int} uid Unique identifier for the block
+     * @return {boolean}
+     */
+    remove:function(uid) {
+        if (!this.items[uid]) {
+            return false;
+        }
+        this.items[uid].remove();
+        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.fire('dock:removed');
+        }
+        return true;
+    },
+    /**
+     * Removes all nodes and puts them back into conventional page sturcture
+     * @function
+     * @return {boolean}
+     */
+    remove_all:function() {
+        for (var i in this.items) {
+            this.items[i].remove();
+            this.count--;
+            delete this.items[i];
+        }
+        Y.fire('dock:toberemoved');
+        this.items = [];
+        this.node.remove();
+        this.node = null;
+        Y.fire('dock:removed');
+        return true;
+    },
+    /**
+     * Resizes the active item
+     * @function
+     * @param {Event} e
+     */
+    resize:function(e){
+        for (var i in this.items) {
+            if (this.items[i].active) {
+                this.items[i].resize_panel(e);
+            }
+        }
+    },
+    /**
+     * Hides all [the active] items
+     * @function
+     */
+    hide_all:function() {
+        for (var i in this.items) {
+            this.items[i].hide();
+        }
+    },
+    /**
+     * This smart little function allows developers to attach event listeners before
+     * the dock has been augmented to allows event listeners.
+     * Once the augmentation is complete this function will be replaced with the proper
+     * on method for handling event listeners.
+     * Finally apply_binds needs to be called in order to properly bind events.
+     * @param {string} event
+     * @param {function} callback
+     */
+    on : function(event, callback) {
+        this.earlybinds.push({event:event,callback:callback});
+    },
+    /**
+     * This function takes all early binds and attaches them as listeners properly
+     * This should only be called once augmentation is complete.
+     */
+    apply_binds : function() {
+        for (var i in this.earlybinds) {
+            var bind = this.earlybinds[i];
+            this.on(bind.event, bind.callback);
+        }
+        this.earlybinds = [];
+    },
+    item_sizer : {
+        enabled : false,
+        init : function() {
+            M.blocks.dock.on('dock:itemadded', this.check_if_required, this);
+            M.blocks.dock.on('dock:itemremoved', this.check_if_required, this);
+            Y.on('windowresize', this.check_if_required, this);
+        },
+        check_if_required : function() {
+            var possibleheight = M.blocks.dock.node.get('offsetHeight') - M.blocks.dock.node.one('.controls').get('offsetHeight') - (M.blocks.dock.cfg.buffer*3) - (M.blocks.dock.items.length*2);
+            var totalheight = 0;
+            for (var id in M.blocks.dock.items) {
+                var dockedtitle = Y.get(M.blocks.dock.items[id].title).ancestor('.'+M.blocks.dock.cfg.css.dockedtitle);
+                if (dockedtitle) {
+                    if (this.enabled) {
+                        dockedtitle.setStyle('height', 'auto');
+                    }
+                    totalheight += dockedtitle.get('offsetHeight') || 0;
+                }
+            }
+            if (totalheight > possibleheight) {
+                this.enable(possibleheight);
+            }
+        },
+        enable : function(possibleheight) {
+            this.enabled = true;
+            var runningcount = 0;
+            var usedheight = 0;
+            for (var id in M.blocks.dock.items) {
+                var itemtitle = Y.get(M.blocks.dock.items[id].title).ancestor('.'+M.blocks.dock.cfg.css.dockedtitle);
+                if (!itemtitle) {
+                    continue;
+                }
+                var itemheight = Math.floor((possibleheight-usedheight) / (M.blocks.dock.count - runningcount));
+                Y.log("("+possibleheight+"-"+usedheight+") / ("+M.blocks.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++;
+            }
+            Y.log('possible: '+possibleheight+' - used height: '+usedheight);
+        }
+    },
+    /**
+     * 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,                  // The block instance id
+        cachedcontentnode : null,   // The cached content node for the actual block
+        blockspacewidth : null,     // The width of the block's original container
+        skipsetposition : false,    // If true the user preference isn't updated
+
+        /**
+         * This function should be called within the block's constructor and is used to
+         * set up the initial controls for swtiching block position as well as an initial
+         * moves that may be required.
+         *
+         * @param {YUI.Node} node The node that contains all of the block's content
+         */
+        init : function(node) {
+            if (!node) {
+                node = Y.one('#inst'+this.id);
+                if (!node) {
+                    return;
+                }
+            }
+
+            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);
+                }
+            }
+
+            var moveto = Y.Node.create('<a class="moveto customcommand requiresjs"></a>');
+            moveto.append(Y.Node.create('<img src="'+get_image_url('t/dock_to_block', 'moodle')+'" alt="'+mstr.block.undockitem+'" title="'+mstr.block.undockitem+'" />'));
+            if (location.href.match(/\?/)) {
+                moveto.set('href', location.href+'&dock='+this.id);
+            } else {
+                moveto.set('href', location.href+'?dock='+this.id);
+            }
+            commands.append(moveto);
+            commands.all('a.moveto').on('movetodock|click', this.move_to_dock, this);
+
+            node.all('.customcommand').each(function(){
+                this.remove();
+                commands.appendChild(this);
+            });
+
+            // Move the block straight to the dock if required
+            if (node.hasClass('dock_on_load')) {
+                node.removeClass('dock_on_load')
+                this.skipsetposition = true;
+                this.move_to_dock();
+            }
+        },
+
+        /**
+         * This function is reponsible for moving a block from the page structure onto the
+         * dock
+         * @param {event}
+         */
+        move_to_dock : function(e) {
+            if (e) {
+                e.halt(true);
+            }
+
+            var node = Y.one('#inst'+this.id);
+            var blockcontent = node.one('.content');
+            if (!blockcontent) {
+                return;
+            }
+
+            this.cachedcontentnode = node;
+
+            node.all('a.moveto').each(function(moveto){
+                Y.Event.purgeElement(Y.Node.getDOMNode(moveto), false, 'click');
+                if (moveto.hasClass('customcommand')) {
+                    moveto.all('img').each(function(movetoimg){
+                        movetoimg.setAttribute('src', get_image_url('t/dock_to_block', 'moodle'));
+                        movetoimg.setAttribute('alt', mstr.block.undockitem);
+                        movetoimg.setAttribute('title', mstr.block.undockitem);
+                    }, this);
+                }
+            }, this);
+
+            var placeholder = Y.Node.create('<div id="content_placeholder_'+this.id+'"></div>');
+            node.replace(Y.Node.getDOMNode(placeholder));
+            node = null;
+
+            var spacewidth = this.resize_block_space(placeholder);
+
+            var blocktitle = Y.Node.getDOMNode(this.cachedcontentnode.one('.title h2')).cloneNode(true);
+            blocktitle.innerHTML = blocktitle.innerHTML.replace(/([a-zA-Z0-9])/g, "$1<br />");
+
+            var commands = this.cachedcontentnode.all('.title .commands');
+            var blockcommands = Y.Node.create('<div class="commands"></div>');
+            if (commands.size() > 0) {
+                blockcommands = commands.item(0);
+            }
+
+            // Create a new dock item for the block
+            var dockitem = new M.blocks.dock.item(this.id, blocktitle, blockcontent, blockcommands);
+            if (spacewidth !== null && M.blocks.dock.cfg.display.mindisplaywidth == null) {
+                dockitem.cfg.display.mindisplaywidth = spacewidth;
+            }
+            // Wire the draw events to register remove events
+            dockitem.on('dockeditem:drawcomplete', function(e){
+                // check the contents block [editing=off]
+                this.contents.all('a.moveto').on('returntoblock|click', function(e){
+                    e.halt();
+                    M.blocks.dock.remove(this.id)
+                }, this);
+                // check the commands block [editing=on]
+                this.commands.all('a.moveto').on('returntoblock|click', function(e){
+                    e.halt();
+                    M.blocks.dock.remove(this.id)
+                }, this);
+            }, dockitem);
+
+            // Register an event so that when it is removed we can put it back as a block
+            dockitem.on('dockitem:itemremoved', this.return_to_block, this, dockitem);
+            M.blocks.dock.add(dockitem);
+
+            if (!this.skipsetposition) {
+                // save the users preference
+                set_user_preference('docked_block_instance_'+this.id, 1);
+            } else {
+                this.skipsetposition = false;
+            }
+        },
+
+        /**
+         * Resizes the space that contained blocks if there were no blocks left in
+         * it. e.g. if all blocks have been moved to the dock
+         * @param {Y.Node} node
+         */
+        resize_block_space : function(node) {
+            node = node.ancestor('.block-region');
+            if (node) {
+                var width =  node.getStyle('width');
+                if (node.all('.sideblock').size() === 0 && this.blockspacewidth === null) {
+                    // If the node has no children then we can shrink it
+                    this.blockspacewidth = width;
+                    node.setStyle('width', '0px');
+                } else if (this.blockspacewidth !== null) {
+                    // Otherwise if it contains children and we have saved a width
+                    // we can reapply the width
+                    node.setStyle('width', this.blockspacewidth);
+                    this.blockspacewidth = null;
+                }
+                return width;
+            }
+            return null;
+        },
+
+        /**
+         * This function removes a block from the dock and puts it back into the page
+         * structure.
+         * @param {M.blocks.dock.class.item}
+         */
+        return_to_block : function(dockitem) {
+            var placeholder = Y.one('#content_placeholder_'+this.id);
+            this.cachedcontentnode.appendChild(dockitem.contents);
+            placeholder.replace(Y.Node.getDOMNode(this.cachedcontentnode));
+            this.cachedcontentnode = Y.one('#'+this.cachedcontentnode.get('id'));
+
+            this.resize_block_space(this.cachedcontentnode);
+
+            this.cachedcontentnode.all('a.moveto').each(function(moveto){
+                Y.Event.purgeElement(Y.Node.getDOMNode(moveto), false, 'click');
+                moveto.on('movetodock|click', this.move_to_dock, this);
+                if (moveto.hasClass('customcommand')) {
+                    moveto.all('img').each(function(movetoimg){
+                        movetoimg.setAttribute('src', get_image_url('t/block_to_dock', 'moodle'));
+                        movetoimg.setAttribute('alt', mstr.block.addtodock);
+                        movetoimg.setAttribute('title', mstr.block.addtodock);
+                    }, this);
+                }
+             }, this);
+
+            var commands = this.cachedcontentnode.all('.commands');
+            var blocktitle = this.cachedcontentnode.all('.title');
+
+            if (commands.size() === 1 && blocktitle.size() === 1) {
+                commands.item(0).remove();
+                blocktitle.item(0).append(commands.item(0));
+            }
+
+            this.cachedcontentnode = null;
+            set_user_preference('docked_block_instance_'+this.id, 0);
+            return true;
+        }
+    },
+    /**
+     * This namespace contains the generic properties, methods and events
+     * that will be bound to the M.blocks.dock.item class.
+     * These can then be overriden to customise the way dock items work/display
+     * @namespace
+     */
+    abstract_item_class : {
+
+        id : null,              // The unique id for the item
+        name : null,            // The name of the item
+        title : null,           // The title of the item
+        contents : null,        // The content of the item
+        commands : null,        // The commands for the item
+        active : false,         // True if the item is being shown
+        panel : null,           // The YUI2 panel the item will be shown in
+        preventhide : false,    // If true the next call to hide will be ignored
+        cfg : null,             // The config options for this item by default M.blocks.cfg
+
+        /**
+         * 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 = Y.Node.create('<div id="dock_item_'+this.id+'_title" class="'+this.cfg.css.dockedtitle+'"></div>');
+            dockitemtitle.append(this.title);
+            var dockitem = Y.Node.create('<div id="dock_item_'+this.id+'" class="'+this.cfg.css.dockeditem+'"></div>');
+            if (M.blocks.dock.count === 1) {
+                dockitem.addClass('firstdockitem');
+            }
+            dockitem.append(dockitemtitle);
+            if (this.commands.hasChildNodes) {
+                this.contents.appendChild(this.commands);
+            }
+            M.blocks.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.setBody(Y.Node.getDOMNode(this.contents));
+            this.panel.render(M.blocks.dock.node);
+            if (this.cfg.display.mindisplaywidth !== null && Y.one(this.panel.body).getStyle('minWidth') == '0px') {
+                Y.one(this.panel.body).setStyle('minWidth', this.cfg.display.mindisplaywidth);
+                Y.one(this.panel.body).setStyle('minHeight', dockitemtitle.get('offsetHeight')+'px');
+            }
+            dockitem.on('showitem|mouseover', this.show, this);
+            this.fire('dockeditem:drawcomplete');
+        },
+        /**
+         * This function removes the node and destroys it's bits
+         * @param {Event} e
+         */
+        remove : function (e) {
+            this.hide(e);
+            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.blocks.dock.hide_all();
+            this.fire('dockeditem:showstart');
+            this.panel.show(e, this);
+            this.active = true;
+            Y.one('#dock_item_'+this.id+'_title').addClass(this.cfg.css.activeitem);
+            Y.detach('mouseover', this.show, Y.one('#dock_item_'+this.id));
+            Y.one('#dock_item_panel_'+this.id).on('dockpreventhide|click', function(){this.preventhide=true;}, this);
+            Y.one('#dock_item_'+this.id).on('dockhide|click', this.hide, this);
+            Y.get(window).on('dockresize|resize', this.resize_panel, this);
+            Y.get(document.body).on('dockhide|click', this.hide, this);
+            this.fire('dockeditem:showcomplete');
+            return true;
+        },
+        /**
+         * This function hides the item and makes it inactive
+         * @param {event}
+         */
+        hide : function(e) {
+            // Ignore this call is preventhide is true
+            if (this.preventhide===true) {
+                this.preventhide = false;
+            } else if (this.active) {
+                this.fire('dockeditem:hidestart');
+                this.active = false;
+                Y.one('#dock_item_'+this.id+'_title').removeClass(this.cfg.css.activeitem);
+                Y.one('#dock_item_'+this.id).on('showitem|mouseover', this.show, this);
+                Y.get(window).detach('dockresize|resize');
+                Y.get(document.body).detach('dockhide|click');
+                this.panel.hide(e, this);
+                this.fire('dockeditem:hidecomplete');
+            }
+        },
+        /**
+         * This function checks the size and position of the panel and moves/resizes if
+         * required to keep it within the bounds of the window.
+         */
+        resize_panel : function() {
+            this.fire('dockeditem:resizestart');
+            var panelbody = Y.one(this.panel.body);
+            var buffer = this.cfg.buffer;
+            var screenheight = parseInt(Y.get(document.body).get('winHeight'));
+            var panelheight = parseInt(panelbody.get('offsetHeight'));
+            var paneltop = parseInt(this.panel.cfg.getProperty('y'));
+            var titletop = parseInt(Y.one('#dock_item_'+this.id+'_title').getY());
+            var scrolltop = window.pageYOffset || document.body.scrollTop || 0;
+
+            // This makes sure that the panel is the same height as the dock title to
+            // begin with
+            if (paneltop > (buffer+scrolltop) && paneltop > (titletop+scrolltop)) {
+                this.panel.cfg.setProperty('y', titletop+scrolltop);
+            }
+
+            // This makes sure that if the panel is big it is moved up to ensure we don't
+            // have wasted space above the panel
+            if ((paneltop+panelheight)>(screenheight+scrolltop) && paneltop > buffer) {
+                paneltop = (screenheight-panelheight-buffer);
+                if (paneltop<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-(buffer*3)-10)+'px');
+                panelbody.addClass('oversized_content');
+            }
+            this.fire('dockeditem:resizecomplete');
+        }
+    }
+};
+
+/**
+ * This class represents a generic block
+ * @class genericblock
+ * @constructor
+ * @param {int} uid
+ */
+M.blocks.genericblock = function(uid){
+    // Save the unique id as the blocks id
+    if (uid && this.id==null) {
+        this.id = uid;
+    }
+    if (this instanceof M.blocks.genericblock) {
+        this.init();
+    }
+};
+/** Properties */
+M.blocks.genericblock.prototype.name =                    M.blocks.dock.abstract_block_class.name;
+M.blocks.genericblock.prototype.cachedcontentnode =       M.blocks.dock.abstract_block_class.cachedcontentnode;
+M.blocks.genericblock.prototype.blockspacewidth =         M.blocks.dock.abstract_block_class.blockspacewidth;
+M.blocks.genericblock.prototype.skipsetposition =         M.blocks.dock.abstract_block_class.skipsetposition;
+/** Methods **/
+M.blocks.genericblock.prototype.init =                    M.blocks.dock.abstract_block_class.init;
+M.blocks.genericblock.prototype.move_to_dock =            M.blocks.dock.abstract_block_class.move_to_dock;
+M.blocks.genericblock.prototype.resize_block_space =      M.blocks.dock.abstract_block_class.resize_block_space;
+M.blocks.genericblock.prototype.return_to_block =         M.blocks.dock.abstract_block_class.return_to_block;
+
+/**
+ * This class represents an item in the dock
+ * @class item
+ * @constructor
+ * @param {int} uid The unique ID for the item
+ * @param {Y.Node} title
+ * @param {Y.Node} contents
+ * @param {Y.Node} commands
+ */
+M.blocks.dock.item = function(uid, title, contents, commands){
+    if (uid && this.id==null) this.id = uid;
+    if (title && this.title==null) this.title = title;
+    if (contents && this.contents==null) this.contents = contents;
+    if (commands && this.commands==null) this.commands = commands;
+    this.init_events();
+}
+/** Properties */
+M.blocks.dock.item.prototype.id =                 M.blocks.dock.abstract_item_class.id;
+M.blocks.dock.item.prototype.name =               M.blocks.dock.abstract_item_class.name;
+M.blocks.dock.item.prototype.title =              M.blocks.dock.abstract_item_class.title;
+M.blocks.dock.item.prototype.contents =           M.blocks.dock.abstract_item_class.contents;
+M.blocks.dock.item.prototype.commands =           M.blocks.dock.abstract_item_class.commands;
+M.blocks.dock.item.prototype.active =             M.blocks.dock.abstract_item_class.active;
+M.blocks.dock.item.prototype.panel =              M.blocks.dock.abstract_item_class.panel;
+M.blocks.dock.item.prototype.preventhide =        M.blocks.dock.abstract_item_class.preventhide;
+M.blocks.dock.item.prototype.cfg =                M.blocks.dock.cfg;
+/** Methods **/
+M.blocks.dock.item.prototype.init_events =        M.blocks.dock.abstract_item_class.init_events;
+M.blocks.dock.item.prototype.draw =               M.blocks.dock.abstract_item_class.draw;
+M.blocks.dock.item.prototype.remove =             M.blocks.dock.abstract_item_class.remove;
+M.blocks.dock.item.prototype.show =               M.blocks.dock.abstract_item_class.show;
+M.blocks.dock.item.prototype.hide =               M.blocks.dock.abstract_item_class.hide;
+M.blocks.dock.item.prototype.resize_panel =       M.blocks.dock.abstract_item_class.resize_panel;
+
+YUI.add('blocks_dock', M.blocks.dock.init, '0.0.0.1', 'requires', yui3loader.modules['blocks_dock'].requires);
Index: moodle/blocks/global_navigation_tree/block_global_navigation_tree.php
--- moodle/blocks/global_navigation_tree/block_global_navigation_tree.php Base (1.22)
+++ moodle/blocks/global_navigation_tree/block_global_navigation_tree.php Locally Modified (Based On 1.22)
@@ -80,8 +80,9 @@
     }
 
     function get_required_javascript() {
+        global $CFG;
         $this->_initialise_dock();
-        $this->page->requires->js('/blocks/global_navigation_tree/navigation.js');
+        $this->page->requires->js_module('blocks_navigation', array('fullpath'=>$CFG->wwwroot.'/blocks/global_navigation_tree/navigation.js', 'requires'=>array('blocks_dock', 'io', 'node', 'dom', 'event-custom')));
         user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT);
     }
 
@@ -153,8 +154,8 @@
         $this->page->navigation->find_expandable($expandable);
 
         // Initialise the JS tree object
-        $args = array($this->instance->id,array('expansions'=>$expandable,'instance'=>$this->instance->id, 'candock'=>$this->instance_can_be_docked()));
-        $this->page->requires->js_function_call('blocks.navigation.setup_new_tree',  $args)->on_dom_ready();
+        $args = array($this->instance->id, array('expansions'=>$expandable,'instance'=>$this->instance->id, 'candock'=>$this->instance_can_be_docked()));
+        $this->page->requires->js_object_init("M.blocks.navigation.treecollection[".$this->instance->id."]", 'M.blocks.navigation.classes.tree', $args, array('blocks_navigation'));
         
         // Grab the items to display
         $this->content->items = array($this->page->navigation);
Index: moodle/blocks/global_navigation_tree/navigation.js
--- moodle/blocks/global_navigation_tree/navigation.js Base (1.4)
+++ moodle/blocks/global_navigation_tree/navigation.js Locally Modified (Based On 1.4)
@@ -34,7 +34,7 @@
  * global navigation and settings.
  * @namespace
  */
-blocks.navigation = {
+M.blocks.navigation = {
     /** The number of expandable branches in existence */
     expandablebranchcount:0,
     /** An array of initialised trees */
@@ -45,35 +45,36 @@
      */
     classes:{},
     /**
+     * This function gets called when the module is first loaded as required by
+     * the YUI.add statement at the bottom of the page.
+     * 
+     * NOTE: This will only be executed ONCE
      * @function
-     * @static
-     * @param {int} uid The id of the block within the page
-     * @param {object} properties
      */
-    setup_new_tree:function(uid, properties) {
-        Y.use('base','dom','io','node', function() {
-            properties = properties || {'instance':uid};
-            blocks.navigation.treecollection[uid] = new blocks.navigation.classes.tree(uid, uid, properties);
-        });
+    init:function() {
+        if (M.blocks.genericblock) {
+            // Give the tree class the dock block properties
+            Y.augment(M.blocks.navigation.classes.tree, M.blocks.genericblock);
     }
+    }
 };
 
 /**
  * @class tree
  * @constructor
- * @base blocks.dock.abstractblock
+ * @base M.blocks.dock.abstractblock
  * @param {string} id The name of the tree
  * @param {int} key The internal id within the tree store
  * @param {object} properties Object containing tree properties
  */
-blocks.navigation.classes.tree = function(id, key, properties) {
+M.blocks.navigation.classes.tree = function(id, properties) {
     this.id = id;
-    this.key = key;
-    this.type = 'blocks.navigation.classes.tree';
+    this.key = id;
+    this.type = 'M.blocks.navigation.classes.tree';
     this.errorlog = [];
     this.ajaxbranches = 0;
     this.expansions = [];
-    this.instance = null;
+    this.instance = id;
     this.cachedcontentnode = null;
     this.cachedfooter = null;
     this.position = 'block';
@@ -102,7 +103,7 @@
     // Attache events to expand by AJAX
     for (var i in this.expansions) {
         Y.one('#'+this.expansions[i].id).on('ajaxload|click', this.init_load_ajax, this, this.expansions[i]);
-        blocks.navigation.expandablebranchcount++;
+        M.blocks.navigation.expandablebranchcount++;
     }
 
     if (node.hasClass('block_js_expansion')) {
@@ -121,7 +122,7 @@
  * @param {event} e The event object
  * @param {object} branch A branch to load via ajax
  */
-blocks.navigation.classes.tree.prototype.init_load_ajax = function(e, branch) {
+M.blocks.navigation.classes.tree.prototype.init_load_ajax = function(e, branch) {
     e.stopPropagation();
     if (e.target.get('nodeName').toUpperCase() != 'P') {
         return true;
@@ -152,14 +153,14 @@
  * @param {mixed} args
  * @return bool
  */
-blocks.navigation.classes.tree.prototype.load_ajax = function(tid, outcome, args) {
+M.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
             if (this.candock) {
-                blocks.dock.resize();
+                M.blocks.dock.resize();
             }
             return true;
         }
@@ -176,10 +177,10 @@
  * @param {int} depth
  * @return bool
  */
-blocks.navigation.classes.tree.prototype.add_branch = function(branchxml, target, depth) {
+M.blocks.navigation.classes.tree.prototype.add_branch = function(branchxml, target, depth) {
 
     // Make the new branch into an object
-    var branch = new blocks.navigation.classes.branch(this, branchxml);
+    var branch = new M.blocks.navigation.classes.branch(this, branchxml);
 
     var childrenul = false;
     if (depth === 1) {
@@ -203,7 +204,7 @@
  * Toggle a branch as expanded or collapsed
  * @param {Event} e
  */
-blocks.navigation.classes.tree.prototype.toggleexpansion = function(e) {
+M.blocks.navigation.classes.tree.prototype.toggleexpansion = function(e) {
     // First check if they managed to click on the li iteslf, then find the closest
     // LI ancestor and use that
     if (e.target.get('nodeName').toUpperCase() == 'LI') {
@@ -212,7 +213,7 @@
         e.target.ancestor('LI').toggleClass('collapsed');
     }
     if (this.candock) {
-        blocks.dock.resize();
+        M.blocks.dock.resize();
     }
 }
 
@@ -220,10 +221,10 @@
  * This class represents a branch for a tree
  * @class branch
  * @constructor
- * @param {blocks.navigation.classes.tree} tree
+ * @param {M.blocks.navigation.classes.tree} tree
  * @param {xmldoc|null} xml
  */
-blocks.navigation.classes.branch = function(tree, xml) {
+M.blocks.navigation.classes.branch = function(tree, xml) {
     this.tree = tree;
     this.name = null;
     this.title = null;
@@ -247,7 +248,7 @@
  * Constructs a branch from XML
  * @param {xmldoc} xml
  */
-blocks.navigation.classes.branch.prototype.construct_from_xml = function(xml) {
+M.blocks.navigation.classes.branch.prototype.construct_from_xml = function(xml) {
     // Get required attributes
     this.title = xml.getAttribute('title');
     this.classname = xml.getAttribute('class');
@@ -264,8 +265,8 @@
 
     if (this.id && this.id.match(/^expandable_branch_\d+$/)) {
         // Assign a new unique id for this new expandable branch
-        blocks.navigation.expandablebranchcount++;
-        this.id = 'expandable_branch_'+blocks.navigation.expandablebranchcount;
+        M.blocks.navigation.expandablebranchcount++;
+        this.id = 'expandable_branch_'+M.blocks.navigation.expandablebranchcount;
     }
 
     // Retrieve any additional information
@@ -284,7 +285,7 @@
  * Injects a branch into the tree at the given location
  * @param {element} element
  */
-blocks.navigation.classes.branch.prototype.inject_into_dom = function(element) {
+M.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>');
@@ -338,9 +339,4 @@
     }
 }
 
-YUI(yui3loader).use('event-custom', 'node', function(Y){
-    if (blocks.genericblock) {
-        // Give the tree class the dock block properties
-        Y.augment(blocks.navigation.classes.tree, blocks.genericblock);
-    }
-});
+YUI.add('blocks_navigation', M.blocks.navigation.init, '0.0.0.1', yui3loader.modules.blocks_navigation.requires);
Index: moodle/blocks/moodleblock.class.php
--- moodle/blocks/moodleblock.class.php Base (1.142)
+++ moodle/blocks/moodleblock.class.php Locally Modified (Based On 1.142)
@@ -578,7 +578,7 @@
     function get_required_javascript() {
         $this->_initialise_dock();
         if ($this->instance_can_be_docked()) {
-            $this->page->requires->js_function_call('blocks.setup_generic_block', array($this->instance->id))->on_dom_ready();
+            $this->page->requires->js_object_init(null, 'M.blocks.genericblock', array($this->instance->id), array('blocks_dock'));
             user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT);
         }
     }
@@ -750,11 +750,10 @@
     }
 
     public function _initialise_dock() {
+        global $CFG;
         if (!self::$dockinitialised) {
-            $this->page->requires->js_function_call('blocks.dock.init')->on_dom_ready();
-            $this->page->requires->data_for_js('blocks.dock.strings.addtodock', get_string('addtodock', 'block'));
-            $this->page->requires->data_for_js('blocks.dock.strings.undockitem', get_string('undockitem', 'block'));
-            $this->page->requires->data_for_js('blocks.dock.strings.undockall', get_string('undockall', 'block'));
+            $this->page->requires->js_module('blocks_dock', array('fullpath'=>$CFG->wwwroot.'/blocks/dock.js', 'requires'=>array('base','dom','io','node', 'event-custom')));
+            $this->page->requires->strings_for_js(array('addtodock','undockitem','undockall'), 'block');
             self::$dockinitialised = true;
         }
     }
@@ -861,7 +860,7 @@
             $this->content->items = array();
         }
         $this->get_content();
-        $content = $output->tree_block_contents($this->content->items,array('class'=>'block_tree'));
+        $content = $output->tree_block_contents($this->content->items,array('class'=>'block_tree list'));
         if (isset($this->id) && !is_numeric($this->id)) {
             $content = $output->box($content, 'block_tree_box', $this->id);
         }
Index: moodle/blocks/settings_navigation_tree/block_settings_navigation_tree.php
--- moodle/blocks/settings_navigation_tree/block_settings_navigation_tree.php Base (1.16)
+++ moodle/blocks/settings_navigation_tree/block_settings_navigation_tree.php Locally Modified (Based On 1.16)
@@ -78,11 +78,12 @@
     }
 
     function get_required_javascript() {
+        global $CFG;
         $this->_initialise_dock();
-        $this->page->requires->js('/blocks/global_navigation_tree/navigation.js');
-        $args = array($this->instance->id, array('instance'=>$this->instance->id, 'candock'=>$this->instance_can_be_docked()));
-        $this->page->requires->js_function_call('blocks.navigation.setup_new_tree', $args)->on_dom_ready();
-        user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT);
+        $this->page->requires->js_module('blocks_navigation', array('fullpath'=>$CFG->wwwroot.'/blocks/global_navigation_tree/navigation.js', 'requires'=>array('blocks_dock', 'io', 'node', 'dom', 'event-custom')));
+        $arguments = array($this->instance->id, array('instance'=>$this->instance->id, 'candock'=>$this->instance_can_be_docked()));
+        $this->page->requires->js_object_init("M.blocks.navigation.treecollection[".$this->instance->id."]", 'M.blocks.navigation.classes.tree', $arguments, array('blocks_navigation'));
+        user_preference_allow_ajax_update('M.docked_block_instance_'.$this->instance->id, PARAM_INT);
     }
 
     /**
Index: moodle/lib/ajax/ajaxlib.php
--- moodle/lib/ajax/ajaxlib.php Base (1.118)
+++ moodle/lib/ajax/ajaxlib.php Locally Modified (Based On 1.118)
@@ -139,6 +139,7 @@
         $this->json_yui3loader->filter       = ($this->yui3loader->filter == YUI_DEBUG) ? 'debug' : '';
         $this->json_yui3loader->insertBefore = 'firstthemesheet';
         $this->json_yui3loader->modules      = array();
+        $this->json_yui3loader->modules['M'] = array('fullpath'=>$CFG->wwwroot.'/lib/module-core.js', 'requires'=>array('node'));
         $this->add_yui2_modules(); // adds loading info for YUI2
     }
 
@@ -472,7 +473,10 @@
      * Ideally the JS code fragment should be stored in plugin renderer so that themes
      * may override it.
      *
-     * Example: "Y.use('mod_mymod'); M.mod_mymod.init_view();"
+     * Example:
+     * Y.use('mod_mymod', function(){
+     *      M.mod_mymod.init_view();"
+     * });
      *
      * @param string $jscode
      * @return void
@@ -482,6 +486,21 @@
     }
 
     /**
+     * Adds a required JavaScript object initialisation to the page.
+     * 
+     * @param string|null $var If null the object is not assigned to any variable
+     * @param string $class
+     * @param array $arguments
+     * @param array $requirements
+     * @return required_js_object_init
+     */
+    public function js_object_init($var, $class, array $arguments = null, array $requirements = null) {
+        $requirement = new required_js_object_init($this, $var, $class, $arguments, $requirements);
+        $this->requiredjscode[] = $requirement;
+        return $requirement;
+    }
+
+    /**
      * Make a language string available to JavaScript.
      *
      * All the strings will be available in a mstr object in the global namespace.
@@ -647,8 +666,11 @@
      * @return unknown_type
      */
     protected function get_javascript_init_code() {
+        if (count($this->jsinitcode)) {
         return implode(";\n", $this->jsinitcode) . ";\n";
     }
+        return '';
+    }
 
     /**
      * Returns basic YUI3 JS loading code.
@@ -817,18 +839,13 @@
         $jsinit = $this->get_javascript_init_code();
         $handlersjs = $this->get_event_handler_code();
         
+        if (!empty($ondomreadyjs)) {
+             $ondomreadyjs = "    Y.on('domready', function() {\n$ondomreadyjs\n    });";
+        }
+
         // the global Y can be used only after it is fully loaded, that means
         // from code executed from the following block
-        $js .= <<<EOD
-Y = YUI(yui3loader).use('node-base', function(Y) {
-$inyuijs    ;
-    Y.on('domready', function() {
-$ondomreadyjs
-    });
-$jsinit
-$handlersjs
-});
-EOD;
+        $js .= "Y = YUI(yui3loader).use('node', function(Y) {\n{$inyuijs}{$ondomreadyjs}{$jsinit}{$handlersjs}\n});";
 
         $output .= html_writer::script($js);
 
@@ -1112,8 +1129,91 @@
     }
 }
 
+/**
+ * This class is used to manage an object initialisation in JavaScript.
+ *
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since Moodle 2.0
+ */
+class required_js_object_init extends required_js_code {
+    /**
+     * The variable to assign the object to or null for none
+     * @var string|null
+     */
+    protected $var;
+    /**
+     * The class of the object to initialise
+     * @var string
+     */
+    protected $class;
+    /**
+     * Arguments to pass in to the constructor
+     */
+    protected $arguments;
+    /**
+     * Required YUI modules
+     */
+    protected $requirements;
+    protected $delay = 0;
 
 /**
+     * Constructor. Normally instances of this class should not be created directly.
+     * Client code should create them via the page_requirements_manager
+     * method {@link page_requirements_manager::js_object_init()}.
+     *
+     * @param page_requirements_manager $manager the page_requirements_manager we are associated with.
+     * @param string|null $var
+     * @param string $class
+     * @param array|null $arguments
+     * @param array|null $requirements
+     */
+    public function __construct(page_requirements_manager $manager, $var, $class, array $arguments = null, array $requirements = null) {
+        parent::__construct($manager);
+        $this->when = page_requirements_manager::WHEN_IN_YUI;
+        $this->var = $var;
+        $this->class = $class;
+        $this->arguments = $arguments;
+        $this->requirements = $requirements;
+    }
+
+    /**
+     * Gets the actual JavaScript code for the required object initialisation
+     * @return string
+     */
+    public function get_js_code() {
+        return js_writer::object_init($this->var, $this->class, $this->arguments, $this->requirements, $this->delay);
+    }
+
+    /**
+     * Indicate that this initalisation should be called in YUI's onDomReady event.
+     *
+     * Thisis needed mostly for buggy IE browsers because they have problems
+     * when JS starts modifying DOM structure before the DOM is ready.
+     */
+    public function on_dom_ready() {
+        if ($this->is_done() || $this->when < page_requirements_manager::WHEN_IN_YUI) {
+            return;
+        }
+        $this->when = page_requirements_manager::WHEN_ON_DOM_READY;
+    }
+
+    /**
+     * Indicate that this function should be called a certain number of seconds
+     * after the page has finished loading. (More exactly, a number of seconds
+     * after the onDomReady event fires.)
+     *
+     * @param integer $seconds the number of seconds delay.
+     */
+    public function after_delay($seconds) {
+        if ($seconds) {
+            $this->on_dom_ready();
+        }
+        $this->delay = $seconds;
+    }
+}
+
+/**
  * This class represents a JavaScript function that must be called from the HTML
  * page. By default the call will be made at the end of the page when YUI initialised,
  * but you can chage that using the {@link asap()}, {@link in_head()}, etc. methods.
Index: moodle/lib/javascript-static.js
--- moodle/lib/javascript-static.js Base (1.111)
+++ moodle/lib/javascript-static.js Locally Modified (Based On 1.111)
@@ -2,7 +2,7 @@
 // Global instance of YUI3
 
 // Global Y instance, inilialised much later in page footer
-var Y = null;
+var Y = Y || null;
 
 // Global M object, this helps with solving of namespace and scope issues
 var M = M || {};
@@ -1414,710 +1414,3 @@
 function submitFormById(id) {
     submit_form_by_id(null, {id: id});
 }
-
-
-/**
- * START OF BLOCKS CODE
- * This code can be included in the footer instead of the header if we ever
- * have a static JS file that will be loaded in the footer.
- * Once this is done we will then also be able to remove the blocks.dock.init
- * function and call
- */
-
-/**
- * This namespace will contain all of content (functions, classes, properties)
- * for the block system
- * @namespace
- */
-var blocks = blocks || {};
-blocks.setup_generic_block = function(uid) {
-    Y.use('base','dom','io','node', 'event-custom', function() {
-        var block = new blocks.genericblock(uid);
-        block.init();
-    });
-}
-
-/**
- * The dock namespace: Contains all things dock related
- * @namespace
- */
-blocks.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
-    /**
-     * Strings used by the dock/dockitems
-     * @namespace
-     */
-    strings:{
-        addtodock : '[[addtodock]]',
-        undockitem : '[[undockitem]]',
-        undockall : '[[undockall]]'
-    },
-    /**
-     * Configuration parameters used during the initialisation and setup
-     * of dock and dock items.
-     * This is here specifically so that themers can override core parameters and
-     * design aspects without having to re-write navigation
-     * @namespace
-     */
-    cfg:{
-        buffer:10,                          // Buffer used when containing a panel
-        position:'left',                    // position of the dock
-        orientation:'vertical',             // vertical || horizontal determines if we change the title
-        /**
-         * Display 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
-        },
-        /**
-         * CSS classes to use with the dock
-         * @namespace
-         */
-        css: {
-            dock:'dock',                    // CSS Class applied to the dock box
-            dockspacer:'dockspacer',        // CSS class applied to the dockspacer
-            controls:'controls',            // CSS class applied to the controls box
-            body:'has_dock',                // CSS class added to the body when there is a dock
-            dockeditem:'dockeditem',        // CSS class added to each item in the dock
-            dockedtitle:'dockedtitle',      // CSS class added to the item's title in each dock
-            activeitem:'activeitem'         // CSS class added to the active item
-        },
-        /**
-         * 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
-            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
-        }
-    },
-    /**
-     * Augments the classes as required and processes early bindings
-     */
-    init:function() {
-        Y.use('event-custom','event', 'node', function(Y){
-            // Give the dock item class the event properties/methods
-            Y.augment(blocks.dock.item, Y.EventTarget);
-            Y.augment(blocks.dock, Y.EventTarget, true);
-            // Re-apply early bindings properly now that we can
-            blocks.dock.apply_binds();
-        });
-    },
-    /**
-     * Adds a dock item into the dock
-     * @function
-     * @param {blocks.dock.item} item
-     */
-    add:function(item) {
-        item.id = this.totalcount;
-        this.count++;
-        this.totalcount++;
-        this.items[item.id] = item;
-        this.draw();
-        this.items[item.id].draw();
-        this.fire('dock:itemadded', item);
-    },
-    append : function(docknode) {
-        blocks.dock.node.one('#dock_item_container').append(docknode);
-    },
-    /**
-     * Draws the dock
-     * @function
-     * @return bool
-     */
-    draw:function() {
-        if (this.node !== null) {
-            return true;
-        }
-        this.fire('dock:drawstarted');
-        this.item_sizer.init();
-        this.node = Y.Node.create('<div id="dock" class="'+blocks.dock.cfg.css.dock+' '+blocks.dock.cfg.css.dock+'_'+blocks.dock.cfg.position+'_'+blocks.dock.cfg.orientation+'"></div>');
-        this.node.appendChild(Y.Node.create('<div class="'+blocks.dock.cfg.css.dockspacer+'" style="height:'+blocks.dock.cfg.display.spacebeforefirstitem+'px"></div>'));
-        this.node.appendChild(Y.Node.create('<div id="dock_item_container"></div>'));
-        if (Y.UA.ie > 0 && Y.UA.ie < 7) {
-            this.node.setStyle('height', this.node.get('winHeight')+'px');
-        }
-
-        var dockcontrol = Y.Node.create('<div class="'+blocks.dock.cfg.css.controls+'"></div>');
-        var removeall = Y.Node.create('<img src="'+get_image_url('t/dock_to_block', 'moodle')+'" alt="'+blocks.dock.strings.undockall+'" title="'+blocks.dock.strings.undockall+'" />');
-        removeall.on('removeall|click', this.remove_all, this);
-        dockcontrol.appendChild(removeall);
-        this.node.appendChild(dockcontrol);
-
-        Y.one(document.body).appendChild(this.node);
-        Y.one(document.body).addClass(blocks.dock.cfg.css.body);
-        this.fire('dock:drawcompleted');
-        return true;
-    },
-    /**
-     * Removes the node at the given index and puts it back into conventional page sturcture
-     * @function
-     * @param {int} uid Unique identifier for the block
-     * @return {boolean}
-     */
-    remove:function(uid) {
-        if (!this.items[uid]) {
-            return false;
-        }
-        this.items[uid].remove();
-        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.fire('dock:removed');
-        }
-        return true;
-    },
-    /**
-     * Removes all nodes and puts them back into conventional page sturcture
-     * @function
-     * @return {boolean}
-     */
-    remove_all:function() {
-        for (var i in this.items) {
-            this.items[i].remove();
-            this.count--;
-            delete this.items[i];
-        }
-        Y.fire('dock:toberemoved');
-        this.items = [];
-        this.node.remove();
-        this.node = null;
-        Y.fire('dock:removed');
-        return true;
-    },
-    /**
-     * Resizes the active item
-     * @function
-     * @param {Event} e
-     */
-    resize:function(e){
-        for (var i in this.items) {
-            if (this.items[i].active) {
-                this.items[i].resize_panel(e);
-            }
-        }
-    },
-    /**
-     * Hides all [the active] items
-     * @function
-     */
-    hide_all:function() {
-        for (var i in this.items) {
-            this.items[i].hide();
-        }
-    },
-    /**
-     * This smart little function allows developers to attach event listeners before
-     * the dock has been augmented to allows event listeners.
-     * Once the augmentation is complete this function will be replaced with the proper
-     * on method for handling event listeners.
-     * Finally apply_binds needs to be called in order to properly bind events.
-     * @param {string} event
-     * @param {function} callback
-     */
-    on : function(event, callback) {
-        this.earlybinds.push({event:event,callback:callback});
-    },
-    /**
-     * This function takes all early binds and attaches them as listeners properly
-     * This should only be called once augmentation is complete.
-     */
-    apply_binds : function() {
-        for (var i in this.earlybinds) {
-            var bind = this.earlybinds[i];
-            this.on(bind.event, bind.callback);
-        }
-        this.earlybinds = [];
-    },
-    item_sizer : {
-        enabled : false,
-        init : function() {
-            blocks.dock.on('dock:itemadded', this.check_if_required, this);
-            blocks.dock.on('dock:itemremoved', this.check_if_required, this);
-            Y.on('windowresize', this.check_if_required, this);
-        },
-        check_if_required : function() {
-            var possibleheight = blocks.dock.node.get('offsetHeight') - blocks.dock.node.one('.controls').get('offsetHeight') - (blocks.dock.cfg.buffer*3) - (blocks.dock.items.length*2);
-            var totalheight = 0;
-            for (var id in blocks.dock.items) {
-                var dockedtitle = Y.get(blocks.dock.items[id].title).ancestor('.'+blocks.dock.cfg.css.dockedtitle);
-                if (dockedtitle) {
-                    if (this.enabled) {
-                        dockedtitle.setStyle('height', 'auto');
-                    }
-                    totalheight += dockedtitle.get('offsetHeight') || 0;
-                }
-            }
-            if (totalheight > possibleheight) {
-                this.enable(possibleheight);
-            }
-        },
-        enable : function(possibleheight) {
-            this.enabled = true;
-            var runningcount = 0;
-            var usedheight = 0;
-            for (var id in blocks.dock.items) {
-                var itemtitle = Y.get(blocks.dock.items[id].title).ancestor('.'+blocks.dock.cfg.css.dockedtitle);
-                if (!itemtitle) {
-                    continue;
-                }
-                var itemheight = Math.floor((possibleheight-usedheight) / (blocks.dock.count - runningcount));
-                Y.log("("+possibleheight+"-"+usedheight+") / ("+blocks.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++;
-            }
-            Y.log('possible: '+possibleheight+' - used height: '+usedheight);
-        }
-    },
-    /**
-     * 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,                  // The block instance id
-        cachedcontentnode : null,   // The cached content node for the actual block
-        blockspacewidth : null,     // The width of the block's original container
-        skipsetposition : false,    // If true the user preference isn't updated
-
-        /**
-         * This function should be called within the block's constructor and is used to
-         * set up the initial controls for swtiching block position as well as an initial
-         * moves that may be required.
-         *
-         * @param {YUI.Node} node The node that contains all of the block's content
-         */
-        init : function(node) {
-            if (!node) {
-                node = Y.one('#inst'+this.id);
-                if (!node) {
-                    return;
-                }
-            }
-
-            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);
-                }
-            }
-
-            var moveto = Y.Node.create('<a class="moveto customcommand requiresjs"></a>');
-            moveto.append(Y.Node.create('<img src="'+get_image_url('t/dock_to_block', 'moodle')+'" alt="'+blocks.dock.strings.undockitem+'" title="'+blocks.dock.strings.undockitem+'" />'));
-            if (location.href.match(/\?/)) {
-                moveto.set('href', location.href+'&dock='+this.id);
-            } else {
-                moveto.set('href', location.href+'?dock='+this.id);
-            }
-            commands.append(moveto);
-            commands.all('a.moveto').on('movetodock|click', this.move_to_dock, this);
-
-            node.all('.customcommand').each(function(){
-                this.remove();
-                commands.appendChild(this);
-            });
-
-            // Move the block straight to the dock if required
-            if (node.hasClass('dock_on_load')) {
-                node.removeClass('dock_on_load')
-                this.skipsetposition = true;
-                this.move_to_dock();
-            }
-        },
-
-        /**
-         * This function is reponsible for moving a block from the page structure onto the
-         * dock
-         * @param {event}
-         */
-        move_to_dock : function(e) {
-            if (e) {
-                e.halt(true);
-            }
-
-            var node = Y.one('#inst'+this.id);
-            var blockcontent = node.one('.content');
-            if (!blockcontent) {
-                return;
-            }
-
-            this.cachedcontentnode = node;
-
-            node.all('a.moveto').each(function(moveto){
-                Y.Event.purgeElement(Y.Node.getDOMNode(moveto), false, 'click');
-                if (moveto.hasClass('customcommand')) {
-                    moveto.all('img').each(function(movetoimg){
-                        movetoimg.setAttribute('src', get_image_url('t/dock_to_block', 'moodle'));
-                        movetoimg.setAttribute('alt', blocks.dock.strings.undockitem);
-                        movetoimg.setAttribute('title', blocks.dock.strings.undockitem);
-                    }, this);
-                }
-            }, this);
-
-            var placeholder = Y.Node.create('<div id="content_placeholder_'+this.id+'"></div>');
-            node.replace(Y.Node.getDOMNode(placeholder));
-            node = null;
-
-            var spacewidth = this.resize_block_space(placeholder);
-
-            var blocktitle = Y.Node.getDOMNode(this.cachedcontentnode.one('.title h2')).cloneNode(true);
-            blocktitle.innerHTML = blocktitle.innerHTML.replace(/([a-zA-Z0-9])/g, "$1<br />");
-
-            var commands = this.cachedcontentnode.all('.title .commands');
-            var blockcommands = Y.Node.create('<div class="commands"></div>');
-            if (commands.size() > 0) {
-                blockcommands = commands.item(0);
-            }
-
-            // Create a new dock item for the block
-            var dockitem = new blocks.dock.item(this.id, blocktitle, blockcontent, blockcommands);
-            if (spacewidth !== null && blocks.dock.cfg.display.mindisplaywidth == null) {
-                dockitem.cfg.display.mindisplaywidth = spacewidth;
-            }
-            // Wire the draw events to register remove events
-            dockitem.on('dockeditem:drawcomplete', function(e){
-                // check the contents block [editing=off]
-                this.contents.all('a.moveto').on('returntoblock|click', function(e){
-                    e.halt();
-                    blocks.dock.remove(this.id)
-                }, this);
-                // check the commands block [editing=on]
-                this.commands.all('a.moveto').on('returntoblock|click', function(e){
-                    e.halt();
-                    blocks.dock.remove(this.id)
-                }, this);
-            }, dockitem);
-            
-            // 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);
-            blocks.dock.add(dockitem);
-
-            if (!this.skipsetposition) {
-                // save the users preference
-                set_user_preference('docked_block_instance_'+this.id, 1);
-            } else {
-                this.skipsetposition = false;
-            }
-        },
-
-        /**
-         * Resizes the space that contained blocks if there were no blocks left in
-         * it. e.g. if all blocks have been moved to the dock
-         * @param {Y.Node} node
-         */
-        resize_block_space : function(node) {
-            node = node.ancestor('.block-region');
-            if (node) {
-                var width =  node.getStyle('width');
-                if (node.all('.sideblock').size() === 0 && this.blockspacewidth === null) {
-                    // If the node has no children then we can shrink it
-                    this.blockspacewidth = width;
-                    node.setStyle('width', '0px');
-                } else if (this.blockspacewidth !== null) {
-                    // Otherwise if it contains children and we have saved a width
-                    // we can reapply the width
-                    node.setStyle('width', this.blockspacewidth);
-                    this.blockspacewidth = null;
-                }
-                return width;
-            }
-            return null;
-        },
-
-        /**
-         * This function removes a block from the dock and puts it back into the page
-         * structure.
-         * @param {blocks.dock.class.item}
-         */
-        return_to_block : function(dockitem) {
-            var placeholder = Y.one('#content_placeholder_'+this.id);
-            this.cachedcontentnode.appendChild(dockitem.contents);
-            placeholder.replace(Y.Node.getDOMNode(this.cachedcontentnode));
-            this.cachedcontentnode = Y.one('#'+this.cachedcontentnode.get('id'));
-
-            this.resize_block_space(this.cachedcontentnode);
-
-            this.cachedcontentnode.all('a.moveto').each(function(moveto){
-                Y.Event.purgeElement(Y.Node.getDOMNode(moveto), false, 'click');
-                moveto.on('movetodock|click', this.move_to_dock, this);
-                if (moveto.hasClass('customcommand')) {
-                    moveto.all('img').each(function(movetoimg){
-                        movetoimg.setAttribute('src', get_image_url('t/block_to_dock', 'moodle'));
-                        movetoimg.setAttribute('alt', blocks.dock.strings.addtodock);
-                        movetoimg.setAttribute('title', blocks.dock.strings.addtodock);
-                    }, this);
-                }
-             }, this);
-
-            var commands = this.cachedcontentnode.all('.commands');
-            var blocktitle = this.cachedcontentnode.all('.title');
-
-            if (commands.size() === 1 && blocktitle.size() === 1) {
-                commands.item(0).remove();
-                blocktitle.item(0).append(commands.item(0));
-            }
-
-            this.cachedcontentnode = null;
-            set_user_preference('docked_block_instance_'+this.id, 0);
-            return true;
-        }
-    },
-    /**
-     * This namespace contains the generic properties, methods and events
-     * that will be bound to the blocks.dock.item class.
-     * These can then be overriden to customise the way dock items work/display
-     * @namespace
-     */
-    abstract_item_class : {
-        
-        id : null,              // The unique id for the item
-        name : null,            // The name of the item
-        title : null,           // The title of the item
-        contents : null,        // The content of the item
-        commands : null,        // The commands for the item
-        active : false,         // True if the item is being shown
-        panel : null,           // The YUI2 panel the item will be shown in
-        preventhide : false,    // If true the next call to hide will be ignored
-        cfg : null,             // The config options for this item by default blocks.cfg
-
-        /**
-         * Initialises all of the items events
-         * @function
-         */
-        init_events : function() {
-            this.publish('dockeditem:drawstart', {prefix:'dockeditem'});
-            this.publish('dockeditem:drawcomplete', {prefix:'dockeditem'});
-            this.publish('dockeditem:showstart', {prefix:'dockeditem'});
-            this.publish('dockeditem:showcomplete', {prefix:'dockeditem'});
-            this.publish('dockeditem:hidestart', {prefix:'dockeditem'});
-            this.publish('dockeditem:hidecomplete', {prefix:'dockeditem'});
-            this.publish('dockeditem:resizestart', {prefix:'dockeditem'});
-            this.publish('dockeditem:resizecomplete', {prefix:'dockeditem'});
-            this.publish('dockeditem:itemremoved', {prefix:'dockeditem'});
-        },
-        
-        /**
-         * This function draws the item on the dock
-         */
-        draw : function() {
-            this.fire('dockeditem:drawstart');
-            var dockitemtitle = Y.Node.create('<div id="dock_item_'+this.id+'_title" class="'+this.cfg.css.dockedtitle+'"></div>');
-            dockitemtitle.append(this.title);
-            var dockitem = Y.Node.create('<div id="dock_item_'+this.id+'" class="'+this.cfg.css.dockeditem+'"></div>');
-            if (blocks.dock.count === 1) {
-                dockitem.addClass('firstdockitem');
-            }
-            dockitem.append(dockitemtitle);
-            if (this.commands.hasChildNodes) {
-                this.contents.appendChild(this.commands);
-            }
-            blocks.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.setBody(Y.Node.getDOMNode(this.contents));
-            this.panel.render(blocks.dock.node);
-            if (this.cfg.display.mindisplaywidth !== null && Y.one(this.panel.body).getStyle('minWidth') == '0px') {
-                Y.one(this.panel.body).setStyle('minWidth', this.cfg.display.mindisplaywidth);
-                Y.one(this.panel.body).setStyle('minHeight', dockitemtitle.get('offsetHeight')+'px');
-            }
-            dockitem.on('showitem|mouseover', this.show, this);
-            this.fire('dockeditem:drawcomplete');
-        },
-        /**
-         * This function removes the node and destroys it's bits
-         * @param {Event} e
-         */
-        remove : function (e) {
-            this.hide(e);
-            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) {
-            blocks.dock.hide_all();
-            this.fire('dockeditem:showstart');
-            this.panel.show(e, this);
-            this.active = true;
-            Y.one('#dock_item_'+this.id+'_title').addClass(this.cfg.css.activeitem);
-            Y.detach('mouseover', this.show, Y.one('#dock_item_'+this.id));
-            Y.one('#dock_item_panel_'+this.id).on('dockpreventhide|click', function(){this.preventhide=true;}, this);
-            Y.one('#dock_item_'+this.id).on('dockhide|click', this.hide, this);
-            Y.get(window).on('dockresize|resize', this.resize_panel, this);
-            Y.get(document.body).on('dockhide|click', this.hide, this);
-            this.fire('dockeditem:showcomplete');
-            return true;
-        },
-        /**
-         * This function hides the item and makes it inactive
-         * @param {event}
-         */
-        hide : function(e) {
-            // Ignore this call is preventhide is true
-            if (this.preventhide===true) {
-                this.preventhide = false;
-            } else if (this.active) {
-                this.fire('dockeditem:hidestart');
-                this.active = false;
-                Y.one('#dock_item_'+this.id+'_title').removeClass(this.cfg.css.activeitem);
-                Y.one('#dock_item_'+this.id).on('showitem|mouseover', this.show, this);
-                Y.get(window).detach('dockresize|resize');
-                Y.get(document.body).detach('dockhide|click');
-                this.panel.hide(e, this);
-                this.fire('dockeditem:hidecomplete');
-            }
-        },
-        /**
-         * This function checks the size and position of the panel and moves/resizes if
-         * required to keep it within the bounds of the window.
-         */
-        resize_panel : function() {
-            this.fire('dockeditem:resizestart');
-            var panelbody = Y.one(this.panel.body);
-            var buffer = this.cfg.buffer;
-            var screenheight = parseInt(Y.get(document.body).get('winHeight'));
-            var panelheight = parseInt(panelbody.get('offsetHeight'));
-            var paneltop = parseInt(this.panel.cfg.getProperty('y'));
-            var titletop = parseInt(Y.one('#dock_item_'+this.id+'_title').getY());
-            var scrolltop = window.pageYOffset || document.body.scrollTop || 0;
-
-            // This makes sure that the panel is the same height as the dock title to
-            // begin with
-            if (paneltop > (buffer+scrolltop) && paneltop > (titletop+scrolltop)) {
-                this.panel.cfg.setProperty('y', titletop+scrolltop);
-            }
-
-            // This makes sure that if the panel is big it is moved up to ensure we don't
-            // have wasted space above the panel
-            if ((paneltop+panelheight)>(screenheight+scrolltop) && paneltop > buffer) {
-                paneltop = (screenheight-panelheight-buffer);
-                if (paneltop<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-(buffer*3)-10)+'px');
-                panelbody.addClass('oversized_content');
-            }
-            this.fire('dockeditem:resizecomplete');
-        }
-    }
-};
-
-/**
- * This class represents a generic block
- * @class genericblock
- * @constructor
- * @param {int} uid
- */
-blocks.genericblock = function(uid){
-    // Save the unique id as the blocks id
-    if (uid && this.id==null) {
-        this.id = uid;
-    }
-};
-/** Properties */
-blocks.genericblock.prototype.name =                    blocks.dock.abstract_block_class.name;
-blocks.genericblock.prototype.cachedcontentnode =       blocks.dock.abstract_block_class.cachedcontentnode;
-blocks.genericblock.prototype.blockspacewidth =         blocks.dock.abstract_block_class.blockspacewidth;
-blocks.genericblock.prototype.skipsetposition =         blocks.dock.abstract_block_class.skipsetposition;
-/** Methods **/
-blocks.genericblock.prototype.init =                    blocks.dock.abstract_block_class.init;
-blocks.genericblock.prototype.move_to_dock =            blocks.dock.abstract_block_class.move_to_dock;
-blocks.genericblock.prototype.resize_block_space =      blocks.dock.abstract_block_class.resize_block_space;
-blocks.genericblock.prototype.return_to_block =         blocks.dock.abstract_block_class.return_to_block;
-
-/**
- * This class represents an item in the dock
- * @class item
- * @constructor
- * @param {int} uid The unique ID for the item
- * @param {Y.Node} title
- * @param {Y.Node} contents
- * @param {Y.Node} commands
- */
-blocks.dock.item = function(uid, title, contents, commands){
-    if (uid && this.id==null) this.id = uid;
-    if (title && this.title==null) this.title = title;
-    if (contents && this.contents==null) this.contents = contents;
-    if (commands && this.commands==null) this.commands = commands;
-    this.init_events();
-}
-/** Properties */
-blocks.dock.item.prototype.id =                 blocks.dock.abstract_item_class.id;
-blocks.dock.item.prototype.name =               blocks.dock.abstract_item_class.name;
-blocks.dock.item.prototype.title =              blocks.dock.abstract_item_class.title;
-blocks.dock.item.prototype.contents =           blocks.dock.abstract_item_class.contents;
-blocks.dock.item.prototype.commands =           blocks.dock.abstract_item_class.commands;
-blocks.dock.item.prototype.active =             blocks.dock.abstract_item_class.active;
-blocks.dock.item.prototype.panel =              blocks.dock.abstract_item_class.panel;
-blocks.dock.item.prototype.preventhide =        blocks.dock.abstract_item_class.preventhide;
-blocks.dock.item.prototype.cfg =                blocks.dock.cfg;
-/** Methods **/
-blocks.dock.item.prototype.init_events =        blocks.dock.abstract_item_class.init_events;
-blocks.dock.item.prototype.draw =               blocks.dock.abstract_item_class.draw;
-blocks.dock.item.prototype.remove =             blocks.dock.abstract_item_class.remove;
-blocks.dock.item.prototype.show =               blocks.dock.abstract_item_class.show;
-blocks.dock.item.prototype.hide =               blocks.dock.abstract_item_class.hide;
-blocks.dock.item.prototype.resize_panel =       blocks.dock.abstract_item_class.resize_panel;
-
-///////////////// END OF BLOCKS CODE \\\\\\\\\\\\\\\\\\\\\\
Index: moodle/lib/outputcomponents.php
--- moodle/lib/outputcomponents.php Base (1.68)
+++ moodle/lib/outputcomponents.php Locally Modified (Based On 1.68)
@@ -579,6 +579,41 @@
     }
 
     /**
+     * Returns JavaScript code to initialise a new object
+     * @param string|null $var If it is null then no var is assigned the new object
+     * @param string $class
+     * @param array $arguments
+     * @param array $requirements
+     * @param int $delay
+     * @return string
+     */
+    public function object_init($var, $class, array $arguments = null, array $requirements = null, $delay=0) {
+        if (is_array($arguments)) {
+            $arguments = array_map('json_encode', $arguments);
+            $arguments = implode(', ', $arguments);
+        }
+
+        if ($var === null) {
+            $js = "new $class($arguments);";
+        } else if (strpos($var, '.')!==false) {
+            $js = "$var = new $class($arguments);";
+        } else {
+            $js = "var $var = new $class($arguments);";
+        }
+
+        if ($delay) {
+            $delay = $delay * 1000; // in miliseconds
+            $js = "setTimeout(function() { $js }, $delay);";
+        }
+
+        if (count($requirements) > 0) {
+            $requirements = implode("', '", $requirements);
+            $js = "Y.use('$requirements', function(){ $js });";
+        }
+        return $js."\n";
+    }
+
+    /**
      * Returns code setting value to variable
      * @param string $name
      * @param mixed $value json serialised value
Index: moodle/theme/standardold/config.php
--- moodle/theme/standardold/config.php Base (1.4)
+++ moodle/theme/standardold/config.php Locally Modified (Based On 1.4)
@@ -177,7 +177,9 @@
 );
 
 /** List of javascript files that need to included on each page */
-$THEME->javascripts = array();
-$THEME->javascripts_footer = array('navigation');
+//$THEME->javascripts_footer = array('navigation');
 
+/**
+ * This enables the dock on the side of the page as this theme supports it.
+ */
 $THEME->enable_dock = true;
