MDL-71672 javascript: Fix the issue of focusOnShowSelector being ignored

When focusOnShowSelector is not present, as a fallback, focus the first
focusable element in YUI dialogues
Ref:
https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/dialog_role
This commit is contained in:
Shamim Rezaie
2021-07-19 16:42:04 +10:00
parent 2e1212eeae
commit d227e72aa4
4 changed files with 62 additions and 44 deletions
@@ -43,7 +43,12 @@ var DIALOGUE_NAME = 'Moodle dialogue',
MENUBAR_SELECTOR = '[role=menubar]',
DOT = '.',
HAS_ZINDEX = 'moodle-has-zindex',
CAN_RECEIVE_FOCUS_SELECTOR = 'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',
CAN_RECEIVE_FOCUS_SELECTOR = 'input:not([type="hidden"]):not([disabled]):not([tabindex^="-"]),' +
'a[href]:not([disabled]):not([tabindex^="-"]),' +
'button:not([disabled]):not([tabindex^="-"]),' +
'textarea:not([disabled]):not([tabindex^="-"]),' +
'select:not([disabled]):not([tabindex^="-"]),' +
'[tabindex]:not([disabled]):not([tabindex^="-"])',
FORM_SELECTOR = 'form';
/**
@@ -316,10 +321,6 @@ Y.extend(DIALOGUE, Y.Panel, {
Y.one(titlebar).setStyle('cursor', 'move');
}
}
require(['core/local/aria/focuslock'], function(FocusLockManager) {
// Trap focus to the current bounding box.
FocusLockManager.trapFocus(this.get('boundingBox').getDOMNode());
}.bind(this));
// Only do accessibility hiding for modals because the ARIA spec
// says that all ARIA dialogues should be modal.
@@ -410,9 +411,12 @@ Y.extend(DIALOGUE, Y.Panel, {
Math.floor(Y.one(document.body).get('winWidth')) < this.get('responsiveWidth');
},
_focus: function() {
this.focus();
},
show: function() {
var result = null,
header = this.headerNode,
content = this.bodyNode,
focusSelector = this.get('focusOnShowSelector'),
focusNode = null;
@@ -429,16 +433,18 @@ Y.extend(DIALOGUE, Y.Panel, {
focusNode = this.get('boundingBox').one(focusSelector);
}
if (!focusNode) {
// Fall back to the header or the content if no focus node was found yet.
if (header && header !== '') {
focusNode = header;
} else if (content && content !== '') {
focusNode = content;
// Fall back to the first focusable element in the body of the dialogue if no focus node was found yet.
if (content && content !== '') {
focusNode = content.one(CAN_RECEIVE_FOCUS_SELECTOR);
}
}
if (focusNode) {
focusNode.focus();
}
require(['core/local/aria/focuslock'], function(FocusLockManager) {
// Trap focus to the current bounding box.
FocusLockManager.trapFocus(this.get('boundingBox').getDOMNode());
if (focusNode) {
focusNode.focus();
}
}.bind(this));
return result;
},
File diff suppressed because one or more lines are too long
@@ -43,7 +43,12 @@ var DIALOGUE_NAME = 'Moodle dialogue',
MENUBAR_SELECTOR = '[role=menubar]',
DOT = '.',
HAS_ZINDEX = 'moodle-has-zindex',
CAN_RECEIVE_FOCUS_SELECTOR = 'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',
CAN_RECEIVE_FOCUS_SELECTOR = 'input:not([type="hidden"]):not([disabled]):not([tabindex^="-"]),' +
'a[href]:not([disabled]):not([tabindex^="-"]),' +
'button:not([disabled]):not([tabindex^="-"]),' +
'textarea:not([disabled]):not([tabindex^="-"]),' +
'select:not([disabled]):not([tabindex^="-"]),' +
'[tabindex]:not([disabled]):not([tabindex^="-"])',
FORM_SELECTOR = 'form';
/**
@@ -316,10 +321,6 @@ Y.extend(DIALOGUE, Y.Panel, {
Y.one(titlebar).setStyle('cursor', 'move');
}
}
require(['core/local/aria/focuslock'], function(FocusLockManager) {
// Trap focus to the current bounding box.
FocusLockManager.trapFocus(this.get('boundingBox').getDOMNode());
}.bind(this));
// Only do accessibility hiding for modals because the ARIA spec
// says that all ARIA dialogues should be modal.
@@ -410,9 +411,12 @@ Y.extend(DIALOGUE, Y.Panel, {
Math.floor(Y.one(document.body).get('winWidth')) < this.get('responsiveWidth');
},
_focus: function() {
this.focus();
},
show: function() {
var result = null,
header = this.headerNode,
content = this.bodyNode,
focusSelector = this.get('focusOnShowSelector'),
focusNode = null;
@@ -429,16 +433,18 @@ Y.extend(DIALOGUE, Y.Panel, {
focusNode = this.get('boundingBox').one(focusSelector);
}
if (!focusNode) {
// Fall back to the header or the content if no focus node was found yet.
if (header && header !== '') {
focusNode = header;
} else if (content && content !== '') {
focusNode = content;
// Fall back to the first focusable element in the body of the dialogue if no focus node was found yet.
if (content && content !== '') {
focusNode = content.one(CAN_RECEIVE_FOCUS_SELECTOR);
}
}
if (focusNode) {
focusNode.focus();
}
require(['core/local/aria/focuslock'], function(FocusLockManager) {
// Trap focus to the current bounding box.
FocusLockManager.trapFocus(this.get('boundingBox').getDOMNode());
if (focusNode) {
focusNode.focus();
}
}.bind(this));
return result;
},
+20 -14
View File
@@ -13,7 +13,12 @@ var DIALOGUE_NAME = 'Moodle dialogue',
MENUBAR_SELECTOR = '[role=menubar]',
DOT = '.',
HAS_ZINDEX = 'moodle-has-zindex',
CAN_RECEIVE_FOCUS_SELECTOR = 'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',
CAN_RECEIVE_FOCUS_SELECTOR = 'input:not([type="hidden"]):not([disabled]):not([tabindex^="-"]),' +
'a[href]:not([disabled]):not([tabindex^="-"]),' +
'button:not([disabled]):not([tabindex^="-"]),' +
'textarea:not([disabled]):not([tabindex^="-"]),' +
'select:not([disabled]):not([tabindex^="-"]),' +
'[tabindex]:not([disabled]):not([tabindex^="-"])',
FORM_SELECTOR = 'form';
/**
@@ -286,10 +291,6 @@ Y.extend(DIALOGUE, Y.Panel, {
Y.one(titlebar).setStyle('cursor', 'move');
}
}
require(['core/local/aria/focuslock'], function(FocusLockManager) {
// Trap focus to the current bounding box.
FocusLockManager.trapFocus(this.get('boundingBox').getDOMNode());
}.bind(this));
// Only do accessibility hiding for modals because the ARIA spec
// says that all ARIA dialogues should be modal.
@@ -380,9 +381,12 @@ Y.extend(DIALOGUE, Y.Panel, {
Math.floor(Y.one(document.body).get('winWidth')) < this.get('responsiveWidth');
},
_focus: function() {
this.focus();
},
show: function() {
var result = null,
header = this.headerNode,
content = this.bodyNode,
focusSelector = this.get('focusOnShowSelector'),
focusNode = null;
@@ -399,16 +403,18 @@ Y.extend(DIALOGUE, Y.Panel, {
focusNode = this.get('boundingBox').one(focusSelector);
}
if (!focusNode) {
// Fall back to the header or the content if no focus node was found yet.
if (header && header !== '') {
focusNode = header;
} else if (content && content !== '') {
focusNode = content;
// Fall back to the first focusable element in the body of the dialogue if no focus node was found yet.
if (content && content !== '') {
focusNode = content.one(CAN_RECEIVE_FOCUS_SELECTOR);
}
}
if (focusNode) {
focusNode.focus();
}
require(['core/local/aria/focuslock'], function(FocusLockManager) {
// Trap focus to the current bounding box.
FocusLockManager.trapFocus(this.get('boundingBox').getDOMNode());
if (focusNode) {
focusNode.focus();
}
}.bind(this));
return result;
},