MDL-72263 courseformat: adding core/tree to course index

This commit is contained in:
Ferran Recio
2021-10-27 10:54:56 +02:00
parent e5894c0455
commit 59128bb411
19 changed files with 325 additions and 22 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
define ("core_courseformat/local/courseindex/keyboardnav",["exports","jquery","core/tree"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=d(b);c=d(c);function d(a){return a&&a.__esModule?a:{default:a}}function e(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){e=function(a){return typeof a}}else{e=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return e(a)}function f(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function g(a,b){for(var c=0,d;c<b.length;c++){d=b[c];d.enumerable=d.enumerable||!1;d.configurable=!0;if("value"in d)d.writable=!0;Object.defineProperty(a,d.key,d)}}function h(a,b,c){if(b)g(a.prototype,b);if(c)g(a,c);return a}function i(a,b){if("function"!=typeof b&&null!==b){throw new TypeError("Super expression must either be null or a function")}a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,writable:!0,configurable:!0}});if(b)j(a,b)}function j(a,b){j=Object.setPrototypeOf||function(a,b){a.__proto__=b;return a};return j(a,b)}function k(a){return function(){var b=p(a),c;if(n()){var d=p(this).constructor;c=Reflect.construct(b,arguments,d)}else{c=b.apply(this,arguments)}return l(this,c)}}function l(a,b){if(b&&("object"===e(b)||"function"==typeof b)){return b}return m(a)}function m(a){if(void 0===a){throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}return a}function n(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{Date.prototype.toString.call(Reflect.construct(Date,[],function(){}));return!0}catch(a){return!1}}function p(a){p=Object.setPrototypeOf?Object.getPrototypeOf:function(a){return a.__proto__||Object.getPrototypeOf(a)};return p(a)}var q=function(a){i(c,a);var d=k(c);function c(a){var b;f(this,c);b=d.call(this,a.element);b.selectors=a.selectors;if(a.reactive.isEditing){b._getVisibleItems=b.getVisibleItems;b.getVisibleItems=function(){b.refreshVisibleItemsCache();return b._getVisibleItems()}}b.treeRoot.on("hidden.bs.collapse shown.bs.collapse",function(){b.refreshVisibleItemsCache()});b.registerEnterCallback(b.enterCallback.bind(m(b)));return b}h(c,[{key:"getActiveItem",value:function getActiveItem(){var a=this.treeRoot.data("activeItem");if(a){return a.get(0)}}},{key:"enterCallback",value:function enterCallback(a){if(this.isGroupItem(a)){window.location.href=a.find(this.selectors.TOGGLER).first().attr("href");a.find(this.selectors.TOGGLER).get(0).click()}else{window.location.href=a.find("a").first().attr("href")}}},{key:"isGroupCollapsed",value:function isGroupCollapsed(a){var b=a.find("[aria-expanded]");return"false"===b.attr("aria-expanded")}},{key:"toggleGroup",value:function toggleGroup(a){var c,d=a.find(this.selectors.COLLAPSE),e=null!==(c=d.data("target"))&&void 0!==c?c:d.attr("href");if(!e){return}e=e.replace("#","");(0,b.default)("#".concat(e)).collapse("toggle")}},{key:"expandGroup",value:function expandGroup(a){if(this.isGroupCollapsed(a)){this.toggleGroup(a)}}},{key:"collapseGroup",value:function collapseGroup(a){if(!this.isGroupCollapsed(a)){this.toggleGroup(a)}}},{key:"expandAllGroups",value:function expandAllGroups(){var a=this,c=this.treeRoot.find(this.selectors.SECTION);c.each(function(c,d){a.expandGroup((0,b.default)(d))})}}]);return c}(c.default);a.default=q;return a.default});
//# sourceMappingURL=keyboardnav.min.js.map
File diff suppressed because one or more lines are too long
@@ -25,6 +25,7 @@
import {BaseComponent} from 'core/reactive';
import {getCurrentCourseEditor} from 'core_courseformat/courseeditor';
import jQuery from 'jquery';
import TreeNav from 'core_courseformat/local/courseindex/keyboardnav';
export default class Component extends BaseComponent {
@@ -41,6 +42,7 @@ export default class Component extends BaseComponent {
CM: `[data-for='cm']`,
TOGGLER: `[data-action="togglecourseindexsection"]`,
COLLAPSE: `[data-toggle="collapse"]`,
DRAWER: `.drawer`,
};
// Default classes to toggle on refresh.
this.classes = {
@@ -48,6 +50,7 @@ export default class Component extends BaseComponent {
CMHIDDEN: 'dimmed',
SECTIONCURRENT: 'current',
COLLAPSED: `collapsed`,
SHOW: `show`,
};
// Arrays to keep cms and sections elements.
this.sections = {};
@@ -85,6 +88,9 @@ export default class Component extends BaseComponent {
cms.forEach((cm) => {
this.cms[cm.dataset.id] = cm;
});
// Configure Aria Tree.
this.treeNav = new TreeNav(this);
}
getWatchers() {
@@ -0,0 +1,153 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Course index keyboard navigation and aria-tree compatibility.
*
* Node tree and bootstrap collapsibles don't use the same HTML structure. However,
* all keybindings and logic is compatible. This class translate the primitive opetations
* to a bootstrap collapsible structure.
*
* @module core_courseformat/local/courseindex/keyboardnav
* @class core_courseformat/local/courseindex/keyboardnav
* @copyright 2021 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// The core/tree uses jQuery to expand all nodes.
import $ from 'jquery';
import Tree from 'core/tree';
export default class extends Tree {
/**
* Setup the core/tree keyboard navigation.
*
* @param {CourseIndex} parent the parent component
*/
constructor(parent) {
// Init this value with the parent DOM element.
super(parent.element);
// Get selectors from parent.
this.selectors = parent.selectors;
// The core/tree library saves the visible elements cache inside the main tree node.
// However, in edit mode content can change suddenly so we need to refresh caches when needed.
if (parent.reactive.isEditing) {
this._getVisibleItems = this.getVisibleItems;
this.getVisibleItems = () => {
this.refreshVisibleItemsCache();
return this._getVisibleItems();
};
}
// Add jQuery events to detect boostrap collapse and uncollapse.
this.treeRoot.on('hidden.bs.collapse shown.bs.collapse', () => {
this.refreshVisibleItemsCache();
});
// Register a custom callback for pressing enter key.
this.registerEnterCallback(this.enterCallback.bind(this));
}
/**
* Return the current active node.
*
* @return {Element|undefined} the active item if any
*/
getActiveItem() {
const activeItem = this.treeRoot.data('activeItem');
if (activeItem) {
return activeItem.get(0);
}
return undefined;
}
/**
* Handle enter key on a collpasible node.
*
* @param {JQuery} item the jQuery object
*/
enterCallback(item) {
if (this.isGroupItem(item)) {
// Group elements is like clicking a topic but without loosing the focus.
window.location.href = item.find(this.selectors.TOGGLER).first().attr('href');
item.find(this.selectors.TOGGLER).get(0).click();
} else {
// Activity links just follow the link href.
window.location.href = item.find('a').first().attr('href');
return;
}
}
/**
* Check if a gorup item is collapsed.
*
* @param {JQuery} item the jQuery object
* @returns {boolean} if the element is collapsed
*/
isGroupCollapsed(item) {
const toggler = item.find(`[aria-expanded]`);
return toggler.attr('aria-expanded') === 'false';
}
/**
* Toggle a group item.
*
* @param {JQuery} item the jQuery object
*/
toggleGroup(item) {
const toggler = item.find(this.selectors.COLLAPSE);
let collapsibleId = toggler.data('target') ?? toggler.attr('href');
if (!collapsibleId) {
return;
}
collapsibleId = collapsibleId.replace('#', '');
// Bootstrap 4 uses jQuery to interact with collapsibles.
$(`#${collapsibleId}`).collapse('toggle');
}
/**
* Expand a group item.
*
* @param {JQuery} item the jQuery object
*/
expandGroup(item) {
if (this.isGroupCollapsed(item)) {
this.toggleGroup(item);
}
}
/**
* Collpase a group item.
*
* @param {JQuery} item the jQuery object
*/
collapseGroup(item) {
if (!this.isGroupCollapsed(item)) {
this.toggleGroup(item);
}
}
/**
* Expand all groups.
*/
expandAllGroups() {
const togglers = this.treeRoot.find(this.selectors.SECTION);
togglers.each((index, item) => {
this.expandGroup($(item));
});
}
}
@@ -28,7 +28,7 @@
"isactive": 1,
"uniqid": "0",
"isactive": 1,
"accessvisible": 1,
"accessvisible": 1
}
}}
<li class="courseindex-item
@@ -38,10 +38,11 @@
id="{{uniqid}}-course-index-cm-{{id}}"
data-for="cm"
data-id="{{id}}"
role="treeitem"
>
{{#url}}
{{#uservisible}}
<a class="courseindex-link text-truncate" href="{{{url}}}" data-for="cm_name">
<a class="courseindex-link text-truncate" href="{{{url}}}" data-for="cm_name" tabindex="-1">
{{{name}}}
</a>
{{/uservisible}}
@@ -60,6 +60,8 @@
data-for="section"
data-id="{{id}}"
data-number="{{number}}"
role="treeitem"
aria-owns="courseindexcollapse{{number}}"
>
<div class="courseindex-item d-flex {{^visible}}dimmed{{/visible}} courseindex-section-title"
id="courseindexsection{{number}}"
@@ -67,9 +69,10 @@
>
<a data-toggle="collapse"
href="#courseindexcollapse{{number}}"
class="courseindex-link icons-collapse-expand {{^isactive}}collapsed{{/isactive}}"
aria-expanded="{{#isactive}}true{{/isactive}}{{^isactive}}false{{/isactive}}"
aria-controls="courseindexcollapse{{number}}"
class="courseindex-link icons-collapse-expand {{^isactive}}collapsed{{/isactive}}"
tabindex="-1"
>
<span class="collapsed-icon icon-no-margin mr-1"
data-toggle="tooltip" title="{{#str}} expand, core {{/str}}">
@@ -86,6 +89,7 @@
class="courseindex-link text-truncate"
data-action="togglecourseindexsection"
data-for="section_title"
tabindex="-1"
>
{{{title}}}
</a>
@@ -96,7 +100,9 @@
</div>
<div id="courseindexcollapse{{number}}"
class="courseindex-item-content collapse {{#isactive}}show{{/isactive}}"
aria-labelledby="courseindexsection{{number}}">
aria-labelledby="courseindexsection{{number}}"
role="group"
>
<ul class="courseindex-sectioncontent unlist" data-for="cmlist" data-id="{{id}}">
{{#cms}}
{{> core_courseformat/local/courseindex/cm }}
@@ -0,0 +1,99 @@
@core @core_courseformat
Feature: Verify that courseindex is usable with the keyboard
In order to use the course index
As a user
I need to be able to navigate it without a mouse
Background:
Given the following "course" exists:
| fullname | Course 1 |
| shortname | C1 |
| category | 0 |
| enablecompletion | 1 |
| numsections | 3 |
And the following "activities" exist:
| activity | name | intro | course | idnumber | section |
| assign | Activity sample 1 | Test assignment description | C1 | sample1 | 1 |
| book | Activity sample 2 | Test book description | C1 | sample2 | 2 |
| choice | Activity sample 3 | Test choice description | C1 | sample3 | 3 |
Given I am on the "C1" "Course" page logged in as "admin"
And I click on "Side panel" "button"
And I click on "Open course index drawer" "button"
And I should see "Topic 1" in the "courseindex-content" "region"
And the focused element is ".drawertoggle" "css_element"
And I press the tab key
Then the focused element is ".courseindex-section" "css_element"
@javascript
Scenario: General focus on open course index.
When I press the shift tab key
And the focused element is ".drawertoggle" "css_element"
And I press enter
Then I should not see "Topic 1" in the "courseindex-content" "region"
@javascript
Scenario: Opening and closing sections.
When I press the down key
And I should see "Activity sample 1" in the "courseindex-content" "region"
# Close section with left key.
Then I press the left key
And I should not see "Activity sample 1" in the "courseindex-content" "region"
# Open a section with right key
And I press the right key
And I should see "Activity sample 1" in the "courseindex-content" "region"
# Key down to focus the module and close the section with two left keys.
And I press the down key
And I press the left key
And I press the left key
And I should not see "Activity sample 1" in the "courseindex-content" "region"
# Open a section using enter key.
And I press the down key
And I press the left key
And I should not see "Activity sample 2" in the "courseindex-content" "region"
And I press enter
And I should see "Activity sample 2" in the "courseindex-content" "region"
@javascript
Scenario: Navigate to an activity.
When I press the down key
And I press the right key
And I press enter
Then I should see "Activity sample 1" in the "page-header" "region"
@javascript
Scenario: Navigate to first and last element.
# Close sections 1 and 3.
Given I press the down key
And I press the left key
And I should not see "Activity sample 1" in the "courseindex-content" "region"
And I press the down key
And I press the down key
And I press the down key
And I press the left key
And I should not see "Activity sample 3" in the "courseindex-content" "region"
# Use end key to go to the last element.
When I press the end key
And I press the right key
And I should see "Activity sample 3" in the "courseindex-content" "region"
And I press the left key
Then I should not see "Activity sample 3" in the "courseindex-content" "region"
# Use home key to go to the first element.
And I press the home key
And I press the down key
And I press the right key
And I should see "Activity sample 1" in the "courseindex-content" "region"
@javascript
Scenario: Asterisc to open all sections.
# Close sections 1 and 2.
Given I press the down key
And I press the left key
And I should not see "Activity sample 1" in the "courseindex-content" "region"
And I press the down key
And I press the left key
And I should not see "Activity sample 2" in the "courseindex-content" "region"
And I should see "Activity sample 3" in the "courseindex-content" "region"
When I press the multiply key
Then I should see "Activity sample 1" in the "courseindex-content" "region"
And I should see "Activity sample 2" in the "courseindex-content" "region"
And I should see "Activity sample 3" in the "courseindex-content" "region"
+1 -1
View File
@@ -1,2 +1,2 @@
define ("core/local/aria/aria-hidden",["exports","core/normalise","./selectors"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.unhideSiblings=a.hideSiblings=a.unhide=a.hide=void 0;c=function(a){return a&&a.__esModule?a:{default:a}}(c);var d=new Map,e=new Map,f=function(){return MutationObserver&&"function"==typeof MutationObserver},g=function(a){if(!(a instanceof HTMLElement)){return}if(a.matches(c.default.elements.focusable)){h(a)}a.querySelectorAll(c.default.elements.focusable).forEach(h)},h=function(a){if("undefined"!=typeof a.dataset.ariaHiddenTabIndex){return}if(a.getAttribute("tabindex")){a.dataset.ariaHiddenTabIndex=a.getAttribute("tabindex")}else{a.dataset.ariaHiddenTabIndex=""}a.setAttribute("tabindex",-1)},i=function(a){if(!(a instanceof HTMLElement)){return}if(a.matches(c.default.elements.focusableToUnhide)){j(a)}a.querySelectorAll(c.default.elements.focusableToUnhide).forEach(j)},j=function(a){if(a.closest(c.default.aria.hidden)){return}var b=a.dataset.ariaHiddenTabIndex;if(""===b){a.removeAttribute("tabindex")}else{a.setAttribute("tabindex",b)}delete a.dataset.ariaHiddenTabIndex},k=function(a){return(0,b.getList)(a).forEach(l)};a.hide=k;var l=function(a){if(!(a instanceof HTMLElement)){return}if(a.closest(c.default.aria.hidden)){return}a.setAttribute("aria-hidden",!0);g(a);if(f()){var b=new MutationObserver(function(a){a.forEach(function(a){a.addedNodes.forEach(g)})});b.observe(a,{childList:!0,subtree:!0});d.set(a,b)}},m=function(a){return(0,b.getList)(a).forEach(n)};a.unhide=m;var n=function(a){if(!(a instanceof HTMLElement)){return}a.removeAttribute("aria-hidden");i(a);if(d.has(a)){d.get(a).disconnect();d.delete(a)}};a.hideSiblings=function hideSiblings(a){return(0,b.getList)(a).forEach(o)};var o=function(a){if(!(a instanceof HTMLElement)){return}if(!a.parentElement){return}a.parentElement.childNodes.forEach(function(b){if(b===a){return}k(b)});if(f()){var b=new MutationObserver(function(b){b.forEach(function(b){b.addedNodes.forEach(function(b){if(a.contains(b)){return}k(b)})})});b.observe(a.parentElement,{childList:!0,subtree:!0});e.set(a.parentElement,b)}};a.unhideSiblings=function unhideSiblings(a){return(0,b.getList)(a).forEach(p)};var p=function(a){if(!(a instanceof HTMLElement)){return}if(!a.parentElement){return}a.parentElement.childNodes.forEach(function(b){if(b===a){return}m(b)});if(e.has(a.parentElement)){e.get(a.parentElement).disconnect();e.delete(a.parentElement)}}});
define ("core/local/aria/aria-hidden",["exports","core/normalise","./selectors"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.unhideSiblings=a.hideSiblings=a.unhide=a.hide=void 0;c=function(a){return a&&a.__esModule?a:{default:a}}(c);var d=new Map,e=new Map,f=function(){return MutationObserver&&"function"==typeof MutationObserver},g=function(a){if(!(a instanceof HTMLElement)){return}if(a.matches(c.default.elements.focusable)){h(a)}a.querySelectorAll(c.default.elements.focusable).forEach(h)},h=function(a){if("undefined"!=typeof a.dataset.ariaHiddenTabIndex){return}if(a.getAttribute("tabindex")){a.dataset.ariaHiddenTabIndex=a.getAttribute("tabindex")}else{a.dataset.ariaHiddenTabIndex=""}a.setAttribute("tabindex",-1)},i=function(a){if(!(a instanceof HTMLElement)){return}if(a.matches(c.default.elements.focusableToUnhide)){j(a)}a.querySelectorAll(c.default.elements.focusableToUnhide).forEach(j)},j=function(a){if(a.closest(c.default.aria.hidden)){return}var b=a.dataset.ariaHiddenTabIndex;if(""===b){a.removeAttribute("tabindex")}else{a.setAttribute("tabindex",b)}delete a.dataset.ariaHiddenTabIndex},k=function(a){return(0,b.getList)(a).forEach(l)};a.hide=k;var l=function(a){if(!(a instanceof HTMLElement)){return}if(a.closest(c.default.aria.hidden)){return}a.setAttribute("aria-hidden",!0);g(a);if(f()){var b=new MutationObserver(function(a){a.forEach(function(a){if("childList"===a.type){a.addedNodes.forEach(g)}else if("attributes"===a.type){var b=a.target,c=b.getAttribute("tabindex");if("-1"!==c){b.dataset.ariaHiddenTabIndex=c;b.setAttribute("tabindex",-1)}}})});b.observe(a,{subtree:!0,childList:!0,attributes:!0,attributeFilter:["tabindex"]});d.set(a,b)}},m=function(a){return(0,b.getList)(a).forEach(n)};a.unhide=m;var n=function(a){if(!(a instanceof HTMLElement)){return}a.removeAttribute("aria-hidden");i(a);if(d.has(a)){d.get(a).disconnect();d.delete(a)}};a.hideSiblings=function hideSiblings(a){return(0,b.getList)(a).forEach(o)};var o=function(a){if(!(a instanceof HTMLElement)){return}if(!a.parentElement){return}a.parentElement.childNodes.forEach(function(b){if(b===a){return}k(b)});if(f()){var b=new MutationObserver(function(b){b.forEach(function(b){b.addedNodes.forEach(function(b){if(a.contains(b)){return}k(b)})})});b.observe(a.parentElement,{childList:!0,subtree:!0});e.set(a.parentElement,b)}};a.unhideSiblings=function unhideSiblings(a){return(0,b.getList)(a).forEach(p)};var p=function(a){if(!(a instanceof HTMLElement)){return}if(!a.parentElement){return}a.parentElement.childNodes.forEach(function(b){if(b===a){return}m(b)});if(e.has(a.parentElement)){e.get(a.parentElement).disconnect();e.delete(a.parentElement)}}});
//# sourceMappingURL=aria-hidden.min.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+26 -4
View File
@@ -153,14 +153,36 @@ const _hide = target => {
if (supportsMutationObservers()) {
// Add a MutationObserver to check for new children to the tree.
const newNodeObserver = new MutationObserver(mutationList => {
const mutationObserver = new MutationObserver(mutationList => {
mutationList.forEach(mutation => {
mutation.addedNodes.forEach(disableElementFocusability);
if (mutation.type === 'childList') {
mutation.addedNodes.forEach(disableElementFocusability);
} else if (mutation.type === 'attributes') {
// The tabindex has been updated on a hidden attribute.
// Ensure that it is stored, ad set to -1 to prevent breakage.
const element = mutation.target;
const proposedTabIndex = element.getAttribute('tabindex');
if (proposedTabIndex !== "-1") {
element.dataset.ariaHiddenTabIndex = proposedTabIndex;
element.setAttribute('tabindex', -1);
}
}
});
});
newNodeObserver.observe(target, {childList: true, subtree: true});
childObserverMap.set(target, newNodeObserver);
mutationObserver.observe(target, {
// Watch for changes to the entire subtree.
subtree: true,
// Watch for new nodes.
childList: true,
// Watch for attribute changes to the tabindex.
attributes: true,
attributeFilter: ['tabindex'],
});
childObserverMap.set(target, mutationObserver);
}
};
+1 -1
View File
@@ -17,7 +17,7 @@
* Implement an accessible aria tree widget, from a nested unordered list.
* Based on http://oaa-accessibility.org/example/41/.
*
* @module tool_lp/tree
* @module core/tree
* @copyright 2015 Damyon Wiese <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+3
View File
@@ -1886,6 +1886,9 @@ EOF;
case 'SPACE':
$keys[] = behat_keys::SPACE;
break;
case 'MULTIPLY':
$keys[] = behat_keys::MULTIPLY;
break;
default:
// You can enter a single ASCII character (e.g. a letter) to directly type that key.
if (strlen($key) === 1) {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+14 -5
View File
@@ -155,10 +155,10 @@ export default class Drawers {
this.drawerNode = drawerNode;
if (this.drawerNode.classList.contains('show')) {
this.openDrawer();
this.openDrawer(true);
} else if (this.drawerNode.dataset.forceopen == 1) {
if (!isSmall()) {
this.openDrawer();
this.openDrawer(true);
}
} else {
Aria.hide(this.drawerNode);
@@ -269,8 +269,15 @@ export default class Drawers {
/**
* Open the drawer.
*
* By default, openDrawer move the page focus to the close drawer button.However, when
* a drawer is opened by default this represents an accessibility problem as the initial
* focus changes without any user interaction. Using the keepfocus param it is possible to
* prevent the focus lose.
*
* @param {boolean} keepfocus true if the drawer has to open but don't alter the page focus.
*/
openDrawer() {
openDrawer(keepfocus) {
const showEvent = this.dispatchEvent(Drawers.eventTypes.drawerShow, true);
if (showEvent.defaultPrevented) {
return;
@@ -301,8 +308,10 @@ export default class Drawers {
.catch();
}
const closeButton = this.drawerNode.querySelector('[data-toggle="drawers"][data-action="closedrawer"]');
closeButton.focus();
if (!keepfocus) {
const closeButton = this.drawerNode.querySelector('[data-toggle="drawers"][data-action="closedrawer"]');
closeButton.focus();
}
this.dispatchEvent(Drawers.eventTypes.drawerShown);
}
+2 -1
View File
@@ -6,6 +6,7 @@
"lib/tests/behat/action_menu.feature",
"blocks/tests/behat/hide_blocks.feature",
"blocks/tests/behat/move_blocks.feature",
"course/format/tests/behat/course_courseindex.feature"
"course/format/tests/behat/course_courseindex.feature",
"course/format/tests/behat/courseindex_keyboardnav.feature"
]
}