From 2a65da304447adc7a05e8aa1c96e1395b947ee6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violet=20Pe=C3=B1a?= Date: Wed, 31 Aug 2022 13:18:32 -0700 Subject: [PATCH 1/4] Radio inputs - fix arrow button functionality --- src/event/behavior/keydown.ts | 4 ++-- src/event/radio.ts | 39 ++++++++++++++++++++++----------- tests/event/behavior/keydown.ts | 19 ++++++++++++---- 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/event/behavior/keydown.ts b/src/event/behavior/keydown.ts index 6927deef..1305ca0c 100644 --- a/src/event/behavior/keydown.ts +++ b/src/event/behavior/keydown.ts @@ -28,7 +28,7 @@ const keydownBehavior: { ArrowDown: (event, target, instance) => { /* istanbul ignore else */ if (isElementType(target, 'input', {type: 'radio'} as const)) { - return () => walkRadio(instance, target, -1) + return () => walkRadio(instance, target, 1) } }, ArrowLeft: (event, target, instance) => { @@ -46,7 +46,7 @@ const keydownBehavior: { ArrowUp: (event, target, instance) => { /* istanbul ignore else */ if (isElementType(target, 'input', {type: 'radio'} as const)) { - return () => walkRadio(instance, target, 1) + return () => walkRadio(instance, target, -1) } }, Backspace: (event, target, instance) => { diff --git a/src/event/radio.ts b/src/event/radio.ts index 9c31098a..73445cc8 100644 --- a/src/event/radio.ts +++ b/src/event/radio.ts @@ -2,6 +2,11 @@ import type {Instance} from '../setup' import {getWindow, isDisabled} from '../utils' import {focusElement} from './focus' +function setNewActiveRadio(instance: Instance, el: HTMLInputElement & {type: 'radio'}) { + focusElement(el) + instance.dispatchUIEvent(el, 'click') +} + export function walkRadio( instance: Instance, el: HTMLInputElement & {type: 'radio'}, @@ -14,19 +19,27 @@ export function walkRadio( ? `input[type="radio"][name="${window.CSS.escape(el.name)}"]` : `input[type="radio"][name=""], input[type="radio"]:not([name])`, ), - ) - for (let i = group.findIndex(e => e === el) + direction; ; i += direction) { - if (!group[i]) { - i = direction > 0 ? 0 : group.length - 1 - } - if (group[i] === el) { - return - } - if (isDisabled(group[i])) { - continue + ).filter(elt => !isDisabled(elt)) + // 1 or 0 radio buttons found + if (group.length <= 1) { + return; + } + const nextRadioIndex = group.indexOf(el) + direction; + // Multiple radio buttons + if (direction === 1) { + // Moving forwards in group + if (nextRadioIndex < group.length) { + // Don't need to wrap around + return setNewActiveRadio(instance, group[nextRadioIndex]) } - - focusElement(group[i]) - instance.dispatchUIEvent(group[i], 'click') + // Special case: do need to wrap around + return setNewActiveRadio(instance, group[0]) + } + // Moving backwards in group + if (nextRadioIndex >= 0) { + // Don't need to wrap around + return setNewActiveRadio(instance, group[nextRadioIndex]) } + // Special case: do need to wrap around + setNewActiveRadio(instance, group[group.length - 1]) } diff --git a/tests/event/behavior/keydown.ts b/tests/event/behavior/keydown.ts index 42feb6c0..632c8165 100644 --- a/tests/event/behavior/keydown.ts +++ b/tests/event/behavior/keydown.ts @@ -318,6 +318,7 @@ cases( + `, {focus}, @@ -359,15 +360,25 @@ cases( key: 'ArrowUp', expectedTarget: '//input[@value="a"]', }, - 'forward around the corner': { - focus: '//input[@value="d"]', + 'ArrowRight around the corner': { + focus: '//input[@value="e"]', key: 'ArrowRight', expectedTarget: '//input[@value="a"]', }, - 'backward around the corner': { + 'ArrowLeft around the corner': { + focus: '//input[@value="a"]', + key: 'ArrowLeft', + expectedTarget: '//input[@value="e"]', + }, + 'ArrowUp around the corner': { focus: '//input[@value="a"]', key: 'ArrowUp', - expectedTarget: '//input[@value="d"]', + expectedTarget: '//input[@value="e"]', + }, + 'ArrowDown around the corner': { + focus: '//input[@value="e"]', + key: 'ArrowDown', + expectedTarget: '//input[@value="a"]', }, 'do nothing on single radio': { focus: '//input[@name="solo"]', From ab0f7e15403a4680747e372b8e731e38a8dcf833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violet=20Pe=C3=B1a?= Date: Wed, 31 Aug 2022 16:09:36 -0700 Subject: [PATCH 2/4] Simplify. --- src/event/radio.ts | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/event/radio.ts b/src/event/radio.ts index 73445cc8..488d7039 100644 --- a/src/event/radio.ts +++ b/src/event/radio.ts @@ -2,11 +2,6 @@ import type {Instance} from '../setup' import {getWindow, isDisabled} from '../utils' import {focusElement} from './focus' -function setNewActiveRadio(instance: Instance, el: HTMLInputElement & {type: 'radio'}) { - focusElement(el) - instance.dispatchUIEvent(el, 'click') -} - export function walkRadio( instance: Instance, el: HTMLInputElement & {type: 'radio'}, @@ -24,22 +19,8 @@ export function walkRadio( if (group.length <= 1) { return; } - const nextRadioIndex = group.indexOf(el) + direction; - // Multiple radio buttons - if (direction === 1) { - // Moving forwards in group - if (nextRadioIndex < group.length) { - // Don't need to wrap around - return setNewActiveRadio(instance, group[nextRadioIndex]) - } - // Special case: do need to wrap around - return setNewActiveRadio(instance, group[0]) - } - // Moving backwards in group - if (nextRadioIndex >= 0) { - // Don't need to wrap around - return setNewActiveRadio(instance, group[nextRadioIndex]) - } - // Special case: do need to wrap around - setNewActiveRadio(instance, group[group.length - 1]) + // Multiple buttons found + const nextRadioElement = group[(group.indexOf(el) + direction + group.length) % group.length]; + focusElement(nextRadioElement) + instance.dispatchUIEvent(nextRadioElement, 'click') } From 1ccaf2b7fb604125a0f4711eec904b7ee7d4a435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violet=20Pe=C3=B1a?= Date: Thu, 1 Sep 2022 11:05:29 -0700 Subject: [PATCH 3/4] Remove redundant tests. --- tests/event/behavior/keydown.ts | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/tests/event/behavior/keydown.ts b/tests/event/behavior/keydown.ts index 632c8165..9c05bd8b 100644 --- a/tests/event/behavior/keydown.ts +++ b/tests/event/behavior/keydown.ts @@ -360,26 +360,16 @@ cases( key: 'ArrowUp', expectedTarget: '//input[@value="a"]', }, - 'ArrowRight around the corner': { + 'forward around the corner': { focus: '//input[@value="e"]', key: 'ArrowRight', expectedTarget: '//input[@value="a"]', }, - 'ArrowLeft around the corner': { + 'backward around the corner': { focus: '//input[@value="a"]', key: 'ArrowLeft', expectedTarget: '//input[@value="e"]', }, - 'ArrowUp around the corner': { - focus: '//input[@value="a"]', - key: 'ArrowUp', - expectedTarget: '//input[@value="e"]', - }, - 'ArrowDown around the corner': { - focus: '//input[@value="e"]', - key: 'ArrowDown', - expectedTarget: '//input[@value="a"]', - }, 'do nothing on single radio': { focus: '//input[@name="solo"]', key: 'ArrowRight', From cd07f09ac5b3530dbd8765774d8ca5a2c66eaa8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violet=20Pe=C3=B1a?= Date: Thu, 1 Sep 2022 11:08:54 -0700 Subject: [PATCH 4/4] Update src/event/radio.ts Co-authored-by: Philipp Fritsche --- src/event/radio.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/event/radio.ts b/src/event/radio.ts index 488d7039..da717515 100644 --- a/src/event/radio.ts +++ b/src/event/radio.ts @@ -14,13 +14,20 @@ export function walkRadio( ? `input[type="radio"][name="${window.CSS.escape(el.name)}"]` : `input[type="radio"][name=""], input[type="radio"]:not([name])`, ), - ).filter(elt => !isDisabled(elt)) - // 1 or 0 radio buttons found - if (group.length <= 1) { - return; + ) + for (let i = group.findIndex(e => e === el) + direction; ; i += direction) { + if (!group[i]) { + i = direction > 0 ? 0 : group.length - 1 + } + if (group[i] === el) { + return + } + if (isDisabled(group[i])) { + continue + } + + focusElement(group[i]) + instance.dispatchUIEvent(group[i], 'click') + return } - // Multiple buttons found - const nextRadioElement = group[(group.indexOf(el) + direction + group.length) % group.length]; - focusElement(nextRadioElement) - instance.dispatchUIEvent(nextRadioElement, 'click') }