* @return {Object} Our built object ready to render out
*/
const templateDataBuilder = (data) => {
+ // Filter the incoming data to find favourite & recommended modules.
+ const favourites = [];
+ const recommended = [];
+
+ // Given the results of the above filters lets figure out what tab to set active.
+
+ // We have some favourites.
+ const favouritesFirst = !!favourites.length;
+ // Check if we have no favourites but have some recommended.
+ const recommendedFirst = !!(recommended.length && favouritesFirst === false);
+ // We have nothing fallback to show all modules.
+ const fallback = favouritesFirst === false && recommendedFirst === false;
+
return {
'default': data,
+ favourites: favourites,
+ recommended: recommended,
+ favouritesFirst: favouritesFirst,
+ recommendedFirst: recommendedFirst,
+ fallback: fallback,
};
};
* Initialise the keyboard navigation controls for the chooser.
*
* @method initKeyboardNavigation
- * @param {NodeElement} body Our modal that we are working with
+ * @param {HTMLElement} body Our modal that we are working with
* @param {Map} mappedModules A map of all of the modules we are working with with K: mod_name V: {Object}
*/
const initKeyboardNavigation = (body, mappedModules) => {
+ // Set up the tab handlers.
+ const favTabNav = body.querySelector(selectors.regions.favouriteTabNav);
+ const recommendedTabNav = body.querySelector(selectors.regions.recommendedTabNav);
+ const defaultTabNav = body.querySelector(selectors.regions.defaultTabNav);
+ const tabNavArray = [favTabNav, recommendedTabNav, defaultTabNav];
+ tabNavArray.forEach((element) => {
+ return element.addEventListener('keyup', (e) => {
+ const firstLink = e.target.parentElement.parentElement.firstElementChild.firstElementChild;
+ const lastLink = e.target.parentElement.parentElement.lastElementChild.firstElementChild;
+
+ if (e.keyCode === arrowRight) {
+ const nextLink = e.target.parentElement.nextElementSibling;
+ if (nextLink === null) {
+ e.srcElement.tabIndex = -1;
+ firstLink.tabIndex = 0;
+ firstLink.focus();
+ } else if (nextLink.firstElementChild.classList.contains('d-none')) {
+ e.srcElement.tabIndex = -1;
+ lastLink.tabIndex = 0;
+ lastLink.focus();
+ } else {
+ e.srcElement.tabIndex = -1;
+ nextLink.firstElementChild.tabIndex = 0;
+ nextLink.firstElementChild.focus();
+ }
+ }
+ if (e.keyCode === arrowLeft) {
+ const previousLink = e.target.parentElement.previousElementSibling;
+ if (previousLink === null) {
+ e.srcElement.tabIndex = -1;
+ lastLink.tabIndex = 0;
+ lastLink.focus();
+ } else if (previousLink.firstElementChild.classList.contains('d-none')) {
+ e.srcElement.tabIndex = -1;
+ firstLink.tabIndex = 0;
+ firstLink.focus();
+ } else {
+ e.srcElement.tabIndex = -1;
+ previousLink.firstElementChild.tabIndex = 0;
+ previousLink.firstElementChild.focus();
+ }
+ }
+ if (e.keyCode === home) {
+ e.srcElement.tabIndex = -1;
+ firstLink.tabIndex = 0;
+ firstLink.focus();
+ }
+ if (e.keyCode === end) {
+ e.srcElement.tabIndex = -1;
+ lastLink.tabIndex = 0;
+ lastLink.focus();
+ }
+ if (e.keyCode === space) {
+ e.preventDefault();
+ e.target.click();
+ }
+ });
+ });
+
+ // Set up the handlers for the modules.
const chooserOptions = body.querySelectorAll(selectors.regions.chooserOption.container);
Array.from(chooserOptions).forEach((element) => {
carousel: getDataSelector('region', 'carousel'),
help: getDataSelector('region', 'help'),
modules: getDataSelector('region', 'modules'),
+ favouriteTabNav: getDataSelector('region', 'favourite-tab-nav'),
+ recommendedTabNav: getDataSelector('region', 'recommended-tab-nav'),
+ defaultTabNav: getDataSelector('region', 'default-tab-nav'),
+ favouriteTab: getDataSelector('region', 'favourites'),
+ recommendedTab: getDataSelector('region', 'recommended'),
+ defaultTab: getDataSelector('region', 'default'),
getModuleSelector: modname => `[role="menuitem"][data-modname="${modname}"]`
},
actions: {
}}
<div data-region="carousel" class="carousel slide">
<div class="carousel-inner" aria-live="polite">
- <div class="carousel-item active" data-region="modules">
- <div class="modchoosercontainer" data-region="chooser-container" aria-label="{{#str}} activitymodules {{/str}}">
- <div class="optionscontainer d-flex flex-wrap mw-100 p-3 position-relative" role="menubar" data-region="chooser-options-container">
- {{#default}}
- {{>core_course/chooser_item}}
- {{/default}}
+ <div class="carousel-item p-4 active" data-region="modules">
+ <ul class="nav nav-tabs mb-2" id="activities-{{uniqid}}" role="tablist">
+ <li class="nav-item">
+ <a class="nav-link {{#favouritesFirst}}active{{/favouritesFirst}} {{^favourites}}d-none{{/favourites}}"
+ id="starred-tab-{{uniqid}}"
+ data-toggle="tab"
+ data-region="favourite-tab-nav"
+ href="#starred-{{uniqid}}"
+ role="tab"
+ aria-label="{{#str}} aria:favouritestab, core_course {{/str}}"
+ aria-controls="starred-{{uniqid}}"
+ aria-selected="{{#favouritesFirst}}true{{/favouritesFirst}}{{^favouritesFirst}}false{{/favouritesFirst}}"
+ tabindex="{{#favouritesFirst}}0{{/favouritesFirst}}{{^favouritesFirst}}-1{{/favouritesFirst}}"
+ >
+ {{#str}}favourites{{/str}}
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link {{#recommendedFirst}}active{{/recommendedFirst}} {{^recommended}}d-none{{/recommended}}"
+ id="recommended-tab-{{uniqid}}"
+ data-region="recommended-tab-nav"
+ data-toggle="tab"
+ href="#recommended-{{uniqid}}"
+ role="tab"
+ aria-label="{{#str}} aria:recommendedtab, core_course {{/str}}"
+ aria-controls="recommended-{{uniqid}}"
+ aria-selected="{{#recommendedFirst}}true{{/recommendedFirst}}{{^recommendedFirst}}false{{/recommendedFirst}}"
+ tabindex="{{#recommendedFirst}}0{{/recommendedFirst}}{{^recommendedFirst}}-1{{/recommendedFirst}}">
+ {{#str}}recommended{{/str}}
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link {{#fallback}}active{{/fallback}}"
+ id="all-tab-{{uniqid}}"
+ data-toggle="tab"
+ data-region="default-tab-nav"
+ href="#all-{{uniqid}}"
+ role="tab"
+ aria-label="{{#str}} aria:defaulttab, core_course {{/str}}"
+ aria-controls="all-{{uniqid}}"
+ aria-selected="{{#fallback}}true{{/fallback}}{{^fallback}}false{{/fallback}}"
+ tabindex="{{#fallback}}0{{/fallback}}{{^fallback}}-1{{/fallback}}"
+ >
+ {{#str}}activities{{/str}}
+ </a>
+ </li>
+ </ul>
+ <div class="tab-content" id="tabbed-activities-{{uniqid}}">
+ <div class="tab-pane {{#favouritesFirst}}active{{/favouritesFirst}}" id="starred-{{uniqid}}" data-region="favourites" role="tabpanel" aria-labelledby="starred-tab-{{uniqid}}">
+ <div class="modchoosercontainer" data-region="chooser-container" aria-label="{{#str}} activitymodules {{/str}}">
+ <div class="optionscontainer d-flex flex-wrap mw-100 p-3 position-relative" role="menubar" data-region="chooser-options-container" data-render="favourites-area">
+ {{#favourites}}
+ {{>core_course/chooser_item}}
+ {{/favourites}}
+ </div>
+ </div>
+ </div>
+ <div class="tab-pane {{#recommendedFirst}}active{{/recommendedFirst}}" id="recommended-{{uniqid}}" data-region="recommended" role="tabpanel" aria-labelledby="recommended-tab-{{uniqid}}">
+ <div class="modchoosercontainer" data-region="chooser-container" aria-label="{{#str}} activitymodules {{/str}}">
+ <div class="optionscontainer d-flex flex-wrap mw-100 p-3 position-relative" role="menubar" data-region="chooser-options-container">
+ {{#recommended}}
+ {{>core_course/chooser_item}}
+ {{/recommended}}
+ </div>
+ </div>
+ </div>
+ <div class="tab-pane {{#fallback}}active{{/fallback}}" id="all-{{uniqid}}" data-region="default" role="tabpanel" aria-labelledby="all-tab-{{uniqid}}">
+ <div class="modchoosercontainer" data-region="chooser-container" aria-label="{{#str}} activitymodules {{/str}}">
+ <div class="optionscontainer d-flex flex-wrap mw-100 p-3 position-relative" role="menubar" data-region="chooser-options-container">
+ {{#default}}
+ {{>core_course/chooser_item}}
+ {{/default}}
+ </div>
+ </div>
</div>
</div>
</div>
And "help" "core_course > Activity chooser screen" should not exist
And "Back" "button" should not exist in the "modules" "core_course > Activity chooser screen"
And I should not see "The assignment activity module enables a teacher to communicate tasks, collect work and provide grades and feedback." in the "Add an activity or resource" "dialogue"
+
+ # Currently stubbed out in MDL-67321 as further issues will add more tabs.
+ Scenario: Navigate between module tabs
+ Given I open the activity chooser
+ And I should see "Activities" in the "Add an activity or resource" "dialogue"
+ Then I should see "Forum" in the "default" "core_course > Activity chooser tab"
"%core_course/activityChooser%//*[@data-region=%locator%][contains(concat(' ', @class, ' '), ' carousel-item ')]"
]
),
+ new behat_component_named_selector(
+ 'Activity chooser tab', [
+ "%core_course/activityChooser%//*[@data-region=%locator%][contains(concat(' ', @class, ' '), ' tab-pane ')]"
+ ]
+ ),
];
}
$string['aria:courseimage'] = 'Course image';
$string['aria:courseshortname'] = 'Course short name';
$string['aria:coursename'] = 'Course name';
+$string['aria:defaulttab'] = 'The default modules';
$string['aria:favourite'] = 'Course is starred';
+$string['aria:favouritestab'] = 'Your starred modules';
+$string['aria:recommendedtab'] = 'The recommended modules';
$string['coursealreadyfinished'] = 'Course already finished';
$string['coursenotyetstarted'] = 'The course has not yet started';
$string['coursenotyetfinished'] = 'The course has not yet finished';
$string['recentactivity'] = 'Recent activity';
$string['recentactivityreport'] = 'Full report of recent activity...';
$string['recipientslist'] = 'Recipients list';
+$string['recommended'] = 'Recommended';
$string['recreatedcategory'] = 'Recreated category {$a}';
$string['redirect'] = 'Redirect';
$string['reducesections'] = 'Reduce the number of sections';