From fde19acd3a4c9179b4b6110a9d7fb85db2c677ff Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:19:17 -0500 Subject: [PATCH 01/24] replace jumpto.js with skipto.js --- ARIA/apg/example-index/accordion/accordion.md | 2 +- ARIA/apg/example-index/alert/alert.md | 2 +- ARIA/apg/example-index/breadcrumb/index.md | 2 +- ARIA/apg/example-index/button/button.md | 2 +- ARIA/apg/example-index/button/button_idl.md | 2 +- .../carousel/carousel-1-prev-next.md | 2 +- .../carousel/carousel-2-tablist.md | 2 +- .../example-index/checkbox/checkbox-mixed.md | 2 +- ARIA/apg/example-index/checkbox/checkbox.md | 2 +- .../combobox/combobox-autocomplete-both.md | 2 +- .../combobox/combobox-autocomplete-list.md | 2 +- .../combobox/combobox-autocomplete-none.md | 2 +- .../combobox/combobox-datepicker.md | 2 +- .../combobox/combobox-select-only.md | 2 +- ARIA/apg/example-index/combobox/grid-combo.md | 2 +- .../example-index/dialog-modal/alertdialog.md | 2 +- .../dialog-modal/datepicker-dialog.md | 2 +- ARIA/apg/example-index/dialog-modal/dialog.md | 2 +- .../disclosure/disclosure-faq.md | 2 +- .../disclosure-image-description.md | 2 +- .../disclosure-navigation-hybrid.md | 2 +- .../disclosure/disclosure-navigation.md | 2 +- ARIA/apg/example-index/feed/feed.md | 2 +- ARIA/apg/example-index/grid/LayoutGrids.md | 2 +- .../example-index/grid/advancedDataGrid.md | 2 +- ARIA/apg/example-index/grid/dataGrids.md | 2 +- ARIA/apg/example-index/index.md | 2 +- ARIA/apg/example-index/js/app.js | 4 +- ARIA/apg/example-index/js/jumpto.js | 1206 -------------- ARIA/apg/example-index/js/skipto.js | 1460 +++++++++++++++++ ARIA/apg/example-index/link/link.md | 2 +- .../listbox/listbox-collapsible.md | 2 +- .../example-index/listbox/listbox-grouped.md | 2 +- .../listbox/listbox-rearrangeable.md | 2 +- .../listbox/listbox-scrollable.md | 2 +- .../menu-button-actions-active-descendant.md | 2 +- .../menu-button/menu-button-actions.md | 2 +- .../menu-button/menu-button-links.md | 2 +- .../example-index/menubar/menubar-editor.md | 2 +- .../menubar/menubar-navigation.md | 2 +- ARIA/apg/example-index/meter/meter.md | 2 +- .../radio/radio-activedescendant.md | 2 +- ARIA/apg/example-index/radio/radio-rating.md | 2 +- ARIA/apg/example-index/radio/radio.md | 2 +- .../slider/slider-color-viewer.md | 2 +- .../example-index/slider/slider-multithumb.md | 2 +- .../apg/example-index/slider/slider-rating.md | 2 +- ARIA/apg/example-index/slider/slider-seek.md | 2 +- .../slider/slider-temperature.md | 2 +- .../spinbutton/datepicker-spinbuttons.md | 2 +- .../apg/example-index/switch/switch-button.md | 2 +- .../example-index/switch/switch-checkbox.md | 2 +- ARIA/apg/example-index/switch/switch.md | 2 +- .../apg/example-index/table/sortable-table.md | 2 +- ARIA/apg/example-index/table/table.md | 2 +- ARIA/apg/example-index/tabs/tabs-automatic.md | 2 +- ARIA/apg/example-index/tabs/tabs-manual.md | 2 +- ARIA/apg/example-index/toolbar/toolbar.md | 2 +- ARIA/apg/example-index/treegrid/treegrid-1.md | 2 +- .../treeview/treeview-1/treeview-1a.md | 2 +- .../treeview/treeview-1/treeview-1b.md | 2 +- .../treeview/treeview-navigation.md | 2 +- content/about.md | 2 +- content/index.md | 2 +- content/pattern-accordion.md | 2 +- content/pattern-alert.md | 2 +- content/pattern-alertdialog.md | 2 +- content/pattern-breadcrumb.md | 2 +- content/pattern-button.md | 2 +- content/pattern-carousel.md | 2 +- content/pattern-checkbox.md | 2 +- content/pattern-combobox.md | 2 +- content/pattern-dialogmodal.md | 2 +- content/pattern-disclosure.md | 2 +- content/pattern-feed.md | 2 +- content/pattern-grid.md | 2 +- content/pattern-link.md | 2 +- content/pattern-listbox.md | 2 +- content/pattern-menu.md | 2 +- content/pattern-menubutton.md | 2 +- content/pattern-meter.md | 2 +- content/pattern-radiobutton.md | 2 +- content/pattern-slider.md | 2 +- content/pattern-slidertwothumb.md | 2 +- content/pattern-spinbutton.md | 2 +- content/pattern-switch.md | 2 +- content/pattern-table.md | 2 +- content/pattern-tabpanel.md | 2 +- content/pattern-toolbar.md | 2 +- content/pattern-tooltip.md | 2 +- content/pattern-treegrid.md | 2 +- content/pattern-treeview.md | 2 +- content/pattern-windowsplitter.md | 2 +- content/patterns.md | 2 +- content/practice-grid-and-table-properties.md | 2 +- content/practice-hiding-semantics.md | 2 +- content/practice-keyboard-interface.md | 2 +- content/practice-landmark-regions.md | 2 +- content/practice-names-and-descriptions.md | 2 +- content/practice-range-related-properties.md | 2 +- content/practice-read-me-first.md | 2 +- content/practice-structural-roles.md | 2 +- content/practices.md | 2 +- .../library/getTemplateBoilerplate.js | 2 +- .../library/loadExamples/loadExamples.js | 2 +- 105 files changed, 1564 insertions(+), 1310 deletions(-) delete mode 100644 ARIA/apg/example-index/js/jumpto.js create mode 100644 ARIA/apg/example-index/js/skipto.js 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..cd7097921 --- /dev/null +++ b/ARIA/apg/example-index/js/skipto.js @@ -0,0 +1,1460 @@ +/*! 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-4.2', + skipToMenuId: 'id-skip-to-menu-4.2', + 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: 'inherit', + fontSize: 'inherit', + positionLeft: '46%', + menuTextColor: '#1a1a1a', + menuBackgroundColor: '#dcdcdc', + menuitemFocusTextColor: '#eeeeee', + menuitemFocusBackgroundColor: '#1a1a1a', + focusBorderColor: '#1a1a1a', + buttonTextColor: '#1a1a1a', + buttonBackgroundColor: '#eeeeee', + }, + 'illinois': { + fontFamily: 'inherit', + fontSize: 'inherit', + positionLeft: '46%', + menuTextColor: '#00132c', + menuBackgroundColor: '#cad9ef', + menuitemFocusTextColor: '#eeeeee', + menuitemFocusBackgroundColor: '#00132c', + focusBorderColor: '#ff552e', + buttonTextColor: '#444444', + buttonBackgroundColor: '#dddede', + }, + 'aria': { + fontFamily: 'sans-serif', + fontSize: '10pt', + positionLeft: '7%', + 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: From dd69d747262f6b6bd770a31a00651e9c7459a2fc Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:24:31 -0500 Subject: [PATCH 02/24] fixing loading bug --- ARIA/apg/example-index/js/skipto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index cd7097921..bdb7b25c8 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -161,7 +161,7 @@ // Check if skipto is already loaded - if (document.querySelector('style#' + this.skipToId)) { + if (document.querySelector('#' + this.skipToId)) { return; } From 4ad7f4e15e354fd926c2e420058ee71f30feb018 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:27:31 -0500 Subject: [PATCH 03/24] fixing loading bug --- ARIA/apg/example-index/js/skipto.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index bdb7b25c8..e1052b2b9 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -18,8 +18,8 @@ (function() { 'use strict'; const SkipTo = { - skipToId: 'id-skip-to-js-4.2', - skipToMenuId: 'id-skip-to-menu-4.2', + skipToId: 'id-skip-to-js-42', + skipToMenuId: 'id-skip-to-menu-42', domNode: null, buttonNode: null, menuNode: null, @@ -161,7 +161,7 @@ // Check if skipto is already loaded - if (document.querySelector('#' + this.skipToId)) { + if (document.querySelector('style#' + this.skipToId)) { return; } From 6bfed4714c49cb863759754e054858f337deb45a Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:36:07 -0500 Subject: [PATCH 04/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 31 +++-------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index e1052b2b9..647703a6f 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -106,33 +106,9 @@ }, colorThemes: { 'default': { - fontFamily: 'inherit', - fontSize: 'inherit', - positionLeft: '46%', - menuTextColor: '#1a1a1a', - menuBackgroundColor: '#dcdcdc', - menuitemFocusTextColor: '#eeeeee', - menuitemFocusBackgroundColor: '#1a1a1a', - focusBorderColor: '#1a1a1a', - buttonTextColor: '#1a1a1a', - buttonBackgroundColor: '#eeeeee', - }, - 'illinois': { - fontFamily: 'inherit', - fontSize: 'inherit', - positionLeft: '46%', - menuTextColor: '#00132c', - menuBackgroundColor: '#cad9ef', - menuitemFocusTextColor: '#eeeeee', - menuitemFocusBackgroundColor: '#00132c', - focusBorderColor: '#ff552e', - buttonTextColor: '#444444', - buttonBackgroundColor: '#dddede', - }, - 'aria': { - fontFamily: 'sans-serif', - fontSize: '10pt', - positionLeft: '7%', + fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', + fontSize: '1.1rem', + positionLeft: '', menuTextColor: '#000', menuBackgroundColor: '#def', menuitemFocusTextColor: '#fff', @@ -140,7 +116,6 @@ 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}', From c351d54323c9ef92a5d34bf6bf83a0b07918ff24 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:38:04 -0500 Subject: [PATCH 05/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 647703a6f..ce9e36788 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -107,8 +107,8 @@ colorThemes: { 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', - fontSize: '1.1rem', - positionLeft: '', + fontSize: `1.1rem`, + positionLeft: 0, menuTextColor: '#000', menuBackgroundColor: '#def', menuitemFocusTextColor: '#fff', From 03c87612374bfa78c4ef4d5a43c42ae71dce9a82 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:39:25 -0500 Subject: [PATCH 06/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index ce9e36788..e52845b7b 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -108,7 +108,7 @@ 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', fontSize: `1.1rem`, - positionLeft: 0, + positionLeft: '0px', menuTextColor: '#000', menuBackgroundColor: '#def', menuitemFocusTextColor: '#fff', From 68aa785f9284f86d3f223eb9a82cbbef01e77085 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:42:00 -0500 Subject: [PATCH 07/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index e52845b7b..2c3bec6ac 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -106,8 +106,8 @@ }, colorThemes: { 'default': { - fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', - fontSize: `1.1rem`, +// fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', +// fontSize: `1.1rem`, positionLeft: '0px', menuTextColor: '#000', menuBackgroundColor: '#def', From 22e74ed26f6493a0c56ad7053fa6ce226e245b50 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:43:24 -0500 Subject: [PATCH 08/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 2c3bec6ac..4cb1f4c4a 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -106,9 +106,9 @@ }, colorThemes: { 'default': { -// fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', -// fontSize: `1.1rem`, - positionLeft: '0px', + fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', + fontSize: `1.1rem`, +// positionLeft: '0px', menuTextColor: '#000', menuBackgroundColor: '#def', menuitemFocusTextColor: '#fff', From 30c8fb3ceb42e433d75d50b0375d14f51945f00c Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:44:36 -0500 Subject: [PATCH 09/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 4cb1f4c4a..d48d73c94 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -116,6 +116,7 @@ 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}', From ff8d9c10a2c31cdec90c91eaa9402d1b05db4b5a Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:49:59 -0500 Subject: [PATCH 10/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index d48d73c94..e07a8ab74 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -107,8 +107,8 @@ colorThemes: { 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', - fontSize: `1.1rem`, -// positionLeft: '0px', + fontSize: '10pt', + positionLeft: '7%', menuTextColor: '#000', menuBackgroundColor: '#def', menuitemFocusTextColor: '#fff', From 134cbaf6e5090a52f5e4d8557263312063bd650f Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:52:25 -0500 Subject: [PATCH 11/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index e07a8ab74..2de23d38f 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -107,7 +107,7 @@ colorThemes: { 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', - fontSize: '10pt', + fontSize: '1rem', positionLeft: '7%', menuTextColor: '#000', menuBackgroundColor: '#def', From f0a01334b6739485e6fd722419a2092b004f62fe Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:56:15 -0500 Subject: [PATCH 12/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 2de23d38f..6301e3469 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -107,7 +107,7 @@ colorThemes: { 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', - fontSize: '1rem', + fontSize: '0.8rem', positionLeft: '7%', menuTextColor: '#000', menuBackgroundColor: '#def', @@ -244,7 +244,7 @@ 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('$positionLeft', this.config.positionLeft, theme. ); this.updateStyle('$menuTextColor', this.config.menuTextColor, theme.menuTextColor); this.updateStyle('$menuBackgroundColor', this.config.menuBackgroundColor, theme.menuBackgroundColor); From 790bba21296d468ad88759de5105cbe6875596ff Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 12:57:31 -0500 Subject: [PATCH 13/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 6301e3469..55cc9e748 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -107,7 +107,7 @@ colorThemes: { 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', - fontSize: '0.8rem', + fontSize: '14pt', positionLeft: '7%', menuTextColor: '#000', menuBackgroundColor: '#def', From 78c388cac4d1cdf8340220f11a7e20f7fbc588e8 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 13:00:05 -0500 Subject: [PATCH 14/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 55cc9e748..2de23d38f 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -107,7 +107,7 @@ colorThemes: { 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', - fontSize: '14pt', + fontSize: '1rem', positionLeft: '7%', menuTextColor: '#000', menuBackgroundColor: '#def', @@ -244,7 +244,7 @@ this.updateStyle('$fontFamily', this.config.fontFamily, theme.fontFamily); this.updateStyle('$fontSize', this.config.fontSize, theme.fontSize); - this.updateStyle('$positionLeft', this.config.positionLeft, theme. ); + this.updateStyle('$positionLeft', this.config.positionLeft, theme.positionLeft); this.updateStyle('$menuTextColor', this.config.menuTextColor, theme.menuTextColor); this.updateStyle('$menuBackgroundColor', this.config.menuBackgroundColor, theme.menuBackgroundColor); From e3d65f709df5cac8722901ed38f76d6e87a5630a Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 13:06:26 -0500 Subject: [PATCH 15/24] updating SKipTo default styling --- ARIA/apg/example-index/js/skipto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 2de23d38f..9291d8c1a 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -107,7 +107,7 @@ colorThemes: { 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', - fontSize: '1rem', + fontSize: '14px', positionLeft: '7%', menuTextColor: '#000', menuBackgroundColor: '#def', From b7b12311d647ac889a6b83ac71a6a5ff53076939 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 13:09:21 -0500 Subject: [PATCH 16/24] updating SkipTo default styling --- ARIA/apg/example-index/js/skipto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 9291d8c1a..aac84d282 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -108,7 +108,7 @@ 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', fontSize: '14px', - positionLeft: '7%', + positionLeft: '20px', menuTextColor: '#000', menuBackgroundColor: '#def', menuitemFocusTextColor: '#fff', From 7b5e1f343903d89022c6591968fe2d0f0a21c80b Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 13:12:29 -0500 Subject: [PATCH 17/24] updating SkipTo default styling --- ARIA/apg/example-index/js/skipto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index aac84d282..be48e9a88 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -108,7 +108,7 @@ 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', fontSize: '14px', - positionLeft: '20px', + positionLeft: '40px', menuTextColor: '#000', menuBackgroundColor: '#def', menuitemFocusTextColor: '#fff', From df7af19a87a05c45fc6dcb999e09ba633fd5d344 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 13:27:12 -0500 Subject: [PATCH 18/24] updating SkipTo default styling --- ARIA/apg/example-index/js/skipto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index be48e9a88..3e8e60c7a 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -108,7 +108,7 @@ 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', fontSize: '14px', - positionLeft: '40px', + positionLeft: '2px', menuTextColor: '#000', menuBackgroundColor: '#def', menuitemFocusTextColor: '#fff', From d729aab3e7de697848a27f9f377a3f9fc8bd4208 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 16 Jun 2022 13:28:35 -0500 Subject: [PATCH 19/24] updating SkipTo default styling --- ARIA/apg/example-index/js/skipto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 3e8e60c7a..7b01ebcfb 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -108,7 +108,7 @@ 'default': { fontFamily: 'Noto Sans, Trebuchet MS, Helvetica Neue, Arial, sans-serif', fontSize: '14px', - positionLeft: '2px', + positionLeft: '0px', menuTextColor: '#000', menuBackgroundColor: '#def', menuitemFocusTextColor: '#fff', From 77b9c14781e0dbb017924c200cd14da6a1036cb6 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Tue, 21 Jun 2022 15:34:00 -0500 Subject: [PATCH 20/24] updated version from 4.2 to 5.0 --- ARIA/apg/example-index/js/skipto.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 7b01ebcfb..e483ea4cc 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -1,11 +1,11 @@ -/*! skipto - v4.2.0 - 2022-06-16 +/*! skipto - v5.0.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) <2022> (ver 5.0) 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: From c3fc9bd375c424a528dc5638a754a6c2d726fc3b Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Tue, 21 Jun 2022 15:37:09 -0500 Subject: [PATCH 21/24] updated id use to 50 instead of 43 --- ARIA/apg/example-index/js/skipto.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index e483ea4cc..0347372f5 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -18,8 +18,8 @@ (function() { 'use strict'; const SkipTo = { - skipToId: 'id-skip-to-js-42', - skipToMenuId: 'id-skip-to-menu-42', + skipToId: 'id-skip-to-js-50', + skipToMenuId: 'id-skip-to-menu-50', domNode: null, buttonNode: null, menuNode: null, From 9cbdc8dab8bf9dc088b6b69945fde3168fe61904 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Thu, 23 Jun 2022 09:38:29 -0500 Subject: [PATCH 22/24] updated reference to where to get code --- ARIA/apg/example-index/js/skipto.js | 2 +- package-lock.json | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 package-lock.json diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 0347372f5..0e265950e 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -1,5 +1,5 @@ /*! skipto - v5.0.0 - 2022-06-16 -* https://github.com/paypal/skipto +* https://github.com/skipto-landmarks-headings/page-script-5 * Copyright (c) 2022 Jon Gunderson; Licensed BSD * Copyright (c) 2021 PayPal Accessibility Team and University of Illinois; Licensed BSD */ /*@cc_on @*/ diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..130e4f79d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "wai-aria-practices", + "lockfileVersion": 2, + "requires": true, + "packages": {} +} From c9babc982079d5271c6f8621d4af236da144dc0a Mon Sep 17 00:00:00 2001 From: Matt King Date: Thu, 23 Jun 2022 11:14:05 -0700 Subject: [PATCH 23/24] Restore correct copyright and license --- ARIA/apg/example-index/js/skipto.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ARIA/apg/example-index/js/skipto.js b/ARIA/apg/example-index/js/skipto.js index 0e265950e..c27fa07a6 100644 --- a/ARIA/apg/example-index/js/skipto.js +++ b/ARIA/apg/example-index/js/skipto.js @@ -1,11 +1,11 @@ -/*! skipto - v5.0.0 - 2022-06-16 -* https://github.com/skipto-landmarks-headings/page-script-5 +/*! 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 5.0) Jon Gunderson +* 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: From f83e9ef3a93dec94aebe295c8b950cd965a6949e Mon Sep 17 00:00:00 2001 From: Howard Edwards Date: Thu, 23 Jun 2022 13:59:38 -0500 Subject: [PATCH 24/24] Remove package-lock.json --- package-lock.json | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 130e4f79d..000000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "wai-aria-practices", - "lockfileVersion": 2, - "requires": true, - "packages": {} -}