diff --git a/lang/ca/exescorm.php b/lang/ca/exescorm.php index bf2ef11..2146d6e 100644 --- a/lang/ca/exescorm.php +++ b/lang/ca/exescorm.php @@ -24,6 +24,7 @@ $string['toc'] = 'Taula de continguts'; $string['navigation'] = 'Navegació'; +$string['contenttitle'] = 'Contingut'; $string['aicchacptimeout'] = 'Temps d\'espera AICC HACP'; $string['aicchacptimeout_desc'] = 'Període de temps en minuts que una sessió externa AICC HACP es mantindrà oberta'; $string['aicchacpkeepsessiondata'] = 'Dades de sessió AICC HACP'; diff --git a/lang/en/exescorm.php b/lang/en/exescorm.php index 6228984..a19c50f 100644 --- a/lang/en/exescorm.php +++ b/lang/en/exescorm.php @@ -23,6 +23,7 @@ */ $string['toc'] = 'TOC'; $string['navigation'] = 'Navigation'; +$string['contenttitle'] = 'Content'; $string['aicchacptimeout'] = 'AICC HACP timeout'; $string['aicchacptimeout_desc'] = 'Length of time in minutes that an external AICC HACP session can remain open'; $string['aicchacpkeepsessiondata'] = 'AICC HACP session data'; diff --git a/lang/es/exescorm.php b/lang/es/exescorm.php index fbb776c..52030de 100644 --- a/lang/es/exescorm.php +++ b/lang/es/exescorm.php @@ -23,6 +23,7 @@ */ $string['toc'] = 'TOC (Tabla de Contenidos)'; $string['navigation'] = 'Navegación'; +$string['contenttitle'] = 'Contenido'; $string['aicchacptimeout'] = 'Tiempo de espera AICC HACP'; $string['aicchacptimeout_desc'] = 'Periodo de tiempo en minutos en el que una sesión externa AICC HACP se mantendrá abierta'; $string['aicchacpkeepsessiondata'] = 'Datos de sesión AICC HACP'; diff --git a/lang/eu/exescorm.php b/lang/eu/exescorm.php index 7502910..586e815 100644 --- a/lang/eu/exescorm.php +++ b/lang/eu/exescorm.php @@ -23,6 +23,7 @@ */ $string['toc'] = 'TOC (Edukien Taula)'; $string['navigation'] = 'Nabigazioa'; +$string['contenttitle'] = 'Edukia'; $string['aicchacptimeout'] = 'AICC HACP itxaronaldia'; $string['aicchacptimeout_desc'] = 'Zenbat minutuz egonen den irekia AICC HACP kanpoko saio bat'; $string['aicchacpkeepsessiondata'] = 'AICC HACP saioaren datuak'; diff --git a/lang/gl/exescorm.php b/lang/gl/exescorm.php index 9729399..f4daa2a 100644 --- a/lang/gl/exescorm.php +++ b/lang/gl/exescorm.php @@ -23,6 +23,7 @@ */ $string['toc'] = 'TOC (Táboa de Contidos)'; $string['navigation'] = 'Navegación'; +$string['contenttitle'] = 'Contido'; $string['aicchacptimeout'] = 'Tempo de espera AICC HACP'; $string['aicchacptimeout_desc'] = 'Período de tempo en minutos no que unha sesión externa AICC HACP se manterá aberta'; $string['aicchacpkeepsessiondata'] = 'Datos de sesión AICC HACP'; diff --git a/locallib.php b/locallib.php index 7088093..bf582f3 100644 --- a/locallib.php +++ b/locallib.php @@ -1848,12 +1848,14 @@ function exescorm_format_toc_for_treeview($user, $exescorm, $scoes, $usertracks, } else { if (!empty($sco->launch)) { if ($sco->exescormtype == 'sco') { - $result->toc .= html_writer::tag('a', $sco->statusicon.' '. - format_string($sco->title).' '.$score, - array('data-scoid' => $sco->id, 'title' => $sco->url)); + $result->toc .= html_writer::tag('a', $sco->statusicon. + format_string($sco->title).($score ? ' '.$score : ''), + array('data-scoid' => $sco->id, 'title' => $sco->url, + 'href' => '#')); } else { - $result->toc .= html_writer::tag('a', ' '.format_string($sco->title).' '.$score, - array('data-scoid' => $sco->id, 'title' => $sco->url)); + $result->toc .= html_writer::tag('a', ' '.format_string($sco->title).($score ? ' '.$score : ''), + array('data-scoid' => $sco->id, 'title' => $sco->url, + 'href' => '#')); } } else { if ($sco->exescormtype == 'sco') { @@ -1960,7 +1962,11 @@ function exescorm_get_toc($user, $exescorm, $cmid, $toclink=EXESCORM_TOCJSLINK, if ($tocheader) { $result->toc = html_writer::start_div('yui3-g-r', array('id' => 'exescorm_layout')); - $result->toc .= html_writer::start_div('yui3-u-1-5 loading', array('id' => 'exescorm_toc')); + $result->toc .= html_writer::start_div('yui3-u-1-5 loading', array( + 'id' => 'exescorm_toc', + 'role' => 'navigation', + 'aria-label' => get_string('contents', 'mod_exescorm'), + )); $result->toc .= html_writer::start_div('', ['id' => 'exescorm_tree']); } @@ -2025,7 +2031,8 @@ function exescorm_get_toc($user, $exescorm, $cmid, $toclink=EXESCORM_TOCJSLINK, $result->toc .= html_writer::end_div().html_writer::end_div(); $result->toc .= html_writer::start_div('loading', array('id' => 'exescorm_toc_toggle')); $result->toc .= html_writer::tag('button', '', - array('id' => 'exescorm_toc_toggle_btn', 'class' => 'bg-primary')).html_writer::end_div(); + array('id' => 'exescorm_toc_toggle_btn', 'class' => 'bg-primary', + 'aria-expanded' => 'true', 'aria-controls' => 'exescorm_toc')).html_writer::end_div(); $result->toc .= html_writer::start_div('', array('id' => 'exescorm_content')); $result->toc .= html_writer::div('', '', array('id' => 'exescorm_navpanel')); $result->toc .= html_writer::end_div().html_writer::end_div(); diff --git a/module.js b/module.js index ab4389f..4266c72 100644 --- a/module.js +++ b/module.js @@ -179,6 +179,22 @@ M.mod_exescorm.init = function(Y, nav_display, navposition_left, navposition_top exescorm_current_node.select(); } + // Mark the active TOC link so screen readers can announce the current item. + Y.one('#exescorm_tree').all('a[aria-current]').each(function(a) { + a.removeAttribute('aria-current'); + a.setAttribute('aria-selected', 'false'); + }); + if (node.id) { + var activeEl = Y.one('#' + node.id); + if (activeEl) { + var activeLink = activeEl.one('a'); + if (activeLink) { + activeLink.setAttribute('aria-current', 'page'); + activeLink.setAttribute('aria-selected', 'true'); + } + } + } + exescorm_tree_node.closeAll(); var url_prefix = M.cfg.wwwroot + '/mod/exescorm/loadSCO.php?'; var el_old_api = document.getElementById('exescormapi123'); @@ -193,6 +209,10 @@ M.mod_exescorm.init = function(Y, nav_display, navposition_left, navposition_top obj.setAttribute('webkitallowfullscreen', 'webkitallowfullscreen'); obj.setAttribute('mozallowfullscreen', 'mozallowfullscreen'); obj.setAttribute('onload', "exescorm_iframe_onload(this)"); + var labelEl = document.createElement('div'); + labelEl.innerHTML = node.label || ''; + var frameTitle = (labelEl.textContent || labelEl.innerText || '').replace(/\s+/g, ' ').trim().replace(/ \| [^|]*$/, '').replace(/["']/g, ''); + obj.setAttribute('title', frameTitle || M.util.get_string('contenttitle', 'mod_exescorm')); if (!window_name && node.title != null) { obj.setAttribute('src', url_prefix + node.title); @@ -294,14 +314,16 @@ M.mod_exescorm.init = function(Y, nav_display, navposition_left, navposition_top toc.addClass(cssclasses.disabled) .setAttribute('disabled-by', 'screen-size'); exescorm_toc_toggle_btn.setHTML('>').addClass('collapsed').removeClass('uncollapsed') - .set('title', M.util.get_string('show', 'moodle')); + .set('title', M.util.get_string('show', 'moodle')) + .setAttribute('aria-expanded', 'false'); exescorm_content.removeClass(cssclasses.exescorm_grid_content_toc_visible) .addClass(cssclasses.exescorm_grid_content_toc_hidden); } else if (body.get('winWidth') > collapsetocwinsize) { toc.removeClass(cssclasses.disabled) .removeAttribute('disabled-by'); exescorm_toc_toggle_btn.setHTML('<').addClass('uncollapsed').removeClass('collapsed') - .set('title', M.util.get_string('hide', 'moodle')); + .set('title', M.util.get_string('hide', 'moodle')) + .setAttribute('aria-expanded', 'true'); exescorm_content.removeClass(cssclasses.exescorm_grid_content_toc_hidden) .addClass(cssclasses.exescorm_grid_content_toc_visible); } @@ -311,14 +333,16 @@ M.mod_exescorm.init = function(Y, nav_display, navposition_left, navposition_top toc.removeClass(cssclasses.disabled) .removeAttribute('disabled-by'); exescorm_toc_toggle_btn.setHTML('<').addClass('uncollapsed').removeClass('collapsed') - .set('title', M.util.get_string('hide', 'moodle')); + .set('title', M.util.get_string('hide', 'moodle')) + .setAttribute('aria-expanded', 'true'); exescorm_content.removeClass(cssclasses.exescorm_grid_content_toc_hidden) .addClass(cssclasses.exescorm_grid_content_toc_visible); } else { toc.addClass(cssclasses.disabled) .setAttribute('disabled-by', 'user'); exescorm_toc_toggle_btn.setHTML('>').addClass('collapsed').removeClass('uncollapsed') - .set('title', M.util.get_string('show', 'moodle')); + .set('title', M.util.get_string('show', 'moodle')) + .setAttribute('aria-expanded', 'false'); exescorm_content.removeClass(cssclasses.exescorm_grid_content_toc_visible) .addClass(cssclasses.exescorm_grid_content_toc_hidden); } @@ -621,7 +645,8 @@ M.mod_exescorm.init = function(Y, nav_display, navposition_left, navposition_top Y.one('#exescorm_toc_toggle').addClass(cssclasses.exescorm_grid_toggle); Y.one('#exescorm_toc_toggle_btn') .setHTML('<') - .setAttribute('title', M.util.get_string('hide', 'moodle')); + .setAttribute('title', M.util.get_string('hide', 'moodle')) + .setAttribute('aria-expanded', 'true'); Y.one('#exescorm_content').addClass(cssclasses.exescorm_grid_content_toc_visible); exescorm_toggle_toc(true); } @@ -632,7 +657,8 @@ M.mod_exescorm.init = function(Y, nav_display, navposition_left, navposition_top Y.one('#exescorm_toc').addClass(cssclasses.disabled); Y.one('#exescorm_toc_toggle_btn') .setHTML('>') - .setAttribute('title', M.util.get_string('show', 'moodle')); + .setAttribute('title', M.util.get_string('show', 'moodle')) + .setAttribute('aria-expanded', 'false'); Y.one('#exescorm_content') .removeClass(cssclasses.exescorm_grid_content_toc_visible) .addClass(cssclasses.exescorm_grid_content_toc_hidden); @@ -707,6 +733,11 @@ M.mod_exescorm.init = function(Y, nav_display, navposition_left, navposition_top tree.render(); tree.openAll(); + // Prevent href="#" on TOC anchors from scrolling to page top. + Y.one('#exescorm_tree').delegate('click', function(e) { + e.preventDefault(); + }, 'a'); + // On getting the window, always set the focus on the current item Y.one(Y.config.win).on('focus', function (e) { var current = exescorm_tree_node.getSelectedNodes()[0]; diff --git a/player.php b/player.php index 7e1ae1f..08d10d8 100644 --- a/player.php +++ b/player.php @@ -218,6 +218,7 @@ $PAGE->requires->string_for_js('hide', 'moodle'); $PAGE->requires->string_for_js('show', 'moodle'); $PAGE->requires->string_for_js('popupsblocked', 'mod_exescorm'); +$PAGE->requires->string_for_js('contenttitle', 'mod_exescorm'); $name = false; diff --git a/styles.css b/styles.css index c7818ca..252d659 100644 --- a/styles.css +++ b/styles.css @@ -79,6 +79,14 @@ font-size: 0.8em; } +#page-mod-exescorm-player #tocbox li a i{ + margin-right: .5em +} + +#page-mod-exescorm-player #tocbox a[aria-current]{ + text-decoration: underline; +} + #page-mod-exescorm-player #toctree { overflow: visible; }