diff --git a/ARIA/apg/example-index/accordion/accordion.md b/ARIA/apg/example-index/accordion/accordion.md index 443bb51fb..13fc1ab04 100644 --- a/ARIA/apg/example-index/accordion/accordion.md +++ b/ARIA/apg/example-index/accordion/accordion.md @@ -339,5 +339,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/alert/alert.md b/ARIA/apg/example-index/alert/alert.md index 3233dd530..0fb9c64f8 100644 --- a/ARIA/apg/example-index/alert/alert.md +++ b/ARIA/apg/example-index/alert/alert.md @@ -202,5 +202,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/breadcrumb/index.md b/ARIA/apg/example-index/breadcrumb/index.md index b7bd3a6c2..c9d374886 100644 --- a/ARIA/apg/example-index/breadcrumb/index.md +++ b/ARIA/apg/example-index/breadcrumb/index.md @@ -200,5 +200,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/button/button.md b/ARIA/apg/example-index/button/button.md index 4851046a0..5b7559a51 100644 --- a/ARIA/apg/example-index/button/button.md +++ b/ARIA/apg/example-index/button/button.md @@ -275,5 +275,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/button/button_idl.md b/ARIA/apg/example-index/button/button_idl.md index 9b84bcc33..329264d36 100644 --- a/ARIA/apg/example-index/button/button_idl.md +++ b/ARIA/apg/example-index/button/button_idl.md @@ -285,5 +285,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/carousel/carousel-1-prev-next.md b/ARIA/apg/example-index/carousel/carousel-1-prev-next.md index a373048eb..35bbb609d 100644 --- a/ARIA/apg/example-index/carousel/carousel-1-prev-next.md +++ b/ARIA/apg/example-index/carousel/carousel-1-prev-next.md @@ -617,5 +617,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/carousel/carousel-2-tablist.md b/ARIA/apg/example-index/carousel/carousel-2-tablist.md index f5231d9fe..f6eb5735d 100644 --- a/ARIA/apg/example-index/carousel/carousel-2-tablist.md +++ b/ARIA/apg/example-index/carousel/carousel-2-tablist.md @@ -856,5 +856,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/checkbox/checkbox-mixed.md b/ARIA/apg/example-index/checkbox/checkbox-mixed.md index 76f8f6f46..b3be77da0 100644 --- a/ARIA/apg/example-index/checkbox/checkbox-mixed.md +++ b/ARIA/apg/example-index/checkbox/checkbox-mixed.md @@ -277,5 +277,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/checkbox/checkbox.md b/ARIA/apg/example-index/checkbox/checkbox.md index a2434505e..8160c6e6e 100644 --- a/ARIA/apg/example-index/checkbox/checkbox.md +++ b/ARIA/apg/example-index/checkbox/checkbox.md @@ -273,5 +273,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/combobox/combobox-autocomplete-both.md b/ARIA/apg/example-index/combobox/combobox-autocomplete-both.md index 38cd0a1bf..bb33b3bcb 100644 --- a/ARIA/apg/example-index/combobox/combobox-autocomplete-both.md +++ b/ARIA/apg/example-index/combobox/combobox-autocomplete-both.md @@ -614,5 +614,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/combobox/combobox-autocomplete-list.md b/ARIA/apg/example-index/combobox/combobox-autocomplete-list.md index 479987af7..ce67a6133 100644 --- a/ARIA/apg/example-index/combobox/combobox-autocomplete-list.md +++ b/ARIA/apg/example-index/combobox/combobox-autocomplete-list.md @@ -607,5 +607,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/combobox/combobox-autocomplete-none.md b/ARIA/apg/example-index/combobox/combobox-autocomplete-none.md index dcc5eb886..d4ca4e9f0 100644 --- a/ARIA/apg/example-index/combobox/combobox-autocomplete-none.md +++ b/ARIA/apg/example-index/combobox/combobox-autocomplete-none.md @@ -549,5 +549,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/combobox/combobox-datepicker.md b/ARIA/apg/example-index/combobox/combobox-datepicker.md index f11fd0968..aab4b311b 100644 --- a/ARIA/apg/example-index/combobox/combobox-datepicker.md +++ b/ARIA/apg/example-index/combobox/combobox-datepicker.md @@ -810,5 +810,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/combobox/combobox-select-only.md b/ARIA/apg/example-index/combobox/combobox-select-only.md index b9f9ad5eb..e9c652bc5 100644 --- a/ARIA/apg/example-index/combobox/combobox-select-only.md +++ b/ARIA/apg/example-index/combobox/combobox-select-only.md @@ -494,5 +494,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/combobox/grid-combo.md b/ARIA/apg/example-index/combobox/grid-combo.md index 309500162..bab63acbe 100644 --- a/ARIA/apg/example-index/combobox/grid-combo.md +++ b/ARIA/apg/example-index/combobox/grid-combo.md @@ -467,5 +467,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/dialog-modal/alertdialog.md b/ARIA/apg/example-index/dialog-modal/alertdialog.md index f2611b1bf..0b6f35410 100644 --- a/ARIA/apg/example-index/dialog-modal/alertdialog.md +++ b/ARIA/apg/example-index/dialog-modal/alertdialog.md @@ -312,5 +312,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/dialog-modal/datepicker-dialog.md b/ARIA/apg/example-index/dialog-modal/datepicker-dialog.md index 0d33b4f9d..1b849b7d5 100644 --- a/ARIA/apg/example-index/dialog-modal/datepicker-dialog.md +++ b/ARIA/apg/example-index/dialog-modal/datepicker-dialog.md @@ -734,5 +734,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/dialog-modal/dialog.md b/ARIA/apg/example-index/dialog-modal/dialog.md index f2896f424..349ebccc9 100644 --- a/ARIA/apg/example-index/dialog-modal/dialog.md +++ b/ARIA/apg/example-index/dialog-modal/dialog.md @@ -434,5 +434,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/disclosure/disclosure-faq.md b/ARIA/apg/example-index/disclosure/disclosure-faq.md index 8fd5deb0e..85fe70be0 100644 --- a/ARIA/apg/example-index/disclosure/disclosure-faq.md +++ b/ARIA/apg/example-index/disclosure/disclosure-faq.md @@ -317,5 +317,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/disclosure/disclosure-image-description.md b/ARIA/apg/example-index/disclosure/disclosure-image-description.md index a65f69b47..9bd9d2525 100644 --- a/ARIA/apg/example-index/disclosure/disclosure-image-description.md +++ b/ARIA/apg/example-index/disclosure/disclosure-image-description.md @@ -468,5 +468,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/disclosure/disclosure-navigation-hybrid.md b/ARIA/apg/example-index/disclosure/disclosure-navigation-hybrid.md index 1ede29dbb..ac0f756e9 100644 --- a/ARIA/apg/example-index/disclosure/disclosure-navigation-hybrid.md +++ b/ARIA/apg/example-index/disclosure/disclosure-navigation-hybrid.md @@ -448,5 +448,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/disclosure/disclosure-navigation.md b/ARIA/apg/example-index/disclosure/disclosure-navigation.md index cc35ebe89..220c498ea 100644 --- a/ARIA/apg/example-index/disclosure/disclosure-navigation.md +++ b/ARIA/apg/example-index/disclosure/disclosure-navigation.md @@ -437,5 +437,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/feed/feed.md b/ARIA/apg/example-index/feed/feed.md index 53ba79dd8..cd2b216e7 100644 --- a/ARIA/apg/example-index/feed/feed.md +++ b/ARIA/apg/example-index/feed/feed.md @@ -270,5 +270,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/grid/LayoutGrids.md b/ARIA/apg/example-index/grid/LayoutGrids.md index 371e66f50..533b092ca 100644 --- a/ARIA/apg/example-index/grid/LayoutGrids.md +++ b/ARIA/apg/example-index/grid/LayoutGrids.md @@ -784,5 +784,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/grid/advancedDataGrid.md b/ARIA/apg/example-index/grid/advancedDataGrid.md index b64887998..3218a17c3 100644 --- a/ARIA/apg/example-index/grid/advancedDataGrid.md +++ b/ARIA/apg/example-index/grid/advancedDataGrid.md @@ -212,5 +212,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/grid/dataGrids.md b/ARIA/apg/example-index/grid/dataGrids.md index ecd61bea0..716ecfab5 100644 --- a/ARIA/apg/example-index/grid/dataGrids.md +++ b/ARIA/apg/example-index/grid/dataGrids.md @@ -908,5 +908,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/index.md b/ARIA/apg/example-index/index.md index 346a049ad..44df3b31a 100644 --- a/ARIA/apg/example-index/index.md +++ b/ARIA/apg/example-index/index.md @@ -938,5 +938,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/js/app.js b/ARIA/apg/example-index/js/app.js index 8b354d624..02809cadd 100644 --- a/ARIA/apg/example-index/js/app.js +++ b/ARIA/apg/example-index/js/app.js @@ -67,14 +67,14 @@ } })(); -// Add jumpto.js to examples +// Add skipto.js to examples (function () { return; // Line added by pre-build script let ref = window.location.href.split('examples')[0]; if (ref) { let head = document.getElementsByTagName('head')[0]; let scriptNode = document.createElement('script'); - scriptNode.setAttribute('src', ref + 'examples/js/jumpto.js'); + scriptNode.setAttribute('src', ref + 'examples/js/skipto.js'); head.appendChild(scriptNode); } })(); diff --git a/ARIA/apg/example-index/js/jumpto.js b/ARIA/apg/example-index/js/jumpto.js deleted file mode 100644 index 9d24505d0..000000000 --- a/ARIA/apg/example-index/js/jumpto.js +++ /dev/null @@ -1,1206 +0,0 @@ -/* - * This content is licensed according to the W3C Software License at - * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document - * - * File: jumpto.js - * - * Desc: Jump to provides keyboard navigation to document structure - * to support the bypass block requirement of WCAG 2.x - * This feature is based on the ARIA APG menu button example - * NOTE: This code has been contributed to the SkipTo.js project - */ - -'use strict'; - -(function () { - var JumpTo = { - jumpToId: 'is-jump-to-js-1', - domNode: null, - buttonNode: null, - menuNode: null, - menuitemNodes: [], - firstMenuitem: false, - lastMenuitem: false, - firstChars: [], - headingLevels: [], - jumpToIdIndex: 1, - usesAltKey: false, - usesOptionKey: false, - contentSelector: - 'h1, h2, h3, h4, h5, h6, p, li, img, input, select, textarea', - // Default configuration values - config: { - // Feature switches - enableHeadingLevelShortcuts: true, - enableHelp: true, - // Customization of button and menu - altAccesskey: '0', // default is the number zero - optionAccesskey: 'º', // default is the character associated with option+0 - displayOption: 'popup', // Line edited by pre-build script // options: static (default), popup - // container element, use containerClass for custom styling - containerElement: 'div', - containerRole: '', - customClass: '', - - // Button labels and messages - altLabel: 'Alt', - optionLabel: 'Option', - buttonShortcut: ' ($modifier+$key)', - buttonLabel: 'Jump To Content', - windowButtonAriaLabel: 'Jump To Content, shortcut Alt plus $key', - macButtonAriaLabel: 'Jump To Content, shortcut Command plus $key', - - // Menu labels and messages - menuLabel: 'Landmarks and Headings', - landmarkGroupLabel: 'Landmarks', - headingGroupLabel: 'Headings', - headingLevelLabel: 'Heading level', - mainLabel: 'main', - searchLabel: 'search', - navLabel: 'navigation', - regionLabel: 'region', - asideLabel: 'aside', - footerLabel: 'footer', - headerLabel: 'header', - formLabel: 'form', - msgNoLandmarksFound: 'No landmarks found', - msgNoHeadingsFound: 'No headings found', - - // Selectors for landmark and headings sections - landmarks: 'main, nav:first-of-type', - headings: 'main h1, [role="main"] h1, main h2, [role="main"] h2', - - // Custom CSS position and colors - colorTheme: '', - positionLeft: '', - menuTextColor: '', - menuBackgroundColor: '', - menuitemFocusTextColor: '', - menuitemFocusBackgroundColor: '', - focusBorderColor: '', - buttonTextColor: '', - buttonBackgroundColor: '', - }, - colorThemes: { - default: { - positionLeft: '', - menuTextColor: '#000', - menuBackgroundColor: '#def', - menuitemFocusTextColor: '#fff', - menuitemFocusBackgroundColor: '#005a9c', - focusBorderColor: '#005a9c', - buttonTextColor: '#005a9c', - buttonBackgroundColor: '#ddd', - }, - }, - defaultCSS: - 'body nav:nth-child(2) {padding-top: 12px}.jump-to.popup{position:absolute;top:-30em;left:0}.jump-to,.jump-to.popup.focus{position:absolute;top:0;left:$positionLeft}.jump-to.fixed{position:fixed}.jump-to button{position:relative;margin:0;padding:6px 8px 6px 8px;border-width:0 1px 1px 1px;border-style:solid;border-radius:0 0 6px 6px;border-color:$buttonBackgroundColor;color:$menuTextColor;background-color:$buttonBackgroundColor;font-size: 14px; z-index:200}.jump-to [role=menu]{position:absolute;min-width:17em;display:none;margin:0;padding:.25rem;background-color:$menuBackgroundColor;border-width:2px;border-style:solid;border-color:$focusBorderColor;border-radius:5px;z-index:1000}.jump-to [role=group]{display:grid;grid-auto-rows:min-content;grid-row-gap:1px}.jump-to [role=separator]:first-child{border-radius:5px 5px 0 0}.jump-to [role=menuitem]{padding:3px;width:auto;border-width:0;border-style:solid;color:$menuTextColor;background-color:$menuBackgroundColor;z-index:1000;display:grid;overflow-y:auto;grid-template-columns:repeat(6,1.2rem) 1fr;grid-column-gap:2px;font-size:1em}.jump-to [role=menuitem] .label,.jump-to [role=menuitem] .level{font-size:90%;font-weight:400;color:$menuTextColor;display:inline-block;background-color:$menuBackgroundColor;line-height:inherit;display:inline-block}.jump-to [role=menuitem] .level{text-align:right;padding-right:4px}.jump-to [role=menuitem] .label{text-align:left;margin:0;padding:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.jump-to [role=menuitem] .label:first-letter,.jump-to [role=menuitem] .level:first-letter{text-decoration:underline;text-transform:uppercase}.jump-to [role=menuitem].jump-to-h1 .level{grid-column:1}.jump-to [role=menuitem].jump-to-h2 .level{grid-column:2}.jump-to [role=menuitem].jump-to-h3 .level{grid-column:3}.jump-to [role=menuitem].jump-to-h4 .level{grid-column:4}.jump-to [role=menuitem].jump-to-h5 .level{grid-column:5}.jump-to [role=menuitem].jump-to-h6 .level{grid-column:8}.jump-to [role=menuitem].jump-to-h1 .label{grid-column:2/8}.jump-to [role=menuitem].jump-to-h2 .label{grid-column:3/8}.jump-to [role=menuitem].jump-to-h3 .label{grid-column:4/8}.jump-to [role=menuitem].jump-to-h4 .label{grid-column:5/8}.jump-to [role=menuitem].jump-to-h5 .label{grid-column:6/8}.jump-to [role=menuitem].jump-to-h6 .label{grid-column:7/8}.jump-to [role=menuitem].jump-to-h1.no-level .label{grid-column:1/8}.jump-to [role=menuitem].jump-to-h2.no-level .label{grid-column:2/8}.jump-to [role=menuitem].jump-to-h3.no-level .label{grid-column:3/8}.jump-to [role=menuitem].jump-to-h4.no-level .label{grid-column:4/8}.jump-to [role=menuitem].jump-to-h5.no-level .label{grid-column:5/8}.jump-to [role=menuitem].jump-to-h6.no-level .label{grid-column:6/8}.jump-to [role=menuitem].jump-to-nesting-level-1 .nesting{grid-column:1}.jump-to [role=menuitem].jump-to-nesting-level-2 .nesting{grid-column:2}.jump-to [role=menuitem].jump-to-nesting-level-3 .nesting{grid-column:3}.jump-to [role=menuitem].jump-to-nesting-level-0 .label{grid-column:1/8}.jump-to [role=menuitem].jump-to-nesting-level-1 .label{grid-column:2/8}.jump-to [role=menuitem].jump-to-nesting-level-2 .label{grid-column:3/8}.jump-to [role=menuitem].jump-to-nesting-level-3 .label{grid-column:4/8}.jump-to [role=menuitem].action .label,.jump-to [role=menuitem].no-items .label{grid-column:1/8}.jump-to [role=separator]{margin:1px 0 1px 0;padding:3px;display:block;width:auto;font-weight:700;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:$menuTextColor;background-color:$menuBackgroundColor;color:$menuTextColor;z-index:1000}.jump-to [role=separator]:first-child{border-radius:5px 5px 0 0}.jump-to [role=menuitem].last{border-radius:0 0 5px 5px}.jump-to.focus{display:block}.jump-to button:focus,.jump-to button:hover{background-color:$menuBackgroundColor;color:$menuTextColor;outline:0}.jump-to button:focus,.jump-to button:hover{padding:4px 7px 5px 7px;border-width:2px;border-color:$focusBorderColor}.jump-to [role=menuitem]:focus{padding:1px;border-width:2px;border-style:solid;border-color:$focusBorderColor;background-color:$menuitemFocusBackgroundColor;color:$menuitemFocusTextColor;outline:0}.jump-to [role=menuitem]:focus .label,.jump-to [role=menuitem]:focus .level{background-color:$menuitemFocusBackgroundColor;color:$menuitemFocusTextColor}', - - // - // Functions related to configuring the features - // of jumpTo - // - isNotEmptyString: function (str) { - return typeof str === 'string' && str.length; - }, - isEmptyString: function (str) { - return typeof str !== 'string' || str.length === 0; - }, - init: function (config) { - var node; - - let platform = navigator.platform.toLowerCase(); - let userAgent = navigator.userAgent.toLowerCase(); - - let hasWin = platform.indexOf('win') >= 0; - let hasMac = platform.indexOf('mac') >= 0; - let hasLinux = - platform.indexOf('linux') >= 0 || platform.indexOf('bsd') >= 0; - - let hasAndroid = userAgent.indexOf('android') >= 0; - - this.usesAltKey = hasWin || (hasLinux && !hasAndroid); - this.usesOptionKey = hasMac; - - // Check if jumpto is already loaded - if (document.querySelector('style#' + this.jumpToId)) { - return; - } - - var attachElement = document.body; - if (config) { - this.setUpConfig(config); - } - if (typeof this.config.attachElement === 'string') { - node = document.querySelector(this.config.attachElement); - if (node && node.nodeType === Node.ELEMENT_NODE) { - attachElement = node; - } - } - this.addCSSColors(); - this.renderStyleElement(this.defaultCSS); - var elem = this.config.containerElement.toLowerCase().trim(); - if (!this.isNotEmptyString(elem)) { - elem = 'div'; - } - this.domNode = document.createElement(elem); - this.domNode.classList.add('jump-to'); - if (this.isNotEmptyString(this.config.customClass)) { - this.domNode.classList.add(this.config.customClass); - } - if (this.isNotEmptyString(this.config.containerRole)) { - this.domNode.setAttribute('role', this.config.containerRole); - } - var displayOption = this.config.displayOption; - if (typeof displayOption === 'string') { - displayOption = displayOption.trim().toLowerCase(); - if (displayOption.length) { - switch (this.config.displayOption) { - case 'fixed': - this.domNode.classList.add('fixed'); - break; - case 'onfocus': // Legacy option - case 'popup': - this.domNode.classList.add('popup'); - break; - default: - break; - } - } - } - // Place skip to at the beginning of the document - if (attachElement.firstElementChild) { - attachElement.insertBefore( - this.domNode, - attachElement.firstElementChild - ); - } else { - attachElement.appendChild(this.domNode); - } - this.buttonNode = document.createElement('button'); - - let label = this.config.buttonLabel; - let buttonShortcut = ''; - let ariaLabel = ''; - - if (this.usesAltKey || this.usesOptionKey) { - buttonShortcut = this.config.buttonShortcut.replace( - '$key', - this.config.altAccesskey - ); - } - if (this.usesAltKey) { - buttonShortcut = buttonShortcut.replace( - '$modifier', - this.config.altLabel - ); - ariaLabel = this.config.windowButtonAriaLabel.replace( - '$key', - this.config.altAccesskey - ); - } - if (this.usesOptionKey) { - buttonShortcut = buttonShortcut.replace( - '$modifier', - this.config.optionLabel - ); - ariaLabel = this.config.macButtonAriaLabel.replace( - '$key', - this.config.altAccesskey - ); - } - this.buttonNode.textContent = label; - if (ariaLabel.length) { - this.buttonNode.textContent += buttonShortcut; - this.buttonNode.setAttribute('aria-label', ariaLabel); - } - this.buttonNode.setAttribute('aria-haspopup', 'true'); - this.buttonNode.setAttribute('aria-expanded', 'false'); - - this.domNode.appendChild(this.buttonNode); - - this.menuNode = document.createElement('div'); - this.domNode.appendChild(this.menuNode); - this.buttonNode.addEventListener( - 'keydown', - this.handleButtonKeydown.bind(this) - ); - this.buttonNode.addEventListener( - 'click', - this.handleButtonClick.bind(this) - ); - // Support shortcut key - if (this.usesAltKey || this.usesOptionKey) { - document.addEventListener( - 'keydown', - this.handleDocumentKeydown.bind(this) - ); - } - - this.domNode.addEventListener('focusin', this.handleFocusin.bind(this)); - this.domNode.addEventListener('focusout', this.handleFocusout.bind(this)); - window.addEventListener( - 'pointerdown', - this.handleBackgroundPointerdown.bind(this), - true - ); - }, - - updateStyle: function (stylePlaceholder, value, defaultValue) { - if (typeof value !== 'string' || value.length === 0) { - value = defaultValue; - } - var index1 = this.defaultCSS.indexOf(stylePlaceholder); - var index2 = index1 + stylePlaceholder.length; - while (index1 >= 0 && index2 < this.defaultCSS.length) { - this.defaultCSS = - this.defaultCSS.substring(0, index1) + - value + - this.defaultCSS.substring(index2); - index1 = this.defaultCSS.indexOf(stylePlaceholder, index2); - index2 = index1 + stylePlaceholder.length; - } - }, - addCSSColors: function () { - var theme = this.colorThemes['default']; - if (typeof this.colorThemes[this.config.colorTheme] === 'object') { - theme = this.colorThemes[this.config.colorTheme]; - } - this.updateStyle( - '$positionLeft', - this.config.positionLeft, - theme.positionLeft - ); - - this.updateStyle( - '$menuTextColor', - this.config.menuTextColor, - theme.menuTextColor - ); - this.updateStyle( - '$menuBackgroundColor', - this.config.menuBackgroundColor, - theme.menuBackgroundColor - ); - - this.updateStyle( - '$menuitemFocusTextColor', - this.config.menuitemFocusTextColor, - theme.menuitemFocusTextColor - ); - this.updateStyle( - '$menuitemFocusBackgroundColor', - this.config.menuitemFocusBackgroundColor, - theme.menuitemFocusBackgroundColor - ); - - this.updateStyle( - '$focusBorderColor', - this.config.focusBorderColor, - theme.focusBorderColor - ); - - this.updateStyle( - '$buttonTextColor', - this.config.buttonTextColor, - theme.buttonTextColor - ); - this.updateStyle( - '$buttonBackgroundColor', - this.config.buttonBackgroundColor, - theme.buttonBackgroundColor - ); - }, - setUpConfig: function (appConfig) { - var localConfig = this.config, - name, - appConfigSettings = - typeof appConfig.settings !== 'undefined' - ? appConfig.settings.jumpTo - : {}; - for (name in appConfigSettings) { - //overwrite values of our local config, based on the external config - if ( - typeof localConfig[name] !== 'undefined' && - ((typeof appConfigSettings[name] === 'string' && - appConfigSettings[name].length > 0) || - typeof appConfigSettings[name] === 'boolean') - ) { - localConfig[name] = appConfigSettings[name]; - } else { - throw new Error( - '** JumpTo Problem with user configuration option "' + name + '".' - ); - } - } - }, - renderStyleElement: function (cssString) { - var styleNode = document.createElement('style'); - var headNode = document.getElementsByTagName('head')[0]; - var css = document.createTextNode(cssString); - - styleNode.setAttribute('type', 'text/css'); - // ID is used to test whether jumpto is already loaded - styleNode.id = this.jumpToId; - styleNode.appendChild(css); - headNode.appendChild(styleNode); - }, - - // - // Functions related to creating and populating the - // the popup menu - // - - getFirstChar: function (menuitem) { - var c = ''; - var label = menuitem.querySelector('.label'); - if (label && this.isNotEmptyString(label.textContent)) { - c = label.textContent.trim()[0].toLowerCase(); - } - return c; - }, - - getHeadingLevelFromAttribute: function (menuitem) { - var level = ''; - if (menuitem.hasAttribute('data-level')) { - level = menuitem.getAttribute('data-level'); - } - return level; - }, - - updateKeyboardShortCuts: function () { - var mi; - this.firstChars = []; - this.headingLevels = []; - - for (var i = 0; i < this.menuitemNodes.length; i += 1) { - mi = this.menuitemNodes[i]; - this.firstChars.push(this.getFirstChar(mi)); - this.headingLevels.push(this.getHeadingLevelFromAttribute(mi)); - } - }, - - updateMenuitems: function () { - var menuitemNodes = this.menuNode.querySelectorAll('[role=menuitem'); - - this.menuitemNodes = []; - for (var i = 0; i < menuitemNodes.length; i += 1) { - this.menuitemNodes.push(menuitemNodes[i]); - } - - this.firstMenuitem = this.menuitemNodes[0]; - this.lastMenuitem = this.menuitemNodes[this.menuitemNodes.length - 1]; - this.lastMenuitem.classList.add('last'); - this.updateKeyboardShortCuts(); - }, - - renderMenuitemToGroup: function (groupNode, mi) { - var tagNode, tagNodeChild, labelNode, nestingNode; - - // only set role after menu button opens it to not interfere with regression tests - this.menuNode.setAttribute('role', 'menu'); - - var menuitemNode = document.createElement('div'); - menuitemNode.setAttribute('role', 'menuitem'); - menuitemNode.classList.add(mi.class); - if (this.isNotEmptyString(mi.tagName)) { - menuitemNode.classList.add('jump-to-' + mi.tagName.toLowerCase()); - } - menuitemNode.setAttribute('data-id', mi.dataId); - menuitemNode.tabIndex = -1; - if (this.isNotEmptyString(mi.ariaLabel)) { - menuitemNode.setAttribute('aria-label', mi.ariaLabel); - } - - // add event handlers - menuitemNode.addEventListener( - 'keydown', - this.handleMenuitemKeydown.bind(this) - ); - menuitemNode.addEventListener( - 'click', - this.handleMenuitemClick.bind(this) - ); - menuitemNode.addEventListener( - 'pointerenter', - this.handleMenuitemPointerenter.bind(this) - ); - - groupNode.appendChild(menuitemNode); - - // add heading level and label - if (mi.class.includes('heading')) { - if (this.config.enableHeadingLevelShortcuts) { - tagNode = document.createElement('span'); - tagNodeChild = document.createElement('span'); - tagNodeChild.appendChild(document.createTextNode(mi.level)); - tagNode.append(tagNodeChild); - tagNode.appendChild(document.createTextNode(')')); - tagNode.classList.add('level'); - menuitemNode.append(tagNode); - } else { - menuitemNode.classList.add('no-level'); - } - menuitemNode.setAttribute('data-level', mi.level); - if (this.isNotEmptyString(mi.tagName)) { - menuitemNode.classList.add('jump-to-' + mi.tagName); - } - } - - // add nesting level for landmarks - if (mi.class.includes('landmark')) { - menuitemNode.setAttribute('data-nesting', mi.nestingLevel); - menuitemNode.classList.add('jump-to-nesting-level-' + mi.nestingLevel); - - if (mi.nestingLevel > 0 && mi.nestingLevel > this.lastNestingLevel) { - nestingNode = document.createElement('span'); - nestingNode.classList.add('nesting'); - menuitemNode.append(nestingNode); - } - this.lastNestingLevel = mi.nestingLevel; - } - - labelNode = document.createElement('span'); - labelNode.appendChild(document.createTextNode(mi.name)); - labelNode.classList.add('label'); - menuitemNode.append(labelNode); - - return menuitemNode; - }, - - renderGroupLabel: function (groupLabelId, title) { - var titleNode; - var groupLabelNode = document.getElementById(groupLabelId); - titleNode = groupLabelNode.querySelector('.title'); - titleNode.textContent = title; - }, - - renderMenuitemGroup: function (groupId, title) { - var labelNode, groupNode, spanNode; - var menuNode = this.menuNode; - if (this.isNotEmptyString(title)) { - labelNode = document.createElement('div'); - labelNode.id = groupId + '-label'; - labelNode.setAttribute('role', 'separator'); - menuNode.appendChild(labelNode); - - spanNode = document.createElement('span'); - spanNode.classList.add('title'); - spanNode.textContent = title; - labelNode.append(spanNode); - - groupNode = document.createElement('div'); - groupNode.setAttribute('role', 'group'); - groupNode.setAttribute('aria-labelledby', labelNode.id); - groupNode.id = groupId; - menuNode.appendChild(groupNode); - menuNode = groupNode; - } - return groupNode; - }, - - removeMenuitemGroup: function (groupId) { - var node = document.getElementById(groupId); - this.menuNode.removeChild(node); - node = document.getElementById(groupId + '-label'); - this.menuNode.removeChild(node); - }, - - renderMenuitemsToGroup: function (groupNode, menuitems, msgNoItemsFound) { - groupNode.innerHTML = ''; - this.lastNestingLevel = 0; - - if (menuitems.length === 0) { - var item = {}; - item.name = msgNoItemsFound; - item.tagName = ''; - item.class = 'no-items'; - item.dataId = ''; - this.renderMenuitemToGroup(groupNode, item); - } else { - for (var i = 0; i < menuitems.length; i += 1) { - this.renderMenuitemToGroup(groupNode, menuitems[i]); - } - } - }, - - renderMenu: function () { - var groupNode, landmarkElements, headingElements; - // remove current menu items from menu - while (this.menuNode.lastElementChild) { - this.menuNode.removeChild(this.menuNode.lastElementChild); - } - - // Create landmarks group - landmarkElements = this.getLandmarks(this.config.landmarks); - - groupNode = this.renderMenuitemGroup( - 'id-jump-to-group-landmarks', - this.config.landmarkGroupLabel - ); - this.renderMenuitemsToGroup( - groupNode, - landmarkElements, - this.config.msgNoLandmarksFound - ); - this.renderGroupLabel( - 'id-jump-to-group-landmarks-label', - this.config.landmarkGroupLabel - ); - - // Create headings group - headingElements = this.getHeadings(this.config.headings); - - groupNode = this.renderMenuitemGroup( - 'id-jump-to-group-headings', - this.config.headingGroupLabel - ); - this.renderMenuitemsToGroup( - groupNode, - headingElements, - this.config.msgNoHeadingsFound - ); - this.renderGroupLabel( - 'id-jump-to-group-headings-label', - this.config.headingGroupLabel - ); - - // Update list of menuitems - this.updateMenuitems(); - }, - - // - // Menu scripting event functions and utilities - // - - setFocusToMenuitem: function (menuitem) { - if (menuitem) { - menuitem.focus(); - } - }, - - setFocusToFirstMenuitem: function () { - this.setFocusToMenuitem(this.firstMenuitem); - }, - - setFocusToLastMenuitem: function () { - this.setFocusToMenuitem(this.lastMenuitem); - }, - - setFocusToPreviousMenuitem: function (menuitem) { - var newMenuitem, index; - if (menuitem === this.firstMenuitem) { - newMenuitem = this.lastMenuitem; - } else { - index = this.menuitemNodes.indexOf(menuitem); - newMenuitem = this.menuitemNodes[index - 1]; - } - this.setFocusToMenuitem(newMenuitem); - return newMenuitem; - }, - - setFocusToNextMenuitem: function (menuitem) { - var newMenuitem, index; - if (menuitem === this.lastMenuitem) { - newMenuitem = this.firstMenuitem; - } else { - index = this.menuitemNodes.indexOf(menuitem); - newMenuitem = this.menuitemNodes[index + 1]; - } - this.setFocusToMenuitem(newMenuitem); - return newMenuitem; - }, - - setFocusByFirstCharacter: function (menuitem, char) { - var start, index; - if (char.length > 1) { - return; - } - char = char.toLowerCase(); - - // Get start index for search based on position of currentItem - start = this.menuitemNodes.indexOf(menuitem) + 1; - if (start >= this.menuitemNodes.length) { - start = 0; - } - - // Check remaining items in the menu - index = this.firstChars.indexOf(char, start); - - // If not found in remaining items, check headings - if (index === -1) { - index = this.headingLevels.indexOf(char, start); - } - - // If not found in remaining items, check from beginning - if (index === -1) { - index = this.firstChars.indexOf(char, 0); - } - - // If not found in remaining items, check headings from beginning - if (index === -1) { - index = this.headingLevels.indexOf(char, 0); - } - - // If match was found... - if (index > -1) { - this.setFocusToMenuitem(this.menuitemNodes[index]); - } - }, - - // Utilities - getIndexFirstChars: function (startIndex, char) { - for (var i = startIndex; i < this.firstChars.length; i += 1) { - if (char === this.firstChars[i]) { - return i; - } - } - return -1; - }, - // Popup menu methods - openPopup: function () { - this.renderMenu(); - this.menuNode.style.display = 'block'; - this.buttonNode.setAttribute('aria-expanded', 'true'); - }, - - closePopup: function () { - if (this.isOpen()) { - this.buttonNode.setAttribute('aria-expanded', 'false'); - this.menuNode.style.display = 'none'; - } - }, - isOpen: function () { - return this.buttonNode.getAttribute('aria-expanded') === 'true'; - }, - // Menu event handlers - handleFocusin: function () { - this.domNode.classList.add('focus'); - }, - handleFocusout: function () { - this.domNode.classList.remove('focus'); - }, - handleMenuitemAction: function (tgt) { - switch (tgt.getAttribute('data-id')) { - case '': - // this means there were no headings or landmarks in the list - break; - - default: - this.closePopup(); - this.jumpToElement(tgt); - break; - } - }, - handleButtonKeydown: function (event) { - var key = event.key, - flag = false; - switch (key) { - case ' ': - case 'Enter': - case 'ArrowDown': - case 'Down': - this.openPopup(); - this.setFocusToFirstMenuitem(); - flag = true; - break; - case 'Esc': - case 'Escape': - this.closePopup(); - this.buttonNode.focus(); - flag = true; - break; - case 'Up': - case 'ArrowUp': - this.openPopup(); - this.setFocusToLastMenuitem(); - flag = true; - break; - default: - break; - } - if (flag) { - event.stopPropagation(); - event.preventDefault(); - } - }, - handleButtonClick: function (event) { - if (this.isOpen()) { - this.closePopup(); - this.buttonNode.focus(); - } else { - this.openPopup(); - this.setFocusToFirstMenuitem(); - } - event.stopPropagation(); - event.preventDefault(); - }, - handleDocumentKeydown: function (event) { - var key = event.key, - flag = false; - - let altPressed = - this.usesAltKey && - event.altKey && - !event.ctrlKey && - !event.shiftKey && - !event.metaKey; - - let optionPressed = - this.usesOptionKey && - event.altKey && - !event.ctrlKey && - !event.shiftKey && - !event.metaKey; - - if ( - (optionPressed && this.config.optionAccesskey === key) || - (altPressed && this.config.altAccesskey === key) - ) { - this.openPopup(); - this.setFocusToFirstMenuitem(); - flag = true; - } - if (flag) { - event.stopPropagation(); - event.preventDefault(); - } - }, - jumpToElement: function (menuitem) { - var focusNode = false; - var scrollNode = false; - var isLandmark = menuitem.classList.contains('landmark'); - var isSearch = menuitem.classList.contains('jump-to-search'); - var isNav = menuitem.classList.contains('jump-to-nav'); - var node = document.querySelector( - '[data-jump-to-id="' + menuitem.getAttribute('data-id') + '"]' - ); - if (node) { - if (isSearch) { - focusNode = node.querySelector('input'); - } - if (isNav) { - focusNode = node.querySelector('a'); - } - if (focusNode && this.isVisible(focusNode)) { - focusNode.focus(); - focusNode.scrollIntoView({ block: 'nearest' }); - } else { - if (isLandmark) { - scrollNode = node.querySelector(this.contentSelector); - if (scrollNode) { - node = scrollNode; - } - } - node.tabIndex = -1; - node.focus(); - node.scrollIntoView({ block: 'center' }); - } - } - }, - handleMenuitemKeydown: function (event) { - var tgt = event.currentTarget, - key = event.key, - flag = false; - - function isPrintableCharacter(str) { - return str.length === 1 && str.match(/\S/); - } - if (event.ctrlKey || event.altKey || event.metaKey) { - return; - } - if (event.shiftKey) { - if (isPrintableCharacter(key)) { - this.setFocusByFirstCharacter(tgt, key); - flag = true; - } - if (event.key === 'Tab') { - this.buttonNode.focus(); - this.closePopup(); - flag = true; - } - } else { - switch (key) { - case 'Enter': - case ' ': - this.handleMenuitemAction(tgt); - flag = true; - break; - case 'Esc': - case 'Escape': - this.closePopup(); - this.buttonNode.focus(); - flag = true; - break; - case 'Up': - case 'ArrowUp': - this.setFocusToPreviousMenuitem(tgt); - flag = true; - break; - case 'ArrowDown': - case 'Down': - this.setFocusToNextMenuitem(tgt); - flag = true; - break; - case 'Home': - case 'PageUp': - this.setFocusToFirstMenuitem(); - flag = true; - break; - case 'End': - case 'PageDown': - this.setFocusToLastMenuitem(); - flag = true; - break; - case 'Tab': - this.closePopup(); - break; - default: - if (isPrintableCharacter(key)) { - this.setFocusByFirstCharacter(tgt, key); - flag = true; - } - break; - } - } - if (flag) { - event.stopPropagation(); - event.preventDefault(); - } - }, - handleMenuitemClick: function (event) { - this.handleMenuitemAction(event.currentTarget); - event.stopPropagation(); - event.preventDefault(); - }, - handleMenuitemPointerenter: function (event) { - var tgt = event.currentTarget; - tgt.focus(); - }, - handleBackgroundPointerdown: function (event) { - if (!this.domNode.contains(event.target)) { - if (this.isOpen()) { - this.closePopup(); - this.buttonNode.focus(); - } - } - }, - // methods to extract landmarks, headings and ids - normalizeName: function (name) { - if (typeof name === 'string') - return name.replace(/\w\S*/g, function (txt) { - return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); - }); - return ''; - }, - getTextContent: function (elem) { - function getText(e, strings) { - // If text node get the text and return - if (e.nodeType === Node.TEXT_NODE) { - strings.push(e.data); - } else { - // if an element for through all the children elements looking for text - if (e.nodeType === Node.ELEMENT_NODE) { - // check to see if IMG or AREA element and to use ALT content if defined - var tagName = e.tagName.toLowerCase(); - if (tagName === 'img' || tagName === 'area') { - if (e.alt) { - strings.push(e.alt); - } - } else { - var c = e.firstChild; - while (c) { - getText(c, strings); - c = c.nextSibling; - } // end loop - } - } - } - } // end function getStrings - // Create return object - var str = 'Test', - strings = []; - getText(elem, strings); - if (strings.length) str = strings.join(' '); - return str; - }, - getAccessibleName: function (elem) { - var labelledbyIds = elem.getAttribute('aria-labelledby'), - label = elem.getAttribute('aria-label'), - title = elem.getAttribute('title'), - name = ''; - if (labelledbyIds && labelledbyIds.length) { - var str, - strings = [], - ids = labelledbyIds.split(' '); - if (!ids.length) ids = [labelledbyIds]; - for (var i = 0, l = ids.length; i < l; i += 1) { - var e = document.getElementById(ids[i]); - if (e) str = this.getTextContent(e); - if (str && str.length) strings.push(str); - } - name = strings.join(' '); - } else { - if (this.isNotEmptyString(label)) { - name = label; - } else { - if (this.isNotEmptyString(title)) { - name = title; - } - } - } - return name; - }, - isVisible: function (element) { - function isVisibleRec(el) { - if (el.nodeType === 9) - return true; /*IE8 does not support Node.DOCUMENT_NODE*/ - var computedStyle = window.getComputedStyle(el); - var display = computedStyle.getPropertyValue('display'); - var visibility = computedStyle.getPropertyValue('visibility'); - var hidden = el.getAttribute('hidden'); - if (display === 'none' || visibility === 'hidden' || hidden !== null) { - return false; - } - return isVisibleRec(el.parentNode); - } - return isVisibleRec(element); - }, - getHeadings: function (targets) { - var dataId, level; - if (typeof targets !== 'string') { - targets = this.config.headings; - } - var headingElementsArr = []; - if (typeof targets !== 'string' || targets.length === 0) return; - var headings = document.querySelectorAll(targets); - for (var i = 0, len = headings.length; i < len; i += 1) { - var heading = headings[i]; - var role = heading.getAttribute('role'); - if (typeof role === 'string' && role === 'presentation') continue; - if (this.isVisible(heading)) { - if (heading.hasAttribute('data-jump-to-id')) { - dataId = heading.getAttribute('data-jump-to-id'); - } else { - heading.setAttribute('data-jump-to-id', this.jumpToIdIndex); - dataId = this.jumpToIdIndex; - } - level = heading.tagName.substring(1); - var headingItem = {}; - headingItem.dataId = dataId.toString(); - headingItem.class = 'heading'; - headingItem.name = this.getTextContent(heading); - headingItem.ariaLabel = headingItem.name + ', '; - headingItem.ariaLabel += this.config.headingLevelLabel + ' ' + level; - headingItem.tagName = heading.tagName.toLowerCase(); - headingItem.role = 'heading'; - headingItem.level = level; - headingElementsArr.push(headingItem); - this.jumpToIdIndex += 1; - } - } - return headingElementsArr; - }, - getLocalizedLandmarkName: function (tagName, name) { - var n; - switch (tagName) { - case 'aside': - n = this.config.asideLabel; - break; - case 'footer': - n = this.config.footerLabel; - break; - case 'form': - n = this.config.formLabel; - break; - case 'header': - n = this.config.headerLabel; - break; - case 'main': - n = this.config.mainLabel; - break; - case 'nav': - n = this.config.navLabel; - break; - case 'region': - n = this.config.regionLabel; - break; - case 'search': - n = this.config.searchLabel; - break; - // When an ID is used as a selector, assume for main content - default: - n = tagName; - break; - } - if (this.isNotEmptyString(name)) { - n += ': ' + name; - } - return n; - }, - getNestingLevel: function (landmark, landmarks) { - var nestingLevel = 0; - var parentNode = landmark.parentNode; - while (parentNode) { - for (var i = 0; i < landmarks.length; i += 1) { - if (landmarks[i] === parentNode) { - nestingLevel += 1; - // no more than 3 levels of nesting supported - if (nestingLevel === 3) { - return 3; - } - continue; - } - } - parentNode = parentNode.parentNode; - } - return nestingLevel; - }, - getLandmarks: function (targets, allFlag) { - if (typeof allFlag !== 'boolean') { - allFlag = false; - } - if (typeof targets !== 'string') { - targets = this.config.landmarks; - } - var landmarks = document.querySelectorAll(targets); - var mainElements = []; - var searchElements = []; - var navElements = []; - var asideElements = []; - var footerElements = []; - var regionElements = []; - var otherElements = []; - var allLandmarks = []; - var dataId = ''; - for (var i = 0, len = landmarks.length; i < len; i += 1) { - var landmark = landmarks[i]; - // if jumpto is a landmark don't include it in the list - if (landmark === this.domNode) { - continue; - } - var role = landmark.getAttribute('role'); - var tagName = landmark.tagName.toLowerCase(); - if (typeof role === 'string' && role === 'presentation') continue; - if (this.isVisible(landmark)) { - if (!role) role = tagName; - var name = this.getAccessibleName(landmark); - if (typeof name !== 'string') { - name = ''; - } - // normalize tagNames - switch (role) { - case 'banner': - tagName = 'header'; - break; - case 'complementary': - tagName = 'aside'; - break; - case 'contentinfo': - tagName = 'footer'; - break; - case 'form': - tagName = 'form'; - break; - case 'main': - tagName = 'main'; - break; - case 'navigation': - tagName = 'nav'; - break; - case 'section': - tagName = 'region'; - break; - case 'search': - tagName = 'search'; - break; - default: - break; - } - // if using ID for selectQuery give tagName as main - if ( - [ - 'aside', - 'footer', - 'form', - 'header', - 'main', - 'nav', - 'region', - 'search', - ].indexOf(tagName) < 0 - ) { - tagName = 'main'; - } - if (landmark.hasAttribute('aria-roledescription')) { - tagName = landmark - .getAttribute('aria-roledescription') - .trim() - .replace(' ', '-'); - } - if (landmark.hasAttribute('data-jump-to-id')) { - dataId = landmark.getAttribute('data-jump-to-id'); - } else { - landmark.setAttribute('data-jump-to-id', this.jumpToIdIndex); - dataId = this.jumpToIdIndex; - } - var landmarkItem = {}; - landmarkItem.dataId = dataId.toString(); - landmarkItem.class = 'landmark'; - landmarkItem.name = this.getLocalizedLandmarkName(tagName, name); - landmarkItem.tagName = tagName; - landmarkItem.nestingLevel = 0; - if (allFlag) { - landmarkItem.nestingLevel = this.getNestingLevel( - landmark, - landmarks - ); - } - this.jumpToIdIndex += 1; - allLandmarks.push(landmarkItem); - // For sorting landmarks into groups - switch (tagName) { - case 'main': - mainElements.push(landmarkItem); - break; - case 'search': - searchElements.push(landmarkItem); - break; - case 'nav': - navElements.push(landmarkItem); - break; - case 'aside': - asideElements.push(landmarkItem); - break; - case 'footer': - footerElements.push(landmarkItem); - break; - case 'region': - regionElements.push(landmarkItem); - break; - default: - otherElements.push(landmarkItem); - break; - } - } - } - if (allFlag) { - return allLandmarks; - } - return [].concat( - mainElements, - regionElements, - searchElements, - navElements, - asideElements, - footerElements, - otherElements - ); - }, - }; - // Initialize jumpto menu button with onload event - window.addEventListener('load', function () { - JumpTo.init(); - }); -})(); -/*@end @*/ diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js new file mode 100644 index 000000000..c27fa07a6 --- /dev/null +++ b/ARIA/apg/example-index/js/skipto.js @@ -0,0 +1,1436 @@ +/*! skipto - v4.2.0 - 2022-06-16 +* https://github.com/paypal/skipto +* Copyright (c) 2022 Jon Gunderson; Licensed BSD +* Copyright (c) 2021 PayPal Accessibility Team and University of Illinois; Licensed BSD */ + /*@cc_on @*/ +/*@if (@_jscript_version >= es6) @*/ +/* ======================================================================== +* Copyright (c) <2022> (ver 4.2) Jon Gunderson +* Copyright (c) <2021> PayPal and University of Illinois +* All rights reserved. +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of PayPal or any of its subsidiaries or affiliates, nor the name of the University of Illinois, nor the names of any other contributors contributors may be used to endorse or promote products derived from this software without specific prior written permission. +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* ======================================================================== */ + +(function() { + 'use strict'; + const SkipTo = { + skipToId: 'id-skip-to-js-50', + skipToMenuId: 'id-skip-to-menu-50', + domNode: null, + buttonNode: null, + menuNode: null, + menuitemNodes: [], + firstMenuitem: false, + lastMenuitem: false, + firstChars: [], + headingLevels: [], + skipToIdIndex: 1, + showAllLandmarksSelector: 'main, [role=main], [role=search], nav, [role=navigation], section[aria-label], section[aria-labelledby], section[title], [role=region][aria-label], [role=region][aria-labelledby], [role=region][title], form[aria-label], form[aria-labelledby], aside, [role=complementary], body > header, [role=banner], body > footer, [role=contentinfo]', + showAllHeadingsSelector: 'h1, h2, h3, h4, h5, h6', + // Default configuration values + config: { + // Feature switches + enableActions: false, + enableMofN: true, + enableHeadingLevelShortcuts: true, + + // Customization of button and menu + altShortcut: '0', // default shortcut key is the number zero + optionShortcut: 'º', // default shortcut key character associated with option+0 on mac + attachElement: 'header', + displayOption: 'popup', // options: static (default), popup + // container element, use containerClass for custom styling + containerElement: 'div', + containerRole: '', + customClass: '', + + // Button labels and messages + buttonLabel: 'Skip To Content', + altLabel: 'Alt', + optionLabel: 'Option', + buttonShortcut: ' ($modifier+$key)', + altButtonAriaLabel: 'Skip To Content, shortcut Alt plus $key', + optionButtonAriaLabel: 'Skip To Content, shortcut Option plus $key', + + // Menu labels and messages + menuLabel: 'Landmarks and Headings', + landmarkGroupLabel: 'Landmarks', + headingGroupLabel: 'Headings', + mofnGroupLabel: ' ($m of $n)', + headingLevelLabel: 'Heading level', + mainLabel: 'main', + searchLabel: 'search', + navLabel: 'navigation', + regionLabel: 'region', + asideLabel: 'complementary', + footerLabel: 'contentinfo', + headerLabel: 'banner', + formLabel: 'form', + msgNoLandmarksFound: 'No landmarks found', + msgNoHeadingsFound: 'No headings found', + + // Action labels and messages + actionGroupLabel: 'Actions', + actionShowHeadingsHelp: 'Toggles between showing "All" and "Selected" Headings.', + actionShowSelectedHeadingsLabel: 'Show Selected Headings ($num)', + actionShowAllHeadingsLabel: 'Show All Headings ($num)', + actionShowLandmarksHelp: 'Toggles between showing "All" and "Selected" Landmarks.', + actionShowSelectedLandmarksLabel: 'Show Selected Landmarks ($num)', + actionShowAllLandmarksLabel: 'Show All Landmarks ($num)', + + actionShowSelectedHeadingsAriaLabel: 'Show $num selected headings', + actionShowAllHeadingsAriaLabel: 'Show all $num headings', + actionShowSelectedLandmarksAriaLabel: 'Show $num selected landmarks', + actionShowAllLandmarksAriaLabel: 'Show all $num landmarks', + + // Selectors for landmark and headings sections + landmarks: 'main, [role="main"], [role="search"], nav, [role="navigation"], aside, [role="complementary"]', + headings: 'main h1, [role="main"] h1, main h2, [role="main"] h2', + + // Custom CSS position and colors + colorTheme: '', + fontFamily: '', + fontSize: '', + positionLeft: '', + menuTextColor: '', + menuBackgroundColor: '', + menuitemFocusTextColor: '', + menuitemFocusBackgroundColor: '', + focusBorderColor: '', + buttonTextColor: '', + buttonBackgroundColor: '', + }, + colorThemes: { + 'default': { + fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', + fontSize: '14px', + positionLeft: '0px', + menuTextColor: '#000', + menuBackgroundColor: '#def', + menuitemFocusTextColor: '#fff', + menuitemFocusBackgroundColor: '#005a9c', + focusBorderColor: '#005a9c', + buttonTextColor: '#005a9c', + buttonBackgroundColor: '#ddd', + } + }, + defaultCSS: '.skip-to.popup{position:absolute;top:-30em;left:0}.skip-to,.skip-to.popup.focus{position:absolute;top:0;left:$positionLeft;font-family:$fontFamily;font-size:$fontSize}.skip-to.fixed{position:fixed}.skip-to button{position:relative;margin:0;padding:6px 8px 6px 8px;border-width:0 1px 1px 1px;border-style:solid;border-radius:0 0 6px 6px;border-color:$buttonBackgroundColor;color:$menuTextColor;background-color:$buttonBackgroundColor;z-index:100000!important;font-family:$fontFamily;font-size:$fontSize}.skip-to [role=menu]{position:absolute;min-width:17em;display:none;margin:0;padding:.25rem;background-color:$menuBackgroundColor;border-width:2px;border-style:solid;border-color:$focusBorderColor;border-radius:5px;z-index:100000!important;overflow-x:hidden}.skip-to [role=group]{display:grid;grid-auto-rows:min-content;grid-row-gap:1px}.skip-to [role=separator]:first-child{border-radius:5px 5px 0 0}.skip-to [role=menuitem]{padding:3px;width:auto;border-width:0;border-style:solid;color:$menuTextColor;background-color:$menuBackgroundColor;z-index:100000!important;display:grid;overflow-y:auto;grid-template-columns:repeat(6,1.2rem) 1fr;grid-column-gap:2px;font-size:1em}.skip-to [role=menuitem] .label,.skip-to [role=menuitem] .level{font-size:100%;font-weight:400;color:$menuTextColor;display:inline-block;background-color:$menuBackgroundColor;line-height:inherit;display:inline-block}.skip-to [role=menuitem] .level{text-align:right;padding-right:4px}.skip-to [role=menuitem] .label{text-align:left;margin:0;padding:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.skip-to [role=menuitem] .label:first-letter,.skip-to [role=menuitem] .level:first-letter{text-decoration:underline;text-transform:uppercase}.skip-to [role=menuitem].skip-to-h1 .level{grid-column:1}.skip-to [role=menuitem].skip-to-h2 .level{grid-column:2}.skip-to [role=menuitem].skip-to-h3 .level{grid-column:3}.skip-to [role=menuitem].skip-to-h4 .level{grid-column:4}.skip-to [role=menuitem].skip-to-h5 .level{grid-column:5}.skip-to [role=menuitem].skip-to-h6 .level{grid-column:8}.skip-to [role=menuitem].skip-to-h1 .label{grid-column:2/8}.skip-to [role=menuitem].skip-to-h2 .label{grid-column:3/8}.skip-to [role=menuitem].skip-to-h3 .label{grid-column:4/8}.skip-to [role=menuitem].skip-to-h4 .label{grid-column:5/8}.skip-to [role=menuitem].skip-to-h5 .label{grid-column:6/8}.skip-to [role=menuitem].skip-to-h6 .label{grid-column:7/8}.skip-to [role=menuitem].skip-to-h1.no-level .label{grid-column:1/8}.skip-to [role=menuitem].skip-to-h2.no-level .label{grid-column:2/8}.skip-to [role=menuitem].skip-to-h3.no-level .label{grid-column:3/8}.skip-to [role=menuitem].skip-to-h4.no-level .label{grid-column:4/8}.skip-to [role=menuitem].skip-to-h5.no-level .label{grid-column:5/8}.skip-to [role=menuitem].skip-to-h6.no-level .label{grid-column:6/8}.skip-to [role=menuitem].skip-to-nesting-level-1 .nesting{grid-column:1}.skip-to [role=menuitem].skip-to-nesting-level-2 .nesting{grid-column:2}.skip-to [role=menuitem].skip-to-nesting-level-3 .nesting{grid-column:3}.skip-to [role=menuitem].skip-to-nesting-level-0 .label{grid-column:1/8}.skip-to [role=menuitem].skip-to-nesting-level-1 .label{grid-column:2/8}.skip-to [role=menuitem].skip-to-nesting-level-2 .label{grid-column:3/8}.skip-to [role=menuitem].skip-to-nesting-level-3 .label{grid-column:4/8}.skip-to [role=menuitem].action .label,.skip-to [role=menuitem].no-items .label{grid-column:1/8}.skip-to [role=separator]{margin:1px 0 1px 0;padding:3px;display:block;width:auto;font-weight:700;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:$menuTextColor;background-color:$menuBackgroundColor;color:$menuTextColor;z-index:100000!important}.skip-to [role=separator] .mofn{font-weight:400;font-size:85%}.skip-to [role=separator]:first-child{border-radius:5px 5px 0 0}.skip-to [role=menuitem].last{border-radius:0 0 5px 5px}.skip-to.focus{display:block}.skip-to button:focus,.skip-to button:hover{background-color:$menuBackgroundColor;color:$menuTextColor;outline:0}.skip-to button:focus{padding:6px 7px 5px 7px;border-width:0 2px 2px 2px;border-color:$focusBorderColor}.skip-to [role=menuitem]:focus{padding:1px;border-width:2px;border-style:solid;border-color:$focusBorderColor;background-color:$menuitemFocusBackgroundColor;color:$menuitemFocusTextColor;outline:0}.skip-to [role=menuitem]:focus .label,.skip-to [role=menuitem]:focus .level{background-color:$menuitemFocusBackgroundColor;color:$menuitemFocusTextColor}', + + // + // Functions related to configuring the features + // of skipTo + // + isNotEmptyString: function(str) { + return (typeof str === 'string') && str.length && str.trim() && str !== " "; + }, + isEmptyString: function(str) { + return (typeof str !== 'string') || str.length === 0 && !str.trim(); + }, + init: function(config) { + let node; + let buttonVisibleLabel; + let buttonAriaLabel; + + // Check if skipto is already loaded + + if (document.querySelector('style#' + this.skipToId)) { + return; + } + + let attachElement = document.body; + if (config) { + this.setUpConfig(config); + } + if (typeof this.config.attachElement === 'string') { + node = document.querySelector(this.config.attachElement); + if (node && node.nodeType === Node.ELEMENT_NODE) { + attachElement = node; + } + } + this.addCSSColors(); + this.renderStyleElement(this.defaultCSS); + var elem = this.config.containerElement.toLowerCase().trim(); + if (!this.isNotEmptyString(elem)) { + elem = 'div'; + } + this.domNode = document.createElement(elem); + this.domNode.classList.add('skip-to'); + if (this.isNotEmptyString(this.config.customClass)) { + this.domNode.classList.add(this.config.customClass); + } + if (this.isNotEmptyString(this.config.containerRole)) { + this.domNode.setAttribute('role', this.config.containerRole); + } + var displayOption = this.config.displayOption; + if (typeof displayOption === 'string') { + displayOption = displayOption.trim().toLowerCase(); + if (displayOption.length) { + switch (this.config.displayOption) { + case 'fixed': + this.domNode.classList.add('fixed'); + break; + case 'onfocus': // Legacy option + case 'popup': + this.domNode.classList.add('popup'); + break; + default: + break; + } + } + } + + // Place skip to at the beginning of the document + if (attachElement.firstElementChild) { + attachElement.insertBefore(this.domNode, attachElement.firstElementChild); + } else { + attachElement.appendChild(this.domNode); + } + + // Menu button + [buttonVisibleLabel, buttonAriaLabel] = this.getBrowserSpecificShortcut(); + + this.buttonNode = document.createElement('button'); + this.buttonNode.textContent = buttonVisibleLabel; + this.buttonNode.setAttribute('aria-label', buttonAriaLabel); + this.buttonNode.setAttribute('aria-haspopup', 'true'); + this.buttonNode.setAttribute('aria-expanded', 'false'); + this.buttonNode.setAttribute('aria-controls', this.skipToMenuId); + + this.buttonNode.addEventListener('keydown', this.handleButtonKeydown.bind(this)); + this.buttonNode.addEventListener('click', this.handleButtonClick.bind(this)); + + this.domNode.appendChild(this.buttonNode); + + + this.menuNode = document.createElement('div'); + this.menuNode.setAttribute('role', 'menu'); + this.menuNode.setAttribute('aria-busy', 'true'); + this.menuNode.setAttribute('id', this.skipToMenuId); + + this.domNode.appendChild(this.menuNode); + this.domNode.addEventListener('focusin', this.handleFocusin.bind(this)); + this.domNode.addEventListener('focusout', this.handleFocusout.bind(this)); + window.addEventListener('pointerdown', this.handleBackgroundPointerdown.bind(this), true); + + if (this.usesAltKey || this.usesOptionKey) { + document.addEventListener( + 'keydown', + this.handleDocumentKeydown.bind(this) + ); + } + }, + + updateStyle: function(stylePlaceholder, value, defaultValue) { + if (typeof value !== 'string' || value.length === 0) { + value = defaultValue; + } + let index1 = this.defaultCSS.indexOf(stylePlaceholder); + let index2 = index1 + stylePlaceholder.length; + while (index1 >= 0 && index2 < this.defaultCSS.length) { + this.defaultCSS = this.defaultCSS.substring(0, index1) + value + this.defaultCSS.substring(index2); + index1 = this.defaultCSS.indexOf(stylePlaceholder, index2); + index2 = index1 + stylePlaceholder.length; + } + }, + addCSSColors: function() { + let theme = this.colorThemes['default']; + if (typeof this.colorThemes[this.config.colorTheme] === 'object') { + theme = this.colorThemes[this.config.colorTheme]; + } + this.updateStyle('$fontFamily', this.config.fontFamily, theme.fontFamily); + this.updateStyle('$fontSize', this.config.fontSize, theme.fontSize); + + this.updateStyle('$positionLeft', this.config.positionLeft, theme.positionLeft); + + this.updateStyle('$menuTextColor', this.config.menuTextColor, theme.menuTextColor); + this.updateStyle('$menuBackgroundColor', this.config.menuBackgroundColor, theme.menuBackgroundColor); + + this.updateStyle('$menuitemFocusTextColor', this.config.menuitemFocusTextColor, theme.menuitemFocusTextColor); + this.updateStyle('$menuitemFocusBackgroundColor', this.config.menuitemFocusBackgroundColor, theme.menuitemFocusBackgroundColor); + + this.updateStyle('$focusBorderColor', this.config.focusBorderColor, theme.focusBorderColor); + + this.updateStyle('$buttonTextColor', this.config.buttonTextColor, theme.buttonTextColor); + this.updateStyle('$buttonBackgroundColor', this.config.buttonBackgroundColor, theme.buttonBackgroundColor); + }, + + getBrowserSpecificShortcut: function () { + const platform = navigator.platform.toLowerCase(); + const userAgent = navigator.userAgent.toLowerCase(); + + const hasWin = platform.indexOf('win') >= 0; + const hasMac = platform.indexOf('mac') >= 0; + const hasLinux = platform.indexOf('linux') >= 0 || platform.indexOf('bsd') >= 0; + const hasAndroid = userAgent.indexOf('android') >= 0; + + this.usesAltKey = hasWin || (hasLinux && !hasAndroid); + this.usesOptionKey = hasMac; + + let label = this.config.buttonLabel; + let ariaLabel = this.config.buttonLabel; + let buttonShortcut; + + // Check to make sure a shortcut key is defined + if (this.config.altShortcut && this.config.optionShortcut) { + if (this.usesAltKey || this.usesOptionKey) { + buttonShortcut = this.config.buttonShortcut.replace( + '$key', + this.config.altShortcut + ); + } + if (this.usesAltKey) { + buttonShortcut = buttonShortcut.replace( + '$modifier', + this.config.altLabel + ); + label = label + buttonShortcut; + ariaLabel = this.config.altButtonAriaLabel.replace('$key', this.config.altShortcut); + } + + if (this.usesOptionKey) { + buttonShortcut = buttonShortcut.replace( + '$modifier', + this.config.optionLabel + ); + label = label + buttonShortcut; + ariaLabel = this.config.optionButtonAriaLabel.replace('$key', this.config.altShortcut); + } + } + return [label, ariaLabel]; + }, + setUpConfig: function(appConfig) { + let localConfig = this.config, + name, + appConfigSettings = typeof appConfig.settings !== 'undefined' ? appConfig.settings.skipTo : {}; + for (name in appConfigSettings) { + //overwrite values of our local config, based on the external config + if ((typeof localConfig[name] !== 'undefined') && + ((typeof appConfigSettings[name] === 'string') && + (appConfigSettings[name].length > 0 ) || + typeof appConfigSettings[name] === 'boolean') + ) { + localConfig[name] = appConfigSettings[name]; + } else { + throw new Error('** SkipTo Problem with user configuration option "' + name + '".'); + } + } + }, + renderStyleElement: function(cssString) { + const styleNode = document.createElement('style'); + const headNode = document.getElementsByTagName('head')[0]; + const css = document.createTextNode(cssString); + + styleNode.setAttribute("type", "text/css"); + // ID is used to test whether skipto is already loaded + styleNode.id = this.skipToId; + styleNode.appendChild(css); + headNode.appendChild(styleNode); + }, + + // + // Functions related to creating and populating the + // the popup menu + // + + getFirstChar: function(menuitem) { + const label = menuitem.querySelector('.label'); + if (label && this.isNotEmptyString(label.textContent)) { + return label.textContent.trim()[0].toLowerCase(); + } + return ''; + }, + + getHeadingLevelFromAttribute: function(menuitem) { + if (menuitem.hasAttribute('data-level')) { + return menuitem.getAttribute('data-level'); + } + return ''; + }, + + updateKeyboardShortCuts: function () { + let mi; + this.firstChars = []; + this.headingLevels = []; + + for(let i = 0; i < this.menuitemNodes.length; i += 1) { + mi = this.menuitemNodes[i]; + this.firstChars.push(this.getFirstChar(mi)); + this.headingLevels.push(this.getHeadingLevelFromAttribute(mi)); + } + }, + + updateMenuitems: function () { + let menuitemNodes = this.menuNode.querySelectorAll('[role=menuitem'); + + this.menuitemNodes = []; + for(let i = 0; i < menuitemNodes.length; i += 1) { + this.menuitemNodes.push(menuitemNodes[i]); + } + + this.firstMenuitem = this.menuitemNodes[0]; + this.lastMenuitem = this.menuitemNodes[this.menuitemNodes.length-1]; + this.lastMenuitem.classList.add('last'); + this.updateKeyboardShortCuts(); + }, + + renderMenuitemToGroup: function (groupNode, mi) { + let tagNode, tagNodeChild, labelNode, nestingNode; + + let menuitemNode = document.createElement('div'); + menuitemNode.setAttribute('role', 'menuitem'); + menuitemNode.classList.add(mi.class); + if (this.isNotEmptyString(mi.tagName)) { + menuitemNode.classList.add('skip-to-' + mi.tagName.toLowerCase()); + } + menuitemNode.setAttribute('data-id', mi.dataId); + menuitemNode.tabIndex = -1; + if (this.isNotEmptyString(mi.ariaLabel)) { + menuitemNode.setAttribute('aria-label', mi.ariaLabel); + } + + // add event handlers + menuitemNode.addEventListener('keydown', this.handleMenuitemKeydown.bind(this)); + menuitemNode.addEventListener('click', this.handleMenuitemClick.bind(this)); + menuitemNode.addEventListener('pointerenter', this.handleMenuitemPointerenter.bind(this)); + + groupNode.appendChild(menuitemNode); + + // add heading level and label + if (mi.class.includes('heading')) { + if (this.config.enableHeadingLevelShortcuts) { + tagNode = document.createElement('span'); + tagNodeChild = document.createElement('span'); + tagNodeChild.appendChild(document.createTextNode(mi.level)); + tagNode.append(tagNodeChild); + tagNode.appendChild(document.createTextNode(')')); + tagNode.classList.add('level'); + menuitemNode.append(tagNode); + } else { + menuitemNode.classList.add('no-level'); + } + menuitemNode.setAttribute('data-level', mi.level); + if (this.isNotEmptyString(mi.tagName)) { + menuitemNode.classList.add('skip-to-' + mi.tagName); + } + } + + // add nesting level for landmarks + if (mi.class.includes('landmark')) { + menuitemNode.setAttribute('data-nesting', mi.nestingLevel); + menuitemNode.classList.add('skip-to-nesting-level-' + mi.nestingLevel); + + if (mi.nestingLevel > 0 && (mi.nestingLevel > this.lastNestingLevel)) { + nestingNode = document.createElement('span'); + nestingNode.classList.add('nesting'); + menuitemNode.append(nestingNode); + } + this.lastNestingLevel = mi.nestingLevel; + } + + labelNode = document.createElement('span'); + labelNode.appendChild(document.createTextNode(mi.name)); + labelNode.classList.add('label'); + menuitemNode.append(labelNode); + + return menuitemNode; + }, + + renderGroupLabel: function (groupLabelId, title, m, n) { + let titleNode, mofnNode, s; + let groupLabelNode = document.getElementById(groupLabelId); + + titleNode = groupLabelNode.querySelector('.title'); + mofnNode = groupLabelNode.querySelector('.mofn'); + + titleNode.textContent = title; + + if (this.config.enableActions && this.config.enableMofN) { + if ((typeof m === 'number') && (typeof n === 'number')) { + s = this.config.mofnGroupLabel; + s = s.replace('$m', m); + s = s.replace('$n', n); + mofnNode.textContent = s; + } + } + }, + + renderMenuitemGroup: function(groupId, title) { + let labelNode, groupNode, spanNode; + let menuNode = this.menuNode; + if (this.isNotEmptyString(title)) { + labelNode = document.createElement('div'); + labelNode.id = groupId + "-label"; + labelNode.setAttribute('role', 'separator'); + menuNode.appendChild(labelNode); + + spanNode = document.createElement('span'); + spanNode.classList.add('title'); + spanNode.textContent = title; + labelNode.append(spanNode); + + spanNode = document.createElement('span'); + spanNode.classList.add('mofn'); + labelNode.append(spanNode); + + groupNode = document.createElement('div'); + groupNode.setAttribute('role', 'group'); + groupNode.setAttribute('aria-labelledby', labelNode.id); + groupNode.id = groupId; + menuNode.appendChild(groupNode); + menuNode = groupNode; + } + return groupNode; + }, + + removeMenuitemGroup: function(groupId) { + let node = document.getElementById(groupId); + this.menuNode.removeChild(node); + node = document.getElementById(groupId + "-label"); + this.menuNode.removeChild(node); + }, + + renderMenuitemsToGroup: function(groupNode, menuitems, msgNoItemsFound) { + groupNode.innerHTML = ''; + this.lastNestingLevel = 0; + + if (menuitems.length === 0) { + const item = {}; + item.name = msgNoItemsFound; + item.tagName = ''; + item.class = 'no-items'; + item.dataId = ''; + this.renderMenuitemToGroup(groupNode, item); + } + else { + for (var i = 0; i < menuitems.length; i += 1) { + this.renderMenuitemToGroup(groupNode, menuitems[i]); + } + } +}, + + getShowMoreHeadingsSelector: function(option) { + if (option === 'all') { + return this.showAllHeadingsSelector; + } + return this.config.headings; + }, + + getShowMoreHeadingsLabel: function(option, n) { + let label = this.config.actionShowSelectedHeadingsLabel; + if (option === 'all') { + label = this.config.actionShowAllHeadingsLabel; + } + return label.replace('$num', n); + }, + + getShowMoreHeadingsAriaLabel: function(option, n) { + let label = this.config.actionShowSelectedHeadingsAriaLabel; + + if (option === 'all') { + label = this.config.actionShowAllHeadingsAriaLabel; + } + + return label.replace('$num', n); + }, + + renderActionMoreHeadings: function(groupNode) { + let item, menuitemNode; + let option = 'all'; + + let selectedHeadingsLen = this.getHeadings(this.getShowMoreHeadingsSelector('selected')).length; + let allHeadingsLen = this.getHeadings(this.getShowMoreHeadingsSelector('all')).length; + let noAction = selectedHeadingsLen === allHeadingsLen; + let headingsLen = allHeadingsLen; + + if (option !== 'all') { + headingsLen = selectedHeadingsLen; + } + + if (!noAction) { + item = {}; + item.tagName = ''; + item.role = 'menuitem'; + item.class = 'action'; + item.dataId = 'skip-to-more-headings'; + item.name = this.getShowMoreHeadingsLabel(option, headingsLen); + item.ariaLabel = this.getShowMoreHeadingsAriaLabel(option, headingsLen); + + menuitemNode = this.renderMenuitemToGroup(groupNode, item); + menuitemNode.setAttribute('data-show-heading-option', option); + menuitemNode.title = this.config.actionShowHeadingsHelp; + } + return noAction; + }, + + updateHeadingGroupMenuitems: function(option) { + let headings, headingsLen, labelNode, groupNode; + + const selectedHeadings = this.getHeadings(this.getShowMoreHeadingsSelector('selected')); + const selectedHeadingsLen = selectedHeadings.length; + const allHeadings = this.getHeadings(this.getShowMoreHeadingsSelector('all')); + const allHeadingsLen = allHeadings.length; + + // Update list of headings + if ( option === 'all' ) { + headings = allHeadings; + } + else { + headings = selectedHeadings; + } + + this.renderGroupLabel('id-skip-to-group-headings-label', this.config.headingGroupLabel, headings.length, allHeadings.length); + + groupNode = document.getElementById('id-skip-to-group-headings'); + this.renderMenuitemsToGroup(groupNode, headings, this.config.msgNoHeadingsFound); + this.updateMenuitems(); + + // Move focus to first heading menuitem + if (groupNode.firstElementChild) { + groupNode.firstElementChild.focus(); + } + + // Update heading action menuitem + if (option === 'all') { + option = 'selected'; + headingsLen = selectedHeadingsLen; + } else { + option = 'all'; + headingsLen = allHeadingsLen; + } + + const menuitemNode = this.menuNode.querySelector('[data-id=skip-to-more-headings]'); + menuitemNode.setAttribute('data-show-heading-option', option); + menuitemNode.setAttribute('aria-label', this.getShowMoreHeadingsAriaLabel(option, headingsLen)); + + labelNode = menuitemNode.querySelector('span.label'); + labelNode.textContent = this.getShowMoreHeadingsLabel(option, headingsLen); + }, + + getShowMoreLandmarksSelector: function(option) { + if (option === 'all') { + return this.showAllLandmarksSelector; + } + return this.config.landmarks; + }, + + getShowMoreLandmarksLabel: function(option, n) { + let label = this.config.actionShowSelectedLandmarksLabel; + + if (option === 'all') { + label = this.config.actionShowAllLandmarksLabel; + } + return label.replace('$num', n); + }, + + getShowMoreLandmarksAriaLabel: function(option, n) { + let label = this.config.actionShowSelectedLandmarksAriaLabel; + + if (option === 'all') { + label = this.config.actionShowAllLandmarksAriaLabel; + } + + return label.replace('$num', n); + }, + + renderActionMoreLandmarks: function(groupNode) { + let item, menuitemNode; + let option = 'all'; + + const selectedLandmarksLen = this.getLandmarks(this.getShowMoreLandmarksSelector('selected')).length; + const allLandmarksLen = this.getLandmarks(this.getShowMoreLandmarksSelector('all')).length; + const noAction = selectedLandmarksLen === allLandmarksLen; + let landmarksLen = allLandmarksLen; + + if (option !== 'all') { + landmarksLen = selectedLandmarksLen; + } + + if (!noAction) { + item = {}; + item.tagName = ''; + item.role = 'menuitem'; + item.class = 'action'; + item.dataId = 'skip-to-more-landmarks'; + item.name = this.getShowMoreLandmarksLabel(option, landmarksLen); + item.ariaLabel = this.getShowMoreLandmarksAriaLabel(option, landmarksLen); + + menuitemNode = this.renderMenuitemToGroup(groupNode, item); + + menuitemNode.setAttribute('data-show-landmark-option', option); + menuitemNode.title = this.config.actionShowLandmarksHelp; + } + return noAction; + }, + + updateLandmarksGroupMenuitems: function(option) { + let landmarks, landmarksLen, labelNode, groupNode; + + const selectedLandmarks = this.getLandmarks(this.getShowMoreLandmarksSelector('selected')); + const selectedLandmarksLen = selectedLandmarks.length; + const allLandmarks = this.getLandmarks(this.getShowMoreLandmarksSelector('all'), true); + const allLandmarksLen = allLandmarks.length; + + // Update landmark menu items + if ( option === 'all' ) { + landmarks = allLandmarks; + } + else { + landmarks = selectedLandmarks; + } + + this.renderGroupLabel('id-skip-to-group-landmarks-label', this.config.landmarkGroupLabel, landmarks.length, allLandmarks.length); + + groupNode = document.getElementById('id-skip-to-group-landmarks'); + this.renderMenuitemsToGroup(groupNode, landmarks, this.config.msgNoLandmarksFound); + this.updateMenuitems(); + + // Move focus to first landmark menuitem + if (groupNode.firstElementChild) { + groupNode.firstElementChild.focus(); + } + + // Update landmark action menuitem + if (option === 'all') { + option = 'selected'; + landmarksLen = selectedLandmarksLen; + } else { + option = 'all'; + landmarksLen = allLandmarksLen; + } + + const menuitemNode = this.menuNode.querySelector('[data-id=skip-to-more-landmarks]'); + menuitemNode.setAttribute('data-show-landmark-option', option); + menuitemNode.setAttribute('aria-label', this.getShowMoreLandmarksAriaLabel(option, landmarksLen)); + + labelNode = menuitemNode.querySelector('span.label'); + labelNode.textContent = this.getShowMoreLandmarksLabel(option, landmarksLen); + }, + + renderMenu: function() { + let groupNode, + selectedLandmarks, + allLandmarks, + landmarkElements, + selectedHeadings, + allHeadings, + headingElements, + selector, + option, + hasNoAction1, + hasNoAction2; + // remove current menu items from menu + while (this.menuNode.lastElementChild) { + this.menuNode.removeChild(this.menuNode.lastElementChild); + } + + option = 'selected'; + // Create landmarks group + selector = this.getShowMoreLandmarksSelector('all'); + allLandmarks = this.getLandmarks(selector, true); + selector = this.getShowMoreLandmarksSelector('selected'); + selectedLandmarks = this.getLandmarks(selector); + landmarkElements = selectedLandmarks; + + if (option === 'all') { + landmarkElements = allLandmarks; + } + + groupNode = this.renderMenuitemGroup('id-skip-to-group-landmarks', this.config.landmarkGroupLabel); + this.renderMenuitemsToGroup(groupNode, landmarkElements, this.config.msgNoLandmarksFound); + this.renderGroupLabel('id-skip-to-group-landmarks-label', this.config.landmarkGroupLabel, landmarkElements.length, allLandmarks.length); + + // Create headings group + selector = this.getShowMoreHeadingsSelector('all'); + allHeadings = this.getHeadings(selector); + selector = this.getShowMoreHeadingsSelector('selected'); + selectedHeadings = this.getHeadings(selector); + headingElements = selectedHeadings; + + if (option === 'all') { + headingElements = allHeadings; + } + + groupNode = this.renderMenuitemGroup('id-skip-to-group-headings', this.config.headingGroupLabel); + this.renderMenuitemsToGroup(groupNode, headingElements, this.config.msgNoHeadingsFound); + this.renderGroupLabel('id-skip-to-group-headings-label', this.config.headingGroupLabel, headingElements.length, allHeadings.length); + + // Create actions, if enabled + if (this.config.enableActions) { + groupNode = this.renderMenuitemGroup('id-skip-to-group-actions', this.config.actionGroupLabel); + hasNoAction1 = this.renderActionMoreLandmarks(groupNode); + hasNoAction2 = this.renderActionMoreHeadings(groupNode); + // Remove action label if no actions are available + if (hasNoAction1 && hasNoAction2) { + this.removeMenuitemGroup('id-skip-to-group-actions'); + } + } + + // Update list of menuitems + this.updateMenuitems(); + }, + + // + // Menu scripting event functions and utilities + // + + setFocusToMenuitem: function(menuitem) { + if (menuitem) { + menuitem.focus(); + } + }, + + setFocusToFirstMenuitem: function() { + this.setFocusToMenuitem(this.firstMenuitem); + }, + + setFocusToLastMenuitem: function() { + this.setFocusToMenuitem(this.lastMenuitem); + }, + + setFocusToPreviousMenuitem: function(menuitem) { + let newMenuitem, index; + if (menuitem === this.firstMenuitem) { + newMenuitem = this.lastMenuitem; + } else { + index = this.menuitemNodes.indexOf(menuitem); + newMenuitem = this.menuitemNodes[index - 1]; + } + this.setFocusToMenuitem(newMenuitem); + return newMenuitem; + }, + + setFocusToNextMenuitem: function(menuitem) { + let newMenuitem, index; + if (menuitem === this.lastMenuitem) { + newMenuitem = this.firstMenuitem; + } else { + index = this.menuitemNodes.indexOf(menuitem); + newMenuitem = this.menuitemNodes[index + 1]; + } + this.setFocusToMenuitem(newMenuitem); + return newMenuitem; + }, + + setFocusByFirstCharacter: function(menuitem, char) { + let start, index; + if (char.length > 1) { + return; + } + char = char.toLowerCase(); + + // Get start index for search based on position of currentItem + start = this.menuitemNodes.indexOf(menuitem) + 1; + if (start >= this.menuitemNodes.length) { + start = 0; + } + + // Check remaining items in the menu + index = this.firstChars.indexOf(char, start); + + // If not found in remaining items, check headings + if (index === -1) { + index = this.headingLevels.indexOf(char, start); + } + + // If not found in remaining items, check from beginning + if (index === -1) { + index = this.firstChars.indexOf(char, 0); + } + + // If not found in remaining items, check headings from beginning + if (index === -1) { + index = this.headingLevels.indexOf(char, 0); + } + + // If match was found... + if (index > -1) { + this.setFocusToMenuitem(this.menuitemNodes[index]); + } + }, + + // Utilities + getIndexFirstChars: function(startIndex, char) { + for (let i = startIndex; i < this.firstChars.length; i += 1) { + if (char === this.firstChars[i]) { + return i; + } + } + return -1; + }, + // Popup menu methods + openPopup: function() { + this.menuNode.setAttribute('aria-busy', 'true'); + const h = (80 * window.innerHeight) / 100; + this.menuNode.style.maxHeight = h + 'px'; + this.renderMenu(); + this.menuNode.style.display = 'block'; + this.menuNode.removeAttribute('aria-busy'); + this.buttonNode.setAttribute('aria-expanded', 'true'); + }, + + closePopup: function() { + if (this.isOpen()) { + this.buttonNode.setAttribute('aria-expanded', 'false'); + this.menuNode.style.display = 'none'; + } + }, + isOpen: function() { + return this.buttonNode.getAttribute('aria-expanded') === 'true'; + }, + // Menu event handlers + handleFocusin: function() { + this.domNode.classList.add('focus'); + }, + handleFocusout: function() { + this.domNode.classList.remove('focus'); + }, + handleButtonKeydown: function(event) { + let key = event.key, + flag = false; + switch (key) { + case ' ': + case 'Enter': + case 'ArrowDown': + case 'Down': + this.openPopup(); + this.setFocusToFirstMenuitem(); + flag = true; + break; + case 'Esc': + case 'Escape': + this.closePopup(); + this.buttonNode.focus(); + flag = true; + break; + case 'Up': + case 'ArrowUp': + this.openPopup(); + this.setFocusToLastMenuitem(); + flag = true; + break; + default: + break; + } + if (flag) { + event.stopPropagation(); + event.preventDefault(); + } + }, + handleButtonClick: function(event) { + if (this.isOpen()) { + this.closePopup(); + this.buttonNode.focus(); + } else { + this.openPopup(); + this.setFocusToFirstMenuitem(); + } + event.stopPropagation(); + event.preventDefault(); + }, + handleDocumentKeydown: function (event) { + let key = event.key, + flag = false; + + let altPressed = + this.usesAltKey && + event.altKey && + !event.ctrlKey && + !event.shiftKey && + !event.metaKey; + + let optionPressed = + this.usesOptionKey && + event.altKey && + !event.ctrlKey && + !event.shiftKey && + !event.metaKey; + + if ( + (optionPressed && this.config.optionShortcut === key) || + (altPressed && this.config.altShortcut === key) + ) { + this.openPopup(); + this.setFocusToFirstMenuitem(); + flag = true; + } + if (flag) { + event.stopPropagation(); + event.preventDefault(); + } + }, + skipToElement: function(menuitem) { + + const isVisible = this.isVisible; + let focusNode = false; + let scrollNode = false; + let elem; + + function findVisibleElement(e, selectors) { + if (e) { + for (let j = 0; j < selectors.length; j += 1) { + const elems = e.querySelectorAll(selectors[j]); + for(let i = 0; i < elems.length; i +=1) { + if (isVisible(elems[i])) { + return elems[i]; + } + } + } + } + return e; + } + + const searchSelectors = ['input', 'button', 'input[type=button]', 'input[type=submit]', 'a']; + const navigationSelectors = ['a', 'input', 'button', 'input[type=button]', 'input[type=submit]']; + const landmarkSelectors = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'section', 'article', 'p', 'li', 'a']; + + const isLandmark = menuitem.classList.contains('landmark'); + const isSearch = menuitem.classList.contains('skip-to-search'); + const isNav = menuitem.classList.contains('skip-to-nav'); + + elem = document.querySelector('[data-skip-to-id="' + menuitem.getAttribute('data-id') + '"]'); + + if (elem) { + if (isSearch) { + focusNode = findVisibleElement(elem, searchSelectors); + } + if (isNav) { + focusNode = findVisibleElement(elem, navigationSelectors); + } + if (focusNode && this.isVisible(focusNode)) { + focusNode.focus(); + focusNode.scrollIntoView({block: 'nearest'}); + } + else { + if (isLandmark) { + scrollNode = findVisibleElement(elem, landmarkSelectors); + if (scrollNode) { + elem = scrollNode; + } + } + elem.tabIndex = -1; + elem.focus(); + elem.scrollIntoView({block: 'center'}); + } + } + }, + handleMenuitemAction: function(tgt) { + let option; + switch (tgt.getAttribute('data-id')) { + case '': + // this means there were no headings or landmarks in the list + break; + + case 'skip-to-more-headings': + option = tgt.getAttribute('data-show-heading-option'); + this.updateHeadingGroupMenuitems(option); + break; + + case 'skip-to-more-landmarks': + option = tgt.getAttribute('data-show-landmark-option'); + this.updateLandmarksGroupMenuitems(option); + break; + + default: + this.closePopup(); + this.skipToElement(tgt); + break; + } + }, + handleMenuitemKeydown: function(event) { + let tgt = event.currentTarget, + key = event.key, + flag = false; + + function isPrintableCharacter(str) { + return str.length === 1 && str.match(/\S/); + } + if (event.ctrlKey || event.altKey || event.metaKey) { + return; + } + if (event.shiftKey) { + if (isPrintableCharacter(key)) { + this.setFocusByFirstCharacter(tgt, key); + flag = true; + } + if (event.key === 'Tab') { + this.buttonNode.focus(); + this.closePopup(); + flag = true; + } + } else { + switch (key) { + case 'Enter': + case ' ': + this.handleMenuitemAction(tgt); + flag = true; + break; + case 'Esc': + case 'Escape': + this.closePopup(); + this.buttonNode.focus(); + flag = true; + break; + case 'Up': + case 'ArrowUp': + this.setFocusToPreviousMenuitem(tgt); + flag = true; + break; + case 'ArrowDown': + case 'Down': + this.setFocusToNextMenuitem(tgt); + flag = true; + break; + case 'Home': + case 'PageUp': + this.setFocusToFirstMenuitem(); + flag = true; + break; + case 'End': + case 'PageDown': + this.setFocusToLastMenuitem(); + flag = true; + break; + case 'Tab': + this.closePopup(); + break; + default: + if (isPrintableCharacter(key)) { + this.setFocusByFirstCharacter(tgt, key); + flag = true; + } + break; + } + } + if (flag) { + event.stopPropagation(); + event.preventDefault(); + } + }, + handleMenuitemClick: function(event) { + this.handleMenuitemAction(event.currentTarget); + event.stopPropagation(); + event.preventDefault(); + }, + handleMenuitemPointerenter: function(event) { + let tgt = event.currentTarget; + tgt.focus(); + }, + handleBackgroundPointerdown: function(event) { + if (!this.domNode.contains(event.target)) { + if (this.isOpen()) { + this.closePopup(); + this.buttonNode.focus(); + } + } + }, + // methods to extract landmarks, headings and ids + normalizeName: function(name) { + if (typeof name === 'string') return name.replace(/\w\S*/g, function(txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); + return ""; + }, + getTextContent: function(elem) { + function getText(e, strings) { + // If text node get the text and return + if (e.nodeType === Node.TEXT_NODE) { + strings.push(e.data); + } else { + // if an element for through all the children elements looking for text + if (e.nodeType === Node.ELEMENT_NODE) { + // check to see if IMG or AREA element and to use ALT content if defined + let tagName = e.tagName.toLowerCase(); + if ((tagName === 'img') || (tagName === 'area')) { + if (e.alt) { + strings.push(e.alt); + } + } else { + let c = e.firstChild; + while (c) { + getText(c, strings); + c = c.nextSibling; + } // end loop + } + } + } + } // end function getStrings + // Create return object + let str = "Test", + strings = []; + getText(elem, strings); + if (strings.length) str = strings.join(" "); + return str; + }, + getAccessibleName: function(elem) { + let labelledbyIds = elem.getAttribute('aria-labelledby'), + label = elem.getAttribute('aria-label'), + title = elem.getAttribute('title'), + name = ""; + if (labelledbyIds && labelledbyIds.length) { + let str, + strings = [], + ids = labelledbyIds.split(' '); + if (!ids.length) ids = [labelledbyIds]; + for (let i = 0, l = ids.length; i < l; i += 1) { + let e = document.getElementById(ids[i]); + if (e) str = this.getTextContent(e); + if (str && str.length) strings.push(str); + } + name = strings.join(" "); + } else { + if (this.isNotEmptyString(label)) { + name = label; + } else { + if (this.isNotEmptyString(title)) { + name = title; + } + } + } + return name; + }, + isVisible: function(element) { + function isVisibleRec(el) { + if (el.parentNode.nodeType !== 1 || + (el.parentNode.tagName === 'BODY')) { + return true; + } + const computedStyle = window.getComputedStyle(el); + const display = computedStyle.getPropertyValue('display'); + const visibility = computedStyle.getPropertyValue('visibility'); + const hidden = el.getAttribute('hidden'); + if ((display === 'none') || + (visibility === 'hidden') || + (hidden !== null)) { + return false; + } + const isVis = isVisibleRec(el.parentNode); + return isVis; + } + + return isVisibleRec(element); + }, + getHeadings: function(targets) { + let dataId, level; + if (typeof targets !== 'string') { + targets = this.config.headings; + } + let headingElementsArr = []; + if (typeof targets !== 'string' || targets.length === 0) return; + const headings = document.querySelectorAll(targets); + for (let i = 0, len = headings.length; i < len; i += 1) { + let heading = headings[i]; + let role = heading.getAttribute('role'); + if ((typeof role === 'string') && (role === 'presentation')) continue; + if (this.isVisible(heading) && this.isNotEmptyString(heading.innerHTML)) { + if (heading.hasAttribute('data-skip-to-id')) { + dataId = heading.getAttribute('data-skip-to-id'); + } else { + heading.setAttribute('data-skip-to-id', this.skipToIdIndex); + dataId = this.skipToIdIndex; + } + level = heading.tagName.substring(1); + const headingItem = {}; + headingItem.dataId = dataId.toString(); + headingItem.class = 'heading'; + headingItem.name = this.getTextContent(heading); + headingItem.ariaLabel = headingItem.name + ', '; + headingItem.ariaLabel += this.config.headingLevelLabel + ' ' + level; + headingItem.tagName = heading.tagName.toLowerCase(); + headingItem.role = 'heading'; + headingItem.level = level; + headingElementsArr.push(headingItem); + this.skipToIdIndex += 1; + } + } + return headingElementsArr; + }, + getLocalizedLandmarkName: function(tagName, name) { + let n; + switch (tagName) { + case 'aside': + n = this.config.asideLabel; + break; + case 'footer': + n = this.config.footerLabel; + break; + case 'form': + n = this.config.formLabel; + break; + case 'header': + n = this.config.headerLabel; + break; + case 'main': + n = this.config.mainLabel; + break; + case 'nav': + n = this.config.navLabel; + break; + case 'section': + case 'region': + n = this.config.regionLabel; + break; + case 'search': + n = this.config.searchLabel; + break; + // When an ID is used as a selector, assume for main content + default: + n = tagName; + break; + } + if (this.isNotEmptyString(name)) { + n += ': ' + name; + } + return n; + }, + getNestingLevel: function(landmark, landmarks) { + let nestingLevel = 0; + let parentNode = landmark.parentNode; + while (parentNode) { + for (let i = 0; i < landmarks.length; i += 1) { + if (landmarks[i] === parentNode) { + nestingLevel += 1; + // no more than 3 levels of nesting supported + if (nestingLevel === 3) { + return 3; + } + continue; + } + } + parentNode = parentNode.parentNode; + } + return nestingLevel; + }, + getLandmarks: function(targets, allFlag) { + if (typeof allFlag !== 'boolean') { + allFlag = false; + } + if (typeof targets !== 'string') { + targets = this.config.landmarks; + } + let landmarks = document.querySelectorAll(targets); + let mainElements = []; + let searchElements = []; + let navElements = []; + let asideElements = []; + let footerElements = []; + let regionElements = []; + let otherElements = []; + let allLandmarks = []; + let dataId = ''; + for (let i = 0, len = landmarks.length; i < len; i += 1) { + let landmark = landmarks[i]; + // if skipto is a landmark don't include it in the list + if (landmark === this.domNode) { + continue; + } + let role = landmark.getAttribute('role'); + let tagName = landmark.tagName.toLowerCase(); + if ((typeof role === 'string') && (role === 'presentation')) continue; + if (this.isVisible(landmark)) { + if (!role) role = tagName; + let name = this.getAccessibleName(landmark); + if (typeof name !== 'string') { + name = ''; + } + // normalize tagNames + switch (role) { + case 'banner': + tagName = 'header'; + break; + case 'complementary': + tagName = 'aside'; + break; + case 'contentinfo': + tagName = 'footer'; + break; + case 'form': + tagName = 'form'; + break; + case 'main': + tagName = 'main'; + break; + case 'navigation': + tagName = 'nav'; + break; + case 'region': + tagName = 'section'; + break; + case 'search': + tagName = 'search'; + break; + default: + break; + } + // if using ID for selectQuery give tagName as main + if (['aside', 'footer', 'form', 'header', 'main', 'nav', 'section', 'search'].indexOf(tagName) < 0) { + tagName = 'main'; + } + if (landmark.hasAttribute('aria-roledescription')) { + tagName = landmark.getAttribute('aria-roledescription').trim().replace(' ', '-'); + } + if (landmark.hasAttribute('data-skip-to-id')) { + dataId = landmark.getAttribute('data-skip-to-id'); + } else { + landmark.setAttribute('data-skip-to-id', this.skipToIdIndex); + dataId = this.skipToIdIndex; + } + const landmarkItem = {}; + landmarkItem.dataId = dataId.toString(); + landmarkItem.class = 'landmark'; + landmarkItem.hasName = name.length > 0; + landmarkItem.name = this.getLocalizedLandmarkName(tagName, name); + landmarkItem.tagName = tagName; + landmarkItem.nestingLevel = 0; + if (allFlag) { + landmarkItem.nestingLevel = this.getNestingLevel(landmark, landmarks); + } + this.skipToIdIndex += 1; + allLandmarks.push(landmarkItem); + + // For sorting landmarks into groups + switch (tagName) { + case 'main': + mainElements.push(landmarkItem); + break; + case 'search': + searchElements.push(landmarkItem); + break; + case 'nav': + navElements.push(landmarkItem); + break; + case 'aside': + asideElements.push(landmarkItem); + break; + case 'footer': + footerElements.push(landmarkItem); + break; + case 'section': + // Regions must have accessible name to be included + if (landmarkItem.hasName) { + regionElements.push(landmarkItem); + } + break; + default: + otherElements.push(landmarkItem); + break; + } + } + } + if (allFlag) { + return allLandmarks; + } + return [].concat(mainElements, searchElements, navElements, asideElements, regionElements, footerElements, otherElements); + } + }; + // Initialize skipto menu button with onload event + window.addEventListener('load', function() { + SkipTo.init(window.SkipToConfig || + ((typeof window.Joomla === 'object' && typeof window.Joomla.getOptions === 'function') ? window.Joomla.getOptions('skipto-settings', {}) : {}) + ); + }); +})(); +/*@end @*/ diff --git a/ARIA/apg/example-index/link/link.md b/ARIA/apg/example-index/link/link.md index 2a7af2328..1f71635c3 100644 --- a/ARIA/apg/example-index/link/link.md +++ b/ARIA/apg/example-index/link/link.md @@ -269,5 +269,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/listbox/listbox-collapsible.md b/ARIA/apg/example-index/listbox/listbox-collapsible.md index 8a11a2def..15a25c70d 100644 --- a/ARIA/apg/example-index/listbox/listbox-collapsible.md +++ b/ARIA/apg/example-index/listbox/listbox-collapsible.md @@ -376,5 +376,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/listbox/listbox-grouped.md b/ARIA/apg/example-index/listbox/listbox-grouped.md index dce817838..1ec47cd7e 100644 --- a/ARIA/apg/example-index/listbox/listbox-grouped.md +++ b/ARIA/apg/example-index/listbox/listbox-grouped.md @@ -302,5 +302,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/listbox/listbox-rearrangeable.md b/ARIA/apg/example-index/listbox/listbox-rearrangeable.md index 2052c0bec..8a07c1352 100644 --- a/ARIA/apg/example-index/listbox/listbox-rearrangeable.md +++ b/ARIA/apg/example-index/listbox/listbox-rearrangeable.md @@ -497,5 +497,5 @@ while in the second example, they may select multiple options before activating diff --git a/ARIA/apg/example-index/listbox/listbox-scrollable.md b/ARIA/apg/example-index/listbox/listbox-scrollable.md index 36c3bbdfa..a0c7ba2d4 100644 --- a/ARIA/apg/example-index/listbox/listbox-scrollable.md +++ b/ARIA/apg/example-index/listbox/listbox-scrollable.md @@ -297,5 +297,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/menu-button/menu-button-actions-active-descendant.md b/ARIA/apg/example-index/menu-button/menu-button-actions-active-descendant.md index 3ee47a604..5e0e4aa74 100644 --- a/ARIA/apg/example-index/menu-button/menu-button-actions-active-descendant.md +++ b/ARIA/apg/example-index/menu-button/menu-button-actions-active-descendant.md @@ -419,5 +419,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/menu-button/menu-button-actions.md b/ARIA/apg/example-index/menu-button/menu-button-actions.md index 0580a0269..d1e52cfc0 100644 --- a/ARIA/apg/example-index/menu-button/menu-button-actions.md +++ b/ARIA/apg/example-index/menu-button/menu-button-actions.md @@ -395,5 +395,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/menu-button/menu-button-links.md b/ARIA/apg/example-index/menu-button/menu-button-links.md index 835b34c1d..9fc8470b6 100644 --- a/ARIA/apg/example-index/menu-button/menu-button-links.md +++ b/ARIA/apg/example-index/menu-button/menu-button-links.md @@ -428,5 +428,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/menubar/menubar-editor.md b/ARIA/apg/example-index/menubar/menubar-editor.md index 93a423611..afa2167fc 100644 --- a/ARIA/apg/example-index/menubar/menubar-editor.md +++ b/ARIA/apg/example-index/menubar/menubar-editor.md @@ -926,5 +926,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/menubar/menubar-navigation.md b/ARIA/apg/example-index/menubar/menubar-navigation.md index b09ac774c..03eea8d57 100644 --- a/ARIA/apg/example-index/menubar/menubar-navigation.md +++ b/ARIA/apg/example-index/menubar/menubar-navigation.md @@ -914,5 +914,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/meter/meter.md b/ARIA/apg/example-index/meter/meter.md index 5d7ac1d3c..2647929c3 100644 --- a/ARIA/apg/example-index/meter/meter.md +++ b/ARIA/apg/example-index/meter/meter.md @@ -207,5 +207,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/radio/radio-activedescendant.md b/ARIA/apg/example-index/radio/radio-activedescendant.md index 0e857d863..451b23e77 100644 --- a/ARIA/apg/example-index/radio/radio-activedescendant.md +++ b/ARIA/apg/example-index/radio/radio-activedescendant.md @@ -356,5 +356,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/radio/radio-rating.md b/ARIA/apg/example-index/radio/radio-rating.md index 874410e00..1327b5f91 100644 --- a/ARIA/apg/example-index/radio/radio-rating.md +++ b/ARIA/apg/example-index/radio/radio-rating.md @@ -353,5 +353,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/radio/radio.md b/ARIA/apg/example-index/radio/radio.md index 4d7a13823..0d8469e25 100644 --- a/ARIA/apg/example-index/radio/radio.md +++ b/ARIA/apg/example-index/radio/radio.md @@ -331,5 +331,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/slider/slider-color-viewer.md b/ARIA/apg/example-index/slider/slider-color-viewer.md index 755ec728e..3a7d479d4 100644 --- a/ARIA/apg/example-index/slider/slider-color-viewer.md +++ b/ARIA/apg/example-index/slider/slider-color-viewer.md @@ -382,5 +382,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/slider/slider-multithumb.md b/ARIA/apg/example-index/slider/slider-multithumb.md index 43828b3ab..85f72e365 100644 --- a/ARIA/apg/example-index/slider/slider-multithumb.md +++ b/ARIA/apg/example-index/slider/slider-multithumb.md @@ -338,5 +338,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/slider/slider-rating.md b/ARIA/apg/example-index/slider/slider-rating.md index 6e5ba742a..9c441ea8d 100644 --- a/ARIA/apg/example-index/slider/slider-rating.md +++ b/ARIA/apg/example-index/slider/slider-rating.md @@ -358,5 +358,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/slider/slider-seek.md b/ARIA/apg/example-index/slider/slider-seek.md index f277d8841..add06358d 100644 --- a/ARIA/apg/example-index/slider/slider-seek.md +++ b/ARIA/apg/example-index/slider/slider-seek.md @@ -391,5 +391,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/slider/slider-temperature.md b/ARIA/apg/example-index/slider/slider-temperature.md index afbc5f48b..4ebdb7d2f 100644 --- a/ARIA/apg/example-index/slider/slider-temperature.md +++ b/ARIA/apg/example-index/slider/slider-temperature.md @@ -368,5 +368,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/spinbutton/datepicker-spinbuttons.md b/ARIA/apg/example-index/spinbutton/datepicker-spinbuttons.md index 564a5451c..f8b6bd56e 100644 --- a/ARIA/apg/example-index/spinbutton/datepicker-spinbuttons.md +++ b/ARIA/apg/example-index/spinbutton/datepicker-spinbuttons.md @@ -429,5 +429,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/switch/switch-button.md b/ARIA/apg/example-index/switch/switch-button.md index 291acba8b..3919f8561 100644 --- a/ARIA/apg/example-index/switch/switch-button.md +++ b/ARIA/apg/example-index/switch/switch-button.md @@ -299,5 +299,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/switch/switch-checkbox.md b/ARIA/apg/example-index/switch/switch-checkbox.md index 39576533b..bcabffc87 100644 --- a/ARIA/apg/example-index/switch/switch-checkbox.md +++ b/ARIA/apg/example-index/switch/switch-checkbox.md @@ -261,5 +261,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/switch/switch.md b/ARIA/apg/example-index/switch/switch.md index 30cf32f9c..b626f0f5d 100644 --- a/ARIA/apg/example-index/switch/switch.md +++ b/ARIA/apg/example-index/switch/switch.md @@ -261,5 +261,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/table/sortable-table.md b/ARIA/apg/example-index/table/sortable-table.md index 8afa8817d..01b832bf9 100644 --- a/ARIA/apg/example-index/table/sortable-table.md +++ b/ARIA/apg/example-index/table/sortable-table.md @@ -276,5 +276,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/table/table.md b/ARIA/apg/example-index/table/table.md index 51c2fcd53..f2543f74f 100644 --- a/ARIA/apg/example-index/table/table.md +++ b/ARIA/apg/example-index/table/table.md @@ -244,5 +244,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/tabs/tabs-automatic.md b/ARIA/apg/example-index/tabs/tabs-automatic.md index 830d11678..d07c880b8 100644 --- a/ARIA/apg/example-index/tabs/tabs-automatic.md +++ b/ARIA/apg/example-index/tabs/tabs-automatic.md @@ -438,5 +438,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/tabs/tabs-manual.md b/ARIA/apg/example-index/tabs/tabs-manual.md index 6d75f3576..4f68f2c57 100644 --- a/ARIA/apg/example-index/tabs/tabs-manual.md +++ b/ARIA/apg/example-index/tabs/tabs-manual.md @@ -430,5 +430,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/toolbar/toolbar.md b/ARIA/apg/example-index/toolbar/toolbar.md index b034a9ce7..a6b2c1a4f 100644 --- a/ARIA/apg/example-index/toolbar/toolbar.md +++ b/ARIA/apg/example-index/toolbar/toolbar.md @@ -1047,5 +1047,5 @@ But, in a larger sense, we can not dedicate, we can not consecrate, we can not h diff --git a/ARIA/apg/example-index/treegrid/treegrid-1.md b/ARIA/apg/example-index/treegrid/treegrid-1.md index c7a240fd4..05b84fef3 100644 --- a/ARIA/apg/example-index/treegrid/treegrid-1.md +++ b/ARIA/apg/example-index/treegrid/treegrid-1.md @@ -546,5 +546,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/treeview/treeview-1/treeview-1a.md b/ARIA/apg/example-index/treeview/treeview-1/treeview-1a.md index 1cf927791..4a2cde317 100644 --- a/ARIA/apg/example-index/treeview/treeview-1/treeview-1a.md +++ b/ARIA/apg/example-index/treeview/treeview-1/treeview-1a.md @@ -612,5 +612,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/treeview/treeview-1/treeview-1b.md b/ARIA/apg/example-index/treeview/treeview-1/treeview-1b.md index c3648fe2e..a74f04ba0 100644 --- a/ARIA/apg/example-index/treeview/treeview-1/treeview-1b.md +++ b/ARIA/apg/example-index/treeview/treeview-1/treeview-1b.md @@ -836,5 +836,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/ARIA/apg/example-index/treeview/treeview-navigation.md b/ARIA/apg/example-index/treeview/treeview-navigation.md index 98bc9091e..f972b90be 100644 --- a/ARIA/apg/example-index/treeview/treeview-navigation.md +++ b/ARIA/apg/example-index/treeview/treeview-navigation.md @@ -796,5 +796,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/about.md b/content/about.md index 5ff345e90..9ca20b31d 100644 --- a/content/about.md +++ b/content/about.md @@ -233,5 +233,5 @@ lang: en diff --git a/content/index.md b/content/index.md index 1f5f69fb3..826cacfc5 100644 --- a/content/index.md +++ b/content/index.md @@ -281,5 +281,5 @@ lang: en diff --git a/content/pattern-accordion.md b/content/pattern-accordion.md index a4f74f176..3559b99d5 100644 --- a/content/pattern-accordion.md +++ b/content/pattern-accordion.md @@ -144,5 +144,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-alert.md b/content/pattern-alert.md index a92d92624..883de3aab 100644 --- a/content/pattern-alert.md +++ b/content/pattern-alert.md @@ -80,5 +80,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-alertdialog.md b/content/pattern-alertdialog.md index 30f0d97d2..493cee83d 100644 --- a/content/pattern-alertdialog.md +++ b/content/pattern-alertdialog.md @@ -94,5 +94,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-breadcrumb.md b/content/pattern-breadcrumb.md index c2caf3f24..543cad79a 100644 --- a/content/pattern-breadcrumb.md +++ b/content/pattern-breadcrumb.md @@ -73,5 +73,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-button.md b/content/pattern-button.md index 1971c2db2..ab34d0c2f 100644 --- a/content/pattern-button.md +++ b/content/pattern-button.md @@ -137,5 +137,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-carousel.md b/content/pattern-carousel.md index a89d085cc..3190c1be6 100644 --- a/content/pattern-carousel.md +++ b/content/pattern-carousel.md @@ -206,5 +206,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-checkbox.md b/content/pattern-checkbox.md index 9c7b3ba44..74fead4c8 100644 --- a/content/pattern-checkbox.md +++ b/content/pattern-checkbox.md @@ -107,5 +107,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-combobox.md b/content/pattern-combobox.md index 69152dbd1..d1d1d7961 100644 --- a/content/pattern-combobox.md +++ b/content/pattern-combobox.md @@ -412,5 +412,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-dialogmodal.md b/content/pattern-dialogmodal.md index 59db252e5..eca61af0c 100644 --- a/content/pattern-dialogmodal.md +++ b/content/pattern-dialogmodal.md @@ -177,5 +177,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-disclosure.md b/content/pattern-disclosure.md index e356924f1..0c350c4a8 100644 --- a/content/pattern-disclosure.md +++ b/content/pattern-disclosure.md @@ -90,5 +90,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-feed.md b/content/pattern-feed.md index d1dead84f..0fc368a98 100644 --- a/content/pattern-feed.md +++ b/content/pattern-feed.md @@ -176,5 +176,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-grid.md b/content/pattern-grid.md index 093e2b8a9..ee9eca600 100644 --- a/content/pattern-grid.md +++ b/content/pattern-grid.md @@ -387,5 +387,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-link.md b/content/pattern-link.md index feb0e0610..1cf9c42b4 100644 --- a/content/pattern-link.md +++ b/content/pattern-link.md @@ -78,5 +78,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-listbox.md b/content/pattern-listbox.md index 1a17c29ef..c6c146350 100644 --- a/content/pattern-listbox.md +++ b/content/pattern-listbox.md @@ -246,5 +246,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-menu.md b/content/pattern-menu.md index 164778ece..4fa35163b 100644 --- a/content/pattern-menu.md +++ b/content/pattern-menu.md @@ -248,5 +248,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-menubutton.md b/content/pattern-menubutton.md index 9da3389d9..c9cf2bb92 100644 --- a/content/pattern-menubutton.md +++ b/content/pattern-menubutton.md @@ -95,5 +95,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-meter.md b/content/pattern-meter.md index e2eac17f5..a7f05a308 100644 --- a/content/pattern-meter.md +++ b/content/pattern-meter.md @@ -83,5 +83,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-radiobutton.md b/content/pattern-radiobutton.md index 39c50320c..ce8e5c1d4 100644 --- a/content/pattern-radiobutton.md +++ b/content/pattern-radiobutton.md @@ -181,5 +181,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-slider.md b/content/pattern-slider.md index e4b7bfbdb..3423cac1c 100644 --- a/content/pattern-slider.md +++ b/content/pattern-slider.md @@ -107,5 +107,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-slidertwothumb.md b/content/pattern-slidertwothumb.md index 96bee8e7d..89545c3bb 100644 --- a/content/pattern-slidertwothumb.md +++ b/content/pattern-slidertwothumb.md @@ -103,5 +103,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-spinbutton.md b/content/pattern-spinbutton.md index 90f15afd7..326730951 100644 --- a/content/pattern-spinbutton.md +++ b/content/pattern-spinbutton.md @@ -127,5 +127,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-switch.md b/content/pattern-switch.md index 7e53700ef..09e28893b 100644 --- a/content/pattern-switch.md +++ b/content/pattern-switch.md @@ -106,5 +106,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-table.md b/content/pattern-table.md index ce8a65144..c9e698ebe 100644 --- a/content/pattern-table.md +++ b/content/pattern-table.md @@ -105,5 +105,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-tabpanel.md b/content/pattern-tabpanel.md index 483512322..ed19b92f4 100644 --- a/content/pattern-tabpanel.md +++ b/content/pattern-tabpanel.md @@ -156,5 +156,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-toolbar.md b/content/pattern-toolbar.md index 446667f49..7f4ede0d0 100644 --- a/content/pattern-toolbar.md +++ b/content/pattern-toolbar.md @@ -117,5 +117,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-tooltip.md b/content/pattern-tooltip.md index 38672f0ae..1e626d193 100644 --- a/content/pattern-tooltip.md +++ b/content/pattern-tooltip.md @@ -84,5 +84,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-treegrid.md b/content/pattern-treegrid.md index 5d418c207..a23d1a6fb 100644 --- a/content/pattern-treegrid.md +++ b/content/pattern-treegrid.md @@ -278,5 +278,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-treeview.md b/content/pattern-treeview.md index 353d64a0b..301aaf46e 100644 --- a/content/pattern-treeview.md +++ b/content/pattern-treeview.md @@ -275,5 +275,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/pattern-windowsplitter.md b/content/pattern-windowsplitter.md index e26487404..5d237dfd3 100644 --- a/content/pattern-windowsplitter.md +++ b/content/pattern-windowsplitter.md @@ -108,5 +108,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/patterns.md b/content/patterns.md index 9c83af20b..ecdb7eaa5 100644 --- a/content/patterns.md +++ b/content/patterns.md @@ -464,5 +464,5 @@ WAI-ARIA supports two types of checkbox widgets: dual-state allows the user to t diff --git a/content/practice-grid-and-table-properties.md b/content/practice-grid-and-table-properties.md index 0f47d5048..d7510fef1 100644 --- a/content/practice-grid-and-table-properties.md +++ b/content/practice-grid-and-table-properties.md @@ -517,5 +517,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/practice-hiding-semantics.md b/content/practice-hiding-semantics.md index d8d0dcee0..be4148c3e 100644 --- a/content/practice-hiding-semantics.md +++ b/content/practice-hiding-semantics.md @@ -191,5 +191,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/practice-keyboard-interface.md b/content/practice-keyboard-interface.md index 1a90508c3..c69e3647d 100644 --- a/content/practice-keyboard-interface.md +++ b/content/practice-keyboard-interface.md @@ -673,5 +673,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/practice-landmark-regions.md b/content/practice-landmark-regions.md index 43921237d..4b6d434aa 100644 --- a/content/practice-landmark-regions.md +++ b/content/practice-landmark-regions.md @@ -460,5 +460,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/practice-names-and-descriptions.md b/content/practice-names-and-descriptions.md index be10c4c17..d9a8fc051 100644 --- a/content/practice-names-and-descriptions.md +++ b/content/practice-names-and-descriptions.md @@ -1601,5 +1601,5 @@ So, As advised by diff --git a/content/practice-range-related-properties.md b/content/practice-range-related-properties.md index 9469178ad..2af6e2389 100644 --- a/content/practice-range-related-properties.md +++ b/content/practice-range-related-properties.md @@ -353,5 +353,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/practice-read-me-first.md b/content/practice-read-me-first.md index d69eef347..4433f2a7a 100644 --- a/content/practice-read-me-first.md +++ b/content/practice-read-me-first.md @@ -126,5 +126,5 @@ Some JavaScript and CSS may not function correctly in Internet Explorer. diff --git a/content/practice-structural-roles.md b/content/practice-structural-roles.md index b37c4a8e4..c52d1e0d8 100644 --- a/content/practice-structural-roles.md +++ b/content/practice-structural-roles.md @@ -117,5 +117,5 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); diff --git a/content/practices.md b/content/practices.md index 2dee247ac..c74efef8b 100644 --- a/content/practices.md +++ b/content/practices.md @@ -125,5 +125,5 @@ To fully present and describe a grid or table, in addition to parsing the header diff --git a/scripts/pre-build/library/getTemplateBoilerplate.js b/scripts/pre-build/library/getTemplateBoilerplate.js index ec0395fef..1ef04961f 100644 --- a/scripts/pre-build/library/getTemplateBoilerplate.js +++ b/scripts/pre-build/library/getTemplateBoilerplate.js @@ -64,7 +64,7 @@ if (enableSidebar) document.body.classList.add('has-sidebar'); ${content} ${/* `, { parser: "html" })} */ ""}`; }; diff --git a/scripts/pre-build/library/loadExamples/loadExamples.js b/scripts/pre-build/library/loadExamples/loadExamples.js index 197545bb7..e669c8b2c 100644 --- a/scripts/pre-build/library/loadExamples/loadExamples.js +++ b/scripts/pre-build/library/loadExamples/loadExamples.js @@ -76,7 +76,7 @@ const loadExamples = async () => { }, ]); - await editFile(path.join(destinationExamplesPath, "js", "jumpto.js"), [ + await editFile(path.join(destinationExamplesPath, "js", "skipto.js"), [ { previousText: "displayOption: 'static',", replacementText: