Skip to content

Commit 4cfd57e

Browse files
authored
Merge pull request #26 from github/clearselection
Avoid clearning selection on ctrlKey
2 parents f1dd8ee + d4ff922 commit 4cfd57e

File tree

3 files changed

+26
-14
lines changed

3 files changed

+26
-14
lines changed

.github/workflows/nodejs.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ on:
66
- master
77
jobs:
88
build:
9-
10-
runs-on: ubuntu-latest
9+
runs-on: ${{ matrix.os }}
1110

1211
strategy:
12+
fail-fast: false
1313
matrix:
14-
node-version: [8.x, 10.x, 12.x]
14+
os: [ubuntu-latest, windows-latest, macos-latest]
1515

1616
steps:
1717
- uses: actions/checkout@v1
18-
- name: Use Node.js ${{ matrix.node-version }}
18+
- name: Use Node.js 12.x
1919
uses: actions/setup-node@v1
2020
with:
21-
node-version: ${{ matrix.node-version }}
21+
node-version: 12.x
2222
- name: npm install, build, and test
2323
run: |
2424
npm install

src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export default class Combobox {
66
input: HTMLTextAreaElement | HTMLInputElement
77
keyboardEventHandler: (event: KeyboardEvent) => void
88
compositionEventHandler: (event: Event) => void
9+
inputHandler: (event: Event) => void
910

1011
constructor(input: HTMLTextAreaElement | HTMLInputElement, list: HTMLElement) {
1112
this.input = input
@@ -20,6 +21,7 @@ export default class Combobox {
2021

2122
this.keyboardEventHandler = event => keyboardBindings(event, this)
2223
this.compositionEventHandler = event => trackComposition(event, this)
24+
this.inputHandler = this.clearSelection.bind(this)
2325
input.setAttribute('role', 'combobox')
2426
input.setAttribute('aria-controls', list.id)
2527
input.setAttribute('aria-expanded', 'false')
@@ -42,6 +44,7 @@ export default class Combobox {
4244
this.input.setAttribute('aria-expanded', 'true')
4345
this.input.addEventListener('compositionstart', this.compositionEventHandler)
4446
this.input.addEventListener('compositionend', this.compositionEventHandler)
47+
this.input.addEventListener('input', this.inputHandler)
4548
;(this.input as HTMLElement).addEventListener('keydown', this.keyboardEventHandler)
4649
this.list.addEventListener('click', commitWithElement)
4750
}
@@ -51,6 +54,7 @@ export default class Combobox {
5154
this.input.setAttribute('aria-expanded', 'false')
5255
this.input.removeEventListener('compositionstart', this.compositionEventHandler)
5356
this.input.removeEventListener('compositionend', this.compositionEventHandler)
57+
this.input.removeEventListener('input', this.inputHandler)
5458
;(this.input as HTMLElement).removeEventListener('keydown', this.keyboardEventHandler)
5559
this.list.removeEventListener('click', commitWithElement)
5660
}
@@ -95,6 +99,7 @@ export default class Combobox {
9599

96100
function keyboardBindings(event: KeyboardEvent, combobox: Combobox) {
97101
if (event.shiftKey || event.metaKey || event.altKey) return
102+
if (!ctrlBindings && event.ctrlKey) return
98103
if (combobox.isComposing) return
99104

100105
switch (event.key) {
@@ -128,6 +133,7 @@ function keyboardBindings(event: KeyboardEvent, combobox: Combobox) {
128133
}
129134
break
130135
default:
136+
if (event.ctrlKey) break
131137
combobox.clearSelection()
132138
}
133139
}

test/test.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import Combobox from '../dist/index.js'
2+
3+
const ctrlBindings = !!navigator.userAgent.match(/Macintosh/)
4+
25
function press(input, key, ctrlKey) {
36
input.dispatchEvent(new KeyboardEvent('keydown', {key, ctrlKey}))
47
}
@@ -105,17 +108,17 @@ describe('combobox-nav', function() {
105108

106109
press(input, 'Enter')
107110

108-
press(input, 'ArrowDown')
111+
ctrlBindings ? press(input, 'n', true) : press(input, 'ArrowDown')
109112
assert.equal(options[2].getAttribute('aria-selected'), 'true')
110113
assert.equal(input.getAttribute('aria-activedescendant'), 'r2-d2')
111114

112-
press(input, 'ArrowDown')
115+
ctrlBindings ? press(input, 'n', true) : press(input, 'ArrowDown')
113116
assert.equal(options[4].getAttribute('aria-selected'), 'true')
114117
assert.equal(input.getAttribute('aria-activedescendant'), 'wall-e')
115118
press(input, 'Enter')
116119
click(document.getElementById('wall-e'))
117120

118-
press(input, 'ArrowDown')
121+
ctrlBindings ? press(input, 'n', true) : press(input, 'ArrowDown')
119122
assert.equal(options[5].getAttribute('aria-selected'), 'true')
120123
assert.equal(input.getAttribute('aria-activedescendant'), 'link')
121124

@@ -127,19 +130,18 @@ describe('combobox-nav', function() {
127130
assert.equal(options[0].getAttribute('aria-selected'), 'true')
128131
assert.equal(input.getAttribute('aria-activedescendant'), 'baymax')
129132

130-
press(input, 'ArrowUp')
133+
ctrlBindings ? press(input, 'p', true) : press(input, 'ArrowUp')
131134
assert(!list.querySelector('[aria-selected=true]'), 'Nothing should be selected')
132135
assert(!input.hasAttribute('aria-activedescendant'), 'Nothing should be selected')
133136

134-
press(input, 'ArrowDown')
135-
press(input, 'ArrowDown')
136-
assert.equal(options[1].getAttribute('aria-selected'), 'true')
137-
assert.equal(input.getAttribute('aria-activedescendant'), 'hubot')
137+
press(input, 'ArrowUp')
138+
assert.equal(options[5].getAttribute('aria-selected'), 'true')
139+
assert.equal(input.getAttribute('aria-activedescendant'), 'link')
138140

139141
press(input, 'Enter')
140142
assert.equal(expectedTargets.length, 2)
141143
assert.equal(expectedTargets[0], 'hubot')
142-
assert.equal(expectedTargets[1], 'hubot')
144+
assert.equal(expectedTargets[1], 'link')
143145
})
144146

145147
it('fires commit events on click', function() {
@@ -171,6 +173,10 @@ describe('combobox-nav', function() {
171173
assert.equal(options[0].getAttribute('aria-selected'), 'true')
172174
assert.equal(input.getAttribute('aria-activedescendant'), 'baymax')
173175

176+
press(input, 'Control', true)
177+
assert.equal(options[0].getAttribute('aria-selected'), 'true', 'Selection stays on modifier keydown')
178+
assert.equal(input.getAttribute('aria-activedescendant'), 'baymax', 'Selection stays on modifier keydown')
179+
174180
press(input, 'Backspace')
175181
assert(!list.querySelector('[aria-selected=true]'), 'Nothing should be selected')
176182
assert(!input.hasAttribute('aria-activedescendant'), 'Nothing should be selected')

0 commit comments

Comments
 (0)