Skip to content

Commit f7d1bf3

Browse files
authored
A11y rule no-onchange (#4788)
* A11y rule no-onchange * Fix message * Fix tests * Removing declarations
1 parent 40dca52 commit f7d1bf3

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

src/compiler/compile/nodes/Element.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ const a11y_required_content = new Set([
5656
'h6'
5757
]);
5858

59+
const a11y_no_onchange = new Set([
60+
'select',
61+
'option'
62+
]);
63+
5964
const invisible_elements = new Set(['meta', 'html', 'script', 'style']);
6065

6166
const valid_modifiers = new Set([
@@ -424,13 +429,18 @@ export default class Element extends Node {
424429
}
425430

426431
validate_special_cases() {
427-
const { component,attributes } = this;
432+
const { component, attributes, handlers } = this;
428433
const attribute_map = new Map();
434+
const handlers_map = new Map();
429435

430436
attributes.forEach(attribute => (
431437
attribute_map.set(attribute.name, attribute)
432438
));
433439

440+
handlers.forEach(handler => (
441+
handlers_map.set(handler.name, handler)
442+
));
443+
434444
if (this.name === 'a') {
435445
const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
436446
const id_attribute = attribute_map.get('id');
@@ -496,6 +506,15 @@ export default class Element extends Node {
496506
}
497507
}
498508
}
509+
510+
if (a11y_no_onchange.has(this.name)) {
511+
if (handlers_map.has('change') && !handlers_map.has('blur')) {
512+
component.warn(this, {
513+
code: `a11y-no-onchange`,
514+
message: `A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.`
515+
});
516+
}
517+
}
499518
}
500519

501520
validate_bindings() {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<select on:change={e => {}}>
2+
<option>foo</option>
3+
<option>bar</option>
4+
</select>
5+
<select on:change={e => {}} on:blur={e => {}}>
6+
<option>foo</option>
7+
<option>bar</option>
8+
</select>
9+
<select>
10+
<option on:change={e => {}}>foo</option>
11+
<option>bar</option>
12+
</select>
13+
<select>
14+
<option on:change={e => {}} on:blur={e => {}}>foo</option>
15+
<option>bar</option>
16+
</select>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[
2+
{
3+
"code": "a11y-no-onchange",
4+
"end": {
5+
"character": 88,
6+
"column": 9,
7+
"line": 4
8+
},
9+
"message": "A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.",
10+
"pos": 0,
11+
"start": {
12+
"character": 0,
13+
"column": 0,
14+
"line": 1
15+
}
16+
},
17+
{
18+
"code": "a11y-no-onchange",
19+
"end": {
20+
"character": 249,
21+
"column": 44,
22+
"line": 10
23+
},
24+
"message": "A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.",
25+
"pos": 209,
26+
"start": {
27+
"character": 209,
28+
"column": 4,
29+
"line": 10
30+
}
31+
}
32+
]

0 commit comments

Comments
 (0)