MDL-40167 dock: tidy up after first peer-review

This commit is contained in:
Sam Hemelryk 2013-07-05 15:44:23 +12:00
parent 84192d7836
commit a69a7e89b8
15 changed files with 834 additions and 635 deletions

View File

@ -230,7 +230,7 @@ class block_base {
global $CFG;
$bc = new block_contents($this->html_attributes());
$bc->attributes['data-block'] = $this->name();
$bc->blockinstanceid = $this->instance->id;
$bc->blockpositionid = $this->instance->blockpositionid;

View File

@ -446,6 +446,9 @@ class block_manager {
throw new coding_exception('block_manager has already prepared the blocks in region ' .
$region . 'for output. It is too late to add a fake block.');
}
if (!isset($bc->attributes['data-block'])) {
$bc->attributes['data-block'] = '_fake';
}
$this->extracontent[$region][] = $bc;
}
@ -1860,6 +1863,7 @@ function block_add_block_ui($page, $output) {
$bc = new block_contents();
$bc->title = get_string('addblock');
$bc->add_class('block_adminblock');
$bc->attributes['data-block'] = 'adminblock';
$missingblocks = $page->blocks->get_addable_blocks();
if (empty($missingblocks)) {

View File

@ -9,28 +9,33 @@ YUI.add('moodle-core-dock', function (Y, NAME) {
*/
var LOGNS = 'moodle-core-dock';
var BODY = Y.one(document.body);
var 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
buttonscontainer: 'buttons_container',
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
contentonly: 'content-only',
dockonload: 'dock_on_load'
};
var SELECTOR = {
dockableblock: '.block[data-instanceid][data-dockable]',
blockmoveto: '.block[data-instanceid][data-dockable] .moveto',
panelmoveto: '#dockeditempanel .commands a.moveto',
dockonload: '.block.'+CSS.dockonload,
blockregion: '[data-blockregion]'
};
var LOGNS = 'moodle-core-dock',
BODY = Y.one(Y.config.doc.body),
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
buttonscontainer: 'buttons_container',
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
contentonly: 'content-only',
dockonload: 'dock_on_load'
},
SELECTOR = {
dockableblock: '.block[data-instanceid][data-dockable]',
blockmoveto: '.block[data-instanceid][data-dockable] .moveto',
panelmoveto: '#dockeditempanel .commands a.moveto',
dockonload: '.block.'+CSS.dockonload,
blockregion: '[data-blockregion]'
},
DOCK,
DOCKPANEL,
TABHEIGHTMANAGER,
BLOCK,
DOCKEDITEM;
/**
* Core namespace.
@ -147,12 +152,18 @@ M.core.dock.dockBlock = function(id) {
* @return {Node} The title node to use.
*/
M.core.dock.fixTitleOrientation = function(title, text) {
var dock = M.core.dock.get();
var dock = M.core.dock.get(),
fontsize = '11px',
transform = 'rotate(270deg)',
test,
width,
height,
container;
title = Y.one(title);
if (dock.get('orientation') !== 'vertical') {
// If the dock isn't vertical don't adjust it!
title.setContent(text);
title.set('innerHTML', text);
return title;
}
@ -161,37 +172,34 @@ M.core.dock.fixTitleOrientation = function(title, text) {
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 />'));
return title.set('innerHTML', text.split('').join('<br />'));
case 'ttb':
clockwise = true;
transform = 'rotate(90deg)';
break;
case 'btt':
clockwise = false;
// Nothing to do here. transform default is good.
break;
}
if (Y.UA.ie === 8) {
// IE8 can flip the text via CSS but not handle transform. IE9+ can handle the CSS3 transform attribute.
title.setContent(text);
title.set('innerHTML', text);
title.setAttribute('style', 'writing-mode: tb-rl; filter: flipV flipH;display:inline;');
title.addClass('filterrotate');
return title;
}
// We need to fix a font-size - sorry theme designers.
var fontsize = '11px';
var transform = (clockwise) ? 'rotate(90deg)' : 'rotate(270deg)';
var test = Y.Node.create('<h2><span class="transform-test-node" style="font-size:'+fontsize+';">'+text+'</span></h2>');
test = Y.Node.create('<h2><span class="transform-test-node" style="font-size:'+fontsize+';">'+text+'</span></h2>');
BODY.insert(test, 0);
var width = test.one('span').get('offsetWidth') * 1.2;
var height = test.one('span').get('offsetHeight');
width = test.one('span').get('offsetWidth') * 1.2;
height = test.one('span').get('offsetHeight');
test.remove();
title.setContent(text);
title.set('innerHTML', text);
title.addClass('css3transform');
// Move the title into position
@ -220,10 +228,12 @@ M.core.dock.fixTitleOrientation = function(title, text) {
'-o-transform' : transform
});
var container = Y.Node.create('<div></div>');
container = Y.Node.create('<div></div>');
container.append(title);
container.setStyle('height', width + (width / 4));
container.setStyle('position', 'relative');
container.setStyles({
height : width + (width / 4),
position : 'relative'
});
return container;
};
@ -256,7 +266,7 @@ M.core.dock.notifyBlockChange = function(instanceid) {
* @extends Y.Base
* @uses Y.EventTarget
*/
var DOCK = function() {
DOCK = function() {
DOCK.superclass.constructor.apply(this, arguments);
};
DOCK.prototype = {
@ -322,7 +332,7 @@ DOCK.prototype = {
*/
initializer : function() {
Y.log('Dock initialising', 'note', LOGNS);
// Publish the events the dock has
/**
* Fired when the dock first starts initialising.
@ -404,7 +414,18 @@ DOCK.prototype = {
if (this.dockdrawn === true) {
return true;
}
var dock = this._initialiseDockNode();
var dock = this._initialiseDockNode(),
clickargs = {
cssselector:'.'+CSS.dockedtitle,
delay:0
},
mouseenterargs = {
cssselector:'.'+CSS.dockedtitle,
delay:0.5,
iscontained:true,
preventevent:'click',
preventdelay:3
};
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');
@ -416,9 +437,6 @@ DOCK.prototype = {
this.tabheightmanager = new TABHEIGHTMANAGER({dock:this});
var clickargs = {cssselector:'.'+CSS.dockedtitle, delay:0};
var mouseenterargs = {cssselector:'.'+CSS.dockedtitle, delay:0.5, iscontained:true, preventevent:'click', preventdelay:3};
// 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
@ -456,8 +474,7 @@ DOCK.prototype = {
return false;
}
e.halt();
var id = target.getAttribute('rel');
this.dockeditems[id].toggle(e.action);
this.dockeditems[target.getAttribute('rel')].toggle(e.action);
},
/**
* Call the theme customisation method "customise_dock_for_theme" if it exists.
@ -506,31 +523,35 @@ DOCK.prototype = {
};
// Check for and apply any legacy configuration.
for (key in M.core_dock.cfg) {
value = M.core_dock.cfg[key];
if (value === null) {
continue;
if (Y.Lang.isString(key) && cfgmap[key]) {
value = M.core_dock.cfg[key];
if (value === null) {
continue;
}
if (!warned) {
Y.log('Warning: customise_dock_for_theme has changed. Please update your code.', 'warn', LOGNS);
warned = true;
}
// Damn, the've set something.
Y.log('Note for customise_dock_for_theme code: M.core_dock.cfg.'+key+' is now dock.set(\''+key+'\', value)', 'info', LOGNS);
this.set(cfgmap[key], value);
}
if (!warned) {
Y.log('Warning: customise_dock_for_theme has changed. Please update your code.', 'warn', LOGNS);
warned = true;
}
// Damn, the've set something.
Y.log('Note for customise_dock_for_theme code: M.core_dock.cfg.'+key+' is now dock.set(\''+key+'\', value)', 'info', LOGNS);
this.set(cfgmap[key], value);
}
// Check for and apply any legacy CSS changes..
for (key in M.core_dock.css) {
value = M.core_dock.css[key];
if (value === null) {
continue;
if (Y.Lang.isString(key)) {
value = M.core_dock.css[key];
if (value === null) {
continue;
}
if (!warned) {
Y.log('Warning: customise_dock_for_theme has changed. Please update your code.', 'warn', LOGNS);
warned = true;
}
// Damn, they've set something.
Y.log('Note for customise_dock_for_theme code: M.core_dock.css.'+key+' is now CSS.'+key+' = value', 'info', LOGNS);
CSS[key] = value;
}
if (!warned) {
Y.log('Warning: customise_dock_for_theme has changed. Please update your code.', 'warn', LOGNS);
warned = true;
}
// Damn, they've set something.
Y.log('Note for customise_dock_for_theme code: M.core_dock.css.'+key+' is now CSS.'+key+' = value', 'info', LOGNS);
CSS[key] = value;
}
}
},
@ -547,7 +568,7 @@ DOCK.prototype = {
holdingarea = Y.Node.create('<div></div>').setStyles({display:'none'}),
buttons = this.get('buttonsNode'),
container = this.get('itemContainerNode');
if (!dock) {
dock = Y.one('#'+CSS.dock);
}
@ -642,7 +663,11 @@ DOCK.prototype = {
* @return {Boolean}
*/
handleEvent : function(e, options) {
var item = this.getActiveItem();
var item = this.getActiveItem(),
target,
targetid,
regex = /^dock_item_(\d+)_title$/,
self = this;
if (options.cssselector === 'body') {
if (!this.get('dockNode').contains(e.target)) {
if (item) {
@ -650,7 +675,6 @@ DOCK.prototype = {
}
}
} else {
var target;
if (e.target.test(options.cssselector)) {
target = e.target;
} else {
@ -665,7 +689,6 @@ DOCK.prototype = {
if (options.preventevent) {
this.preventevent = options.preventevent;
if (options.preventdelay) {
var self = this;
setTimeout(function(){
self.preventevent = null;
}, options.preventdelay * 1000);
@ -679,8 +702,7 @@ DOCK.prototype = {
if (options.delay > 0) {
return this.delayEvent(e, options, target);
}
var targetid = target.get('id');
var regex = /^dock_item_(\d+)_title$/;
targetid = target.get('id');
if (targetid.match(regex)) {
item = this.dockeditems[targetid.replace(regex, '$1')];
if (item.active) {
@ -735,7 +757,8 @@ DOCK.prototype = {
var blockregions = [],
populatedblockregions = 0,
allnewregions = true,
showregions = false;
showregions = false,
i;
// First look for understood regions.
Y.all(SELECTOR.blockregion).each(function(){
var regionname = region.getData('blockregion');
@ -775,22 +798,27 @@ DOCK.prototype = {
}
if (!allnewregions) {
var i = null;
if (populatedblockregions === 0 && showregions === false) {
for (i in blockregions) {
BODY.removeClass(blockregions[i].bodyclass);
if (blockregions[i].bodyclass) {
BODY.removeClass(blockregions[i].bodyclass);
}
}
} else if (populatedblockregions === 1 && showregions === false) {
for (i in blockregions) {
if (!blockregions[i].hasblocks) {
BODY.removeClass(blockregions[i].bodyclass);
} else {
BODY.addClass(blockregions[i].bodyclass);
if (blockregions[i].bodyclass) {
if (!blockregions[i].hasblocks) {
BODY.removeClass(blockregions[i].bodyclass);
} else {
BODY.addClass(blockregions[i].bodyclass);
}
}
}
} else {
for (i in blockregions) {
BODY.removeClass(blockregions[i].bodyclass);
if (blockregions[i].bodyclass) {
BODY.removeClass(blockregions[i].bodyclass);
}
}
}
}
@ -863,8 +891,11 @@ DOCK.prototype = {
*/
removeAll : function() {
Y.log('Undocking all '+this.dockeditems.length+' blocks', 'note', LOGNS);
for (var i in this.dockeditems) {
this.remove(i);
var i;
for (i in this.dockeditems) {
if (Y.Lang.isNumber(i) || Y.Lang.isString(i)) {
this.remove(i);
}
}
return true;
},
@ -902,34 +933,43 @@ DOCK.prototype = {
* @return {Boolean}
*/
resize : function() {
var panel = this.getPanel();
var item = this.getActiveItem();
var panel = this.getPanel(),
item = this.getActiveItem(),
buffer,
screenh,
docky,
titletop,
containery,
containerheight,
scrolltop,
panelheight,
dockx,
titleleft;
if (!panel.get('visible') || !item) {
return true;
}
this.fire('dock:panelresizestart');
if (this.get('orientation') === 'vertical') {
var buffer = this.get('bufferPanel');
var screenheight = parseInt(BODY.get('winHeight'), 10)-(buffer*2);
var docky = this.get('dockNode').getY();
var titletop = item.get('dockTitleNode').getY()-docky-buffer;
var containery = this.get('itemContainerNode').getY();
var containerheight = containery-docky+this.get('buttonsNode').get('offsetHeight');
var scrolltop = panel.get('bodyNode').get('scrollTop');
buffer = this.get('bufferPanel');
screenh = parseInt(BODY.get('winHeight'), 10)-(buffer*2);
docky = this.get('dockNode').getY();
titletop = item.get('dockTitleNode').getY()-docky-buffer;
containery = this.get('itemContainerNode').getY();
containerheight = containery-docky+this.get('buttonsNode').get('offsetHeight');
scrolltop = panel.get('bodyNode').get('scrollTop');
panel.get('bodyNode').setStyle('height', 'auto');
panel.get('node').removeClass('oversized_content');
var panelheight = panel.get('node').get('offsetHeight');
panelheight = panel.get('node').get('offsetHeight');
if (Y.UA.ie > 0 && Y.UA.ie < 7) {
panel.setTop(item.get('dockTitleNode').getY());
} else if (panelheight > screenheight) {
} else if (panelheight > screenh) {
panel.setTop(buffer-containerheight);
panel.get('bodyNode').setStyle('height', (screenheight-panel.get('headerNode').get('offsetHeight'))+'px');
panel.get('bodyNode').setStyle('height', (screenh-panel.get('headerNode').get('offsetHeight'))+'px');
panel.get('node').addClass('oversized_content');
} else if (panelheight > (screenheight-(titletop-buffer))) {
var difference = panelheight - (screenheight-titletop);
panel.setTop(titletop-containerheight-difference+buffer);
} else if (panelheight > (screenh-(titletop-buffer))) {
panel.setTop(titletop-containerheight-(panelheight - (screenh-titletop))+buffer);
} else {
panel.setTop(titletop-containerheight+buffer);
}
@ -943,8 +983,8 @@ DOCK.prototype = {
panel.get('node').setStyle('left', -panel.get('offsetWidth')+'px');
} else if (this.get('position') === 'top') {
var dockx = this.get('dockNode').getX();
var titleleft = item.get('dockTitleNode').getX()-dockx;
dockx = this.get('dockNode').getX();
titleleft = item.get('dockTitleNode').getX()-dockx;
panel.get('node').setStyle('left', titleleft+'px');
}
@ -957,7 +997,8 @@ DOCK.prototype = {
* @return {DOCKEDITEM}
*/
getActiveItem : function() {
for (var i in this.dockeditems) {
var i;
for (i in this.dockeditems) {
if (this.dockeditems[i].active) {
return this.dockeditems[i];
}
@ -1094,7 +1135,7 @@ Y.augment(DOCK, Y.EventTarget);
* @extends Y.Base
* @uses Y.EventTarget
*/
var DOCKPANEL = function() {
DOCKPANEL = function() {
DOCKPANEL.superclass.constructor.apply(this, arguments);
};
DOCKPANEL.prototype = {
@ -1188,11 +1229,14 @@ DOCKPANEL.prototype = {
*/
setHeader : function(content) {
this.create();
var header = this.get('headerNode');
var header = this.get('headerNode'),
i;
header.setContent(content);
if (arguments.length > 1) {
for (var i=1;i < arguments.length;i++) {
header.append(arguments[i]);
for (i = 1; i < arguments.length; i++) {
if (Y.Lang.isNumber(i) || Y.Lang.isString(i)) {
header.append(arguments[i]);
}
}
}
},
@ -1327,7 +1371,7 @@ Y.augment(DOCKPANEL, Y.EventTarget);
* @constructor
* @extends Y.Base
*/
var TABHEIGHTMANAGER = function() {
TABHEIGHTMANAGER = function() {
TABHEIGHTMANAGER.superclass.constructor.apply(this, arguments);
};
TABHEIGHTMANAGER.prototype = {
@ -1354,12 +1398,14 @@ TABHEIGHTMANAGER.prototype = {
id, dockedtitle;
if (items.length > 0) {
for (id in items) {
dockedtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (dockedtitle) {
if (this.get('enabled')) {
dockedtitle.setStyle('height', 'auto');
if (Y.Lang.isNumber(id) || Y.Lang.isString(id)) {
dockedtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (dockedtitle) {
if (this.get('enabled')) {
dockedtitle.setStyle('height', 'auto');
}
totalheight += dockedtitle.get('offsetHeight') || 0;
}
totalheight += dockedtitle.get('offsetHeight') || 0;
}
}
if (totalheight > possibleheight) {
@ -1382,20 +1428,22 @@ TABHEIGHTMANAGER.prototype = {
Y.log('Enabling the dock tab sizer.', 'note', LOGNS);
this.set('enabled', true);
for (id in items) {
itemtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (!itemtitle) {
continue;
if (Y.Lang.isNumber(id) || Y.Lang.isString(id)) {
itemtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (!itemtitle) {
continue;
}
itemheight = Math.floor((possibleheight-usedheight) / (count - runningcount));
offsetheight = itemtitle.get('offsetHeight');
itemtitle.setStyle('overflow', 'hidden');
if (offsetheight > itemheight) {
itemtitle.setStyle('height', itemheight+'px');
usedheight += itemheight;
} else {
usedheight += offsetheight;
}
runningcount++;
}
itemheight = Math.floor((possibleheight-usedheight) / (count - runningcount));
offsetheight = itemtitle.get('offsetHeight');
itemtitle.setStyle('overflow', 'hidden');
if (offsetheight > itemheight) {
itemtitle.setStyle('height', itemheight+'px');
usedheight += itemheight;
} else {
usedheight += offsetheight;
}
runningcount++;
}
}
};
@ -1444,24 +1492,24 @@ Y.extend(TABHEIGHTMANAGER, Y.Base, TABHEIGHTMANAGER.prototype, {
* @class ActionKey
*/
Y.Event.define("dock:actionkey", {
// Webkit and IE repeat keydown when you hold down arrow keys.
// Opera links keypress to page scroll; others keydown.
// Firefox prevents page scroll via preventDefault() on either
// keydown or keypress.
_event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress',
// Webkit and IE repeat keydown when you hold down arrow keys.
// Opera links keypress to page scroll; others keydown.
// Firefox prevents page scroll via preventDefault() on either
// keydown or keypress.
_event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress',
/**
* The keys to trigger on.
* @method _keys
* @property _keys
*/
_keys: {
//arrows
'37': 'collapse',
'39': 'expand',
//(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings)
'32': 'toggle',
'13': 'enter'
},
_keys: {
//arrows
'37': 'collapse',
'39': 'expand',
//(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings)
'32': 'toggle',
'13': 'enter'
},
/**
* Handles key events
@ -1470,18 +1518,18 @@ Y.Event.define("dock:actionkey", {
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
* @param {Object} args
*/
_keyHandler: function (e, notifier, args) {
var actObj;
if (!args.actions) {
actObj = {collapse:true, expand:true, toggle:true, enter:true};
} else {
actObj = args.actions;
}
if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) {
e.action = this._keys[e.keyCode];
notifier.fire(e);
}
},
_keyHandler: function (e, notifier, args) {
var actObj;
if (!args.actions) {
actObj = {collapse: true, expand: true, toggle: true, enter: true};
} else {
actObj = args.actions;
}
if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) {
e.action = this._keys[e.keyCode];
notifier.fire(e);
}
},
/**
* Subscribes to events.
@ -1490,24 +1538,27 @@ Y.Event.define("dock:actionkey", {
* @param {Subscription} sub The object tracking this subscription.
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
*/
on: function (node, sub, notifier) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._detacher = node.on(this._event, this._keyHandler,this, notifier, {actions:false});
} else {
sub._detacher = node.on(this._event, this._keyHandler,this, notifier, sub.args[0]);
}
},
on: function (node, sub, notifier) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._detacher = node.on(this._event, this._keyHandler, this, notifier, {actions: false});
} else {
sub._detacher = node.on(this._event, this._keyHandler, this, notifier, sub.args[0]);
}
},
/**
* Detaches an event listener
* @method detach
* @param {Node} node The node this subscription was applied to.
* @param {Subscription} sub The object tracking this subscription.
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
*/
detach: function (node, sub, notifier) {
//detach our _detacher handle of the subscription made in on()
sub._detacher.detach();
},
detach: function (node, sub) {
//detach our _detacher handle of the subscription made in on()
sub._detacher.detach();
},
/**
* Creates a delegated event listener.
@ -1517,15 +1568,15 @@ Y.Event.define("dock:actionkey", {
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
* @param {String|function} filter Selector string or function that accpets an event object and returns null.
*/
delegate: function (node, sub, notifier, filter) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, {actions:false});
} else {
sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, sub.args[0]);
}
},
delegate: function (node, sub, notifier, filter) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._delegateDetacher = node.delegate(this._event, this._keyHandler, filter, this, notifier, {actions:false});
} else {
sub._delegateDetacher = node.delegate(this._event, this._keyHandler, filter, this, notifier, sub.args[0]);
}
},
/**
* Detaches a delegated event listener.
@ -1535,9 +1586,9 @@ Y.Event.define("dock:actionkey", {
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
* @param {String|function} filter Selector string or function that accpets an event object and returns null.
*/
detachDelegate: function (node, sub, notifier, filter) {
sub._delegateDetacher.detach();
}
detachDelegate: function (node, sub) {
sub._delegateDetacher.detach();
}
});
/**
* Dock JS.
@ -1555,7 +1606,7 @@ Y.Event.define("dock:actionkey", {
* @constructor
* @extends Y.Base
*/
var BLOCK = function() {
BLOCK = function() {
BLOCK.superclass.constructor.apply(this, arguments);
};
BLOCK.prototype = {
@ -1591,7 +1642,7 @@ BLOCK.prototype = {
* The dock item associated with this block
* @property dockitem
* @protected
* @type DOCKITEM
* @type DOCKEDITEM
*/
dockitem : null,
/**
@ -1599,7 +1650,8 @@ BLOCK.prototype = {
* @method initializer
*/
initializer : function() {
var node = Y.one('#inst'+this.get('id'));
var node = Y.one('#inst'+this.get('id')),
commands;
if (!node) {
return false;
}
@ -1611,7 +1663,7 @@ BLOCK.prototype = {
// Move the block straight to the dock if required
if (node.hasClass(CSS.dockonload)) {
node.removeClass(CSS.dockonload);
var commands = node.one('.header .title .commands');
commands = node.one('.header .title .commands');
if (!commands) {
commands = Y.Node.create('<div class="commands"></div>');
if (node.one('.header .title')) {
@ -1631,9 +1683,14 @@ BLOCK.prototype = {
* @return String
*/
_getBlockClass : function(node) {
var classes = node.getAttribute('className').toString(),
regex = /(^|\s)(block_[a-zA-Z0-9_]+)(\s|$)/,
matches = regex.exec(classes);
var block = node.getData('block'),
classes,
matches;
if (Y.Lang.isString(block) && block !== '') {
return block;
}
classes = node.getAttribute('className').toString();
matches = /(^| )block_([^ ]+)/.exec(classes);
if (matches) {
return matches[2];
}
@ -1641,7 +1698,7 @@ BLOCK.prototype = {
},
/**
* This function is reponsible for moving a block from the page structure onto the dock.
* This function is responsible for moving a block from the page structure onto the dock.
* @method moveToDock
* @param {EventFacade} e
*/
@ -1652,7 +1709,13 @@ BLOCK.prototype = {
var dock = M.core.dock.get(),
id = this.get('id'),
blockcontent = Y.one('#inst'+id).one('.content');
blockcontent = Y.one('#inst'+id).one('.content'),
icon = (right_to_left()) ? 't/dock_to_block_rtl' : 't/dock_to_block',
breakchar = (location.href.match(/\?/)) ? '&' : '?',
blocktitle,
blockcommands,
movetoimg,
moveto;
if (!blockcontent) {
return;
@ -1660,25 +1723,22 @@ BLOCK.prototype = {
Y.log('Moving block to the dock:'+this.get('id'), 'note', LOGNS);
var icon = (right_to_left()) ? 't/dock_to_block_rtl' : 't/dock_to_block',
char = (location.href.match(/\?/)) ? '&' : '?',
blocktitle,
blockcommands,
movetoimg,
moveto;
this.recordBlockState();
blocktitle = this.cachedcontentnode.one('.title h2').cloneNode(true);
blockcommands = this.cachedcontentnode.one('.title .commands').cloneNode(true);
// Must set the image src seperatly of we get an error with XML strict headers
movetoimg = Y.Node.create('<img alt="'+Y.Escape.html(M.str.block.undockitem)+'" title="'+
Y.Escape.html(M.util.get_string('undockblock', 'block', blocktitle.innerHTML)) +'" />');
movetoimg.setAttribute('src', M.util.image_url(icon, 'moodle'));
moveto = Y.Node.create('<a class="moveto customcommand requiresjs"></a>').append(movetoimg);
moveto.set('href', location.href + char + 'dock='+id);
blockcommands.append(moveto);
movetoimg = Y.Node.create('<img />').setAttrs({
alt : Y.Escape.html(M.str.block.undockitem),
title : Y.Escape.html(M.util.get_string('undockblock', 'block', blocktitle.innerHTML)),
src : M.util.image_url(icon, 'moodle')
});
moveto = Y.Node.create('<a class="moveto customcommand requiresjs"></a>').setAttrs({
className : 'moveto customcommand requiresjs',
href : Y.config.win.location.href + breakchar + 'dock='+id
});
moveto.append(movetoimg);
blockcommands.append(moveto.append(movetoimg));
// Create a new dock item for the block
this.dockitem = new DOCKEDITEM({
@ -1698,7 +1758,7 @@ BLOCK.prototype = {
M.util.set_user_preference('docked_block_instance_'+id, 1);
}
this.set('idDocked', true);
this.set('isDocked', true);
},
/**
* Records the block state and adds it to the docks holding area.
@ -1726,11 +1786,12 @@ BLOCK.prototype = {
/**
* This function removes a block from the dock and puts it back into the page structure.
* @method returnToBlock
* @method returnToPage
* @return {Boolean}
*/
returnToBlock : function() {
var id = this.get('id');
returnToPage : function() {
var id = this.get('id'),
commands;
Y.log('Moving block out of the dock:'+this.get('id'), 'note', LOGNS);
@ -1748,7 +1809,7 @@ BLOCK.prototype = {
this.contentplaceholder.replace(this.cachedcontentnode);
this.cachedcontentnode = Y.one('#'+this.cachedcontentnode.get('id'));
var commands = this.dockitem.get('commands');
commands = this.dockitem.get('commands');
if (commands) {
commands.all('.hidepanelicon').remove();
commands.all('.moveto').remove();
@ -1757,7 +1818,7 @@ BLOCK.prototype = {
this.cachedcontentnode.one('.title').append(commands);
this.cachedcontentnode = null;
M.util.set_user_preference('docked_block_instance_'+id, 0);
this.set('idDocked', false);
this.set('isDocked', false);
return true;
}
};
@ -1804,7 +1865,7 @@ Y.extend(BLOCK, Y.Base, BLOCK.prototype, {
* @extends Y.Base
* @uses Y.EventTarget
*/
var DOCKEDITEM = function() {
DOCKEDITEM = function() {
DOCKEDITEM.superclass.constructor.apply(this, arguments);
};
DOCKEDITEM.prototype = {
@ -1821,7 +1882,8 @@ DOCKEDITEM.prototype = {
*/
initializer : function() {
var title = this.get('title'),
titlestring;
titlestring,
type;
/**
* Fired before the docked item has been drawn.
* @event dockeditem:drawstart
@ -1858,7 +1920,7 @@ DOCKEDITEM.prototype = {
*/
this.publish('dockeditem:itemremoved', {prefix:'dockeditem'});
if (title) {
var type = title.get('nodeName');
type = title.get('nodeName');
titlestring = title.cloneNode(true);
title = Y.Node.create('<'+type+'></'+type+'>');
title = M.core.dock.fixTitleOrientation(title, titlestring.get('text'));
@ -1920,7 +1982,7 @@ DOCKEDITEM.prototype = {
this.fire('dockeditem:showstart');
Y.log('Showing '+this._getLogDescription(), 'info', LOGNS);
panel.setHeader(this.get('titlestring'), this.get('commands'));
panel.setBody(Y.Node.create('<div class="'+this.get('blockclass')+' block_docked"></div>').append(this.get('contents')));
panel.setBody(Y.Node.create('<div class="block_'+this.get('blockclass')+' block_docked"></div>').append(this.get('contents')));
panel.show();
panel.correctWidth();
@ -1972,7 +2034,7 @@ DOCKEDITEM.prototype = {
remove : function () {
this.hide();
// Return the block to its original position.
this.get('block').returnToBlock();
this.get('block').returnToPage();
// Remove the dock item node.
this.get('dockItemNode').remove();
this.fire('dockeditem:itemremoved');

File diff suppressed because one or more lines are too long

View File

@ -9,28 +9,33 @@ YUI.add('moodle-core-dock', function (Y, NAME) {
*/
var LOGNS = 'moodle-core-dock';
var BODY = Y.one(document.body);
var 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
buttonscontainer: 'buttons_container',
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
contentonly: 'content-only',
dockonload: 'dock_on_load'
};
var SELECTOR = {
dockableblock: '.block[data-instanceid][data-dockable]',
blockmoveto: '.block[data-instanceid][data-dockable] .moveto',
panelmoveto: '#dockeditempanel .commands a.moveto',
dockonload: '.block.'+CSS.dockonload,
blockregion: '[data-blockregion]'
};
var LOGNS = 'moodle-core-dock',
BODY = Y.one(Y.config.doc.body),
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
buttonscontainer: 'buttons_container',
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
contentonly: 'content-only',
dockonload: 'dock_on_load'
},
SELECTOR = {
dockableblock: '.block[data-instanceid][data-dockable]',
blockmoveto: '.block[data-instanceid][data-dockable] .moveto',
panelmoveto: '#dockeditempanel .commands a.moveto',
dockonload: '.block.'+CSS.dockonload,
blockregion: '[data-blockregion]'
},
DOCK,
DOCKPANEL,
TABHEIGHTMANAGER,
BLOCK,
DOCKEDITEM;
/**
* Core namespace.
@ -146,12 +151,18 @@ M.core.dock.dockBlock = function(id) {
* @return {Node} The title node to use.
*/
M.core.dock.fixTitleOrientation = function(title, text) {
var dock = M.core.dock.get();
var dock = M.core.dock.get(),
fontsize = '11px',
transform = 'rotate(270deg)',
test,
width,
height,
container;
title = Y.one(title);
if (dock.get('orientation') !== 'vertical') {
// If the dock isn't vertical don't adjust it!
title.setContent(text);
title.set('innerHTML', text);
return title;
}
@ -160,37 +171,34 @@ M.core.dock.fixTitleOrientation = function(title, text) {
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 />'));
return title.set('innerHTML', text.split('').join('<br />'));
case 'ttb':
clockwise = true;
transform = 'rotate(90deg)';
break;
case 'btt':
clockwise = false;
// Nothing to do here. transform default is good.
break;
}
if (Y.UA.ie === 8) {
// IE8 can flip the text via CSS but not handle transform. IE9+ can handle the CSS3 transform attribute.
title.setContent(text);
title.set('innerHTML', text);
title.setAttribute('style', 'writing-mode: tb-rl; filter: flipV flipH;display:inline;');
title.addClass('filterrotate');
return title;
}
// We need to fix a font-size - sorry theme designers.
var fontsize = '11px';
var transform = (clockwise) ? 'rotate(90deg)' : 'rotate(270deg)';
var test = Y.Node.create('<h2><span class="transform-test-node" style="font-size:'+fontsize+';">'+text+'</span></h2>');
test = Y.Node.create('<h2><span class="transform-test-node" style="font-size:'+fontsize+';">'+text+'</span></h2>');
BODY.insert(test, 0);
var width = test.one('span').get('offsetWidth') * 1.2;
var height = test.one('span').get('offsetHeight');
width = test.one('span').get('offsetWidth') * 1.2;
height = test.one('span').get('offsetHeight');
test.remove();
title.setContent(text);
title.set('innerHTML', text);
title.addClass('css3transform');
// Move the title into position
@ -219,10 +227,12 @@ M.core.dock.fixTitleOrientation = function(title, text) {
'-o-transform' : transform
});
var container = Y.Node.create('<div></div>');
container = Y.Node.create('<div></div>');
container.append(title);
container.setStyle('height', width + (width / 4));
container.setStyle('position', 'relative');
container.setStyles({
height : width + (width / 4),
position : 'relative'
});
return container;
};
@ -255,7 +265,7 @@ M.core.dock.notifyBlockChange = function(instanceid) {
* @extends Y.Base
* @uses Y.EventTarget
*/
var DOCK = function() {
DOCK = function() {
DOCK.superclass.constructor.apply(this, arguments);
};
DOCK.prototype = {
@ -320,7 +330,7 @@ DOCK.prototype = {
* @method initializer
*/
initializer : function() {
// Publish the events the dock has
/**
* Fired when the dock first starts initialising.
@ -402,7 +412,18 @@ DOCK.prototype = {
if (this.dockdrawn === true) {
return true;
}
var dock = this._initialiseDockNode();
var dock = this._initialiseDockNode(),
clickargs = {
cssselector:'.'+CSS.dockedtitle,
delay:0
},
mouseenterargs = {
cssselector:'.'+CSS.dockedtitle,
delay:0.5,
iscontained:true,
preventevent:'click',
preventdelay:3
};
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');
@ -414,9 +435,6 @@ DOCK.prototype = {
this.tabheightmanager = new TABHEIGHTMANAGER({dock:this});
var clickargs = {cssselector:'.'+CSS.dockedtitle, delay:0};
var mouseenterargs = {cssselector:'.'+CSS.dockedtitle, delay:0.5, iscontained:true, preventevent:'click', preventdelay:3};
// 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
@ -454,8 +472,7 @@ DOCK.prototype = {
return false;
}
e.halt();
var id = target.getAttribute('rel');
this.dockeditems[id].toggle(e.action);
this.dockeditems[target.getAttribute('rel')].toggle(e.action);
},
/**
* Call the theme customisation method "customise_dock_for_theme" if it exists.
@ -503,27 +520,31 @@ DOCK.prototype = {
};
// Check for and apply any legacy configuration.
for (key in M.core_dock.cfg) {
value = M.core_dock.cfg[key];
if (value === null) {
continue;
if (Y.Lang.isString(key) && cfgmap[key]) {
value = M.core_dock.cfg[key];
if (value === null) {
continue;
}
if (!warned) {
warned = true;
}
// Damn, the've set something.
this.set(cfgmap[key], value);
}
if (!warned) {
warned = true;
}
// Damn, the've set something.
this.set(cfgmap[key], value);
}
// Check for and apply any legacy CSS changes..
for (key in M.core_dock.css) {
value = M.core_dock.css[key];
if (value === null) {
continue;
if (Y.Lang.isString(key)) {
value = M.core_dock.css[key];
if (value === null) {
continue;
}
if (!warned) {
warned = true;
}
// Damn, they've set something.
CSS[key] = value;
}
if (!warned) {
warned = true;
}
// Damn, they've set something.
CSS[key] = value;
}
}
},
@ -540,7 +561,7 @@ DOCK.prototype = {
holdingarea = Y.Node.create('<div></div>').setStyles({display:'none'}),
buttons = this.get('buttonsNode'),
container = this.get('itemContainerNode');
if (!dock) {
dock = Y.one('#'+CSS.dock);
}
@ -635,7 +656,11 @@ DOCK.prototype = {
* @return {Boolean}
*/
handleEvent : function(e, options) {
var item = this.getActiveItem();
var item = this.getActiveItem(),
target,
targetid,
regex = /^dock_item_(\d+)_title$/,
self = this;
if (options.cssselector === 'body') {
if (!this.get('dockNode').contains(e.target)) {
if (item) {
@ -643,7 +668,6 @@ DOCK.prototype = {
}
}
} else {
var target;
if (e.target.test(options.cssselector)) {
target = e.target;
} else {
@ -658,7 +682,6 @@ DOCK.prototype = {
if (options.preventevent) {
this.preventevent = options.preventevent;
if (options.preventdelay) {
var self = this;
setTimeout(function(){
self.preventevent = null;
}, options.preventdelay * 1000);
@ -672,8 +695,7 @@ DOCK.prototype = {
if (options.delay > 0) {
return this.delayEvent(e, options, target);
}
var targetid = target.get('id');
var regex = /^dock_item_(\d+)_title$/;
targetid = target.get('id');
if (targetid.match(regex)) {
item = this.dockeditems[targetid.replace(regex, '$1')];
if (item.active) {
@ -728,7 +750,8 @@ DOCK.prototype = {
var blockregions = [],
populatedblockregions = 0,
allnewregions = true,
showregions = false;
showregions = false,
i;
// First look for understood regions.
Y.all(SELECTOR.blockregion).each(function(){
var regionname = region.getData('blockregion');
@ -768,22 +791,27 @@ DOCK.prototype = {
}
if (!allnewregions) {
var i = null;
if (populatedblockregions === 0 && showregions === false) {
for (i in blockregions) {
BODY.removeClass(blockregions[i].bodyclass);
if (blockregions[i].bodyclass) {
BODY.removeClass(blockregions[i].bodyclass);
}
}
} else if (populatedblockregions === 1 && showregions === false) {
for (i in blockregions) {
if (!blockregions[i].hasblocks) {
BODY.removeClass(blockregions[i].bodyclass);
} else {
BODY.addClass(blockregions[i].bodyclass);
if (blockregions[i].bodyclass) {
if (!blockregions[i].hasblocks) {
BODY.removeClass(blockregions[i].bodyclass);
} else {
BODY.addClass(blockregions[i].bodyclass);
}
}
}
} else {
for (i in blockregions) {
BODY.removeClass(blockregions[i].bodyclass);
if (blockregions[i].bodyclass) {
BODY.removeClass(blockregions[i].bodyclass);
}
}
}
}
@ -853,8 +881,11 @@ DOCK.prototype = {
* @return {Boolean}
*/
removeAll : function() {
for (var i in this.dockeditems) {
this.remove(i);
var i;
for (i in this.dockeditems) {
if (Y.Lang.isNumber(i) || Y.Lang.isString(i)) {
this.remove(i);
}
}
return true;
},
@ -892,34 +923,43 @@ DOCK.prototype = {
* @return {Boolean}
*/
resize : function() {
var panel = this.getPanel();
var item = this.getActiveItem();
var panel = this.getPanel(),
item = this.getActiveItem(),
buffer,
screenh,
docky,
titletop,
containery,
containerheight,
scrolltop,
panelheight,
dockx,
titleleft;
if (!panel.get('visible') || !item) {
return true;
}
this.fire('dock:panelresizestart');
if (this.get('orientation') === 'vertical') {
var buffer = this.get('bufferPanel');
var screenheight = parseInt(BODY.get('winHeight'), 10)-(buffer*2);
var docky = this.get('dockNode').getY();
var titletop = item.get('dockTitleNode').getY()-docky-buffer;
var containery = this.get('itemContainerNode').getY();
var containerheight = containery-docky+this.get('buttonsNode').get('offsetHeight');
var scrolltop = panel.get('bodyNode').get('scrollTop');
buffer = this.get('bufferPanel');
screenh = parseInt(BODY.get('winHeight'), 10)-(buffer*2);
docky = this.get('dockNode').getY();
titletop = item.get('dockTitleNode').getY()-docky-buffer;
containery = this.get('itemContainerNode').getY();
containerheight = containery-docky+this.get('buttonsNode').get('offsetHeight');
scrolltop = panel.get('bodyNode').get('scrollTop');
panel.get('bodyNode').setStyle('height', 'auto');
panel.get('node').removeClass('oversized_content');
var panelheight = panel.get('node').get('offsetHeight');
panelheight = panel.get('node').get('offsetHeight');
if (Y.UA.ie > 0 && Y.UA.ie < 7) {
panel.setTop(item.get('dockTitleNode').getY());
} else if (panelheight > screenheight) {
} else if (panelheight > screenh) {
panel.setTop(buffer-containerheight);
panel.get('bodyNode').setStyle('height', (screenheight-panel.get('headerNode').get('offsetHeight'))+'px');
panel.get('bodyNode').setStyle('height', (screenh-panel.get('headerNode').get('offsetHeight'))+'px');
panel.get('node').addClass('oversized_content');
} else if (panelheight > (screenheight-(titletop-buffer))) {
var difference = panelheight - (screenheight-titletop);
panel.setTop(titletop-containerheight-difference+buffer);
} else if (panelheight > (screenh-(titletop-buffer))) {
panel.setTop(titletop-containerheight-(panelheight - (screenh-titletop))+buffer);
} else {
panel.setTop(titletop-containerheight+buffer);
}
@ -933,8 +973,8 @@ DOCK.prototype = {
panel.get('node').setStyle('left', -panel.get('offsetWidth')+'px');
} else if (this.get('position') === 'top') {
var dockx = this.get('dockNode').getX();
var titleleft = item.get('dockTitleNode').getX()-dockx;
dockx = this.get('dockNode').getX();
titleleft = item.get('dockTitleNode').getX()-dockx;
panel.get('node').setStyle('left', titleleft+'px');
}
@ -947,7 +987,8 @@ DOCK.prototype = {
* @return {DOCKEDITEM}
*/
getActiveItem : function() {
for (var i in this.dockeditems) {
var i;
for (i in this.dockeditems) {
if (this.dockeditems[i].active) {
return this.dockeditems[i];
}
@ -1084,7 +1125,7 @@ Y.augment(DOCK, Y.EventTarget);
* @extends Y.Base
* @uses Y.EventTarget
*/
var DOCKPANEL = function() {
DOCKPANEL = function() {
DOCKPANEL.superclass.constructor.apply(this, arguments);
};
DOCKPANEL.prototype = {
@ -1177,11 +1218,14 @@ DOCKPANEL.prototype = {
*/
setHeader : function(content) {
this.create();
var header = this.get('headerNode');
var header = this.get('headerNode'),
i;
header.setContent(content);
if (arguments.length > 1) {
for (var i=1;i < arguments.length;i++) {
header.append(arguments[i]);
for (i = 1; i < arguments.length; i++) {
if (Y.Lang.isNumber(i) || Y.Lang.isString(i)) {
header.append(arguments[i]);
}
}
}
},
@ -1316,7 +1360,7 @@ Y.augment(DOCKPANEL, Y.EventTarget);
* @constructor
* @extends Y.Base
*/
var TABHEIGHTMANAGER = function() {
TABHEIGHTMANAGER = function() {
TABHEIGHTMANAGER.superclass.constructor.apply(this, arguments);
};
TABHEIGHTMANAGER.prototype = {
@ -1343,12 +1387,14 @@ TABHEIGHTMANAGER.prototype = {
id, dockedtitle;
if (items.length > 0) {
for (id in items) {
dockedtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (dockedtitle) {
if (this.get('enabled')) {
dockedtitle.setStyle('height', 'auto');
if (Y.Lang.isNumber(id) || Y.Lang.isString(id)) {
dockedtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (dockedtitle) {
if (this.get('enabled')) {
dockedtitle.setStyle('height', 'auto');
}
totalheight += dockedtitle.get('offsetHeight') || 0;
}
totalheight += dockedtitle.get('offsetHeight') || 0;
}
}
if (totalheight > possibleheight) {
@ -1370,20 +1416,22 @@ TABHEIGHTMANAGER.prototype = {
id, itemtitle, itemheight, offsetheight;
this.set('enabled', true);
for (id in items) {
itemtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (!itemtitle) {
continue;
if (Y.Lang.isNumber(id) || Y.Lang.isString(id)) {
itemtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (!itemtitle) {
continue;
}
itemheight = Math.floor((possibleheight-usedheight) / (count - runningcount));
offsetheight = itemtitle.get('offsetHeight');
itemtitle.setStyle('overflow', 'hidden');
if (offsetheight > itemheight) {
itemtitle.setStyle('height', itemheight+'px');
usedheight += itemheight;
} else {
usedheight += offsetheight;
}
runningcount++;
}
itemheight = Math.floor((possibleheight-usedheight) / (count - runningcount));
offsetheight = itemtitle.get('offsetHeight');
itemtitle.setStyle('overflow', 'hidden');
if (offsetheight > itemheight) {
itemtitle.setStyle('height', itemheight+'px');
usedheight += itemheight;
} else {
usedheight += offsetheight;
}
runningcount++;
}
}
};
@ -1432,24 +1480,24 @@ Y.extend(TABHEIGHTMANAGER, Y.Base, TABHEIGHTMANAGER.prototype, {
* @class ActionKey
*/
Y.Event.define("dock:actionkey", {
// Webkit and IE repeat keydown when you hold down arrow keys.
// Opera links keypress to page scroll; others keydown.
// Firefox prevents page scroll via preventDefault() on either
// keydown or keypress.
_event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress',
// Webkit and IE repeat keydown when you hold down arrow keys.
// Opera links keypress to page scroll; others keydown.
// Firefox prevents page scroll via preventDefault() on either
// keydown or keypress.
_event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress',
/**
* The keys to trigger on.
* @method _keys
* @property _keys
*/
_keys: {
//arrows
'37': 'collapse',
'39': 'expand',
//(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings)
'32': 'toggle',
'13': 'enter'
},
_keys: {
//arrows
'37': 'collapse',
'39': 'expand',
//(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings)
'32': 'toggle',
'13': 'enter'
},
/**
* Handles key events
@ -1458,18 +1506,18 @@ Y.Event.define("dock:actionkey", {
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
* @param {Object} args
*/
_keyHandler: function (e, notifier, args) {
var actObj;
if (!args.actions) {
actObj = {collapse:true, expand:true, toggle:true, enter:true};
} else {
actObj = args.actions;
}
if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) {
e.action = this._keys[e.keyCode];
notifier.fire(e);
}
},
_keyHandler: function (e, notifier, args) {
var actObj;
if (!args.actions) {
actObj = {collapse: true, expand: true, toggle: true, enter: true};
} else {
actObj = args.actions;
}
if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) {
e.action = this._keys[e.keyCode];
notifier.fire(e);
}
},
/**
* Subscribes to events.
@ -1478,24 +1526,27 @@ Y.Event.define("dock:actionkey", {
* @param {Subscription} sub The object tracking this subscription.
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
*/
on: function (node, sub, notifier) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._detacher = node.on(this._event, this._keyHandler,this, notifier, {actions:false});
} else {
sub._detacher = node.on(this._event, this._keyHandler,this, notifier, sub.args[0]);
}
},
on: function (node, sub, notifier) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._detacher = node.on(this._event, this._keyHandler, this, notifier, {actions: false});
} else {
sub._detacher = node.on(this._event, this._keyHandler, this, notifier, sub.args[0]);
}
},
/**
* Detaches an event listener
* @method detach
* @param {Node} node The node this subscription was applied to.
* @param {Subscription} sub The object tracking this subscription.
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
*/
detach: function (node, sub, notifier) {
//detach our _detacher handle of the subscription made in on()
sub._detacher.detach();
},
detach: function (node, sub) {
//detach our _detacher handle of the subscription made in on()
sub._detacher.detach();
},
/**
* Creates a delegated event listener.
@ -1505,15 +1556,15 @@ Y.Event.define("dock:actionkey", {
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
* @param {String|function} filter Selector string or function that accpets an event object and returns null.
*/
delegate: function (node, sub, notifier, filter) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, {actions:false});
} else {
sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, sub.args[0]);
}
},
delegate: function (node, sub, notifier, filter) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._delegateDetacher = node.delegate(this._event, this._keyHandler, filter, this, notifier, {actions:false});
} else {
sub._delegateDetacher = node.delegate(this._event, this._keyHandler, filter, this, notifier, sub.args[0]);
}
},
/**
* Detaches a delegated event listener.
@ -1523,9 +1574,9 @@ Y.Event.define("dock:actionkey", {
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
* @param {String|function} filter Selector string or function that accpets an event object and returns null.
*/
detachDelegate: function (node, sub, notifier, filter) {
sub._delegateDetacher.detach();
}
detachDelegate: function (node, sub) {
sub._delegateDetacher.detach();
}
});
/**
* Dock JS.
@ -1543,7 +1594,7 @@ Y.Event.define("dock:actionkey", {
* @constructor
* @extends Y.Base
*/
var BLOCK = function() {
BLOCK = function() {
BLOCK.superclass.constructor.apply(this, arguments);
};
BLOCK.prototype = {
@ -1579,7 +1630,7 @@ BLOCK.prototype = {
* The dock item associated with this block
* @property dockitem
* @protected
* @type DOCKITEM
* @type DOCKEDITEM
*/
dockitem : null,
/**
@ -1587,7 +1638,8 @@ BLOCK.prototype = {
* @method initializer
*/
initializer : function() {
var node = Y.one('#inst'+this.get('id'));
var node = Y.one('#inst'+this.get('id')),
commands;
if (!node) {
return false;
}
@ -1598,7 +1650,7 @@ BLOCK.prototype = {
// Move the block straight to the dock if required
if (node.hasClass(CSS.dockonload)) {
node.removeClass(CSS.dockonload);
var commands = node.one('.header .title .commands');
commands = node.one('.header .title .commands');
if (!commands) {
commands = Y.Node.create('<div class="commands"></div>');
if (node.one('.header .title')) {
@ -1618,9 +1670,14 @@ BLOCK.prototype = {
* @return String
*/
_getBlockClass : function(node) {
var classes = node.getAttribute('className').toString(),
regex = /(^|\s)(block_[a-zA-Z0-9_]+)(\s|$)/,
matches = regex.exec(classes);
var block = node.getData('block'),
classes,
matches;
if (Y.Lang.isString(block) && block !== '') {
return block;
}
classes = node.getAttribute('className').toString();
matches = /(^| )block_([^ ]+)/.exec(classes);
if (matches) {
return matches[2];
}
@ -1628,7 +1685,7 @@ BLOCK.prototype = {
},
/**
* This function is reponsible for moving a block from the page structure onto the dock.
* This function is responsible for moving a block from the page structure onto the dock.
* @method moveToDock
* @param {EventFacade} e
*/
@ -1639,32 +1696,35 @@ BLOCK.prototype = {
var dock = M.core.dock.get(),
id = this.get('id'),
blockcontent = Y.one('#inst'+id).one('.content');
blockcontent = Y.one('#inst'+id).one('.content'),
icon = (right_to_left()) ? 't/dock_to_block_rtl' : 't/dock_to_block',
breakchar = (location.href.match(/\?/)) ? '&' : '?',
blocktitle,
blockcommands,
movetoimg,
moveto;
if (!blockcontent) {
return;
}
var icon = (right_to_left()) ? 't/dock_to_block_rtl' : 't/dock_to_block',
char = (location.href.match(/\?/)) ? '&' : '?',
blocktitle,
blockcommands,
movetoimg,
moveto;
this.recordBlockState();
blocktitle = this.cachedcontentnode.one('.title h2').cloneNode(true);
blockcommands = this.cachedcontentnode.one('.title .commands').cloneNode(true);
// Must set the image src seperatly of we get an error with XML strict headers
movetoimg = Y.Node.create('<img alt="'+Y.Escape.html(M.str.block.undockitem)+'" title="'+
Y.Escape.html(M.util.get_string('undockblock', 'block', blocktitle.innerHTML)) +'" />');
movetoimg.setAttribute('src', M.util.image_url(icon, 'moodle'));
moveto = Y.Node.create('<a class="moveto customcommand requiresjs"></a>').append(movetoimg);
moveto.set('href', location.href + char + 'dock='+id);
blockcommands.append(moveto);
movetoimg = Y.Node.create('<img />').setAttrs({
alt : Y.Escape.html(M.str.block.undockitem),
title : Y.Escape.html(M.util.get_string('undockblock', 'block', blocktitle.innerHTML)),
src : M.util.image_url(icon, 'moodle')
});
moveto = Y.Node.create('<a class="moveto customcommand requiresjs"></a>').setAttrs({
className : 'moveto customcommand requiresjs',
href : Y.config.win.location.href + breakchar + 'dock='+id
});
moveto.append(movetoimg);
blockcommands.append(moveto.append(movetoimg));
// Create a new dock item for the block
this.dockitem = new DOCKEDITEM({
@ -1684,7 +1744,7 @@ BLOCK.prototype = {
M.util.set_user_preference('docked_block_instance_'+id, 1);
}
this.set('idDocked', true);
this.set('isDocked', true);
},
/**
* Records the block state and adds it to the docks holding area.
@ -1712,11 +1772,12 @@ BLOCK.prototype = {
/**
* This function removes a block from the dock and puts it back into the page structure.
* @method returnToBlock
* @method returnToPage
* @return {Boolean}
*/
returnToBlock : function() {
var id = this.get('id');
returnToPage : function() {
var id = this.get('id'),
commands;
// Enable the skip anchor when going back to block mode
@ -1733,7 +1794,7 @@ BLOCK.prototype = {
this.contentplaceholder.replace(this.cachedcontentnode);
this.cachedcontentnode = Y.one('#'+this.cachedcontentnode.get('id'));
var commands = this.dockitem.get('commands');
commands = this.dockitem.get('commands');
if (commands) {
commands.all('.hidepanelicon').remove();
commands.all('.moveto').remove();
@ -1742,7 +1803,7 @@ BLOCK.prototype = {
this.cachedcontentnode.one('.title').append(commands);
this.cachedcontentnode = null;
M.util.set_user_preference('docked_block_instance_'+id, 0);
this.set('idDocked', false);
this.set('isDocked', false);
return true;
}
};
@ -1789,7 +1850,7 @@ Y.extend(BLOCK, Y.Base, BLOCK.prototype, {
* @extends Y.Base
* @uses Y.EventTarget
*/
var DOCKEDITEM = function() {
DOCKEDITEM = function() {
DOCKEDITEM.superclass.constructor.apply(this, arguments);
};
DOCKEDITEM.prototype = {
@ -1806,7 +1867,8 @@ DOCKEDITEM.prototype = {
*/
initializer : function() {
var title = this.get('title'),
titlestring;
titlestring,
type;
/**
* Fired before the docked item has been drawn.
* @event dockeditem:drawstart
@ -1843,7 +1905,7 @@ DOCKEDITEM.prototype = {
*/
this.publish('dockeditem:itemremoved', {prefix:'dockeditem'});
if (title) {
var type = title.get('nodeName');
type = title.get('nodeName');
titlestring = title.cloneNode(true);
title = Y.Node.create('<'+type+'></'+type+'>');
title = M.core.dock.fixTitleOrientation(title, titlestring.get('text'));
@ -1903,7 +1965,7 @@ DOCKEDITEM.prototype = {
dock.hideActive();
this.fire('dockeditem:showstart');
panel.setHeader(this.get('titlestring'), this.get('commands'));
panel.setBody(Y.Node.create('<div class="'+this.get('blockclass')+' block_docked"></div>').append(this.get('contents')));
panel.setBody(Y.Node.create('<div class="block_'+this.get('blockclass')+' block_docked"></div>').append(this.get('contents')));
panel.show();
panel.correctWidth();
@ -1954,7 +2016,7 @@ DOCKEDITEM.prototype = {
remove : function () {
this.hide();
// Return the block to its original position.
this.get('block').returnToBlock();
this.get('block').returnToPage();
// Remove the dock item node.
this.get('dockItemNode').remove();
this.fire('dockeditem:itemremoved');

View File

@ -91,7 +91,8 @@ M.core.dock.loader.delegationEvents = [];
M.core.dock.loader.initLoader = function() {
Y.log('Dock loader initialising', 'note', LOADERNAME);
var dockedblocks = Y.all('.block[data-instanceid][data-dockable]'),
body = Y.one(document.body);
body = Y.one(document.body),
callback;
dockedblocks.each(function() {
var id = parseInt(this.getData('instanceid'), 10);
Y.log('Dock loader watching block with instance id: '+id, 'note', LOADERNAME);
@ -103,13 +104,15 @@ M.core.dock.loader.initLoader = function() {
M.core.dock.init();
});
} else {
var callback = function(e) {
callback = function(e) {
var i,
block = this.ancestor('.block[data-instanceid]'),
instanceid = block.getData('instanceid');
e.halt();
for (i in M.core.dock.loader.delegationEvents) {
M.core.dock.loader.delegationEvents[i].detach();
if (Y.Lang.isNumber(i) || Y.Lang.isString(i)) {
M.core.dock.loader.delegationEvents[i].detach();
}
}
block.addClass('dock_on_load');
Y.log('Loading dock module', 'note', LOADERNAME);

View File

@ -1 +1 @@
YUI.add("moodle-core-dockloader",function(e,t){var n="moodle-core-dock-loader";M.core=M.core||{},M.core.dock=M.core.dock||{},M.core.dock.ensureMoveToIconExists=function(t){if(t.one(".moveto"))return!0;var n,r=e.Node.create('<input type="image" class="moveto customcommand requiresjs" />'),i=t.one(".block_action"),s="t/block_to_dock";return right_to_left()&&(s+="_rtl"),r.setAttribute("alt",M.util.get_string("addtodock","block")),r.setAttribute("title",e.Escape.html(M.util.get_string("dockblock","block",t.one(".header .title h2").getHTML()))),r.setAttribute("src",M.util.image_url(s,"moodle")),i?i.prepend(r):(n=t.one(".header .title .commands"),!n&&t.one(".header .title")&&(n=e.Node.create('<div class="commands"></div>'),t.one(".header .title").append(n)),n.append(r)),!0},M.core.dock.loader=M.core.dock.loader||{},M.core.dock.loader.delegationEvents=[],M.core.dock.loader.initLoader=function(){var t=e.all(".block[data-instanceid][data-dockable]"),n=e.one(document.body);t.each(function(){var e=parseInt(this.getData("instanceid"),10);M.core.dock.ensureMoveToIconExists(this)});if(t.some(function(e){return e.hasClass("dock_on_load")}))e.use("moodle-core-dock",function(){M.core.dock.init()});else{var r=function(t){var n,r=this.ancestor(".block[data-instanceid]"),i=r.getData("instanceid");t.halt();for(n in M.core.dock.loader.delegationEvents)M.core.dock.loader.delegationEvents[n].detach();r.addClass("dock_on_load"),e.use("moodle-core-dock",function(){M.util.set_user_preference("docked_block_instance_"+i,1),M.core.dock.init()})};M.core.dock.loader.delegationEvents.push(n.delegate("click",r,".moveto")),M.core.dock.loader.delegationEvents.push(n.delegate("key",r,".moveto","enter"))}}},"@VERSION@",{requires:["escape"]});
YUI.add("moodle-core-dockloader",function(e,t){var n="moodle-core-dock-loader";M.core=M.core||{},M.core.dock=M.core.dock||{},M.core.dock.ensureMoveToIconExists=function(t){if(t.one(".moveto"))return!0;var n,r=e.Node.create('<input type="image" class="moveto customcommand requiresjs" />'),i=t.one(".block_action"),s="t/block_to_dock";return right_to_left()&&(s+="_rtl"),r.setAttribute("alt",M.util.get_string("addtodock","block")),r.setAttribute("title",e.Escape.html(M.util.get_string("dockblock","block",t.one(".header .title h2").getHTML()))),r.setAttribute("src",M.util.image_url(s,"moodle")),i?i.prepend(r):(n=t.one(".header .title .commands"),!n&&t.one(".header .title")&&(n=e.Node.create('<div class="commands"></div>'),t.one(".header .title").append(n)),n.append(r)),!0},M.core.dock.loader=M.core.dock.loader||{},M.core.dock.loader.delegationEvents=[],M.core.dock.loader.initLoader=function(){var t=e.all(".block[data-instanceid][data-dockable]"),n=e.one(document.body),r;t.each(function(){var e=parseInt(this.getData("instanceid"),10);M.core.dock.ensureMoveToIconExists(this)}),t.some(function(e){return e.hasClass("dock_on_load")})?e.use("moodle-core-dock",function(){M.core.dock.init()}):(r=function(t){var n,r=this.ancestor(".block[data-instanceid]"),i=r.getData("instanceid");t.halt();for(n in M.core.dock.loader.delegationEvents)(e.Lang.isNumber(n)||e.Lang.isString(n))&&M.core.dock.loader.delegationEvents[n].detach();r.addClass("dock_on_load"),e.use("moodle-core-dock",function(){M.util.set_user_preference("docked_block_instance_"+i,1),M.core.dock.init()})},M.core.dock.loader.delegationEvents.push(n.delegate("click",r,".moveto")),M.core.dock.loader.delegationEvents.push(n.delegate("key",r,".moveto","enter")))}},"@VERSION@",{requires:["escape"]});

View File

@ -90,7 +90,8 @@ M.core.dock.loader.delegationEvents = [];
*/
M.core.dock.loader.initLoader = function() {
var dockedblocks = Y.all('.block[data-instanceid][data-dockable]'),
body = Y.one(document.body);
body = Y.one(document.body),
callback;
dockedblocks.each(function() {
var id = parseInt(this.getData('instanceid'), 10);
M.core.dock.ensureMoveToIconExists(this);
@ -100,13 +101,15 @@ M.core.dock.loader.initLoader = function() {
M.core.dock.init();
});
} else {
var callback = function(e) {
callback = function(e) {
var i,
block = this.ancestor('.block[data-instanceid]'),
instanceid = block.getData('instanceid');
e.halt();
for (i in M.core.dock.loader.delegationEvents) {
M.core.dock.loader.delegationEvents[i].detach();
if (Y.Lang.isNumber(i) || Y.Lang.isString(i)) {
M.core.dock.loader.delegationEvents[i].detach();
}
}
block.addClass('dock_on_load');
Y.use('moodle-core-dock', function(){

View File

@ -21,24 +21,24 @@
* @class ActionKey
*/
Y.Event.define("dock:actionkey", {
// Webkit and IE repeat keydown when you hold down arrow keys.
// Opera links keypress to page scroll; others keydown.
// Firefox prevents page scroll via preventDefault() on either
// keydown or keypress.
_event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress',
// Webkit and IE repeat keydown when you hold down arrow keys.
// Opera links keypress to page scroll; others keydown.
// Firefox prevents page scroll via preventDefault() on either
// keydown or keypress.
_event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress',
/**
* The keys to trigger on.
* @method _keys
* @property _keys
*/
_keys: {
//arrows
'37': 'collapse',
'39': 'expand',
//(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings)
'32': 'toggle',
'13': 'enter'
},
_keys: {
//arrows
'37': 'collapse',
'39': 'expand',
//(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings)
'32': 'toggle',
'13': 'enter'
},
/**
* Handles key events
@ -47,18 +47,18 @@ Y.Event.define("dock:actionkey", {
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
* @param {Object} args
*/
_keyHandler: function (e, notifier, args) {
var actObj;
if (!args.actions) {
actObj = {collapse:true, expand:true, toggle:true, enter:true};
} else {
actObj = args.actions;
}
if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) {
e.action = this._keys[e.keyCode];
notifier.fire(e);
}
},
_keyHandler: function (e, notifier, args) {
var actObj;
if (!args.actions) {
actObj = {collapse: true, expand: true, toggle: true, enter: true};
} else {
actObj = args.actions;
}
if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) {
e.action = this._keys[e.keyCode];
notifier.fire(e);
}
},
/**
* Subscribes to events.
@ -67,24 +67,27 @@ Y.Event.define("dock:actionkey", {
* @param {Subscription} sub The object tracking this subscription.
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
*/
on: function (node, sub, notifier) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._detacher = node.on(this._event, this._keyHandler,this, notifier, {actions:false});
} else {
sub._detacher = node.on(this._event, this._keyHandler,this, notifier, sub.args[0]);
}
},
on: function (node, sub, notifier) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._detacher = node.on(this._event, this._keyHandler, this, notifier, {actions: false});
} else {
sub._detacher = node.on(this._event, this._keyHandler, this, notifier, sub.args[0]);
}
},
/**
* Detaches an event listener
* @method detach
* @param {Node} node The node this subscription was applied to.
* @param {Subscription} sub The object tracking this subscription.
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
*/
detach: function (node, sub, notifier) {
//detach our _detacher handle of the subscription made in on()
sub._detacher.detach();
},
detach: function (node, sub) {
//detach our _detacher handle of the subscription made in on()
sub._detacher.detach();
},
/**
* Creates a delegated event listener.
@ -94,15 +97,15 @@ Y.Event.define("dock:actionkey", {
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
* @param {String|function} filter Selector string or function that accpets an event object and returns null.
*/
delegate: function (node, sub, notifier, filter) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, {actions:false});
} else {
sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, sub.args[0]);
}
},
delegate: function (node, sub, notifier, filter) {
// subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions).
if (sub.args === null) {
//no actions given
sub._delegateDetacher = node.delegate(this._event, this._keyHandler, filter, this, notifier, {actions:false});
} else {
sub._delegateDetacher = node.delegate(this._event, this._keyHandler, filter, this, notifier, sub.args[0]);
}
},
/**
* Detaches a delegated event listener.
@ -112,7 +115,7 @@ Y.Event.define("dock:actionkey", {
* @param {SyntheticEvent.Notifier} notifier The notifier used to trigger the execution of subscribers
* @param {String|function} filter Selector string or function that accpets an event object and returns null.
*/
detachDelegate: function (node, sub, notifier, filter) {
sub._delegateDetacher.detach();
}
detachDelegate: function (node, sub) {
sub._delegateDetacher.detach();
}
});

View File

@ -14,7 +14,7 @@
* @constructor
* @extends Y.Base
*/
var BLOCK = function() {
BLOCK = function() {
BLOCK.superclass.constructor.apply(this, arguments);
};
BLOCK.prototype = {
@ -50,7 +50,7 @@ BLOCK.prototype = {
* The dock item associated with this block
* @property dockitem
* @protected
* @type DOCKITEM
* @type DOCKEDITEM
*/
dockitem : null,
/**
@ -58,7 +58,8 @@ BLOCK.prototype = {
* @method initializer
*/
initializer : function() {
var node = Y.one('#inst'+this.get('id'));
var node = Y.one('#inst'+this.get('id')),
commands;
if (!node) {
return false;
}
@ -70,7 +71,7 @@ BLOCK.prototype = {
// Move the block straight to the dock if required
if (node.hasClass(CSS.dockonload)) {
node.removeClass(CSS.dockonload);
var commands = node.one('.header .title .commands');
commands = node.one('.header .title .commands');
if (!commands) {
commands = Y.Node.create('<div class="commands"></div>');
if (node.one('.header .title')) {
@ -90,9 +91,14 @@ BLOCK.prototype = {
* @return String
*/
_getBlockClass : function(node) {
var classes = node.getAttribute('className').toString(),
regex = /(^|\s)(block_[a-zA-Z0-9_]+)(\s|$)/,
matches = regex.exec(classes);
var block = node.getData('block'),
classes,
matches;
if (Y.Lang.isString(block) && block !== '') {
return block;
}
classes = node.getAttribute('className').toString();
matches = /(^| )block_([^ ]+)/.exec(classes);
if (matches) {
return matches[2];
}
@ -100,7 +106,7 @@ BLOCK.prototype = {
},
/**
* This function is reponsible for moving a block from the page structure onto the dock.
* This function is responsible for moving a block from the page structure onto the dock.
* @method moveToDock
* @param {EventFacade} e
*/
@ -111,7 +117,13 @@ BLOCK.prototype = {
var dock = M.core.dock.get(),
id = this.get('id'),
blockcontent = Y.one('#inst'+id).one('.content');
blockcontent = Y.one('#inst'+id).one('.content'),
icon = (right_to_left()) ? 't/dock_to_block_rtl' : 't/dock_to_block',
breakchar = (location.href.match(/\?/)) ? '&' : '?',
blocktitle,
blockcommands,
movetoimg,
moveto;
if (!blockcontent) {
return;
@ -119,25 +131,22 @@ BLOCK.prototype = {
Y.log('Moving block to the dock:'+this.get('id'), 'note', LOGNS);
var icon = (right_to_left()) ? 't/dock_to_block_rtl' : 't/dock_to_block',
char = (location.href.match(/\?/)) ? '&' : '?',
blocktitle,
blockcommands,
movetoimg,
moveto;
this.recordBlockState();
blocktitle = this.cachedcontentnode.one('.title h2').cloneNode(true);
blockcommands = this.cachedcontentnode.one('.title .commands').cloneNode(true);
// Must set the image src seperatly of we get an error with XML strict headers
movetoimg = Y.Node.create('<img alt="'+Y.Escape.html(M.str.block.undockitem)+'" title="'+
Y.Escape.html(M.util.get_string('undockblock', 'block', blocktitle.innerHTML)) +'" />');
movetoimg.setAttribute('src', M.util.image_url(icon, 'moodle'));
moveto = Y.Node.create('<a class="moveto customcommand requiresjs"></a>').append(movetoimg);
moveto.set('href', location.href + char + 'dock='+id);
blockcommands.append(moveto);
movetoimg = Y.Node.create('<img />').setAttrs({
alt : Y.Escape.html(M.str.block.undockitem),
title : Y.Escape.html(M.util.get_string('undockblock', 'block', blocktitle.innerHTML)),
src : M.util.image_url(icon, 'moodle')
});
moveto = Y.Node.create('<a class="moveto customcommand requiresjs"></a>').setAttrs({
className : 'moveto customcommand requiresjs',
href : Y.config.win.location.href + breakchar + 'dock='+id
});
moveto.append(movetoimg);
blockcommands.append(moveto.append(movetoimg));
// Create a new dock item for the block
this.dockitem = new DOCKEDITEM({
@ -157,7 +166,7 @@ BLOCK.prototype = {
M.util.set_user_preference('docked_block_instance_'+id, 1);
}
this.set('idDocked', true);
this.set('isDocked', true);
},
/**
* Records the block state and adds it to the docks holding area.
@ -185,11 +194,12 @@ BLOCK.prototype = {
/**
* This function removes a block from the dock and puts it back into the page structure.
* @method returnToBlock
* @method returnToPage
* @return {Boolean}
*/
returnToBlock : function() {
var id = this.get('id');
returnToPage : function() {
var id = this.get('id'),
commands;
Y.log('Moving block out of the dock:'+this.get('id'), 'note', LOGNS);
@ -207,7 +217,7 @@ BLOCK.prototype = {
this.contentplaceholder.replace(this.cachedcontentnode);
this.cachedcontentnode = Y.one('#'+this.cachedcontentnode.get('id'));
var commands = this.dockitem.get('commands');
commands = this.dockitem.get('commands');
if (commands) {
commands.all('.hidepanelicon').remove();
commands.all('.moveto').remove();
@ -216,7 +226,7 @@ BLOCK.prototype = {
this.cachedcontentnode.one('.title').append(commands);
this.cachedcontentnode = null;
M.util.set_user_preference('docked_block_instance_'+id, 0);
this.set('idDocked', false);
this.set('isDocked', false);
return true;
}
};

View File

@ -7,28 +7,33 @@
*/
var LOGNS = 'moodle-core-dock';
var BODY = Y.one(document.body);
var 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
buttonscontainer: 'buttons_container',
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
contentonly: 'content-only',
dockonload: 'dock_on_load'
};
var SELECTOR = {
dockableblock: '.block[data-instanceid][data-dockable]',
blockmoveto: '.block[data-instanceid][data-dockable] .moveto',
panelmoveto: '#dockeditempanel .commands a.moveto',
dockonload: '.block.'+CSS.dockonload,
blockregion: '[data-blockregion]'
};
var LOGNS = 'moodle-core-dock',
BODY = Y.one(Y.config.doc.body),
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
buttonscontainer: 'buttons_container',
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
contentonly: 'content-only',
dockonload: 'dock_on_load'
},
SELECTOR = {
dockableblock: '.block[data-instanceid][data-dockable]',
blockmoveto: '.block[data-instanceid][data-dockable] .moveto',
panelmoveto: '#dockeditempanel .commands a.moveto',
dockonload: '.block.'+CSS.dockonload,
blockregion: '[data-blockregion]'
},
DOCK,
DOCKPANEL,
TABHEIGHTMANAGER,
BLOCK,
DOCKEDITEM;
/**
* Core namespace.
@ -145,12 +150,18 @@ M.core.dock.dockBlock = function(id) {
* @return {Node} The title node to use.
*/
M.core.dock.fixTitleOrientation = function(title, text) {
var dock = M.core.dock.get();
var dock = M.core.dock.get(),
fontsize = '11px',
transform = 'rotate(270deg)',
test,
width,
height,
container;
title = Y.one(title);
if (dock.get('orientation') !== 'vertical') {
// If the dock isn't vertical don't adjust it!
title.setContent(text);
title.set('innerHTML', text);
return title;
}
@ -159,37 +170,34 @@ M.core.dock.fixTitleOrientation = function(title, text) {
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 />'));
return title.set('innerHTML', text.split('').join('<br />'));
case 'ttb':
clockwise = true;
transform = 'rotate(90deg)';
break;
case 'btt':
clockwise = false;
// Nothing to do here. transform default is good.
break;
}
if (Y.UA.ie === 8) {
// IE8 can flip the text via CSS but not handle transform. IE9+ can handle the CSS3 transform attribute.
title.setContent(text);
title.set('innerHTML', text);
title.setAttribute('style', 'writing-mode: tb-rl; filter: flipV flipH;display:inline;');
title.addClass('filterrotate');
return title;
}
// We need to fix a font-size - sorry theme designers.
var fontsize = '11px';
var transform = (clockwise) ? 'rotate(90deg)' : 'rotate(270deg)';
var test = Y.Node.create('<h2><span class="transform-test-node" style="font-size:'+fontsize+';">'+text+'</span></h2>');
test = Y.Node.create('<h2><span class="transform-test-node" style="font-size:'+fontsize+';">'+text+'</span></h2>');
BODY.insert(test, 0);
var width = test.one('span').get('offsetWidth') * 1.2;
var height = test.one('span').get('offsetHeight');
width = test.one('span').get('offsetWidth') * 1.2;
height = test.one('span').get('offsetHeight');
test.remove();
title.setContent(text);
title.set('innerHTML', text);
title.addClass('css3transform');
// Move the title into position
@ -218,10 +226,12 @@ M.core.dock.fixTitleOrientation = function(title, text) {
'-o-transform' : transform
});
var container = Y.Node.create('<div></div>');
container = Y.Node.create('<div></div>');
container.append(title);
container.setStyle('height', width + (width / 4));
container.setStyle('position', 'relative');
container.setStyles({
height : width + (width / 4),
position : 'relative'
});
return container;
};
@ -254,7 +264,7 @@ M.core.dock.notifyBlockChange = function(instanceid) {
* @extends Y.Base
* @uses Y.EventTarget
*/
var DOCK = function() {
DOCK = function() {
DOCK.superclass.constructor.apply(this, arguments);
};
DOCK.prototype = {
@ -320,7 +330,7 @@ DOCK.prototype = {
*/
initializer : function() {
Y.log('Dock initialising', 'note', LOGNS);
// Publish the events the dock has
/**
* Fired when the dock first starts initialising.
@ -402,7 +412,18 @@ DOCK.prototype = {
if (this.dockdrawn === true) {
return true;
}
var dock = this._initialiseDockNode();
var dock = this._initialiseDockNode(),
clickargs = {
cssselector:'.'+CSS.dockedtitle,
delay:0
},
mouseenterargs = {
cssselector:'.'+CSS.dockedtitle,
delay:0.5,
iscontained:true,
preventevent:'click',
preventdelay:3
};
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');
@ -414,9 +435,6 @@ DOCK.prototype = {
this.tabheightmanager = new TABHEIGHTMANAGER({dock:this});
var clickargs = {cssselector:'.'+CSS.dockedtitle, delay:0};
var mouseenterargs = {cssselector:'.'+CSS.dockedtitle, delay:0.5, iscontained:true, preventevent:'click', preventdelay:3};
// 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
@ -454,8 +472,7 @@ DOCK.prototype = {
return false;
}
e.halt();
var id = target.getAttribute('rel');
this.dockeditems[id].toggle(e.action);
this.dockeditems[target.getAttribute('rel')].toggle(e.action);
},
/**
* Call the theme customisation method "customise_dock_for_theme" if it exists.
@ -504,31 +521,35 @@ DOCK.prototype = {
};
// Check for and apply any legacy configuration.
for (key in M.core_dock.cfg) {
value = M.core_dock.cfg[key];
if (value === null) {
continue;
if (Y.Lang.isString(key) && cfgmap[key]) {
value = M.core_dock.cfg[key];
if (value === null) {
continue;
}
if (!warned) {
Y.log('Warning: customise_dock_for_theme has changed. Please update your code.', 'warn', LOGNS);
warned = true;
}
// Damn, the've set something.
Y.log('Note for customise_dock_for_theme code: M.core_dock.cfg.'+key+' is now dock.set(\''+key+'\', value)', 'info', LOGNS);
this.set(cfgmap[key], value);
}
if (!warned) {
Y.log('Warning: customise_dock_for_theme has changed. Please update your code.', 'warn', LOGNS);
warned = true;
}
// Damn, the've set something.
Y.log('Note for customise_dock_for_theme code: M.core_dock.cfg.'+key+' is now dock.set(\''+key+'\', value)', 'info', LOGNS);
this.set(cfgmap[key], value);
}
// Check for and apply any legacy CSS changes..
for (key in M.core_dock.css) {
value = M.core_dock.css[key];
if (value === null) {
continue;
if (Y.Lang.isString(key)) {
value = M.core_dock.css[key];
if (value === null) {
continue;
}
if (!warned) {
Y.log('Warning: customise_dock_for_theme has changed. Please update your code.', 'warn', LOGNS);
warned = true;
}
// Damn, they've set something.
Y.log('Note for customise_dock_for_theme code: M.core_dock.css.'+key+' is now CSS.'+key+' = value', 'info', LOGNS);
CSS[key] = value;
}
if (!warned) {
Y.log('Warning: customise_dock_for_theme has changed. Please update your code.', 'warn', LOGNS);
warned = true;
}
// Damn, they've set something.
Y.log('Note for customise_dock_for_theme code: M.core_dock.css.'+key+' is now CSS.'+key+' = value', 'info', LOGNS);
CSS[key] = value;
}
}
},
@ -545,7 +566,7 @@ DOCK.prototype = {
holdingarea = Y.Node.create('<div></div>').setStyles({display:'none'}),
buttons = this.get('buttonsNode'),
container = this.get('itemContainerNode');
if (!dock) {
dock = Y.one('#'+CSS.dock);
}
@ -640,7 +661,11 @@ DOCK.prototype = {
* @return {Boolean}
*/
handleEvent : function(e, options) {
var item = this.getActiveItem();
var item = this.getActiveItem(),
target,
targetid,
regex = /^dock_item_(\d+)_title$/,
self = this;
if (options.cssselector === 'body') {
if (!this.get('dockNode').contains(e.target)) {
if (item) {
@ -648,7 +673,6 @@ DOCK.prototype = {
}
}
} else {
var target;
if (e.target.test(options.cssselector)) {
target = e.target;
} else {
@ -663,7 +687,6 @@ DOCK.prototype = {
if (options.preventevent) {
this.preventevent = options.preventevent;
if (options.preventdelay) {
var self = this;
setTimeout(function(){
self.preventevent = null;
}, options.preventdelay * 1000);
@ -677,8 +700,7 @@ DOCK.prototype = {
if (options.delay > 0) {
return this.delayEvent(e, options, target);
}
var targetid = target.get('id');
var regex = /^dock_item_(\d+)_title$/;
targetid = target.get('id');
if (targetid.match(regex)) {
item = this.dockeditems[targetid.replace(regex, '$1')];
if (item.active) {
@ -733,7 +755,8 @@ DOCK.prototype = {
var blockregions = [],
populatedblockregions = 0,
allnewregions = true,
showregions = false;
showregions = false,
i;
// First look for understood regions.
Y.all(SELECTOR.blockregion).each(function(){
var regionname = region.getData('blockregion');
@ -773,22 +796,27 @@ DOCK.prototype = {
}
if (!allnewregions) {
var i = null;
if (populatedblockregions === 0 && showregions === false) {
for (i in blockregions) {
BODY.removeClass(blockregions[i].bodyclass);
if (blockregions[i].bodyclass) {
BODY.removeClass(blockregions[i].bodyclass);
}
}
} else if (populatedblockregions === 1 && showregions === false) {
for (i in blockregions) {
if (!blockregions[i].hasblocks) {
BODY.removeClass(blockregions[i].bodyclass);
} else {
BODY.addClass(blockregions[i].bodyclass);
if (blockregions[i].bodyclass) {
if (!blockregions[i].hasblocks) {
BODY.removeClass(blockregions[i].bodyclass);
} else {
BODY.addClass(blockregions[i].bodyclass);
}
}
}
} else {
for (i in blockregions) {
BODY.removeClass(blockregions[i].bodyclass);
if (blockregions[i].bodyclass) {
BODY.removeClass(blockregions[i].bodyclass);
}
}
}
}
@ -861,8 +889,11 @@ DOCK.prototype = {
*/
removeAll : function() {
Y.log('Undocking all '+this.dockeditems.length+' blocks', 'note', LOGNS);
for (var i in this.dockeditems) {
this.remove(i);
var i;
for (i in this.dockeditems) {
if (Y.Lang.isNumber(i) || Y.Lang.isString(i)) {
this.remove(i);
}
}
return true;
},
@ -900,34 +931,43 @@ DOCK.prototype = {
* @return {Boolean}
*/
resize : function() {
var panel = this.getPanel();
var item = this.getActiveItem();
var panel = this.getPanel(),
item = this.getActiveItem(),
buffer,
screenh,
docky,
titletop,
containery,
containerheight,
scrolltop,
panelheight,
dockx,
titleleft;
if (!panel.get('visible') || !item) {
return true;
}
this.fire('dock:panelresizestart');
if (this.get('orientation') === 'vertical') {
var buffer = this.get('bufferPanel');
var screenheight = parseInt(BODY.get('winHeight'), 10)-(buffer*2);
var docky = this.get('dockNode').getY();
var titletop = item.get('dockTitleNode').getY()-docky-buffer;
var containery = this.get('itemContainerNode').getY();
var containerheight = containery-docky+this.get('buttonsNode').get('offsetHeight');
var scrolltop = panel.get('bodyNode').get('scrollTop');
buffer = this.get('bufferPanel');
screenh = parseInt(BODY.get('winHeight'), 10)-(buffer*2);
docky = this.get('dockNode').getY();
titletop = item.get('dockTitleNode').getY()-docky-buffer;
containery = this.get('itemContainerNode').getY();
containerheight = containery-docky+this.get('buttonsNode').get('offsetHeight');
scrolltop = panel.get('bodyNode').get('scrollTop');
panel.get('bodyNode').setStyle('height', 'auto');
panel.get('node').removeClass('oversized_content');
var panelheight = panel.get('node').get('offsetHeight');
panelheight = panel.get('node').get('offsetHeight');
if (Y.UA.ie > 0 && Y.UA.ie < 7) {
panel.setTop(item.get('dockTitleNode').getY());
} else if (panelheight > screenheight) {
} else if (panelheight > screenh) {
panel.setTop(buffer-containerheight);
panel.get('bodyNode').setStyle('height', (screenheight-panel.get('headerNode').get('offsetHeight'))+'px');
panel.get('bodyNode').setStyle('height', (screenh-panel.get('headerNode').get('offsetHeight'))+'px');
panel.get('node').addClass('oversized_content');
} else if (panelheight > (screenheight-(titletop-buffer))) {
var difference = panelheight - (screenheight-titletop);
panel.setTop(titletop-containerheight-difference+buffer);
} else if (panelheight > (screenh-(titletop-buffer))) {
panel.setTop(titletop-containerheight-(panelheight - (screenh-titletop))+buffer);
} else {
panel.setTop(titletop-containerheight+buffer);
}
@ -941,8 +981,8 @@ DOCK.prototype = {
panel.get('node').setStyle('left', -panel.get('offsetWidth')+'px');
} else if (this.get('position') === 'top') {
var dockx = this.get('dockNode').getX();
var titleleft = item.get('dockTitleNode').getX()-dockx;
dockx = this.get('dockNode').getX();
titleleft = item.get('dockTitleNode').getX()-dockx;
panel.get('node').setStyle('left', titleleft+'px');
}
@ -955,7 +995,8 @@ DOCK.prototype = {
* @return {DOCKEDITEM}
*/
getActiveItem : function() {
for (var i in this.dockeditems) {
var i;
for (i in this.dockeditems) {
if (this.dockeditems[i].active) {
return this.dockeditems[i];
}

View File

@ -15,7 +15,7 @@
* @extends Y.Base
* @uses Y.EventTarget
*/
var DOCKEDITEM = function() {
DOCKEDITEM = function() {
DOCKEDITEM.superclass.constructor.apply(this, arguments);
};
DOCKEDITEM.prototype = {
@ -32,7 +32,8 @@ DOCKEDITEM.prototype = {
*/
initializer : function() {
var title = this.get('title'),
titlestring;
titlestring,
type;
/**
* Fired before the docked item has been drawn.
* @event dockeditem:drawstart
@ -69,7 +70,7 @@ DOCKEDITEM.prototype = {
*/
this.publish('dockeditem:itemremoved', {prefix:'dockeditem'});
if (title) {
var type = title.get('nodeName');
type = title.get('nodeName');
titlestring = title.cloneNode(true);
title = Y.Node.create('<'+type+'></'+type+'>');
title = M.core.dock.fixTitleOrientation(title, titlestring.get('text'));
@ -131,7 +132,7 @@ DOCKEDITEM.prototype = {
this.fire('dockeditem:showstart');
Y.log('Showing '+this._getLogDescription(), 'info', LOGNS);
panel.setHeader(this.get('titlestring'), this.get('commands'));
panel.setBody(Y.Node.create('<div class="'+this.get('blockclass')+' block_docked"></div>').append(this.get('contents')));
panel.setBody(Y.Node.create('<div class="block_'+this.get('blockclass')+' block_docked"></div>').append(this.get('contents')));
panel.show();
panel.correctWidth();
@ -183,7 +184,7 @@ DOCKEDITEM.prototype = {
remove : function () {
this.hide();
// Return the block to its original position.
this.get('block').returnToBlock();
this.get('block').returnToPage();
// Remove the dock item node.
this.get('dockItemNode').remove();
this.fire('dockeditem:itemremoved');

View File

@ -89,7 +89,8 @@ M.core.dock.loader.delegationEvents = [];
M.core.dock.loader.initLoader = function() {
Y.log('Dock loader initialising', 'note', LOADERNAME);
var dockedblocks = Y.all('.block[data-instanceid][data-dockable]'),
body = Y.one(document.body);
body = Y.one(document.body),
callback;
dockedblocks.each(function() {
var id = parseInt(this.getData('instanceid'), 10);
Y.log('Dock loader watching block with instance id: '+id, 'note', LOADERNAME);
@ -101,13 +102,15 @@ M.core.dock.loader.initLoader = function() {
M.core.dock.init();
});
} else {
var callback = function(e) {
callback = function(e) {
var i,
block = this.ancestor('.block[data-instanceid]'),
instanceid = block.getData('instanceid');
e.halt();
for (i in M.core.dock.loader.delegationEvents) {
M.core.dock.loader.delegationEvents[i].detach();
if (Y.Lang.isNumber(i) || Y.Lang.isString(i)) {
M.core.dock.loader.delegationEvents[i].detach();
}
}
block.addClass('dock_on_load');
Y.log('Loading dock module', 'note', LOADERNAME);

View File

@ -15,7 +15,7 @@
* @extends Y.Base
* @uses Y.EventTarget
*/
var DOCKPANEL = function() {
DOCKPANEL = function() {
DOCKPANEL.superclass.constructor.apply(this, arguments);
};
DOCKPANEL.prototype = {
@ -109,11 +109,14 @@ DOCKPANEL.prototype = {
*/
setHeader : function(content) {
this.create();
var header = this.get('headerNode');
var header = this.get('headerNode'),
i;
header.setContent(content);
if (arguments.length > 1) {
for (var i=1;i < arguments.length;i++) {
header.append(arguments[i]);
for (i = 1; i < arguments.length; i++) {
if (Y.Lang.isNumber(i) || Y.Lang.isString(i)) {
header.append(arguments[i]);
}
}
}
},

View File

@ -15,7 +15,7 @@
* @constructor
* @extends Y.Base
*/
var TABHEIGHTMANAGER = function() {
TABHEIGHTMANAGER = function() {
TABHEIGHTMANAGER.superclass.constructor.apply(this, arguments);
};
TABHEIGHTMANAGER.prototype = {
@ -42,12 +42,14 @@ TABHEIGHTMANAGER.prototype = {
id, dockedtitle;
if (items.length > 0) {
for (id in items) {
dockedtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (dockedtitle) {
if (this.get('enabled')) {
dockedtitle.setStyle('height', 'auto');
if (Y.Lang.isNumber(id) || Y.Lang.isString(id)) {
dockedtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (dockedtitle) {
if (this.get('enabled')) {
dockedtitle.setStyle('height', 'auto');
}
totalheight += dockedtitle.get('offsetHeight') || 0;
}
totalheight += dockedtitle.get('offsetHeight') || 0;
}
}
if (totalheight > possibleheight) {
@ -70,20 +72,22 @@ TABHEIGHTMANAGER.prototype = {
Y.log('Enabling the dock tab sizer.', 'note', LOGNS);
this.set('enabled', true);
for (id in items) {
itemtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (!itemtitle) {
continue;
if (Y.Lang.isNumber(id) || Y.Lang.isString(id)) {
itemtitle = Y.one(items[id].get('title')).ancestor('.'+CSS.dockedtitle);
if (!itemtitle) {
continue;
}
itemheight = Math.floor((possibleheight-usedheight) / (count - runningcount));
offsetheight = itemtitle.get('offsetHeight');
itemtitle.setStyle('overflow', 'hidden');
if (offsetheight > itemheight) {
itemtitle.setStyle('height', itemheight+'px');
usedheight += itemheight;
} else {
usedheight += offsetheight;
}
runningcount++;
}
itemheight = Math.floor((possibleheight-usedheight) / (count - runningcount));
offsetheight = itemtitle.get('offsetHeight');
itemtitle.setStyle('overflow', 'hidden');
if (offsetheight > itemheight) {
itemtitle.setStyle('height', itemheight+'px');
usedheight += itemheight;
} else {
usedheight += offsetheight;
}
runningcount++;
}
}
};