Skip to content

Commit d4ec6b3

Browse files
silverwindGiteaBot
andauthored
Add form field id generation, remove duplicated ids (#30546)
Fixes: #30384 On repo settings page, there id `repo_name` was used 5 times on the same page, some in modal and such. I think we are better off just auto-generating these IDs in the future so that labels link up with their form element. Ideally this id generation would be done in backend in a subtemplate, but seeing that we already have similar JS patches for checkboxes, I took the easy path for now. I also checked that these `#repo_name` were not in use in JS and the only case where this id appears in JS is on the migration page where it's still there. --------- Co-authored-by: Giteabot <[email protected]>
1 parent 3153813 commit d4ec6b3

File tree

5 files changed

+40
-23
lines changed

5 files changed

+40
-23
lines changed

templates/repo/settings/options.tmpl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
{{.CsrfTokenHtml}}
1010
<input type="hidden" name="action" value="update">
1111
<div class="required field {{if .Err_RepoName}}error{{end}}">
12-
<label for="repo_name">{{ctx.Locale.Tr "repo.repo_name"}}</label>
13-
<input id="repo_name" name="repo_name" value="{{.Repository.Name}}" data-repo-name="{{.Repository.Name}}" autofocus required>
12+
<label>{{ctx.Locale.Tr "repo.repo_name"}}</label>
13+
<input name="repo_name" value="{{.Repository.Name}}" data-repo-name="{{.Repository.Name}}" autofocus required>
1414
</div>
1515
<div class="inline field">
1616
<label>{{ctx.Locale.Tr "repo.repo_size"}}</label>
@@ -898,8 +898,8 @@
898898
</label>
899899
</div>
900900
<div class="required field">
901-
<label for="repo_name">{{ctx.Locale.Tr "repo.repo_name"}}</label>
902-
<input id="repo_name" name="repo_name" required maxlength="100">
901+
<label>{{ctx.Locale.Tr "repo.repo_name"}}</label>
902+
<input name="repo_name" required maxlength="100">
903903
</div>
904904

905905
<div class="text right actions">
@@ -929,8 +929,8 @@
929929
</label>
930930
</div>
931931
<div class="required field">
932-
<label for="repo_name">{{ctx.Locale.Tr "repo.repo_name"}}</label>
933-
<input id="repo_name" name="repo_name" required>
932+
<label>{{ctx.Locale.Tr "repo.repo_name"}}</label>
933+
<input name="repo_name" required>
934934
</div>
935935

936936
<div class="text right actions">
@@ -961,8 +961,8 @@
961961
</label>
962962
</div>
963963
<div class="required field">
964-
<label for="repo_name">{{ctx.Locale.Tr "repo.repo_name"}}</label>
965-
<input id="repo_name" name="repo_name" required>
964+
<label>{{ctx.Locale.Tr "repo.repo_name"}}</label>
965+
<input name="repo_name" required>
966966
</div>
967967
<div class="required field">
968968
<label for="new_owner_name">{{ctx.Locale.Tr "repo.settings.transfer_owner"}}</label>
@@ -1031,8 +1031,8 @@
10311031
</label>
10321032
</div>
10331033
<div class="required field">
1034-
<label for="repo_name">{{ctx.Locale.Tr "repo.repo_name"}}</label>
1035-
<input id="repo_name" name="repo_name" required>
1034+
<label>{{ctx.Locale.Tr "repo.repo_name"}}</label>
1035+
<input name="repo_name" required>
10361036
</div>
10371037

10381038
<div class="text right actions">

web_src/js/modules/fomantic.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import $ from 'jquery';
22
import {initFomanticApiPatch} from './fomantic/api.js';
33
import {initAriaCheckboxPatch} from './fomantic/checkbox.js';
4+
import {initAriaFormFieldPatch} from './fomantic/form.js';
45
import {initAriaDropdownPatch} from './fomantic/dropdown.js';
56
import {initAriaModalPatch} from './fomantic/modal.js';
67
import {initFomanticTransition} from './fomantic/transition.js';
@@ -27,6 +28,7 @@ export function initGiteaFomantic() {
2728

2829
// Use the patches to improve accessibility, these patches are designed to be as independent as possible, make it easy to modify or remove in the future.
2930
initAriaCheckboxPatch();
31+
initAriaFormFieldPatch();
3032
initAriaDropdownPatch();
3133
initAriaModalPatch();
3234
}

web_src/js/modules/fomantic/base.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,16 @@ let ariaIdCounter = 0;
33
export function generateAriaId() {
44
return `_aria_auto_id_${ariaIdCounter++}`;
55
}
6+
7+
export function linkLabelAndInput(label, input) {
8+
const labelFor = label.getAttribute('for');
9+
const inputId = input.getAttribute('id');
10+
11+
if (inputId && !labelFor) { // missing "for"
12+
label.setAttribute('for', inputId);
13+
} else if (!inputId && !labelFor) { // missing both "id" and "for"
14+
const id = generateAriaId();
15+
input.setAttribute('id', id);
16+
label.setAttribute('for', id);
17+
}
18+
}
Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {generateAriaId} from './base.js';
1+
import {linkLabelAndInput} from './base.js';
22

33
export function initAriaCheckboxPatch() {
44
// link the label and the input element so it's clickable and accessible
@@ -7,18 +7,7 @@ export function initAriaCheckboxPatch() {
77
const label = el.querySelector('label');
88
const input = el.querySelector('input');
99
if (!label || !input) continue;
10-
const inputId = input.getAttribute('id');
11-
const labelFor = label.getAttribute('for');
12-
13-
if (inputId && !labelFor) { // missing "for"
14-
label.setAttribute('for', inputId);
15-
} else if (!inputId && !labelFor) { // missing both "id" and "for"
16-
const id = generateAriaId();
17-
input.setAttribute('id', id);
18-
label.setAttribute('for', id);
19-
} else {
20-
continue;
21-
}
10+
linkLabelAndInput(label, input);
2211
el.setAttribute('data-checkbox-patched', 'true');
2312
}
2413
}

web_src/js/modules/fomantic/form.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {linkLabelAndInput} from './base.js';
2+
3+
export function initAriaFormFieldPatch() {
4+
// link the label and the input element so it's clickable and accessible
5+
for (const el of document.querySelectorAll('.ui.form .field')) {
6+
if (el.hasAttribute('data-field-patched')) continue;
7+
const label = el.querySelector(':scope > label');
8+
const input = el.querySelector(':scope > input');
9+
if (!label || !input) continue;
10+
linkLabelAndInput(label, input);
11+
el.setAttribute('data-field-patched', 'true');
12+
}
13+
}

0 commit comments

Comments
 (0)