mirror of
https://github.com/moodle/moodle.git
synced 2025-04-20 07:56:06 +02:00
MDL-40975 ActionMenu: Ensure we maintain consistent tab order
When the actionmenu is open, we should focus on it's first element, and then naturally tab through it. Tabbing from the end should take us to the first element after the menu button. This may not be the same as the first element after the menu itself because of the nature of primary and secondary action links. We also need to shift-tab back in the same manner.
This commit is contained in:
parent
7f4f7081f0
commit
79864ef25f
@ -11,8 +11,11 @@ var BODY = Y.one(Y.config.doc.body),
|
||||
MENUSHOWN : 'action-menu-shown'
|
||||
},
|
||||
SELECTOR = {
|
||||
CAN_RECEIVE_FOCUS_SELECTOR: 'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',
|
||||
MENU : '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',
|
||||
MENUCONTENT : '.menu[data-rel=menu-content]',
|
||||
MENUCONTENTCHILD: 'li a',
|
||||
MENUCHILD: '.menu li a',
|
||||
TOGGLE : '.toggle-display'
|
||||
},
|
||||
ACTIONMENU,
|
||||
@ -59,6 +62,15 @@ ACTIONMENU.prototype = {
|
||||
*/
|
||||
owner : null,
|
||||
|
||||
/**
|
||||
* The menu button that toggles this open.
|
||||
*
|
||||
* @property menulink
|
||||
* @type Node
|
||||
* @protected
|
||||
*/
|
||||
menulink: null,
|
||||
|
||||
/**
|
||||
* Called during the initialisation process of the object.
|
||||
* @method initializer
|
||||
@ -104,16 +116,21 @@ ACTIONMENU.prototype = {
|
||||
this.dialogue.one(SELECTOR.MENUCONTENT).set('aria-hidden', true);
|
||||
this.dialogue = null;
|
||||
}
|
||||
if (this.owner) {
|
||||
this.owner.removeClass(CSS.MENUSHOWN);
|
||||
this.owner = null;
|
||||
}
|
||||
for (var i in this.events) {
|
||||
if (this.events[i].detach) {
|
||||
this.events[i].detach();
|
||||
}
|
||||
}
|
||||
this.events = [];
|
||||
if (this.owner) {
|
||||
this.owner.removeClass(CSS.MENUSHOWN);
|
||||
this.owner = null;
|
||||
}
|
||||
|
||||
if (this.menulink) {
|
||||
this.menulink.focus();
|
||||
this.menulink = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -132,13 +149,49 @@ ACTIONMENU.prototype = {
|
||||
// The menu was visible and the user has clicked to toggle it again.
|
||||
return;
|
||||
}
|
||||
this.showMenu(menu);
|
||||
this.showMenu(e, menu);
|
||||
// Close the menu if the user presses escape.
|
||||
this.events.push(BODY.on('key', this.hideMenu, 'esc', this));
|
||||
// Close the menu if the user clicks outside the menu.
|
||||
this.events.push(BODY.on('click', this.hideIfOutside, this));
|
||||
// Close the menu if the user focuses outside the menu.
|
||||
this.events.push(BODY.delegate('focus', this.hideIfOutside, '*', this));
|
||||
|
||||
// Check tabbing.
|
||||
this.events.push(menu.delegate('key', this.checkFocus, 'down:9', SELECTOR.MENUCHILD, this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Check current focus when moving around with the tab key.
|
||||
* This will ensure that when the etreme menu items are reached, the
|
||||
* menu is closed and the next DOM element is focused.
|
||||
*
|
||||
* @method checkFocus
|
||||
* @param {EventFacade} e The key event
|
||||
*/
|
||||
checkFocus: function(e) {
|
||||
var nodelist = this.dialogue.all(SELECTOR.MENUCHILD),
|
||||
firstNode,
|
||||
lastNode;
|
||||
|
||||
if (nodelist) {
|
||||
firstNode = nodelist.item(0);
|
||||
lastNode = nodelist.pop();
|
||||
}
|
||||
|
||||
var menulink = this.menulink;
|
||||
if (e.target === firstNode && e.shiftKey) {
|
||||
this.hideMenu();
|
||||
e.preventDefault();
|
||||
} else if (e.target === lastNode && !e.shiftKey) {
|
||||
var next;
|
||||
if (this.hideMenu()) {
|
||||
next = menulink.next(SELECTOR.CAN_RECEIVE_FOCUS_SELECTOR);
|
||||
if (next) {
|
||||
next.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -156,21 +209,31 @@ ACTIONMENU.prototype = {
|
||||
|
||||
/**
|
||||
* Displays the menu with the given content and alignment.
|
||||
* @param {EventFacade} e
|
||||
* @param {Node} menu
|
||||
* @param Array align
|
||||
* @returns {M.core.dialogue|dialogue}
|
||||
*/
|
||||
showMenu : function(menu) {
|
||||
showMenu : function(e, menu) {
|
||||
Y.log('Displaying an action menu', 'debug', ACTIONMENU.NAME);
|
||||
var ownerselector = menu.getData('owner'),
|
||||
menucontent = menu.one(SELECTOR.MENUCONTENT);
|
||||
menucontent = menu.one(SELECTOR.MENUCONTENT),
|
||||
menuchild;
|
||||
this.owner = (ownerselector) ? menu.ancestor(ownerselector) : null;
|
||||
this.dialogue = menu;
|
||||
menu.addClass('show');
|
||||
if (this.owner) {
|
||||
this.owner.addClass(CSS.MENUSHOWN);
|
||||
this.menulink = this.owner.one(SELECTOR.TOGGLE);
|
||||
}
|
||||
this.constrain(menucontent.set('aria-hidden', false));
|
||||
|
||||
if (e.type && e.type === 'key') {
|
||||
menuchild = menucontent.one(SELECTOR.MENUCONTENTCHILD);
|
||||
if (menuchild) {
|
||||
menuchild.focus();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
@ -1 +1 @@
|
||||
YUI.add("moodle-core-actionmenu",function(e,t){var n=e.one(e.config.doc.body),r={MENUSHOWN:"action-menu-shown"},i={MENU:".moodle-actionmenu[data-enhance=moodle-core-actionmenu]",MENUCONTENT:".menu[data-rel=menu-content]",TOGGLE:".toggle-display"},s,o={TL:"tl",TR:"tr",BL:"bl",BR:"br"};s=function(){s.superclass.constructor.apply(this,arguments)},s.prototype={dialogue:null,events:[],owner:null,initializer:function(){e.all(i.MENU).each(this.enhance,this),n.delegate("click",this.toggleMenu,i.MENU+" "+i.TOGGLE,this),n.delegate("key",this.toggleMenu,"enter,space",i.MENU+" "+i.TOGGLE,this)},enhance:function(e){var t=e.one(i.MENUCONTENT),n;if(!t)return!1;n=t.getData("align")||this.get("align").join("-"),e.one(i.TOGGLE).set("aria-haspopup",!0),t.set("aria-hidden",!0),t.hasClass("align-"+n)||t.addClass("align-"+n),t.hasChildNodes()&&e.setAttribute("data-enhanced","1")},hideMenu:function(){this.dialogue&&(this.dialogue.removeClass("show"),this.dialogue.one(i.MENUCONTENT).set("aria-hidden",!0),this.dialogue=null),this.owner&&(this.owner.removeClass(r.MENUSHOWN),this.owner=null);for(var e in this.events)this.events[e].detach&&this.events[e].detach();this.events=[]},toggleMenu:function(e){var t=e.target.ancestor(i.MENU),r=t.hasClass("show");e.halt(!0),this.hideMenu();if(r)return;this.showMenu(t),this.events.push(n.on("key",this.hideMenu,"esc",this)),this.events.push(n.on("click",this.hideIfOutside,this)),this.events.push(n.delegate("focus",this.hideIfOutside,"*",this))},hideIfOutside:function(e){!e.target.test(i.MENU)&&!e.target.ancestor(i.MENU)&&this.hideMenu()},showMenu:function(e){var t=e.getData("owner"),n=e.one(i.MENUCONTENT);return this.owner=t?e.ancestor(t):null,this.dialogue=e,e.addClass("show"),this.owner&&this.owner.addClass(r.MENUSHOWN),this.constrain(n.set("aria-hidden",!1)),!0},constrain:function(e){var t=e.getData("constraint"),n=e.getX(),r=e.getY(),i=e.get("offsetWidth"),s=e.get("offsetHeight"),o=0,u=0,a,f,l="auto",c=null,h=null,p=null,d=null,v=null;t&&(t=e.ancestor(t)),t?(a=t.get("offsetWidth"),f=t.get("offsetHeight"),o=t.getX(),u=t.getY(),l=t.getStyle("overflow")||"auto"):(a=e.get("docWidth"),f=e.get("docHeight")),i>a?(c=i=a,p=n=o):n<o?p=n=o:n+i>=o+a&&(p=o+a-i),s>f&&l.toLowerCase()==="hidden"&&(h=s=f,e.setStyle("overflow","auto"));if(r>=u&&r+s>u+f){d=u+f-s;try{v=e.getStyle("boxShadow").replace(/.*? (\d+)px \d+px$/,"$1"),(new RegExp(/^\d+$/)).test(v)&&d-u>v&&(d-=v)}catch(m){}}p!==null&&e.setX(p),d!==null&&e.setY(d),c!==null&&e.setStyle("width",c.toString()+"px"),h!==null&&e.setStyle("height",h.toString()+"px")}},e.extend(s,e.Base,s.prototype,{NAME:"moodle-core-actionmenu",ATTRS:{align:{value:[o.TR,o.BR]}}}),M.core=M.core||{},M.core.actionmenu=M.core.actionmenu||{},M.core.actionmenu.instance=null,M.core.actionmenu.init=M.core.actionmenu.init||function(e){M.core.actionmenu.instance=M.core.actionmenu.instance||new s(e)},M.core.actionmenu.newDOMNode=function(e){if(M.core.actionmenu.instance===null)return!0;e.all(i.MENU).each(M.core.actionmenu.instance.enhance,M.core.actionmenu.instance)}},"@VERSION@",{requires:["base","event"]});
|
||||
YUI.add("moodle-core-actionmenu",function(e,t){var n=e.one(e.config.doc.body),r={MENUSHOWN:"action-menu-shown"},i={CAN_RECEIVE_FOCUS_SELECTOR:'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',MENU:".moodle-actionmenu[data-enhance=moodle-core-actionmenu]",MENUCONTENT:".menu[data-rel=menu-content]",MENUCONTENTCHILD:"li a",MENUCHILD:".menu li a",TOGGLE:".toggle-display"},s,o={TL:"tl",TR:"tr",BL:"bl",BR:"br"};s=function(){s.superclass.constructor.apply(this,arguments)},s.prototype={dialogue:null,events:[],owner:null,menulink:null,initializer:function(){e.all(i.MENU).each(this.enhance,this),n.delegate("click",this.toggleMenu,i.MENU+" "+i.TOGGLE,this),n.delegate("key",this.toggleMenu,"enter,space",i.MENU+" "+i.TOGGLE,this)},enhance:function(e){var t=e.one(i.MENUCONTENT),n;if(!t)return!1;n=t.getData("align")||this.get("align").join("-"),e.one(i.TOGGLE).set("aria-haspopup",!0),t.set("aria-hidden",!0),t.hasClass("align-"+n)||t.addClass("align-"+n),t.hasChildNodes()&&e.setAttribute("data-enhanced","1")},hideMenu:function(){this.dialogue&&(this.dialogue.removeClass("show"),this.dialogue.one(i.MENUCONTENT).set("aria-hidden",!0),this.dialogue=null);for(var e in this.events)this.events[e].detach&&this.events[e].detach();this.events=[],this.owner&&(this.owner.removeClass(r.MENUSHOWN),this.owner=null),this.menulink&&(this.menulink.focus(),this.menulink=null)},toggleMenu:function(e){var t=e.target.ancestor(i.MENU),r=t.hasClass("show");e.halt(!0),this.hideMenu();if(r)return;this.showMenu(e,t),this.events.push(n.on("key",this.hideMenu,"esc",this)),this.events.push(n.on("click",this.hideIfOutside,this)),this.events.push(n.delegate("focus",this.hideIfOutside,"*",this)),this.events.push(t.delegate("key",this.checkFocus,"down:9",i.MENUCHILD,this))},checkFocus:function(e){var t=this.dialogue.all(i.MENUCHILD),n,r;t&&(n=t.item(0),r=t.pop());var s=this.menulink;if(e.target===n&&e.shiftKey)this.hideMenu(),e.preventDefault();else if(e.target===r&&!e.shiftKey){var o;this.hideMenu()&&(o=s.next(i.CAN_RECEIVE_FOCUS_SELECTOR),o&&o.focus())}},hideIfOutside:function(e){!e.target.test(i.MENU)&&!e.target.ancestor(i.MENU)&&this.hideMenu()},showMenu:function(e,t){var n=t.getData("owner"),s=t.one(i.MENUCONTENT),o;return this.owner=n?t.ancestor(n):null,this.dialogue=t,t.addClass("show"),this.owner&&(this.owner.addClass(r.MENUSHOWN),this.menulink=this.owner.one(i.TOGGLE)),this.constrain(s.set("aria-hidden",!1)),e.type&&e.type==="key"&&(o=s.one(i.MENUCONTENTCHILD),o&&o.focus()),!0},constrain:function(e){var t=e.getData("constraint"),n=e.getX(),r=e.getY(),i=e.get("offsetWidth"),s=e.get("offsetHeight"),o=0,u=0,a,f,l="auto",c=null,h=null,p=null,d=null,v=null;t&&(t=e.ancestor(t)),t?(a=t.get("offsetWidth"),f=t.get("offsetHeight"),o=t.getX(),u=t.getY(),l=t.getStyle("overflow")||"auto"):(a=e.get("docWidth"),f=e.get("docHeight")),i>a?(c=i=a,p=n=o):n<o?p=n=o:n+i>=o+a&&(p=o+a-i),s>f&&l.toLowerCase()==="hidden"&&(h=s=f,e.setStyle("overflow","auto"));if(r>=u&&r+s>u+f){d=u+f-s;try{v=e.getStyle("boxShadow").replace(/.*? (\d+)px \d+px$/,"$1"),(new RegExp(/^\d+$/)).test(v)&&d-u>v&&(d-=v)}catch(m){}}p!==null&&e.setX(p),d!==null&&e.setY(d),c!==null&&e.setStyle("width",c.toString()+"px"),h!==null&&e.setStyle("height",h.toString()+"px")}},e.extend(s,e.Base,s.prototype,{NAME:"moodle-core-actionmenu",ATTRS:{align:{value:[o.TR,o.BR]}}}),M.core=M.core||{},M.core.actionmenu=M.core.actionmenu||{},M.core.actionmenu.instance=null,M.core.actionmenu.init=M.core.actionmenu.init||function(e){M.core.actionmenu.instance=M.core.actionmenu.instance||new s(e)},M.core.actionmenu.newDOMNode=function(e){if(M.core.actionmenu.instance===null)return!0;e.all(i.MENU).each(M.core.actionmenu.instance.enhance,M.core.actionmenu.instance)}},"@VERSION@",{requires:["base","event"]});
|
||||
|
@ -11,8 +11,11 @@ var BODY = Y.one(Y.config.doc.body),
|
||||
MENUSHOWN : 'action-menu-shown'
|
||||
},
|
||||
SELECTOR = {
|
||||
CAN_RECEIVE_FOCUS_SELECTOR: 'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',
|
||||
MENU : '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',
|
||||
MENUCONTENT : '.menu[data-rel=menu-content]',
|
||||
MENUCONTENTCHILD: 'li a',
|
||||
MENUCHILD: '.menu li a',
|
||||
TOGGLE : '.toggle-display'
|
||||
},
|
||||
ACTIONMENU,
|
||||
@ -59,6 +62,15 @@ ACTIONMENU.prototype = {
|
||||
*/
|
||||
owner : null,
|
||||
|
||||
/**
|
||||
* The menu button that toggles this open.
|
||||
*
|
||||
* @property menulink
|
||||
* @type Node
|
||||
* @protected
|
||||
*/
|
||||
menulink: null,
|
||||
|
||||
/**
|
||||
* Called during the initialisation process of the object.
|
||||
* @method initializer
|
||||
@ -102,16 +114,21 @@ ACTIONMENU.prototype = {
|
||||
this.dialogue.one(SELECTOR.MENUCONTENT).set('aria-hidden', true);
|
||||
this.dialogue = null;
|
||||
}
|
||||
if (this.owner) {
|
||||
this.owner.removeClass(CSS.MENUSHOWN);
|
||||
this.owner = null;
|
||||
}
|
||||
for (var i in this.events) {
|
||||
if (this.events[i].detach) {
|
||||
this.events[i].detach();
|
||||
}
|
||||
}
|
||||
this.events = [];
|
||||
if (this.owner) {
|
||||
this.owner.removeClass(CSS.MENUSHOWN);
|
||||
this.owner = null;
|
||||
}
|
||||
|
||||
if (this.menulink) {
|
||||
this.menulink.focus();
|
||||
this.menulink = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -130,13 +147,49 @@ ACTIONMENU.prototype = {
|
||||
// The menu was visible and the user has clicked to toggle it again.
|
||||
return;
|
||||
}
|
||||
this.showMenu(menu);
|
||||
this.showMenu(e, menu);
|
||||
// Close the menu if the user presses escape.
|
||||
this.events.push(BODY.on('key', this.hideMenu, 'esc', this));
|
||||
// Close the menu if the user clicks outside the menu.
|
||||
this.events.push(BODY.on('click', this.hideIfOutside, this));
|
||||
// Close the menu if the user focuses outside the menu.
|
||||
this.events.push(BODY.delegate('focus', this.hideIfOutside, '*', this));
|
||||
|
||||
// Check tabbing.
|
||||
this.events.push(menu.delegate('key', this.checkFocus, 'down:9', SELECTOR.MENUCHILD, this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Check current focus when moving around with the tab key.
|
||||
* This will ensure that when the etreme menu items are reached, the
|
||||
* menu is closed and the next DOM element is focused.
|
||||
*
|
||||
* @method checkFocus
|
||||
* @param {EventFacade} e The key event
|
||||
*/
|
||||
checkFocus: function(e) {
|
||||
var nodelist = this.dialogue.all(SELECTOR.MENUCHILD),
|
||||
firstNode,
|
||||
lastNode;
|
||||
|
||||
if (nodelist) {
|
||||
firstNode = nodelist.item(0);
|
||||
lastNode = nodelist.pop();
|
||||
}
|
||||
|
||||
var menulink = this.menulink;
|
||||
if (e.target === firstNode && e.shiftKey) {
|
||||
this.hideMenu();
|
||||
e.preventDefault();
|
||||
} else if (e.target === lastNode && !e.shiftKey) {
|
||||
var next;
|
||||
if (this.hideMenu()) {
|
||||
next = menulink.next(SELECTOR.CAN_RECEIVE_FOCUS_SELECTOR);
|
||||
if (next) {
|
||||
next.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -154,20 +207,30 @@ ACTIONMENU.prototype = {
|
||||
|
||||
/**
|
||||
* Displays the menu with the given content and alignment.
|
||||
* @param {EventFacade} e
|
||||
* @param {Node} menu
|
||||
* @param Array align
|
||||
* @returns {M.core.dialogue|dialogue}
|
||||
*/
|
||||
showMenu : function(menu) {
|
||||
showMenu : function(e, menu) {
|
||||
var ownerselector = menu.getData('owner'),
|
||||
menucontent = menu.one(SELECTOR.MENUCONTENT);
|
||||
menucontent = menu.one(SELECTOR.MENUCONTENT),
|
||||
menuchild;
|
||||
this.owner = (ownerselector) ? menu.ancestor(ownerselector) : null;
|
||||
this.dialogue = menu;
|
||||
menu.addClass('show');
|
||||
if (this.owner) {
|
||||
this.owner.addClass(CSS.MENUSHOWN);
|
||||
this.menulink = this.owner.one(SELECTOR.TOGGLE);
|
||||
}
|
||||
this.constrain(menucontent.set('aria-hidden', false));
|
||||
|
||||
if (e.type && e.type === 'key') {
|
||||
menuchild = menucontent.one(SELECTOR.MENUCONTENTCHILD);
|
||||
if (menuchild) {
|
||||
menuchild.focus();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
79
lib/yui/src/actionmenu/js/actionmenu.js
vendored
79
lib/yui/src/actionmenu/js/actionmenu.js
vendored
@ -9,8 +9,11 @@ var BODY = Y.one(Y.config.doc.body),
|
||||
MENUSHOWN : 'action-menu-shown'
|
||||
},
|
||||
SELECTOR = {
|
||||
CAN_RECEIVE_FOCUS_SELECTOR: 'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',
|
||||
MENU : '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',
|
||||
MENUCONTENT : '.menu[data-rel=menu-content]',
|
||||
MENUCONTENTCHILD: 'li a',
|
||||
MENUCHILD: '.menu li a',
|
||||
TOGGLE : '.toggle-display'
|
||||
},
|
||||
ACTIONMENU,
|
||||
@ -57,6 +60,15 @@ ACTIONMENU.prototype = {
|
||||
*/
|
||||
owner : null,
|
||||
|
||||
/**
|
||||
* The menu button that toggles this open.
|
||||
*
|
||||
* @property menulink
|
||||
* @type Node
|
||||
* @protected
|
||||
*/
|
||||
menulink: null,
|
||||
|
||||
/**
|
||||
* Called during the initialisation process of the object.
|
||||
* @method initializer
|
||||
@ -102,16 +114,21 @@ ACTIONMENU.prototype = {
|
||||
this.dialogue.one(SELECTOR.MENUCONTENT).set('aria-hidden', true);
|
||||
this.dialogue = null;
|
||||
}
|
||||
if (this.owner) {
|
||||
this.owner.removeClass(CSS.MENUSHOWN);
|
||||
this.owner = null;
|
||||
}
|
||||
for (var i in this.events) {
|
||||
if (this.events[i].detach) {
|
||||
this.events[i].detach();
|
||||
}
|
||||
}
|
||||
this.events = [];
|
||||
if (this.owner) {
|
||||
this.owner.removeClass(CSS.MENUSHOWN);
|
||||
this.owner = null;
|
||||
}
|
||||
|
||||
if (this.menulink) {
|
||||
this.menulink.focus();
|
||||
this.menulink = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -130,13 +147,49 @@ ACTIONMENU.prototype = {
|
||||
// The menu was visible and the user has clicked to toggle it again.
|
||||
return;
|
||||
}
|
||||
this.showMenu(menu);
|
||||
this.showMenu(e, menu);
|
||||
// Close the menu if the user presses escape.
|
||||
this.events.push(BODY.on('key', this.hideMenu, 'esc', this));
|
||||
// Close the menu if the user clicks outside the menu.
|
||||
this.events.push(BODY.on('click', this.hideIfOutside, this));
|
||||
// Close the menu if the user focuses outside the menu.
|
||||
this.events.push(BODY.delegate('focus', this.hideIfOutside, '*', this));
|
||||
|
||||
// Check tabbing.
|
||||
this.events.push(menu.delegate('key', this.checkFocus, 'down:9', SELECTOR.MENUCHILD, this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Check current focus when moving around with the tab key.
|
||||
* This will ensure that when the etreme menu items are reached, the
|
||||
* menu is closed and the next DOM element is focused.
|
||||
*
|
||||
* @method checkFocus
|
||||
* @param {EventFacade} e The key event
|
||||
*/
|
||||
checkFocus: function(e) {
|
||||
var nodelist = this.dialogue.all(SELECTOR.MENUCHILD),
|
||||
firstNode,
|
||||
lastNode;
|
||||
|
||||
if (nodelist) {
|
||||
firstNode = nodelist.item(0);
|
||||
lastNode = nodelist.pop();
|
||||
}
|
||||
|
||||
var menulink = this.menulink;
|
||||
if (e.target === firstNode && e.shiftKey) {
|
||||
this.hideMenu();
|
||||
e.preventDefault();
|
||||
} else if (e.target === lastNode && !e.shiftKey) {
|
||||
var next;
|
||||
if (this.hideMenu()) {
|
||||
next = menulink.next(SELECTOR.CAN_RECEIVE_FOCUS_SELECTOR);
|
||||
if (next) {
|
||||
next.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -154,21 +207,31 @@ ACTIONMENU.prototype = {
|
||||
|
||||
/**
|
||||
* Displays the menu with the given content and alignment.
|
||||
* @param {EventFacade} e
|
||||
* @param {Node} menu
|
||||
* @param Array align
|
||||
* @returns {M.core.dialogue|dialogue}
|
||||
*/
|
||||
showMenu : function(menu) {
|
||||
showMenu : function(e, menu) {
|
||||
Y.log('Displaying an action menu', 'debug', ACTIONMENU.NAME);
|
||||
var ownerselector = menu.getData('owner'),
|
||||
menucontent = menu.one(SELECTOR.MENUCONTENT);
|
||||
menucontent = menu.one(SELECTOR.MENUCONTENT),
|
||||
menuchild;
|
||||
this.owner = (ownerselector) ? menu.ancestor(ownerselector) : null;
|
||||
this.dialogue = menu;
|
||||
menu.addClass('show');
|
||||
if (this.owner) {
|
||||
this.owner.addClass(CSS.MENUSHOWN);
|
||||
this.menulink = this.owner.one(SELECTOR.TOGGLE);
|
||||
}
|
||||
this.constrain(menucontent.set('aria-hidden', false));
|
||||
|
||||
if (e.type && e.type === 'key') {
|
||||
menuchild = menucontent.one(SELECTOR.MENUCONTENTCHILD);
|
||||
if (menuchild) {
|
||||
menuchild.focus();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user