diff options
-rw-r--r-- | Package_html_static.mk | 1 | ||||
-rw-r--r-- | help3xsl/a11y-toggle.js | 100 | ||||
-rw-r--r-- | help3xsl/default.css | 40 | ||||
-rw-r--r-- | help3xsl/help2.js | 16 | ||||
-rw-r--r-- | help3xsl/online_transform.xsl | 11 |
5 files changed, 142 insertions, 26 deletions
diff --git a/Package_html_static.mk b/Package_html_static.mk index d1ebbbb1b3..249783c220 100644 --- a/Package_html_static.mk +++ b/Package_html_static.mk @@ -17,6 +17,7 @@ $(eval $(call gb_Package_add_files,helpcontent2_html_static,$(LIBO_SHARE_HELP_FO $(eval $(call gb_Package_add_file,helpcontent2_html_static,$(LIBO_SHARE_HELP_FOLDER)$(if $(HELP_ONLINE),/$(PRODUCTVERSION))/index.html,index2.html)) $(eval $(call gb_Package_add_files,helpcontent2_html_static,$(LIBO_SHARE_HELP_FOLDER)$(if $(HELP_ONLINE),/$(PRODUCTVERSION)),\ + a11y-toggle.js \ default.css \ fuzzysort.js \ help.js \ diff --git a/help3xsl/a11y-toggle.js b/help3xsl/a11y-toggle.js new file mode 100644 index 0000000000..821a8e0272 --- /dev/null +++ b/help3xsl/a11y-toggle.js @@ -0,0 +1,100 @@ +/* +MIT License + +Copyright (c) 2016 Edenspiekermann + +*/ + +(function () { + 'use strict'; + + var internalId = 0; + var togglesMap = {}; + var targetsMap = {}; + + function $ (selector, context) { + return Array.prototype.slice.call( + (context || document).querySelectorAll(selector) + ); + } + + function getClosestToggle (element) { + if (element.closest) { + return element.closest('[data-a11y-toggle]'); + } + + while (element) { + if (element.nodeType === 1 && element.hasAttribute('data-a11y-toggle')) { + return element; + } + + element = element.parentNode; + } + + return null; + } + + function handleToggle (toggle) { + var target = toggle && targetsMap[toggle.getAttribute('aria-controls')]; + + if (!target) { + return false; + } + + var toggles = togglesMap['#' + target.id]; + var isExpanded = target.getAttribute('aria-hidden') === 'false'; + + target.setAttribute('aria-hidden', isExpanded); + toggles.forEach(function (toggle) { + toggle.setAttribute('aria-expanded', !isExpanded); + }); + } + + var initA11yToggle = function (context) { + togglesMap = $('[data-a11y-toggle]', context).reduce(function (acc, toggle) { + var selector = '#' + toggle.getAttribute('data-a11y-toggle'); + acc[selector] = acc[selector] || []; + acc[selector].push(toggle); + return acc; + }, togglesMap); + + var targets = Object.keys(togglesMap); + targets.length && $(targets).forEach(function (target) { + var toggles = togglesMap['#' + target.id]; + var isExpanded = target.hasAttribute('data-a11y-toggle-open'); + var labelledby = []; + + toggles.forEach(function (toggle) { + toggle.id || toggle.setAttribute('id', 'a11y-toggle-' + internalId++); + toggle.setAttribute('aria-controls', target.id); + toggle.setAttribute('aria-expanded', isExpanded); + labelledby.push(toggle.id); + }); + + target.setAttribute('aria-hidden', !isExpanded); + target.hasAttribute('aria-labelledby') || target.setAttribute('aria-labelledby', labelledby.join(' ')); + + targetsMap[target.id] = target; + }); + }; + + document.addEventListener('DOMContentLoaded', function () { + initA11yToggle(); + }); + + document.addEventListener('click', function (event) { + var toggle = getClosestToggle(event.target); + handleToggle(toggle); + }); + + document.addEventListener('keyup', function (event) { + if (event.which === 13 || event.which === 32) { + var toggle = getClosestToggle(event.target); + if (toggle && toggle.getAttribute('role') === 'button') { + handleToggle(toggle); + } + } + }); + + window && (window.a11yToggle = initA11yToggle); +})(); diff --git a/help3xsl/default.css b/help3xsl/default.css index bf1358ee11..482f3ed6d4 100644 --- a/help3xsl/default.css +++ b/help3xsl/default.css @@ -375,7 +375,11 @@ header { height: 60px; margin-right: 10px; } -.lang nav, .modules nav { +[aria-hidden='true'], +[data-a11y-toggle]:not([aria-controls]) { + display: none; +} +#langs-nav:not([aria-hidden='true']), #modules-nav:not([aria-hidden='true']) { z-index: 100; /* line them up horizontally */ display: flex; @@ -386,7 +390,7 @@ header { /* make it smooth on iOS */ -webkit-overflow-scrolling: touch; } -.lang nav a, .modules nav a { +#langs-nav a, #modules-nav a { color: #fff; background-color: #233336; display: block; @@ -411,7 +415,6 @@ footer p { background-color: transparent !important; padding: 3px 0 0 0 !important; } -.modules input[type=checkbox], .lang input[type=checkbox], .contents-treeview input[type=checkbox], aside input[type=checkbox] { position: absolute; opacity: 0; @@ -604,7 +607,7 @@ li.disabled a { border-bottom: 2px solid #f3f3f3; background-color: #233336; } -.modules label:after, .lang label:after { +#modules:after, #langs:after { font-size: 30px; color: #fff; content:"⌄"; @@ -612,10 +615,10 @@ li.disabled a { .lang { background-color: #233336; } -.lang label, .modules label { +#langs, #modules { display: none; } -.modules nav div { +#modules-nav div { background-repeat: no-repeat; background-size: contain; float: left; @@ -739,24 +742,30 @@ li.disabled a { } } @media screen and (min-width: 960px) { - .lang nav { + #langs-nav { display: none; } - .lang nav a { + #langs-nav a { font-size: 19px; white-space: normal; } - .lang label, .modules label { + /* these are buttons, so also reset some default stylings */ + #langs, #modules { cursor: pointer; color: #fff; font-size: 19px; position: relative; top: 40px; display: block; + background: transparent; + border: none; + text-transform: none; + padding:0; + line-height: normal; } - /* change the menu direction to stacked */ - .lang input[type="checkbox"]:checked ~ nav, .modules input[type="checkbox"]:checked ~ nav { + /* change the menu direction to stacked */ + #langs-nav:not([aria-hidden='true']), #modules-nav:not([aria-hidden='true']) { display: flex; flex-direction: column; max-width: 120px; @@ -766,17 +775,14 @@ li.disabled a { position: absolute; top: 80px; } - .modules input[type="checkbox"]:checked ~ nav { + #modules-nav { background-color: #101820; text-align: left; } - .modules nav { - display: none; - } - .modules nav div { + #modules-nav div { display: block; } - .modules nav a { + #modules-nav a { font-size: 19px; } aside { diff --git a/help3xsl/help2.js b/help3xsl/help2.js index f62105dc62..54dd195ab3 100644 --- a/help3xsl/help2.js +++ b/help3xsl/help2.js @@ -217,10 +217,16 @@ debugInfo(getParameterByName("Debug")); // Mobile devices need the modules and langs on page load if (Math.max(document.documentElement.clientWidth, window.innerWidth || 0) < 960) { - var e = new Event('change'); - var modules = document.getElementById('modules'); - var langs = document.getElementById('langs'); - modules.dispatchEvent(e); - langs.dispatchEvent(e); + var e = new Event('click'); + var modulesBtn = document.getElementById('modules'); + var langsBtn = document.getElementById('langs'); + var modules = document.getElementById('modules-nav'); + var langs = document.getElementById('langs-nav'); + modules.setAttribute('data-a11y-toggle-open', ''); + modulesBtn.dispatchEvent(e); + if (langs) { + langs.setAttribute('data-a11y-toggle-open', ''); + langsBtn.dispatchEvent(e); + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/help3xsl/online_transform.xsl b/help3xsl/online_transform.xsl index 95d19bc56a..2ca8deded7 100644 --- a/help3xsl/online_transform.xsl +++ b/help3xsl/online_transform.xsl @@ -154,6 +154,7 @@ <script type="text/javascript" src="{$target}fuzzysort.js"></script> <script type="text/javascript" src="{$target}prism.js"></script> <script type="text/javascript" src="{$target}help2.js" defer=""></script> + <script type="text/javascript" src="{$target}a11y-toggle.js" defer=""></script> <script type="text/javascript" src="{$target}{$lang}/langnames.js" defer=""></script> <script type="text/javascript" src="{$target}paginathing.js" defer=""></script> <script type="text/javascript" src="{$target}{$lang}/bookmarks.js" defer=""></script> @@ -179,14 +180,16 @@ </div> </header> <div class="modules"> - <input id="modules" name="modules" type="checkbox" onchange="setupModules('{$target}', '{$lang}');"/> - <label for="modules"><xsl:value-of select="$ui_module"/></label> + <button type="button" data-a11y-toggle="modules-nav" id="modules" onclick="setupModules('{$target}', '{$lang}');"> + <xsl:value-of select="$ui_module"/> + </button> <nav id="modules-nav"/><!-- is filled in via setupModules() on demand --> </div> <xsl:if test="$online"> <div class="lang"> - <input id="langs" name="language-menu" type="checkbox" onchange="setupLanguages('{$target}', '{$htmlpage}');"/> - <label for="langs"><xsl:value-of select="$ui_language"/></label> + <button type="button" data-a11y-toggle="langs-nav" id="langs" onclick="setupLanguages('{$target}', '{$htmlpage}');"> + <xsl:value-of select="$ui_language"/> + </button> <nav id="langs-nav"/><!-- is filled in via setupLanguages() on demand --> </div> </xsl:if> |