diff --git a/blocks/dock.js b/blocks/dock.js index a3016c547f6..5128c659140 100644 --- a/blocks/dock.js +++ b/blocks/dock.js @@ -67,10 +67,15 @@ M.core_dock.init = function(Y) { Y.augment(this.item, Y.EventTarget); Y.augment(this, Y.EventTarget, true); /** - * A 'actionkey' Event to help with Y.delegate(). + * A 'dock:actionkey' Event. * The event consists of the left arrow, right arrow, enter and space keys. - * Possibly more keys can be mapped to the action meanings - * This is used by the dock to listen to this event and act on. + * More keys can be mapped to action meanings. + * actions: collapse , expand, toggle, enter. + * + * This event is subscribed to by dockitems. + * The on() method to subscribe allows specifying the desired trigger actions as JSON. + * + * This event can also be delegated if needed. * Todo: This could be centralised, a similar Event is defined in blocks/navigation/yui/navigation/navigation.js */ Y.Event.define("dock:actionkey", { @@ -89,23 +94,41 @@ M.core_dock.init = function(Y) { '13': 'enter' }, - _keyHandler: function (e, notifier) { - if (this._keys[e.keyCode]) { + _keyHandler: function (e, notifier, args) { + if (!args.actions) { + var actObj = {collapse:true, expand:true, toggle:true, enter:true}; + } else { + var actObj = args.actions; + } + if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) { e.action = this._keys[e.keyCode]; notifier.fire(e); } }, on: function (node, sub, notifier) { - sub._detacher = node.on(this._event, this._keyHandler,this, 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]); + } }, detach: function (node, sub, notifier) { + //detach our _detacher handle of the subscription made in on() sub._detacher.detach(); }, delegate: function (node, sub, notifier, filter) { - sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier); + // 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]); + } }, detachDelegate: function (node, sub, notifier) { @@ -173,7 +196,7 @@ M.core_dock.init = function(Y) { var removeall = Y.Node.create(''+M.str.block.undockall+''); removeall.setAttribute('src',this.cfg.removeallicon); removeall.on('removeall|click', this.remove_all, this); - removeall.on('dock:actionkey', this.remove_all, this); + removeall.on('dock:actionkey', this.remove_all, this, {actions:{enter:true}}); this.nodes.buttons.appendChild(Y.Node.create('
').append(removeall)); // Create a manager for the height of the tabs. Once set this can be forgotten about @@ -637,10 +660,8 @@ M.core_dock.resetFirstItem = function() { * @return {boolean} */ M.core_dock.remove_all = function(e) { - if (!(e.type == 'dock:actionkey' && e.action=='collapse')) { - for (var i in this.items) { - this.remove(i); - } + for (var i in this.items) { + this.remove(i); } return true; }; @@ -891,7 +912,7 @@ M.core_dock.genericblock.prototype = { var closeicon = Y.Node.create(''); closeicon.one('img').setAttribute('src', M.util.image_url('t/dockclose', 'moodle')); closeicon.on('forceclose|click', this.hide, this); - closeicon.on('dock:actionkey',this.close, this); + closeicon.on('dock:actionkey',this.hide, this, {actions:{enter:true,toggle:true}}); this.commands.append(closeicon); }, dockitem); // Register an event so that when it is removed we can put it back as a block @@ -1062,15 +1083,6 @@ M.core_dock.item.prototype = { this.show(); } }, - /** - * A hide() wrapper that applies rules to key press events (dock:actionkey) - * @param {Event} e - */ - close : function(e) { - if (!(e.type == 'dock:actionkey' && (e.action=='expand' || e.action=='collapse'))) { - this.hide(); - } - }, /** * This function removes the node and destroys it's bits * @param {Event} e diff --git a/blocks/navigation/yui/navigation/navigation.js b/blocks/navigation/yui/navigation/navigation.js index e2a32e4cc98..21133c1930c 100644 --- a/blocks/navigation/yui/navigation/navigation.js +++ b/blocks/navigation/yui/navigation/navigation.js @@ -3,41 +3,65 @@ YUI.add('moodle-block_navigation-navigation', function(Y){ /** * A 'actionkey' Event to help with Y.delegate(). * The event consists of the left arrow, right arrow, enter and space keys. - * This is used below to delegate an Event listener to the multiple possible branches in a menu. + * More keys can be mapped to action meanings. + * actions: collapse , expand, toggle, enter. + * + * This event is delegated to branches in the navigation tree. + * The on() method to subscribe allows specifying the desired trigger actions as JSON. + * + * Todo: This could be centralised, a similar Event is defined in blocks/dock.js */ Y.Event.define("actionkey", { - // Webkit and IE repeat keydown when you hold down arrow keys. + // 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', _keys: { - //arrows - '37': 'collapse', - '39': 'expand', - //(@todo: lrt/rtl decision to assign arrow to meanings) - '32': 'toggle', - '13': 'enter' + //arrows + '37': 'collapse', + '39': 'expand', + //(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings) + '32': 'toggle', + '13': 'enter' }, - _keyHandler: function (e, notifier) { - if (this._keys[e.keyCode]) { + _keyHandler: function (e, notifier, args) { + if (!args.actions) { + var actObj = {collapse:true, expand:true, toggle:true, enter:true}; + } else { + var actObj = args.actions; + } + if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) { e.action = this._keys[e.keyCode]; notifier.fire(e); } }, on: function (node, sub, notifier) { - sub._detacher = node.on(this._event, this._keyHandler,this, 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]); + } }, detach: function (node, sub, notifier) { + //detach our _detacher handle of the subscription made in on() sub._detacher.detach(); }, delegate: function (node, sub, notifier, filter) { - sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier); + // 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]); + } }, detachDelegate: function (node, sub, notifier) { @@ -255,14 +279,12 @@ BRANCH.prototype = { var isbranch = (this.get('expandable') || this.get('haschildren')); var branchli = Y.Node.create('
  • '); var link = this.get('link'); + var branchp = Y.Node.create('

    ').setAttribute('id', this.get('id')); if (!link) { //add tab focus if not link (so still one focus per menu node). // it was suggested to have 2 foci. one for the node and one for the link in MDL-27428. - var branchp = Y.Node.create('

    ').setAttribute('id', this.get('id')); - } else { - var branchp = Y.Node.create('

    ').setAttribute('id', this.get('id')); + branchp.setAttribute('tabindex', '0'); } - if (isbranch) { branchli.addClass('collapsed').addClass('contains_branch'); branchp.addClass('branch'); @@ -342,7 +364,7 @@ BRANCH.prototype = { * request made here. */ ajaxLoad : function(e) { - if (e.type = 'actionkey' && e.action != 'enter') { + if (e.type == 'actionkey' && e.action != 'enter') { e.halt(); } else { e.stopPropagation(); @@ -350,7 +372,7 @@ BRANCH.prototype = { if (e.type = 'actionkey' && e.action == 'enter' && e.target.test('A')) { this.event_ajaxload_actionkey.detach(); this.event_ajaxload.detach(); - return; // no ajaxLoad for enter + return true; // no ajaxLoad for enter } if (this.node.hasClass('loadingbranch')) {