diff --git a/scripts/keyboard-nav.js b/scripts/keyboard-nav.js index 17098c2..b712ebe 100644 --- a/scripts/keyboard-nav.js +++ b/scripts/keyboard-nav.js @@ -113,10 +113,6 @@ H5P.KeyboardNav = (function (EventDispatcher) { * @public */ KeyboardNav.prototype.disableSelectability = function () { - this.elements.forEach(function (el) { - el.el.removeEventListener('keydown', el.keyDown); - el.el.removeEventListener('click', el.onClick); - }.bind(this)); this.selectability = false; }; @@ -126,10 +122,6 @@ H5P.KeyboardNav = (function (EventDispatcher) { * @public */ KeyboardNav.prototype.enableSelectability = function () { - this.elements.forEach(function (el) { - el.el.addEventListener('keydown', el.keyDown); - el.el.addEventListener('click', el.onClick); - }.bind(this)); this.selectability = true; }; diff --git a/scripts/mark-the-words.js b/scripts/mark-the-words.js index 1c1b102..e50340f 100644 --- a/scripts/mark-the-words.js +++ b/scripts/mark-the-words.js @@ -53,6 +53,8 @@ H5P.MarkTheWords = (function ($, Question, Word, KeyboardNav, XapiGenerator) { a11yRetry: 'Retry the task. Reset all responses and start the task over again.', }, params); + this.resetTask = this.resetTask.bind(this); + this.contentData = contentData; if (this.contentData !== undefined && this.contentData.previousState !== undefined) { this.previousState = this.contentData.previousState; @@ -260,13 +262,6 @@ H5P.MarkTheWords = (function ($, Question, Word, KeyboardNav, XapiGenerator) { text: ariaText, }).appendTo($ariaTextWrapper); - // A11y clickable list label - this.$a11yClickableTextLabel = $('
', { - 'class': 'hidden-but-read', - html: self.params.a11yClickableTextLabel, - tabIndex: '-1', - }).appendTo($container); - $wordContainer.appendTo($container); self.$wordContainer = $wordContainer; }; @@ -295,13 +290,20 @@ H5P.MarkTheWords = (function ($, Question, Word, KeyboardNav, XapiGenerator) { self.showButton('try-again'); } } - // Set focus to start of text - self.$a11yClickableTextLabel.html(self.params.a11yCheckingHeader + ' - ' + self.params.a11yClickableTextLabel); - self.$a11yClickableTextLabel.focus(); self.hideButton('check-answer'); self.trigger(self.XapiGenerator.generateAnsweredEvent()); + self.toggleSelectable(true); + + self.read( + self.params.a11yCheckingHeader + ' - ' + + self.params.a11yClickableTextLabel + ); + + window.setTimeout(() => { + self.focusOnFirstElement(); + }, 1); // Read 'checking mode' before announcing focus of first answer }, true, { 'aria-label': this.params.a11yCheck, }, { @@ -310,24 +312,31 @@ H5P.MarkTheWords = (function ($, Question, Word, KeyboardNav, XapiGenerator) { }); } - this.addButton('try-again', this.params.tryAgainButton, this.resetTask.bind(this), false, { - 'aria-label': this.params.a11yRetry, - }); + this.addButton( + 'try-again', + this.params.tryAgainButton, + () => { + this.resetTask({ focusOnFirst: true }) + }, + false, + { 'aria-label': this.params.a11yRetry } + ); - this.addButton('show-solution', this.params.showSolutionButton, function () { + this.addButton('show-solution', this.params.showSolutionButton, () => { self.setAllMarks(); - self.$a11yClickableTextLabel.html(self.params.a11ySolutionModeHeader + ' - ' + self.params.a11yClickableTextLabel); - self.$a11yClickableTextLabel.focus(); - if (self.params.behaviour.enableRetry) { self.showButton('try-again'); } self.hideButton('check-answer'); self.hideButton('show-solution'); - self.read(self.params.displaySolutionDescription); self.toggleSelectable(true); + + self.read(self.params.displaySolutionDescription); + window.setTimeout(() => { + self.focusOnFirstElement(); + }, 10); // Read 'checking mode' before announcing focus of first answer }, false, { 'aria-label': this.params.a11yShowSolution, }); @@ -341,23 +350,34 @@ H5P.MarkTheWords = (function ($, Question, Word, KeyboardNav, XapiGenerator) { this.keyboardNavigators.forEach(function (navigator) { if (disable) { navigator.disableSelectability(); - navigator.removeAllTabbable(); } else { navigator.enableSelectability(); - navigator.setTabbableAt((0)); } }); if (disable) { - this.$wordContainer.removeAttr('aria-multiselectable').removeAttr('role'); + this.$wordContainer.removeAttr('aria-multiselectable'); } else { - this.$wordContainer.attr('aria-multiselectable', 'true') - .attr('role', 'listbox'); + this.$wordContainer.attr('aria-multiselectable', 'true'); } }; + /** + * Focus on first element. + */ + MarkTheWords.prototype.focusOnFirstElement = function () { + this.keyboardNavigators.forEach((navigator, index) => { + if (index === 0) { + navigator.focusOnElementAt(0); + } + else { + navigator.setTabbableAt((0)); + } + }); + }; + /** * Get Xapi Data. * @@ -559,9 +579,12 @@ H5P.MarkTheWords = (function ($, Question, Word, KeyboardNav, XapiGenerator) { this.hideButton('try-again'); this.hideButton('show-solution'); this.hideButton('check-answer'); - this.$a11yClickableTextLabel.html(this.params.a11ySolutionModeHeader + ' - ' + this.params.a11yClickableTextLabel); this.toggleSelectable(true); + this.keyboardNavigators.forEach((navigator) => { + navigator.setTabbableAt((0)); + }); + this.trigger('resize'); }; @@ -569,18 +592,28 @@ H5P.MarkTheWords = (function ($, Question, Word, KeyboardNav, XapiGenerator) { * Resets the task back to its' initial state. * * @fires MarkTheWords#resize + * @param {object} [params={}] Parameters. + * @param {boolean} [params.focusOnFirst] If true, set focus on first element. * @see {@link https://h5p.org/documentation/developers/contracts|Needed for contracts.} */ - MarkTheWords.prototype.resetTask = function () { + MarkTheWords.prototype.resetTask = function (params={}) { this.isAnswered = false; this.clearAllMarks(); this.hideEvaluation(); this.hideButton('try-again'); this.hideButton('show-solution'); this.showButton('check-answer'); - this.$a11yClickableTextLabel.html(this.params.a11yClickableTextLabel); this.toggleSelectable(false); + + this.read(this.params.a11yClickableTextLabel); + + if (params.focusOnFirst) { + window.setTimeout(() => { + this.focusOnFirstElement(); + }, 10); // Read 'checking mode' before announcing focus of first answer + } + this.trigger('resize'); };