Skip to content

Commit 4fec3a3

Browse files
GiteaBotsilverwind
andauthored
Add form field id generation, remove duplicated ids (#30546) (#30561)
Backport #30546 by @silverwind 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: silverwind <me@silverwind.io>
1 parent b4a3831 commit 4fec3a3

File tree

5 files changed

+40
-23
lines changed

5 files changed

+40
-23
lines changed

templates/repo/settings/options.tmpl

+10-10
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>
@@ -884,8 +884,8 @@
884884
</label>
885885
</div>
886886
<div class="required field">
887-
<label for="repo_name">{{ctx.Locale.Tr "repo.repo_name"}}</label>
888-
<input id="repo_name" name="repo_name" required maxlength="100">
887+
<label>{{ctx.Locale.Tr "repo.repo_name"}}</label>
888+
<input name="repo_name" required maxlength="100">
889889
</div>
890890

891891
<div class="text right actions">
@@ -915,8 +915,8 @@
915915
</label>
916916
</div>
917917
<div class="required field">
918-
<label for="repo_name">{{ctx.Locale.Tr "repo.repo_name"}}</label>
919-
<input id="repo_name" name="repo_name" required>
918+
<label>{{ctx.Locale.Tr "repo.repo_name"}}</label>
919+
<input name="repo_name" required>
920920
</div>
921921

922922
<div class="text right actions">
@@ -947,8 +947,8 @@
947947
</label>
948948
</div>
949949
<div class="required field">
950-
<label for="repo_name">{{ctx.Locale.Tr "repo.repo_name"}}</label>
951-
<input id="repo_name" name="repo_name" required>
950+
<label>{{ctx.Locale.Tr "repo.repo_name"}}</label>
951+
<input name="repo_name" required>
952952
</div>
953953
<div class="required field">
954954
<label for="new_owner_name">{{ctx.Locale.Tr "repo.settings.transfer_owner"}}</label>
@@ -1017,8 +1017,8 @@
10171017
</label>
10181018
</div>
10191019
<div class="required field">
1020-
<label for="repo_name">{{ctx.Locale.Tr "repo.repo_name"}}</label>
1021-
<input id="repo_name" name="repo_name" required>
1020+
<label>{{ctx.Locale.Tr "repo.repo_name"}}</label>
1021+
<input name="repo_name" required>
10221022
</div>
10231023

10241024
<div class="text right actions">

web_src/js/modules/fomantic.js

+2
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

+13
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+
}
+2-13
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

+13
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)