diff --git a/.husky/_/husky.sh b/.husky/_/husky.sh
new file mode 100644
index 0000000000..ca2720e08a
--- /dev/null
+++ b/.husky/_/husky.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+if [ -z "$husky_skip_init" ]; then
+ debug () {
+ [ "$HUSKY_DEBUG" = "1" ] && echo "husky (debug) - $1"
+ }
+
+ readonly hook_name="$(basename "$0")"
+ debug "starting $hook_name..."
+
+ if [ "$HUSKY" = "0" ]; then
+ debug "HUSKY env variable is set to 0, skipping hook"
+ exit 0
+ fi
+
+ if [ -f ~/.huskyrc ]; then
+ debug "sourcing ~/.huskyrc"
+ . ~/.huskyrc
+ fi
+
+ export readonly husky_skip_init=1
+ sh -e "$0" "$@"
+ exitCode="$?"
+
+ if [ $exitCode != 0 ]; then
+ echo "husky - $hook_name hook exited with code $exitCode (error)"
+ exit $exitCode
+ fi
+
+ exit 0
+fi
diff --git a/aria-practices.html b/aria-practices.html
index 10a16ba1f6..9aed12c918 100644
--- a/aria-practices.html
+++ b/aria-practices.html
@@ -2432,7 +2432,7 @@
diff --git a/examples/index.html b/examples/index.html
index 25b17c118c..c3a4039ea7 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -343,7 +343,6 @@ Examples by Role
slider
- Horizontal Multi-Thumb Slider
Color Viewer Slider (HC )
Rating Slider (HC )
Media Seek Slider (HC )
@@ -628,7 +627,6 @@ Examples By Properties and States
Link
Editor Menubar (HC )
Navigation Menubar (HC )
- Horizontal Multi-Thumb Slider
Date Picker Spin Button
Table
Tabs with Automatic Activation
@@ -814,7 +812,6 @@ Examples By Properties and States
Meter
- Horizontal Multi-Thumb Slider
Color Viewer Slider (HC )
Rating Slider (HC )
Media Seek Slider (HC )
@@ -829,7 +826,6 @@ Examples By Properties and States
Meter
- Horizontal Multi-Thumb Slider
Color Viewer Slider (HC )
Rating Slider (HC )
Media Seek Slider (HC )
@@ -844,7 +840,6 @@ Examples By Properties and States
Meter
- Horizontal Multi-Thumb Slider
Color Viewer Slider (HC )
Rating Slider (HC )
Media Seek Slider (HC )
@@ -858,7 +853,6 @@ Examples By Properties and States
aria-valuetext
- Horizontal Multi-Thumb Slider
Rating Slider (HC )
Media Seek Slider (HC )
Vertical Temperature Slider (HC )
diff --git a/examples/slider/css/multithumb-slider.css b/examples/slider/css/multithumb-slider.css
deleted file mode 100644
index a442e09d2f..0000000000
--- a/examples/slider/css/multithumb-slider.css
+++ /dev/null
@@ -1,48 +0,0 @@
-/* CSS Document */
-
-div.aria-widget-slider {
- clear: both;
- padding-top: 0.5em;
- padding-bottom: 1em;
-}
-
-div.rail-label {
- padding-right: 0.5em;
- text-align: right;
- float: left;
- width: 4em;
- position: relative;
- top: -0.5em;
-}
-
-div.rail-label.max {
- padding-left: 0.5em;
- text-align: left;
-}
-
-div.aria-widget-slider .rail {
- background-color: #eee;
- border: 1px solid #888;
- position: relative;
- height: 4px;
- float: left;
-}
-
-div.aria-widget-slider img[role="slider"] {
- position: absolute;
- padding: 0;
- margin: 0;
- top: -10px;
-}
-
-div.aria-widget-slider img[role="slider"].focus,
-div.aria-widget-slider img[role="slider"]:hover {
- outline-color: rgb(140, 203, 242);
- outline-style: solid;
- outline-width: 2px;
- outline-offset: 2px;
-}
-
-div.aria-widget-slider .rail.focus {
- background-color: #aaa;
-}
diff --git a/examples/slider/css/slider-multithumb.css b/examples/slider/css/slider-multithumb.css
new file mode 100644
index 0000000000..fb26f97a4e
--- /dev/null
+++ b/examples/slider/css/slider-multithumb.css
@@ -0,0 +1,88 @@
+/* CSS Document */
+
+.slider-multithumb {
+ padding: 6px;
+ width: 350px;
+ touch-action: pan-y;
+}
+
+.slider-multithumb svg {
+ forced-color-adjust: auto;
+}
+
+.slider-multithumb .slider-group {
+ color: black;
+}
+
+.slider-multithumb .slider-group .value {
+ font-size: 80%;
+ color: currentColor;
+ fill: currentColor;
+}
+
+.slider-multithumb .slider-group .rail {
+ stroke: currentColor;
+ stroke-width: 2px;
+ fill-opacity: 0;
+}
+
+.slider-multithumb .slider-group .range {
+ fill: currentColor;
+ opacity: 0.4;
+}
+
+.slider-multithumb .slider-group .thumb {
+ stroke-opacity: 0;
+ stroke-width: 2px;
+ fill: currentColor;
+}
+
+.slider-multithumb .slider-group .focus-ring {
+ stroke-opacity: 0;
+ fill-opacity: 0;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+}
+
+/* Focus and hover styling */
+
+.slider-multithumb .slider-group g.rail,
+.slider-multithumb .slider-group g.focus {
+ color: currentColor;
+}
+
+.slider-multithumb .slider-group.active g.rail {
+ opacity: 0.8;
+}
+
+.slider-multithumb .slider-group.active g.range {
+ fill: #005a9c;
+ fill-opacity: 1;
+}
+
+.slider-multithumb [role="slider"]:focus {
+ outline: none;
+ color: #005a9c;
+}
+
+.slider-multithumb [role="slider"]:hover .focus-ring {
+ stroke: currentColor;
+ stroke-width: 1px;
+ stroke-opacity: 0.8;
+}
+
+.slider-multithumb [role="slider"]:hover .focus-ring,
+.slider-multithumb [role="slider"]:focus .focus-ring {
+ stroke: currentColor;
+ stroke-opacity: 1;
+ stroke-width: 3px;
+}
+
+.slider-multithumb [role="slider"]:focus .thumb {
+ stroke: currentColor;
+}
+
+.slider-multithumb [role="slider"]:focus .value {
+ color: currentColor;
+ font-weight: bold;
+}
diff --git a/examples/slider/js/multithumb-slider.js b/examples/slider/js/multithumb-slider.js
deleted file mode 100644
index b71eb2bb82..0000000000
--- a/examples/slider/js/multithumb-slider.js
+++ /dev/null
@@ -1,235 +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: slider.js
- *
- * Desc: Slider widget that implements ARIA Authoring Practices
- */
-
-'use strict';
-
-// Create Slider that contains value, valuemin, valuemax, and valuenow
-var Slider = function (domNode) {
- this.domNode = domNode;
- this.railDomNode = domNode.parentNode;
-
- this.labelDomNode = false;
- this.minDomNode = false;
- this.maxDomNode = false;
-
- this.valueNow = 50;
-
- this.railMin = 0;
- this.railMax = 100;
- this.railWidth = 0;
- this.railBorderWidth = 1;
-
- this.thumbWidth = 20;
- this.thumbHeight = 24;
-
- this.keyCode = Object.freeze({
- left: 37,
- up: 38,
- right: 39,
- down: 40,
- pageUp: 33,
- pageDown: 34,
- end: 35,
- home: 36,
- });
-};
-
-// Initialize slider
-Slider.prototype.init = function () {
- if (this.domNode.previousElementSibling) {
- this.minDomNode = this.domNode.previousElementSibling;
- this.railMin = parseInt(this.minDomNode.getAttribute('aria-valuemin'));
- } else {
- this.railMin = parseInt(this.domNode.getAttribute('aria-valuemin'));
- }
-
- if (this.domNode.nextElementSibling) {
- this.maxDomNode = this.domNode.nextElementSibling;
- this.railMax = parseInt(this.maxDomNode.getAttribute('aria-valuemax'));
- } else {
- this.railMax = parseInt(this.domNode.getAttribute('aria-valuemax'));
- }
-
- this.valueNow = parseInt(this.domNode.getAttribute('aria-valuenow'));
-
- this.railWidth = parseInt(this.railDomNode.style.width.slice(0, -2));
-
- if (this.domNode.classList.contains('min')) {
- this.labelDomNode = this.domNode.parentElement.previousElementSibling;
- }
-
- if (this.domNode.classList.contains('max')) {
- this.labelDomNode = this.domNode.parentElement.nextElementSibling;
- }
-
- if (this.domNode.tabIndex != 0) {
- this.domNode.tabIndex = 0;
- }
-
- this.domNode.addEventListener('keydown', this.handleKeyDown.bind(this));
- this.domNode.addEventListener('mousedown', this.handleMouseDown.bind(this));
- this.domNode.addEventListener('focus', this.handleFocus.bind(this));
- this.domNode.addEventListener('blur', this.handleBlur.bind(this));
-
- this.moveSliderTo(this.valueNow);
-};
-
-Slider.prototype.moveSliderTo = function (value) {
- var valueMax = parseInt(this.domNode.getAttribute('aria-valuemax'));
- var valueMin = parseInt(this.domNode.getAttribute('aria-valuemin'));
-
- if (value > valueMax) {
- value = valueMax;
- }
-
- if (value < valueMin) {
- value = valueMin;
- }
-
- this.valueNow = value;
- this.dolValueNow = '$' + value;
-
- this.domNode.setAttribute('aria-valuenow', this.valueNow);
- this.domNode.setAttribute('aria-valuetext', this.dolValueNow);
-
- if (this.minDomNode) {
- this.minDomNode.setAttribute('aria-valuemax', this.valueNow);
- }
-
- if (this.maxDomNode) {
- this.maxDomNode.setAttribute('aria-valuemin', this.valueNow);
- }
-
- var pos = Math.round(
- ((this.valueNow - this.railMin) *
- (this.railWidth - 2 * (this.thumbWidth - this.railBorderWidth))) /
- (this.railMax - this.railMin)
- );
-
- if (this.minDomNode) {
- this.domNode.style.left =
- pos + this.thumbWidth - this.railBorderWidth + 'px';
- } else {
- this.domNode.style.left = pos - this.railBorderWidth + 'px';
- }
-
- if (this.labelDomNode) {
- this.labelDomNode.innerHTML = this.dolValueNow.toString();
- }
-};
-
-Slider.prototype.handleKeyDown = function (event) {
- var flag = false;
-
- switch (event.keyCode) {
- case this.keyCode.left:
- case this.keyCode.down:
- this.moveSliderTo(this.valueNow - 1);
- flag = true;
- break;
-
- case this.keyCode.right:
- case this.keyCode.up:
- this.moveSliderTo(this.valueNow + 1);
- flag = true;
- break;
-
- case this.keyCode.pageDown:
- this.moveSliderTo(this.valueNow - 10);
- flag = true;
- break;
-
- case this.keyCode.pageUp:
- this.moveSliderTo(this.valueNow + 10);
- flag = true;
- break;
-
- case this.keyCode.home:
- this.moveSliderTo(this.railMin);
- flag = true;
- break;
-
- case this.keyCode.end:
- this.moveSliderTo(this.railMax);
- flag = true;
- break;
-
- default:
- break;
- }
-
- if (flag) {
- event.preventDefault();
- event.stopPropagation();
- }
-};
-
-Slider.prototype.handleFocus = function () {
- this.domNode.classList.add('focus');
- this.railDomNode.classList.add('focus');
-};
-
-Slider.prototype.handleBlur = function () {
- this.domNode.classList.remove('focus');
- this.railDomNode.classList.remove('focus');
-};
-
-Slider.prototype.handleMouseDown = function (event) {
- var self = this;
-
- var handleMouseMove = function (event) {
- var diffX = event.pageX - self.railDomNode.offsetLeft;
- self.valueNow =
- self.railMin +
- parseInt(((self.railMax - self.railMin) * diffX) / self.railWidth);
- self.moveSliderTo(self.valueNow);
-
- event.preventDefault();
- event.stopPropagation();
- };
-
- var handleMouseUp = function () {
- document.removeEventListener('mousemove', handleMouseMove);
- document.removeEventListener('mouseup', handleMouseUp);
- };
-
- // bind a mousemove event handler to move pointer
- document.addEventListener('mousemove', handleMouseMove);
-
- // bind a mouseup event handler to stop tracking mouse movements
- document.addEventListener('mouseup', handleMouseUp);
-
- event.preventDefault();
- event.stopPropagation();
-
- // Set focus to the clicked handle
- this.domNode.focus();
-};
-
-// handleMouseMove has the same functionality as we need for handleMouseClick on the rail
-// Slider.prototype.handleClick = function (event) {
-
-// var diffX = event.pageX - this.railDomNode.offsetLeft;
-// this.valueNow = parseInt(((this.railMax - this.railMin) * diffX) / this.railWidth);
-// this.moveSliderTo(this.valueNow);
-
-// event.preventDefault();
-// event.stopPropagation();
-
-// };
-
-// Initialize Sliders on the page
-window.addEventListener('load', function () {
- var sliders = document.querySelectorAll('[role=slider]');
-
- for (var i = 0; i < sliders.length; i++) {
- var s = new Slider(sliders[i]);
- s.init();
- }
-});
diff --git a/examples/slider/js/slider-multithumb.js b/examples/slider/js/slider-multithumb.js
new file mode 100644
index 0000000000..fcb2ae6288
--- /dev/null
+++ b/examples/slider/js/slider-multithumb.js
@@ -0,0 +1,359 @@
+/*
+ * This content is licensed according to the W3C Software License at
+ * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
+ *
+ * File: slider-multithumb.js
+ *
+ * Desc: A dual slider widget that implements ARIA Authoring Practices
+ */
+
+'use strict';
+class SliderMultithumb {
+ constructor(domNode) {
+ this.isMoving = false;
+ this.movingSliderNode = false;
+
+ this.domNode = domNode;
+
+ this.svgNode = domNode.querySelector('svg');
+ this.svgPoint = this.svgNode.createSVGPoint();
+
+ this.railNode = domNode.querySelector('.rail rect');
+ this.rangeNode = domNode.querySelector('.range rect');
+
+ this.minSliderNode = domNode.querySelector('[role=slider].minimum');
+ this.maxSliderNode = domNode.querySelector('[role=slider].maximum');
+
+ this.minSliderValueNode = this.minSliderNode.querySelector('.value');
+ this.maxSliderValueNode = this.maxSliderNode.querySelector('.value');
+
+ this.minSliderFocusNode = this.minSliderNode.querySelector('.focus-ring');
+ this.maxSliderFocusNode = this.maxSliderNode.querySelector('.focus-ring');
+
+ this.minSliderThumbNode = this.minSliderNode.querySelector('.thumb');
+ this.maxSliderThumbNode = this.maxSliderNode.querySelector('.thumb');
+
+ // Dimensions of the slider focus ring, thumb and rail
+
+ this.svgWidth = 360;
+ this.svgHeight = 80;
+
+ this.valueTop = 24;
+ this.valueHeight = this.minSliderValueNode.getBoundingClientRect().height;
+
+ this.railHeight = 6;
+ this.railWidth = 300;
+ this.railY = 42;
+ this.railX = 10;
+
+ this.thumbTop = 31;
+ this.thumbHeight = 28;
+ this.thumbWidth = 28;
+ this.thumb2Width = 2 * this.thumbWidth;
+ this.thumbMiddle = this.thumbTop + this.thumbHeight / 2;
+ this.thumbBottom = this.thumbTop + this.thumbHeight;
+
+ this.focusOffset = 8;
+ this.focusY = this.valueTop - this.valueHeight - this.focusOffset + 2;
+ this.focusWidth = this.thumbWidth + 2 * this.focusOffset;
+ this.focusHeight = this.thumbBottom - this.focusY + this.focusOffset + 2;
+ this.focusRadius = this.focusWidth / 8;
+
+ this.svgNode.setAttribute('width', this.svgWidth);
+ this.svgNode.setAttribute('height', this.svgHeight);
+
+ this.minSliderFocusNode.setAttribute('y', this.focusY);
+ this.maxSliderFocusNode.setAttribute('y', this.focusY);
+ this.minSliderFocusNode.setAttribute('width', this.focusWidth);
+ this.maxSliderFocusNode.setAttribute('width', this.focusWidth);
+ this.minSliderFocusNode.setAttribute('height', this.focusHeight);
+ this.maxSliderFocusNode.setAttribute('height', this.focusHeight);
+ this.minSliderFocusNode.setAttribute('rx', this.focusRadius);
+ this.maxSliderFocusNode.setAttribute('rx', this.focusRadius);
+
+ this.minSliderValueNode.setAttribute('y', this.valueTop);
+ this.maxSliderValueNode.setAttribute('y', this.valueTop);
+
+ this.railNode.setAttribute('y', this.railY);
+ this.railNode.setAttribute('x', this.railX);
+ this.railNode.setAttribute('height', this.railHeight);
+ this.railNode.setAttribute('width', this.railWidth + this.thumbWidth);
+ this.railNode.setAttribute('rx', this.railHeight / 2);
+
+ this.rangeNode.setAttribute('y', this.railY);
+ this.rangeNode.setAttribute('x', this.railX / 2);
+ this.rangeNode.setAttribute('height', this.railHeight);
+ this.rangeNode.setAttribute('width', 0);
+
+ this.sliderMinValue = this.getValueMin(this.minSliderNode);
+ this.sliderMaxValue = this.getValueMax(this.maxSliderNode);
+ this.sliderDiffValue = this.sliderMaxValue - this.sliderMinValue;
+
+ this.minSliderRight = 0;
+ this.maxSliderLeft = this.railWidth;
+
+ this.minSliderNode.addEventListener(
+ 'keydown',
+ this.onSliderKeydown.bind(this)
+ );
+ this.minSliderNode.addEventListener(
+ 'pointerdown',
+ this.onSliderPointerdown.bind(this)
+ );
+
+ this.minSliderNode.addEventListener('focus', this.onSliderFocus.bind(this));
+ this.minSliderNode.addEventListener('blur', this.onSliderBlur.bind(this));
+
+ this.maxSliderNode.addEventListener(
+ 'keydown',
+ this.onSliderKeydown.bind(this)
+ );
+ this.maxSliderNode.addEventListener(
+ 'pointerdown',
+ this.onSliderPointerdown.bind(this)
+ );
+
+ // bind a pointermove event handler to move pointer
+ document.addEventListener('pointermove', this.onPointermove.bind(this));
+
+ // bind a pointerup event handler to stop tracking pointer movements
+ document.addEventListener('pointerup', this.onPointerup.bind(this));
+
+ this.maxSliderNode.addEventListener('focus', this.onSliderFocus.bind(this));
+ this.maxSliderNode.addEventListener('blur', this.onSliderBlur.bind(this));
+
+ this.moveSliderTo(this.minSliderNode, this.getValue(this.minSliderNode));
+ this.moveSliderTo(this.maxSliderNode, this.getValue(this.maxSliderNode));
+ }
+
+ getSVGPoint(event) {
+ this.svgPoint.x = event.clientX;
+ this.svgPoint.y = event.clientY;
+ return this.svgPoint.matrixTransform(this.svgNode.getScreenCTM().inverse());
+ }
+
+ getValue(sliderNode) {
+ return parseInt(sliderNode.getAttribute('aria-valuenow'));
+ }
+
+ getValueMin(sliderNode) {
+ return parseInt(sliderNode.getAttribute('aria-valuemin'));
+ }
+
+ getValueMax(sliderNode) {
+ return parseInt(sliderNode.getAttribute('aria-valuemax'));
+ }
+
+ isMinSlider(sliderNode) {
+ return this.minSliderNode === sliderNode;
+ }
+
+ isInRange(sliderNode, value) {
+ let valueMin = this.getValueMin(sliderNode);
+ let valueMax = this.getValueMax(sliderNode);
+ return value <= valueMax && value >= valueMin;
+ }
+
+ isOutOfRange(value) {
+ let valueMin = this.getValueMin(this.minSliderNode);
+ let valueMax = this.getValueMax(this.maxSliderNode);
+ return value > valueMax || value < valueMin;
+ }
+
+ getXFromThumb(node) {
+ var points = node.getAttribute('points').split(',');
+ return parseInt(points[0]);
+ }
+
+ moveSliderTo(sliderNode, value) {
+ var valueMax,
+ valueMin,
+ pos,
+ x,
+ points = '',
+ width,
+ dollarValue;
+
+ if (this.isMinSlider(sliderNode)) {
+ valueMin = this.getValueMin(this.minSliderNode);
+ valueMax = this.getValueMax(this.minSliderNode);
+ } else {
+ valueMin = this.getValueMin(this.maxSliderNode);
+ valueMax = this.getValueMax(this.maxSliderNode);
+ }
+
+ value = Math.min(Math.max(value, valueMin), valueMax);
+
+ sliderNode.setAttribute('aria-valuenow', value);
+ dollarValue = '$' + value;
+
+ pos = this.railX;
+ pos += Math.round(
+ (value * (this.railWidth - this.thumbWidth)) /
+ (this.sliderMaxValue - this.sliderMinValue)
+ );
+
+ if (this.isMinSlider(sliderNode)) {
+ // update ARIA attributes
+ this.minSliderValueNode.textContent = dollarValue;
+ this.maxSliderNode.setAttribute('aria-valuemin', value);
+
+ // move the SVG focus ring and thumb elements
+ x = pos - this.focusOffset - 1;
+ this.minSliderFocusNode.setAttribute('x', x);
+
+ points = `${pos},${this.thumbTop}`;
+ points += ` ${pos + this.thumbWidth},${this.thumbMiddle}`;
+ points += ` ${pos},${this.thumbBottom}`;
+ this.minSliderThumbNode.setAttribute('points', points);
+
+ // Position value
+ width = this.minSliderValueNode.getBoundingClientRect().width;
+ pos = pos + (this.thumbWidth - width) / 2;
+ if (pos + width > this.maxSliderLeft - 2) {
+ pos = this.maxSliderLeft - width - 2;
+ }
+ this.minSliderValueNode.setAttribute('x', pos);
+ this.minSliderRight = pos;
+ } else {
+ // update label and ARIA attributes
+ this.maxSliderValueNode.textContent = dollarValue;
+ this.minSliderNode.setAttribute('aria-valuemax', value);
+
+ // move the SVG focus ring and thumb elements
+ x = pos + this.thumbWidth - this.focusOffset + 1;
+ this.maxSliderFocusNode.setAttribute('x', x);
+
+ points = `${pos + this.thumbWidth},${this.thumbMiddle}`;
+ points += ` ${pos + this.thumb2Width},${this.thumbTop}`;
+ points += ` ${pos + this.thumb2Width},${this.thumbBottom}`;
+ this.maxSliderThumbNode.setAttribute('points', points);
+
+ width = this.maxSliderValueNode.getBoundingClientRect().width;
+ pos = pos + this.thumbWidth + (this.thumbWidth - width) / 2;
+ if (pos - width < this.minSliderRight + 2) {
+ pos = this.minSliderRight + width + 2;
+ }
+
+ this.maxSliderValueNode.setAttribute('x', pos);
+ this.maxSliderLeft = pos;
+ }
+
+ // Set range rect
+
+ x = this.getXFromThumb(this.minSliderThumbNode) + this.thumbWidth / 2;
+ width =
+ this.getXFromThumb(this.maxSliderThumbNode) - x + this.thumbWidth / 2;
+ this.rangeNode.setAttribute('x', x);
+ this.rangeNode.setAttribute('width', width);
+ }
+
+ onSliderKeydown(event) {
+ var flag = false;
+ var sliderNode = event.currentTarget;
+ var value = this.getValue(sliderNode);
+ var valueMin = this.getValueMin(sliderNode);
+ var valueMax = this.getValueMax(sliderNode);
+
+ switch (event.key) {
+ case 'ArrowLeft':
+ case 'ArrowDown':
+ this.moveSliderTo(sliderNode, value - 1);
+ flag = true;
+ break;
+
+ case 'ArrowRight':
+ case 'ArrowUp':
+ this.moveSliderTo(sliderNode, value + 1);
+ flag = true;
+ break;
+
+ case 'PageDown':
+ this.moveSliderTo(sliderNode, value - 10);
+ flag = true;
+ break;
+
+ case 'PageUp':
+ this.moveSliderTo(sliderNode, value + 10);
+ flag = true;
+ break;
+
+ case 'Home':
+ this.moveSliderTo(sliderNode, valueMin);
+ flag = true;
+ break;
+
+ case 'End':
+ this.moveSliderTo(sliderNode, valueMax);
+ flag = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if (flag) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+
+ onSliderFocus(event) {
+ event.currentTarget.classList.add('focus');
+ this.svgNode.classList.add('active');
+ }
+
+ onSliderBlur(event) {
+ event.currentTarget.classList.remove('focus');
+ this.svgNode.classList.remove('active');
+ }
+
+ onSliderPointerdown(event) {
+ this.isMoving = true;
+ this.movingSliderNode = event.currentTarget;
+ this.isMinSliderMoving = this.isMinSlider(event.currentTarget);
+
+ event.preventDefault();
+ event.stopPropagation();
+
+ // Set focus to the clicked handle
+ this.movingSliderNode.focus();
+ }
+
+ onPointermove(event) {
+ if (
+ this.isMoving &&
+ this.movingSliderNode &&
+ this.domNode.contains(event.target)
+ ) {
+ var x = this.getSVGPoint(event).x - this.railX;
+ if (this.isMinSliderMoving) {
+ x = Math.max(0, x - this.thumbWidth / 3);
+ } else {
+ x = Math.max(0, x - (5 * this.thumbWidth) / 3);
+ }
+ x = Math.min(x, this.railWidth - this.thumbWidth);
+ var value = Math.round(
+ (x * this.sliderDiffValue) / (this.railWidth - this.thumbWidth)
+ );
+ this.moveSliderTo(this.movingSliderNode, value);
+
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+
+ onPointerup() {
+ this.isMoving = false;
+ this.movingSliderNode = false;
+ }
+}
+
+// Initialize Multithumb Slider widgets on the page
+window.addEventListener('load', function () {
+ var slidersMultithumb = document.querySelectorAll('.slider-multithumb');
+
+ for (let i = 0; i < slidersMultithumb.length; i++) {
+ new SliderMultithumb(slidersMultithumb[i]);
+ }
+});
diff --git a/examples/slider/multithumb-slider.html b/examples/slider/multithumb-slider.html
deleted file mode 100644
index a40edc524d..0000000000
--- a/examples/slider/multithumb-slider.html
+++ /dev/null
@@ -1,277 +0,0 @@
-
-
-
-
- Horizontal Multi-Thumb Slider Example | WAI-ARIA Authoring Practices 1.2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Horizontal Multi-Thumb Slider Example
-
- The below example section includes a slider for setting a price range that demonstrates the
- multi-thumb slider design pattern.
- Users set a price range by moving the arrows (thumbs).
- Each slider has two thumbs: one for the minimum price and one for the maximum price.
- The price labels at the ends of the slider update as their corresponding thumbs are moved.
-
- Similar examples include:
-
-
-
-
-
-
Hotel Price Range
-
-
Flight Price Range
-
-
-
-
-
-
- Keyboard Support
-
-
-
- Key
- Function
-
-
-
-
- Right Arrow
- Increases slider value one step.
-
-
- Up Arrow
- Increases slider value one step.
-
-
- Left Arrow
- Decreases slider value one step.
-
-
- Down Arrow
- Decreases slider value one step.
-
-
- Page Up
- Increases slider value multiple steps. In this slider, jumps ten steps.
-
-
- Page Down
- Decreases slider value multiple steps. In this slider, jumps ten steps.
-
-
- Home
- Sets slider to its minimum value.
-
-
- End
- Sets slider to its maximum value.
-
-
-
-
-
-
- Role, Property, State, and Tabindex Attributes
-
-
-
- Role
- Attribute
- Element
- Usage
-
-
-
-
-
- slider
-
-
-
- img
-
-
-
- Identifies the img
element as a slider.
- Set on the movable thumb because it is the operable element that receives focus and represents the slider value.
-
-
-
-
-
-
- tabindex=0
-
-
- img
-
- Includes the slider thumb in the page tab sequence.
-
-
-
-
- aria-valuemax=NUMBER
-
-
- img
-
- Specifies the maximum value of the slider.
-
-
-
-
- aria-valuemin=NUMBER
-
-
- img
-
- Specifies the minimum value of the slider.
-
-
-
-
- aria-valuenow=NUMBER
-
-
- img
-
- Indicates the current value of the slider.
-
-
-
-
- aria-valuetext=DOLLAR AMOUNT
-
-
- img
-
- Indicates the current value of the slider in dollars using the $ character as a prefix.
-
-
-
-
- aria-label=text
-
-
- img
-
- A label identifying the purpose of the slider, e.g., Hotel Minimum Price .
-
-
-
-
-
-
- Javascript and CSS Source Code
-
-
-
-
- HTML Source Code
-
-
-
-
-
-
-
-
- Slider (Multi-Thumb) design pattern in WAI-ARIA Authoring Practices 1.2
-
-
-
diff --git a/examples/slider/slider-multithumb.html b/examples/slider/slider-multithumb.html
new file mode 100644
index 0000000000..1617fd6ce2
--- /dev/null
+++ b/examples/slider/slider-multithumb.html
@@ -0,0 +1,279 @@
+
+
+
+
+
+ Horizontal Multi-Thumb Slider Example | WAI-ARIA Authoring Practices 1.2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Horizontal Multi-Thumb Slider Example
+
+
+ WARNING! Some users of touch-based assistive technologies may experience difficulty utilizing widgets that implement this slider pattern because the gestures their assistive technology provides for operating sliders may not yet generate the necessary output.
+ To change the slider value, touch-based assistive technologies need to respond to user gestures for increasing and decreasing the value by synthesizing key events.
+ This is a new convention that may not be fully implemented by some assistive technologies.
+ Authors should fully test slider widgets using assistive technologies on devices where touch is a primary input mechanism before considering incorporation into production systems.
+
+
+
+ The following example of the
+ multi-thumb slider design pattern
+ demonstrates an input for setting a pair of values that represent a range.
+ This example enables users to specify a price range for a hotel reservation by moving the two arrows (thumbs) that represent the minimum and maximum price.
+
+ Similar examples include:
+
+ Color Viewer Slider Example : Basic horizontal sliders that illustrate setting numeric values for a color picker.
+ Vertical Temperature Slider Example : Demonstrates using aria-orientation
to specify vertical orientation and aria-valuetext
to communicate unit of measure for a temperature input.
+ Rating Slider Example : Horizontal slider that demonstrates using aria-valuetext
to communicate current and maximum value of a rating input for a five star rating scale.
+ Media Seek Slider Example : Horizontal slider that demonstrates using aria-valuetext
to communicate current and maximum values of time in media to make the values easy to understand for assistive technology users by converting the total number of seconds to minutes and seconds.
+
+
+
+
+
+
+
Hotel Price Range (in USD )
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+ Accessibility Features
+
+ The display of the slider's current value remains adjacent to the thumb as the thumb is moved, so people with a small field of view (e.g., due to magnification) can easily see the value while focusing on the thumb as they move it.
+ To highlight the interactive nature of the thumb, the focus ring is drawn around the thumb and the value.
+
+ To ensure the borders of the slider rail, thumb and focus ring have sufficient contrast with the background when high contrast settings invert colors, the color of the borders are synchronized with the color of the text content.
+ For example, the color of the focus ring border is set to match the foreground color of high contrast mode text by specifying the CSS currentColor
value for the stroke
property of the inline SVG rect
element used to draw the focus ring border.
+ To make the background of the rect
match the high contrast background color, the fill-opacity
attribute of the rect
is set to zero.
+ If specific colors were instead used to specify the stroke
and fill
properties, those colors would remain the same in high contrast mode, which could lead to insufficient contrast between the rail and the thumb or even make them invisible if their color matched the high contrast mode background.
+ Note: The SVG element needs to have the CSS forced-color-adjust
property set to auto
for the currentColor
value to be updated in high contrast mode.
+ Some browsers do not use auto
for the default value.
+
+
+
+
+
+ Keyboard Support
+
+
+
+ Key
+ Function
+
+
+
+
+ Right Arrow
+ Increases slider value one step.
+
+
+ Up Arrow
+ Increases slider value one step.
+
+
+ Left Arrow
+ Decreases slider value one step.
+
+
+ Down Arrow
+ Decreases slider value one step.
+
+
+ Page Up
+ Increases slider value multiple steps. In this slider, jumps ten steps.
+
+
+ Page Down
+ Decreases slider value multiple steps. In this slider, jumps ten steps.
+
+
+ Home
+ Sets slider to its minimum value.
+
+
+ End
+ Sets slider to its maximum value.
+
+
+
+
+
+ Role, Property, State, and Tabindex Attributes
+
+
+
+ Role
+ Attribute
+ Element
+ Usage
+
+
+
+
+
+ none
+
+
+
+ svg
+
+
+ The use of the none
role on the SVG element ensures assistive technologies do not interpret the SVG element as an image or some other role.
+
+
+
+ slider
+
+
+
+ g
+
+
+
+ Identifies the img
element as a slider.
+ Set on the movable thumb because it is the operable element that receives focus and represents the slider value.
+
+
+
+
+
+
+ tabindex=0
+
+
+ g
+
+ Includes the slider thumb in the page tab sequence.
+
+
+
+
+ aria-valuemax=NUMBER
+
+
+ g
+
+ Specifies the maximum value of the slider.
+
+
+
+
+ aria-valuemin=NUMBER
+
+
+ g
+
+ Specifies the minimum value of the slider.
+
+
+
+
+ aria-valuenow=NUMBER
+
+
+ g
+
+ Indicates the current value of the slider.
+
+
+
+
+ aria-label=text
+
+
+ g
+
+ A label identifying the purpose of the slider, e.g., Hotel Minimum Price .
+
+
+
+
+ aria-hidden=true
+
+
+ g
+
+ Removes the SVG g
element from the accessibility tree to prevent assistive technologies from presenting it as an image separate from the slider.
+
+
+
+
+
+
+ Javascript and CSS Source Code
+
+
+
+
+ HTML Source Code
+
+
+
+
+
+
+
+ Slider (Multi-Thumb) design pattern in WAI-ARIA Authoring Practices 1.2
+
+
+
diff --git a/examples/slider/slider-rating.html b/examples/slider/slider-rating.html
index e05f4d2261..4409d384b6 100644
--- a/examples/slider/slider-rating.html
+++ b/examples/slider/slider-rating.html
@@ -268,7 +268,7 @@ Role, Property, State, and Tabindex Attributes
aria-hidden="true"
svg
- Removes the SVG elements from the accessibility tree. Some assistive technologies will describe the SVG elements, unless they are explicitly hidden.
+ Removes the SVG elements from the accessibility tree to prevent assistive technologies from presenting them as elements separate from the slider.
diff --git a/test/tests/slider_multithumb.js b/test/tests/slider_slider-multithumb.js
similarity index 50%
rename from test/tests/slider_multithumb.js
rename to test/tests/slider_slider-multithumb.js
index 46e6f47827..fd123a667f 100644
--- a/test/tests/slider_multithumb.js
+++ b/test/tests/slider_slider-multithumb.js
@@ -4,22 +4,19 @@ const assertAttributeValues = require('../util/assertAttributeValues');
const assertAriaLabelExists = require('../util/assertAriaLabelExists');
const assertAriaRoles = require('../util/assertAriaRoles');
-const exampleFile = 'slider/multithumb-slider.html';
+const exampleFile = 'slider/slider-multithumb.html';
const ex = {
sliderSelector: '#ex1 [role="slider"]',
- hotelSliderSelector:
- '#ex1 div.aria-widget-slider:nth-of-type(1) [role="slider"]',
- flightSliderSelector:
- '#ex1 div.aria-widget-slider:nth-of-type(2) [role="slider"]',
+ svgSelector: '#ex1 svg',
+ railSelector: '#ex1 g.rail',
+ rangeSelector: '#ex1 g.range',
+ hotelSliderSelector: '#ex1 .slider-multithumb:nth-of-type(1) [role="slider"]',
hotelMin: '0',
hotelMax: '400',
- flightMin: '0',
- flightMax: '1000',
hotelDefaultValues: ['100', '250'],
- flightDefaultValues: ['100', '250'],
- hotelLabelSelector: '#ex1 div.aria-widget-slider:nth-of-type(1) .rail-label',
- flightLabelSelector: '#ex1 div.aria-widget-slider:nth-of-type(2) .rail-label',
+ hotelLabelSelector:
+ '#ex1 .slider-multithumb:nth-of-type(1) [role=slider] .value',
};
const verifyAllValues = async function (
@@ -49,12 +46,34 @@ const verifyAllValues = async function (
// Attributes
+ariaTest('role="none" on SVG element', exampleFile, 'svg-none', async (t) => {
+ await assertAriaRoles(t, 'ex1', 'none', '1', 'svg');
+});
+
+ariaTest(
+ 'SVG g elements used for the rail have aria-hidden',
+ exampleFile,
+ 'aria-hidden-g',
+ async (t) => {
+ await assertAttributeValues(t, ex.railSelector, 'aria-hidden', 'true');
+ }
+);
+
+ariaTest(
+ 'SVG g elements used for the range have aria-hidden',
+ exampleFile,
+ 'aria-hidden-g',
+ async (t) => {
+ await assertAttributeValues(t, ex.rangeSelector, 'aria-hidden', 'true');
+ }
+);
+
ariaTest(
'role="slider" on div element',
exampleFile,
'slider-role',
async (t) => {
- await assertAriaRoles(t, 'ex1', 'slider', '4', 'img');
+ await assertAriaRoles(t, 'ex1', 'slider', '2', 'g');
}
);
@@ -76,10 +95,6 @@ ariaTest(
t,
ex.hotelSliderSelector
);
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
t.is(
await hotelSliders[0].getAttribute('aria-valuemax'),
@@ -93,19 +108,6 @@ ariaTest(
'Value of "aria-valuemax" for second hotel slider on page load should be: ' +
ex.hotelMax
);
- t.is(
- await flightSliders[0].getAttribute('aria-valuemax'),
- ex.flightDefaultValues[1],
- 'Value of "aria-valuemax" for first flight slider on page load should be: ' +
- ex.flightDefaultValues[1]
- );
-
- t.is(
- await flightSliders[1].getAttribute('aria-valuemax'),
- ex.flightMax,
- 'Value of "aria-valuemax" for second flight slider on page load should be: ' +
- ex.flightMax
- );
}
);
@@ -118,10 +120,6 @@ ariaTest(
t,
ex.hotelSliderSelector
);
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
t.is(
await hotelSliders[0].getAttribute('aria-valuemin'),
@@ -134,17 +132,6 @@ ariaTest(
'Value of "aria-valuemin" for second hotel slider on page load should be: ' +
ex.hotelDefaultValues[0]
);
- t.is(
- await flightSliders[0].getAttribute('aria-valuemin'),
- '0',
- 'Value of "aria-valuemin" for first flight slider on page load should be: "0"'
- );
- t.is(
- await flightSliders[1].getAttribute('aria-valuemin'),
- ex.flightDefaultValues[0],
- 'Value of "aria-valuemin" for second flight slider on page load should be: ' +
- ex.flightDefaultValues[0]
- );
}
);
@@ -157,10 +144,6 @@ ariaTest(
t,
ex.hotelSliderSelector
);
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
t.is(
await hotelSliders[0].getAttribute('aria-valuenow'),
@@ -174,59 +157,6 @@ ariaTest(
'Value of "aria-valuenow" for second hotel slider on page load should be: ' +
ex.hotelDefaultValues[1]
);
- t.is(
- await flightSliders[0].getAttribute('aria-valuenow'),
- ex.flightDefaultValues[0],
- 'Value of "aria-valuenow" for first flight slider on page load should be: ' +
- ex.flightDefaultValues[0]
- );
- t.is(
- await flightSliders[1].getAttribute('aria-valuenow'),
- ex.flightDefaultValues[1],
- 'Value of "aria-valuenow" for second flight slider on page load should be: ' +
- ex.flightDefaultValues[1]
- );
- }
-);
-
-ariaTest(
- '"aria-valuetext" reflects slider value',
- exampleFile,
- 'aria-valuetext',
- async (t) => {
- const hotelSliders = await t.context.queryElements(
- t,
- ex.hotelSliderSelector
- );
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
-
- t.is(
- await hotelSliders[0].getAttribute('aria-valuetext'),
- '$' + ex.hotelDefaultValues[0],
- 'Value of "aria-valuetext" for first hotel slider on page load should be: $' +
- ex.hotelDefaultValues[0]
- );
- t.is(
- await hotelSliders[1].getAttribute('aria-valuetext'),
- '$' + ex.hotelDefaultValues[1],
- 'Value of "aria-valuetext" for second hotel slider on page load should be: $' +
- ex.hotelDefaultValues[1]
- );
- t.is(
- await flightSliders[0].getAttribute('aria-valuetext'),
- '$' + ex.flightDefaultValues[0],
- 'Value of "aria-valuetext" for first flight slider on page load should be: $' +
- ex.flightDefaultValues[0]
- );
- t.is(
- await flightSliders[1].getAttribute('aria-valuetext'),
- '$' + ex.flightDefaultValues[1],
- 'Value of "aria-valuetext" for second flight slider on page load should be: $' +
- ex.flightDefaultValues[1]
- );
}
);
@@ -305,69 +235,6 @@ ariaTest(
hotelLabels[1],
'after END then one ARROW RIGHT to upper hotel slider'
);
-
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
- const flightLabels = await t.context.queryElements(
- t,
- ex.flightLabelSelector
- );
-
- // Send 1 key to lower flight slider
- await flightSliders[0].sendKeys(Key.ARROW_RIGHT);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[0]) + 1).toString(),
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after one ARROW RIGHT to lower flight slider'
- );
-
- await flightSliders[0].sendKeys(Key.END, Key.ARROW_RIGHT);
-
- await verifyAllValues(
- t,
- ex.flightDefaultValues[1],
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after END then one ARROW RIGHT to lower flight slider'
- );
-
- // Send 1 key to lower upper slider
- await flightSliders[1].sendKeys(Key.ARROW_RIGHT);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[1]) + 1).toString(),
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after one ARROW RIGHT to lower flight slider'
- );
-
- await flightSliders[1].sendKeys(Key.END, Key.ARROW_RIGHT);
-
- await verifyAllValues(
- t,
- ex.flightMax,
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after END then one ARROW RIGHT to upper flight slider'
- );
}
);
@@ -435,69 +302,6 @@ ariaTest(
hotelLabels[1],
'after END then one ARROW UP to upper hotel slider'
);
-
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
- const flightLabels = await t.context.queryElements(
- t,
- ex.flightLabelSelector
- );
-
- // Send 1 key to lower flight slider
- await flightSliders[0].sendKeys(Key.ARROW_UP);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[0]) + 1).toString(),
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after one ARROW UP to lower flight slider'
- );
-
- await flightSliders[0].sendKeys(Key.END, Key.ARROW_UP);
-
- await verifyAllValues(
- t,
- ex.flightDefaultValues[1],
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after END then one ARROW UP to lower flight slider'
- );
-
- // Send 1 key to lower upper slider
- await flightSliders[1].sendKeys(Key.ARROW_UP);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[1]) + 1).toString(),
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after one ARROW UP to lower flight slider'
- );
-
- await flightSliders[1].sendKeys(Key.END, Key.ARROW_UP);
-
- await verifyAllValues(
- t,
- ex.flightMax,
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after END then one ARROW UP to upper flight slider'
- );
}
);
@@ -565,69 +369,6 @@ ariaTest(
hotelLabels[1],
'after END then one PAGE UP to upper hotel slider'
);
-
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
- const flightLabels = await t.context.queryElements(
- t,
- ex.flightLabelSelector
- );
-
- // Send 1 key to lower flight slider
- await flightSliders[0].sendKeys(Key.PAGE_UP);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[0]) + 10).toString(),
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after one PAGE UP to lower flight slider'
- );
-
- await flightSliders[0].sendKeys(Key.END, Key.PAGE_UP);
-
- await verifyAllValues(
- t,
- ex.flightDefaultValues[1],
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after END then one PAGE UP to lower flight slider'
- );
-
- // Send 1 key to lower upper slider
- await flightSliders[1].sendKeys(Key.PAGE_UP);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[1]) + 10).toString(),
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after one PAGE UP to upper flight slider'
- );
-
- await flightSliders[1].sendKeys(Key.END, Key.PAGE_UP);
-
- await verifyAllValues(
- t,
- ex.flightMax,
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after END then one PAGE UP to upper flight slider'
- );
}
);
@@ -695,69 +436,6 @@ ariaTest(
hotelLabels[1],
'after HOME then one ARROW LEFT to upper hotel slider'
);
-
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
- const flightLabels = await t.context.queryElements(
- t,
- ex.flightLabelSelector
- );
-
- // Send 1 key to lower flight slider
- await flightSliders[0].sendKeys(Key.ARROW_LEFT);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[0]) - 1).toString(),
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after one ARROW LEFT to lower flight slider'
- );
-
- await flightSliders[0].sendKeys(Key.HOME, Key.ARROW_LEFT);
-
- await verifyAllValues(
- t,
- ex.flightMin,
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after HOME then one ARROW LEFT to lower flight slider'
- );
-
- // Send 1 key to lower upper slider
- await flightSliders[1].sendKeys(Key.ARROW_LEFT);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[1]) - 1).toString(),
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after one ARROW LEFT to upper flight slider'
- );
-
- await flightSliders[1].sendKeys(Key.HOME, Key.ARROW_LEFT);
-
- await verifyAllValues(
- t,
- ex.flightMin,
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after HOME then one ARROW LEFT to upper flight slider'
- );
}
);
@@ -825,69 +503,6 @@ ariaTest(
hotelLabels[1],
'after HOME then one ARROW DOWN to upper hotel slider'
);
-
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
- const flightLabels = await t.context.queryElements(
- t,
- ex.flightLabelSelector
- );
-
- // Send 1 key to lower flight slider
- await flightSliders[0].sendKeys(Key.ARROW_DOWN);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[0]) - 1).toString(),
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after one ARROW DOWN to lower flight slider'
- );
-
- await flightSliders[0].sendKeys(Key.HOME, Key.ARROW_DOWN);
-
- await verifyAllValues(
- t,
- ex.flightMin,
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after HOME then one ARROW DOWN to lower flight slider'
- );
-
- // Send 1 key to lower upper slider
- await flightSliders[1].sendKeys(Key.ARROW_DOWN);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[1]) - 1).toString(),
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after one ARROW DOWN to upper flight slider'
- );
-
- await flightSliders[1].sendKeys(Key.HOME, Key.ARROW_DOWN);
-
- await verifyAllValues(
- t,
- ex.flightMin,
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after HOME then one ARROW DOWN to upper flight slider'
- );
}
);
@@ -955,69 +570,6 @@ ariaTest(
hotelLabels[1],
'after HOME then one PAGE DOWN to upper hotel slider'
);
-
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
- const flightLabels = await t.context.queryElements(
- t,
- ex.flightLabelSelector
- );
-
- // Send 1 key to lower flight slider
- await flightSliders[0].sendKeys(Key.PAGE_DOWN);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[0]) - 10).toString(),
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after one PAGE DOWN to lower flight slider'
- );
-
- await flightSliders[0].sendKeys(Key.HOME, Key.PAGE_DOWN);
-
- await verifyAllValues(
- t,
- ex.flightMin,
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after HOME then one PAGE DOWN to lower flight slider'
- );
-
- // Send 1 key to lower upper slider
- await flightSliders[1].sendKeys(Key.PAGE_DOWN);
-
- await verifyAllValues(
- t,
- (parseInt(ex.flightDefaultValues[1]) - 10).toString(),
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after one PAGE DOWN to lower flight slider'
- );
-
- await flightSliders[1].sendKeys(Key.HOME, Key.PAGE_DOWN);
-
- await verifyAllValues(
- t,
- ex.flightMin,
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after HOME then one PAGE DOWN to upper flight slider'
- );
}
);
@@ -1052,40 +604,6 @@ ariaTest('home sends value to minimum', exampleFile, 'key-home', async (t) => {
hotelLabels[0],
'after one HOME to lower hotel slider'
);
-
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
- const flightLabels = await t.context.queryElements(t, ex.flightLabelSelector);
-
- // Send 1 key to upper flight slider
- await flightSliders[1].sendKeys(Key.HOME);
-
- await verifyAllValues(
- t,
- ex.flightDefaultValues[0],
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after one HOME to upper flight slider'
- );
-
- // Send 1 key to upper flight slider
- await flightSliders[0].sendKeys(Key.HOME);
-
- await verifyAllValues(
- t,
- ex.flightMin,
- flightSliders[0],
- 'aria-valuenow',
- flightSliders[1],
- 'aria-valuemin',
- flightLabels[0],
- 'after one HOME to lower flight slider'
- );
});
ariaTest('end sends value to minimum', exampleFile, 'key-end', async (t) => {
@@ -1117,36 +635,4 @@ ariaTest('end sends value to minimum', exampleFile, 'key-end', async (t) => {
hotelLabels[1],
'after one END to upper hotel slider'
);
-
- const flightSliders = await t.context.queryElements(
- t,
- ex.flightSliderSelector
- );
- const flightLabels = await t.context.queryElements(t, ex.flightLabelSelector);
-
- await flightSliders[0].sendKeys(Key.END);
-
- await verifyAllValues(
- t,
- ex.flightDefaultValues[1],
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[0],
- 'after one END to lower flight slider'
- );
-
- await flightSliders[1].sendKeys(Key.END);
-
- await verifyAllValues(
- t,
- ex.flightMax,
- flightSliders[0],
- 'aria-valuemax',
- flightSliders[1],
- 'aria-valuenow',
- flightLabels[1],
- 'after one END to upper flight slider'
- );
});