From 507fbf4c3ceffba9143edbe421a134b904210a4c Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 10 Jun 2024 22:49:33 +0200 Subject: [PATCH] Use `querySelector` over alternative DOM methods (#31280) As per https://github.com/go-gitea/gitea/pull/30115#discussion_r1626060164, prefer `querySelector` by enabling [`unicorn/prefer-query-selector`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-query-selector.md) and autofixing all except 10 issues. According to [this](https://old.reddit.com/r/learnjavascript/comments/i0f5o8/performance_of_getelementbyid_vs_queryselector/), querySelector may be faster as well, so it's a win-win. --------- Co-authored-by: wxiaoguang Co-authored-by: Giteabot --- .eslintrc.yaml | 2 +- web_src/js/components/DashboardRepoList.vue | 4 +- web_src/js/components/DiffCommitSelector.vue | 2 +- web_src/js/components/DiffFileList.vue | 4 +- web_src/js/components/DiffFileTree.vue | 2 +- web_src/js/components/RepoActionView.vue | 2 +- .../js/components/RepoActivityTopAuthors.vue | 2 +- .../js/components/RepoBranchTagSelector.vue | 2 +- .../components/ScopedAccessTokenSelector.vue | 12 ++-- web_src/js/features/admin/common.js | 60 +++++++++---------- web_src/js/features/citation.js | 8 +-- web_src/js/features/code-frequency.js | 2 +- web_src/js/features/colorpicker.js | 2 +- web_src/js/features/common-global.js | 4 +- web_src/js/features/common-issue-list.js | 2 +- web_src/js/features/comp/SearchUserBox.js | 2 +- web_src/js/features/comp/WebHookEditor.js | 6 +- web_src/js/features/contributors.js | 2 +- web_src/js/features/copycontent.js | 2 +- web_src/js/features/heatmap.js | 2 +- web_src/js/features/install.js | 16 ++--- web_src/js/features/notification.js | 8 +-- web_src/js/features/pull-view-file.js | 4 +- web_src/js/features/recent-commits.js | 2 +- web_src/js/features/repo-diff-commitselect.js | 2 +- web_src/js/features/repo-diff-filetree.js | 4 +- web_src/js/features/repo-diff.js | 2 +- web_src/js/features/repo-editor.js | 2 +- web_src/js/features/repo-findfile.js | 4 +- web_src/js/features/repo-graph.js | 28 ++++----- web_src/js/features/repo-home.js | 8 +-- web_src/js/features/repo-issue-edit.js | 6 +- web_src/js/features/repo-issue-list.js | 4 +- web_src/js/features/repo-issue-pr-form.js | 2 +- web_src/js/features/repo-issue.js | 14 ++--- web_src/js/features/repo-migrate.js | 8 +-- web_src/js/features/repo-migration.js | 22 +++---- web_src/js/features/repo-projects.js | 14 ++--- web_src/js/features/repo-release.js | 6 +- web_src/js/features/repo-settings.js | 16 ++--- web_src/js/features/sshkey-helper.js | 4 +- web_src/js/features/user-auth-webauthn.js | 6 +- web_src/js/features/user-auth.js | 4 +- web_src/js/features/user-settings.js | 6 +- web_src/js/markup/anchors.js | 9 +-- web_src/js/standalone/devtest.js | 6 +- web_src/js/standalone/swagger.js | 2 +- 47 files changed, 165 insertions(+), 168 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index cbfe0220e..3b25995c0 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -798,7 +798,7 @@ rules: unicorn/prefer-object-has-own: [0] unicorn/prefer-optional-catch-binding: [2] unicorn/prefer-prototype-methods: [0] - unicorn/prefer-query-selector: [0] + unicorn/prefer-query-selector: [2] unicorn/prefer-reflect-apply: [0] unicorn/prefer-regexp-test: [2] unicorn/prefer-set-has: [0] diff --git a/web_src/js/components/DashboardRepoList.vue b/web_src/js/components/DashboardRepoList.vue index 3f9f427cd..23984b316 100644 --- a/web_src/js/components/DashboardRepoList.vue +++ b/web_src/js/components/DashboardRepoList.vue @@ -101,7 +101,7 @@ const sfc = { }, mounted() { - const el = document.getElementById('dashboard-repo-list'); + const el = document.querySelector('#dashboard-repo-list'); this.changeReposFilter(this.reposFilter); $(el).find('.dropdown').dropdown(); nextTick(() => { @@ -330,7 +330,7 @@ const sfc = { }; export function initDashboardRepoList() { - const el = document.getElementById('dashboard-repo-list'); + const el = document.querySelector('#dashboard-repo-list'); if (el) { createApp(sfc).mount(el); } diff --git a/web_src/js/components/DiffCommitSelector.vue b/web_src/js/components/DiffCommitSelector.vue index 352d08573..c28be67e3 100644 --- a/web_src/js/components/DiffCommitSelector.vue +++ b/web_src/js/components/DiffCommitSelector.vue @@ -5,7 +5,7 @@ import {GET} from '../modules/fetch.js'; export default { components: {SvgIcon}, data: () => { - const el = document.getElementById('diff-commit-select'); + const el = document.querySelector('#diff-commit-select'); return { menuVisible: false, isLoading: false, diff --git a/web_src/js/components/DiffFileList.vue b/web_src/js/components/DiffFileList.vue index 916780d91..806c8385b 100644 --- a/web_src/js/components/DiffFileList.vue +++ b/web_src/js/components/DiffFileList.vue @@ -7,10 +7,10 @@ export default { return {store: diffTreeStore()}; }, mounted() { - document.getElementById('show-file-list-btn').addEventListener('click', this.toggleFileList); + document.querySelector('#show-file-list-btn').addEventListener('click', this.toggleFileList); }, unmounted() { - document.getElementById('show-file-list-btn').removeEventListener('click', this.toggleFileList); + document.querySelector('#show-file-list-btn').removeEventListener('click', this.toggleFileList); }, methods: { toggleFileList() { diff --git a/web_src/js/components/DiffFileTree.vue b/web_src/js/components/DiffFileTree.vue index cddfee1e0..fd5120f18 100644 --- a/web_src/js/components/DiffFileTree.vue +++ b/web_src/js/components/DiffFileTree.vue @@ -112,7 +112,7 @@ export default { updateState(visible) { const btn = document.querySelector('.diff-toggle-file-tree-button'); const [toShow, toHide] = btn.querySelectorAll('.icon'); - const tree = document.getElementById('diff-file-tree'); + const tree = document.querySelector('#diff-file-tree'); const newTooltip = btn.getAttribute(visible ? 'data-hide-text' : 'data-show-text'); btn.setAttribute('data-tooltip-content', newTooltip); toggleElem(tree, visible); diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue index 8b39d0504..7f6524c7e 100644 --- a/web_src/js/components/RepoActionView.vue +++ b/web_src/js/components/RepoActionView.vue @@ -325,7 +325,7 @@ const sfc = { export default sfc; export function initRepositoryActionView() { - const el = document.getElementById('repo-action-view'); + const el = document.querySelector('#repo-action-view'); if (!el) return; // TODO: the parent element's full height doesn't work well now, diff --git a/web_src/js/components/RepoActivityTopAuthors.vue b/web_src/js/components/RepoActivityTopAuthors.vue index a41fb61d7..295641f7e 100644 --- a/web_src/js/components/RepoActivityTopAuthors.vue +++ b/web_src/js/components/RepoActivityTopAuthors.vue @@ -51,7 +51,7 @@ const sfc = { }; export function initRepoActivityTopAuthorsChart() { - const el = document.getElementById('repo-activity-top-authors-chart'); + const el = document.querySelector('#repo-activity-top-authors-chart'); if (el) { createApp(sfc).mount(el); } diff --git a/web_src/js/components/RepoBranchTagSelector.vue b/web_src/js/components/RepoBranchTagSelector.vue index 87530225e..d18378bea 100644 --- a/web_src/js/components/RepoBranchTagSelector.vue +++ b/web_src/js/components/RepoBranchTagSelector.vue @@ -85,7 +85,7 @@ const sfc = { this.isViewBranch = false; this.$refs.dropdownRefName.textContent = item.name; if (this.setAction) { - document.getElementById(this.branchForm)?.setAttribute('action', url); + document.querySelector(`#${this.branchForm}`)?.setAttribute('action', url); } else { $(`#${this.branchForm} input[name="refURL"]`).val(url); } diff --git a/web_src/js/components/ScopedAccessTokenSelector.vue b/web_src/js/components/ScopedAccessTokenSelector.vue index 103cc525a..9ff3627c1 100644 --- a/web_src/js/components/ScopedAccessTokenSelector.vue +++ b/web_src/js/components/ScopedAccessTokenSelector.vue @@ -43,25 +43,25 @@ const sfc = { }, mounted() { - document.getElementById('scoped-access-submit').addEventListener('click', this.onClickSubmit); + document.querySelector('#scoped-access-submit').addEventListener('click', this.onClickSubmit); }, unmounted() { - document.getElementById('scoped-access-submit').removeEventListener('click', this.onClickSubmit); + document.querySelector('#scoped-access-submit').removeEventListener('click', this.onClickSubmit); }, methods: { onClickSubmit(e) { e.preventDefault(); - const warningEl = document.getElementById('scoped-access-warning'); + const warningEl = document.querySelector('#scoped-access-warning'); // check that at least one scope has been selected - for (const el of document.getElementsByClassName('access-token-select')) { + for (const el of document.querySelectorAll('.access-token-select')) { if (el.value) { // Hide the error if it was visible from previous attempt. hideElem(warningEl); // Submit the form. - document.getElementById('scoped-access-form').submit(); + document.querySelector('#scoped-access-form').submit(); // Don't show the warning. return; } @@ -78,7 +78,7 @@ export default sfc; * Initialize category toggle sections */ export function initScopedAccessTokenCategories() { - for (const el of document.getElementsByClassName('scoped-access-token-mount')) { + for (const el of document.querySelectorAll('.scoped-access-token-mount')) { createApp({}) .component('scoped-access-token-selector', sfc) .mount(el); diff --git a/web_src/js/features/admin/common.js b/web_src/js/features/admin/common.js index 3c90b546b..429d6a808 100644 --- a/web_src/js/features/admin/common.js +++ b/web_src/js/features/admin/common.js @@ -6,7 +6,7 @@ import {POST} from '../../modules/fetch.js'; const {appSubUrl} = window.config; function onSecurityProtocolChange() { - if (Number(document.getElementById('security_protocol')?.value) > 0) { + if (Number(document.querySelector('#security_protocol')?.value) > 0) { showElem('.has-tls'); } else { hideElem('.has-tls'); @@ -21,34 +21,34 @@ export function initAdminCommon() { // New user if ($('.admin.new.user').length > 0 || $('.admin.edit.user').length > 0) { - document.getElementById('login_type')?.addEventListener('change', function () { + document.querySelector('#login_type')?.addEventListener('change', function () { if (this.value?.substring(0, 1) === '0') { - document.getElementById('user_name')?.removeAttribute('disabled'); - document.getElementById('login_name')?.removeAttribute('required'); + document.querySelector('#user_name')?.removeAttribute('disabled'); + document.querySelector('#login_name')?.removeAttribute('required'); hideElem('.non-local'); showElem('.local'); - document.getElementById('user_name')?.focus(); + document.querySelector('#user_name')?.focus(); if (this.getAttribute('data-password') === 'required') { - document.getElementById('password')?.setAttribute('required', 'required'); + document.querySelector('#password')?.setAttribute('required', 'required'); } } else { if (document.querySelector('.admin.edit.user')) { - document.getElementById('user_name')?.setAttribute('disabled', 'disabled'); + document.querySelector('#user_name')?.setAttribute('disabled', 'disabled'); } - document.getElementById('login_name')?.setAttribute('required', 'required'); + document.querySelector('#login_name')?.setAttribute('required', 'required'); showElem('.non-local'); hideElem('.local'); - document.getElementById('login_name')?.focus(); + document.querySelector('#login_name')?.focus(); - document.getElementById('password')?.removeAttribute('required'); + document.querySelector('#password')?.removeAttribute('required'); } }); } function onUsePagedSearchChange() { const searchPageSizeElements = document.querySelectorAll('.search-page-size'); - if (document.getElementById('use_paged_search').checked) { + if (document.querySelector('#use_paged_search').checked) { showElem('.search-page-size'); for (const el of searchPageSizeElements) { el.querySelector('input')?.setAttribute('required', 'required'); @@ -67,7 +67,7 @@ export function initAdminCommon() { input.removeAttribute('required'); } - const provider = document.getElementById('oauth2_provider').value; + const provider = document.querySelector('#oauth2_provider').value; switch (provider) { case 'openidConnect': document.querySelector('.open_id_connect_auto_discovery_url input').setAttribute('required', 'required'); @@ -91,19 +91,19 @@ export function initAdminCommon() { } function onOAuth2UseCustomURLChange(applyDefaultValues) { - const provider = document.getElementById('oauth2_provider').value; + const provider = document.querySelector('#oauth2_provider').value; hideElem('.oauth2_use_custom_url_field'); for (const input of document.querySelectorAll('.oauth2_use_custom_url_field input[required]')) { input.removeAttribute('required'); } const elProviderCustomUrlSettings = document.querySelector(`#${provider}_customURLSettings`); - if (elProviderCustomUrlSettings && document.getElementById('oauth2_use_custom_url').checked) { + if (elProviderCustomUrlSettings && document.querySelector('#oauth2_use_custom_url').checked) { for (const custom of ['token_url', 'auth_url', 'profile_url', 'email_url', 'tenant']) { if (applyDefaultValues) { - document.getElementById(`oauth2_${custom}`).value = document.getElementById(`${provider}_${custom}`).value; + document.querySelector(`#oauth2_${custom}`).value = document.querySelector(`#${provider}_${custom}`).value; } - const customInput = document.getElementById(`${provider}_${custom}`); + const customInput = document.querySelector(`#${provider}_${custom}`); if (customInput && customInput.getAttribute('data-available') === 'true') { for (const input of document.querySelectorAll(`.oauth2_${custom} input`)) { input.setAttribute('required', 'required'); @@ -115,12 +115,12 @@ export function initAdminCommon() { } function onEnableLdapGroupsChange() { - toggleElem(document.getElementById('ldap-group-options'), $('.js-ldap-group-toggle')[0].checked); + toggleElem(document.querySelector('#ldap-group-options'), $('.js-ldap-group-toggle')[0].checked); } // New authentication if (document.querySelector('.admin.new.authentication')) { - document.getElementById('auth_type')?.addEventListener('change', function () { + document.querySelector('#auth_type')?.addEventListener('change', function () { hideElem('.ldap, .dldap, .smtp, .pam, .oauth2, .has-tls, .search-page-size, .sspi'); for (const input of document.querySelectorAll('.ldap input[required], .binddnrequired input[required], .dldap input[required], .smtp input[required], .pam input[required], .oauth2 input[required], .has-tls input[required], .sspi input[required]')) { @@ -180,25 +180,25 @@ export function initAdminCommon() { } }); $('#auth_type').trigger('change'); - document.getElementById('security_protocol')?.addEventListener('change', onSecurityProtocolChange); - document.getElementById('use_paged_search')?.addEventListener('change', onUsePagedSearchChange); - document.getElementById('oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true)); - document.getElementById('oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(true)); + document.querySelector('#security_protocol')?.addEventListener('change', onSecurityProtocolChange); + document.querySelector('#use_paged_search')?.addEventListener('change', onUsePagedSearchChange); + document.querySelector('#oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true)); + document.querySelector('#oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(true)); $('.js-ldap-group-toggle').on('change', onEnableLdapGroupsChange); } // Edit authentication if (document.querySelector('.admin.edit.authentication')) { - const authType = document.getElementById('auth_type')?.value; + const authType = document.querySelector('#auth_type')?.value; if (authType === '2' || authType === '5') { - document.getElementById('security_protocol')?.addEventListener('change', onSecurityProtocolChange); + document.querySelector('#security_protocol')?.addEventListener('change', onSecurityProtocolChange); $('.js-ldap-group-toggle').on('change', onEnableLdapGroupsChange); onEnableLdapGroupsChange(); if (authType === '2') { - document.getElementById('use_paged_search')?.addEventListener('change', onUsePagedSearchChange); + document.querySelector('#use_paged_search')?.addEventListener('change', onUsePagedSearchChange); } } else if (authType === '6') { - document.getElementById('oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true)); - document.getElementById('oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(false)); + document.querySelector('#oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true)); + document.querySelector('#oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(false)); onOAuth2Change(false); } } @@ -206,13 +206,13 @@ export function initAdminCommon() { if (document.querySelector('.admin.authentication')) { $('#auth_name').on('input', function () { // appSubUrl is either empty or is a path that starts with `/` and doesn't have a trailing slash. - document.getElementById('oauth2-callback-url').textContent = `${window.location.origin}${appSubUrl}/user/oauth2/${encodeURIComponent(this.value)}/callback`; + document.querySelector('#oauth2-callback-url').textContent = `${window.location.origin}${appSubUrl}/user/oauth2/${encodeURIComponent(this.value)}/callback`; }).trigger('input'); } // Notice if (document.querySelector('.admin.notice')) { - const detailModal = document.getElementById('detail-modal'); + const detailModal = document.querySelector('#detail-modal'); // Attach view detail modals $('.view-detail').on('click', function () { @@ -244,7 +244,7 @@ export function initAdminCommon() { break; } }); - document.getElementById('delete-selection')?.addEventListener('click', async function (e) { + document.querySelector('#delete-selection')?.addEventListener('click', async function (e) { e.preventDefault(); this.classList.add('is-loading', 'disabled'); const data = new FormData(); diff --git a/web_src/js/features/citation.js b/web_src/js/features/citation.js index 918a46713..245ba56f8 100644 --- a/web_src/js/features/citation.js +++ b/web_src/js/features/citation.js @@ -27,9 +27,9 @@ export async function initCitationFileCopyContent() { if (!pageData.citationFileContent) return; - const citationCopyApa = document.getElementById('citation-copy-apa'); - const citationCopyBibtex = document.getElementById('citation-copy-bibtex'); - const inputContent = document.getElementById('citation-copy-content'); + const citationCopyApa = document.querySelector('#citation-copy-apa'); + const citationCopyBibtex = document.querySelector('#citation-copy-bibtex'); + const inputContent = document.querySelector('#citation-copy-content'); if ((!citationCopyApa && !citationCopyBibtex) || !inputContent) return; @@ -41,7 +41,7 @@ export async function initCitationFileCopyContent() { citationCopyApa.classList.toggle('primary', !isBibtex); }; - document.getElementById('cite-repo-button')?.addEventListener('click', async (e) => { + document.querySelector('#cite-repo-button')?.addEventListener('click', async (e) => { const dropdownBtn = e.target.closest('.ui.dropdown.button'); dropdownBtn.classList.add('is-loading'); diff --git a/web_src/js/features/code-frequency.js b/web_src/js/features/code-frequency.js index 47e1539dd..da7cd6b2c 100644 --- a/web_src/js/features/code-frequency.js +++ b/web_src/js/features/code-frequency.js @@ -1,7 +1,7 @@ import {createApp} from 'vue'; export async function initRepoCodeFrequency() { - const el = document.getElementById('repo-code-frequency-chart'); + const el = document.querySelector('#repo-code-frequency-chart'); if (!el) return; const {default: RepoCodeFrequency} = await import(/* webpackChunkName: "code-frequency-graph" */'../components/RepoCodeFrequency.vue'); diff --git a/web_src/js/features/colorpicker.js b/web_src/js/features/colorpicker.js index 6d00d908c..a85c04de4 100644 --- a/web_src/js/features/colorpicker.js +++ b/web_src/js/features/colorpicker.js @@ -1,7 +1,7 @@ import {createTippy} from '../modules/tippy.js'; export async function initColorPickers() { - const els = document.getElementsByClassName('js-color-picker-input'); + const els = document.querySelectorAll('.js-color-picker-input'); if (!els.length) return; await Promise.all([ diff --git a/web_src/js/features/common-global.js b/web_src/js/features/common-global.js index 5162c7150..1ab2a5569 100644 --- a/web_src/js/features/common-global.js +++ b/web_src/js/features/common-global.js @@ -24,8 +24,8 @@ export function initGlobalFormDirtyLeaveConfirm() { } export function initHeadNavbarContentToggle() { - const navbar = document.getElementById('navbar'); - const btn = document.getElementById('navbar-expand-toggle'); + const navbar = document.querySelector('#navbar'); + const btn = document.querySelector('#navbar-expand-toggle'); if (!navbar || !btn) return; btn.addEventListener('click', () => { diff --git a/web_src/js/features/common-issue-list.js b/web_src/js/features/common-issue-list.js index 219a8a9c9..707776487 100644 --- a/web_src/js/features/common-issue-list.js +++ b/web_src/js/features/common-issue-list.js @@ -29,7 +29,7 @@ export function parseIssueListQuickGotoLink(repoLink, searchText) { } export function initCommonIssueListQuickGoto() { - const goto = document.getElementById('issue-list-quick-goto'); + const goto = document.querySelector('#issue-list-quick-goto'); if (!goto) return; const form = goto.closest('form'); diff --git a/web_src/js/features/comp/SearchUserBox.js b/web_src/js/features/comp/SearchUserBox.js index 081c47425..7ef23fe4b 100644 --- a/web_src/js/features/comp/SearchUserBox.js +++ b/web_src/js/features/comp/SearchUserBox.js @@ -5,7 +5,7 @@ const {appSubUrl} = window.config; const looksLikeEmailAddressCheck = /^\S+@\S+$/; export function initCompSearchUserBox() { - const searchUserBox = document.getElementById('search-user-box'); + const searchUserBox = document.querySelector('#search-user-box'); if (!searchUserBox) return; const $searchUserBox = $(searchUserBox); diff --git a/web_src/js/features/comp/WebHookEditor.js b/web_src/js/features/comp/WebHookEditor.js index d74b59fd2..38ff75e5a 100644 --- a/web_src/js/features/comp/WebHookEditor.js +++ b/web_src/js/features/comp/WebHookEditor.js @@ -23,18 +23,18 @@ export function initCompWebHookEditor() { } // some webhooks (like Gitea) allow to set the request method (GET/POST), and it would toggle the "Content Type" field - const httpMethodInput = document.getElementById('http_method'); + const httpMethodInput = document.querySelector('#http_method'); if (httpMethodInput) { const updateContentType = function () { const visible = httpMethodInput.value === 'POST'; - toggleElem(document.getElementById('content_type').closest('.field'), visible); + toggleElem(document.querySelector('#content_type').closest('.field'), visible); }; updateContentType(); httpMethodInput.addEventListener('change', updateContentType); } // Test delivery - document.getElementById('test-delivery')?.addEventListener('click', async function () { + document.querySelector('#test-delivery')?.addEventListener('click', async function () { this.classList.add('is-loading', 'disabled'); await POST(this.getAttribute('data-link')); setTimeout(() => { diff --git a/web_src/js/features/contributors.js b/web_src/js/features/contributors.js index 79b3389fe..475c66e90 100644 --- a/web_src/js/features/contributors.js +++ b/web_src/js/features/contributors.js @@ -1,7 +1,7 @@ import {createApp} from 'vue'; export async function initRepoContributors() { - const el = document.getElementById('repo-contributors-chart'); + const el = document.querySelector('#repo-contributors-chart'); if (!el) return; const {default: RepoContributors} = await import(/* webpackChunkName: "contributors-graph" */'../components/RepoContributors.vue'); diff --git a/web_src/js/features/copycontent.js b/web_src/js/features/copycontent.js index 03efe0070..ea1e5cf7d 100644 --- a/web_src/js/features/copycontent.js +++ b/web_src/js/features/copycontent.js @@ -6,7 +6,7 @@ import {GET} from '../modules/fetch.js'; const {i18n} = window.config; export function initCopyContent() { - const btn = document.getElementById('copy-content'); + const btn = document.querySelector('#copy-content'); if (!btn || btn.classList.contains('disabled')) return; btn.addEventListener('click', async () => { diff --git a/web_src/js/features/heatmap.js b/web_src/js/features/heatmap.js index 719eeb75f..9155e844a 100644 --- a/web_src/js/features/heatmap.js +++ b/web_src/js/features/heatmap.js @@ -3,7 +3,7 @@ import ActivityHeatmap from '../components/ActivityHeatmap.vue'; import {translateMonth, translateDay} from '../utils.js'; export function initHeatmap() { - const el = document.getElementById('user-heatmap'); + const el = document.querySelector('#user-heatmap'); if (!el) return; try { diff --git a/web_src/js/features/install.js b/web_src/js/features/install.js index 54ba3778f..6354db6cd 100644 --- a/web_src/js/features/install.js +++ b/web_src/js/features/install.js @@ -22,12 +22,12 @@ function initPreInstall() { mssql: '127.0.0.1:1433', }; - const dbHost = document.getElementById('db_host'); - const dbUser = document.getElementById('db_user'); - const dbName = document.getElementById('db_name'); + const dbHost = document.querySelector('#db_host'); + const dbUser = document.querySelector('#db_user'); + const dbName = document.querySelector('#db_name'); // Database type change detection. - document.getElementById('db_type').addEventListener('change', function () { + document.querySelector('#db_type').addEventListener('change', function () { const dbType = this.value; hideElem('div[data-db-setting-for]'); showElem(`div[data-db-setting-for=${dbType}]`); @@ -46,14 +46,14 @@ function initPreInstall() { } } // else: for SQLite3, the default path is always prepared by backend code (setting) }); - document.getElementById('db_type').dispatchEvent(new Event('change')); + document.querySelector('#db_type').dispatchEvent(new Event('change')); - const appUrl = document.getElementById('app_url'); + const appUrl = document.querySelector('#app_url'); if (appUrl.value.includes('://localhost')) { appUrl.value = window.location.href; } - const domain = document.getElementById('domain'); + const domain = document.querySelector('#domain'); if (domain.value.trim() === 'localhost') { domain.value = window.location.hostname; } @@ -103,7 +103,7 @@ function initPreInstall() { } function initPostInstall() { - const el = document.getElementById('goto-user-login'); + const el = document.querySelector('#goto-user-login'); if (!el) return; const targetUrl = el.getAttribute('href'); diff --git a/web_src/js/features/notification.js b/web_src/js/features/notification.js index f045879de..c22fc1730 100644 --- a/web_src/js/features/notification.js +++ b/web_src/js/features/notification.js @@ -7,13 +7,13 @@ const {appSubUrl, notificationSettings, assetVersionEncoded} = window.config; let notificationSequenceNumber = 0; export function initNotificationsTable() { - const table = document.getElementById('notification_table'); + const table = document.querySelector('#notification_table'); if (!table) return; // when page restores from bfcache, delete previously clicked items window.addEventListener('pageshow', (e) => { if (e.persisted) { // page was restored from bfcache - const table = document.getElementById('notification_table'); + const table = document.querySelector('#notification_table'); const unreadCountEl = document.querySelector('.notifications-unread-count'); let unreadCount = parseInt(unreadCountEl.textContent); for (const item of table.querySelectorAll('.notifications-item[data-remove="true"]')) { @@ -145,7 +145,7 @@ async function updateNotificationCountWithCallback(callback, timeout, lastCount) } async function updateNotificationTable() { - const notificationDiv = document.getElementById('notification_div'); + const notificationDiv = document.querySelector('#notification_div'); if (notificationDiv) { try { const params = new URLSearchParams(window.location.search); @@ -181,7 +181,7 @@ async function updateNotificationCount() { toggleElem('.notification_count', data.new !== 0); - for (const el of document.getElementsByClassName('notification_count')) { + for (const el of document.querySelectorAll('.notification_count')) { el.textContent = `${data.new}`; } diff --git a/web_src/js/features/pull-view-file.js b/web_src/js/features/pull-view-file.js index 2472e5a0b..84c5eddb4 100644 --- a/web_src/js/features/pull-view-file.js +++ b/web_src/js/features/pull-view-file.js @@ -12,9 +12,9 @@ const collapseFilesBtnSelector = '#collapse-files-btn'; // Refreshes the summary of viewed files if present // The data used will be window.config.pageData.prReview.numberOf{Viewed}Files function refreshViewedFilesSummary() { - const viewedFilesProgress = document.getElementById('viewed-files-summary'); + const viewedFilesProgress = document.querySelector('#viewed-files-summary'); viewedFilesProgress?.setAttribute('value', prReview.numberOfViewedFiles); - const summaryLabel = document.getElementById('viewed-files-summary-label'); + const summaryLabel = document.querySelector('#viewed-files-summary-label'); if (summaryLabel) summaryLabel.innerHTML = summaryLabel.getAttribute('data-text-changed-template') .replace('%[1]d', prReview.numberOfViewedFiles) .replace('%[2]d', prReview.numberOfFiles); diff --git a/web_src/js/features/recent-commits.js b/web_src/js/features/recent-commits.js index 030c251a0..b7f7c4998 100644 --- a/web_src/js/features/recent-commits.js +++ b/web_src/js/features/recent-commits.js @@ -1,7 +1,7 @@ import {createApp} from 'vue'; export async function initRepoRecentCommits() { - const el = document.getElementById('repo-recent-commits-chart'); + const el = document.querySelector('#repo-recent-commits-chart'); if (!el) return; const {default: RepoRecentCommits} = await import(/* webpackChunkName: "recent-commits-graph" */'../components/RepoRecentCommits.vue'); diff --git a/web_src/js/features/repo-diff-commitselect.js b/web_src/js/features/repo-diff-commitselect.js index ebac64e85..2d0d63946 100644 --- a/web_src/js/features/repo-diff-commitselect.js +++ b/web_src/js/features/repo-diff-commitselect.js @@ -2,7 +2,7 @@ import {createApp} from 'vue'; import DiffCommitSelector from '../components/DiffCommitSelector.vue'; export function initDiffCommitSelect() { - const el = document.getElementById('diff-commit-select'); + const el = document.querySelector('#diff-commit-select'); if (!el) return; const commitSelect = createApp(DiffCommitSelector); diff --git a/web_src/js/features/repo-diff-filetree.js b/web_src/js/features/repo-diff-filetree.js index 5dd2c42e7..6d9533d06 100644 --- a/web_src/js/features/repo-diff-filetree.js +++ b/web_src/js/features/repo-diff-filetree.js @@ -3,13 +3,13 @@ import DiffFileTree from '../components/DiffFileTree.vue'; import DiffFileList from '../components/DiffFileList.vue'; export function initDiffFileTree() { - const el = document.getElementById('diff-file-tree'); + const el = document.querySelector('#diff-file-tree'); if (!el) return; const fileTreeView = createApp(DiffFileTree); fileTreeView.mount(el); - const fileListElement = document.getElementById('diff-file-list'); + const fileListElement = document.querySelector('#diff-file-list'); if (!fileListElement) return; const fileListView = createApp(DiffFileList); diff --git a/web_src/js/features/repo-diff.js b/web_src/js/features/repo-diff.js index 00f74515d..cd01232a7 100644 --- a/web_src/js/features/repo-diff.js +++ b/web_src/js/features/repo-diff.js @@ -13,7 +13,7 @@ import {POST, GET} from '../modules/fetch.js'; const {pageData, i18n} = window.config; function initRepoDiffReviewButton() { - const reviewBox = document.getElementById('review-box'); + const reviewBox = document.querySelector('#review-box'); if (!reviewBox) return; const counter = reviewBox.querySelector('.review-comments-counter'); diff --git a/web_src/js/features/repo-editor.js b/web_src/js/features/repo-editor.js index b4fae4f6a..aa9ca657b 100644 --- a/web_src/js/features/repo-editor.js +++ b/web_src/js/features/repo-editor.js @@ -112,7 +112,7 @@ export function initRepoEditor() { // Using events from https://github.com/codedance/jquery.AreYouSure#advanced-usage // to enable or disable the commit button - const commitButton = document.getElementById('commit-button'); + const commitButton = document.querySelector('#commit-button'); const $editForm = $('.ui.edit.form'); const dirtyFileClass = 'dirty-file'; diff --git a/web_src/js/features/repo-findfile.js b/web_src/js/features/repo-findfile.js index cff5068a1..945eeecef 100644 --- a/web_src/js/features/repo-findfile.js +++ b/web_src/js/features/repo-findfile.js @@ -106,11 +106,11 @@ async function loadRepoFiles() { } export function initFindFileInRepo() { - repoFindFileInput = document.getElementById('repo-file-find-input'); + repoFindFileInput = document.querySelector('#repo-file-find-input'); if (!repoFindFileInput) return; repoFindFileTableBody = document.querySelector('#repo-find-file-table tbody'); - repoFindFileNoResult = document.getElementById('repo-find-file-no-result'); + repoFindFileNoResult = document.querySelector('#repo-find-file-no-result'); repoFindFileInput.addEventListener('input', () => filterRepoFiles(repoFindFileInput.value)); loadRepoFiles(); diff --git a/web_src/js/features/repo-graph.js b/web_src/js/features/repo-graph.js index 0086b9202..7084e4097 100644 --- a/web_src/js/features/repo-graph.js +++ b/web_src/js/features/repo-graph.js @@ -3,12 +3,12 @@ import {hideElem, showElem} from '../utils/dom.js'; import {GET} from '../modules/fetch.js'; export function initRepoGraphGit() { - const graphContainer = document.getElementById('git-graph-container'); + const graphContainer = document.querySelector('#git-graph-container'); if (!graphContainer) return; - document.getElementById('flow-color-monochrome')?.addEventListener('click', () => { - document.getElementById('flow-color-monochrome').classList.add('active'); - document.getElementById('flow-color-colored')?.classList.remove('active'); + document.querySelector('#flow-color-monochrome')?.addEventListener('click', () => { + document.querySelector('#flow-color-monochrome').classList.add('active'); + document.querySelector('#flow-color-colored')?.classList.remove('active'); graphContainer.classList.remove('colored'); graphContainer.classList.add('monochrome'); const params = new URLSearchParams(window.location.search); @@ -30,9 +30,9 @@ export function initRepoGraphGit() { } }); - document.getElementById('flow-color-colored')?.addEventListener('click', () => { - document.getElementById('flow-color-colored').classList.add('active'); - document.getElementById('flow-color-monochrome')?.classList.remove('active'); + document.querySelector('#flow-color-colored')?.addEventListener('click', () => { + document.querySelector('#flow-color-colored').classList.add('active'); + document.querySelector('#flow-color-monochrome')?.classList.remove('active'); graphContainer.classList.add('colored'); graphContainer.classList.remove('monochrome'); for (const link of document.querySelectorAll('.pagination a')) { @@ -60,7 +60,7 @@ export function initRepoGraphGit() { const ajaxUrl = new URL(url); ajaxUrl.searchParams.set('div-only', 'true'); window.history.replaceState({}, '', queryString ? `?${queryString}` : window.location.pathname); - document.getElementById('pagination').innerHTML = ''; + document.querySelector('#pagination').innerHTML = ''; hideElem('#rel-container'); hideElem('#rev-container'); showElem('#loading-indicator'); @@ -69,9 +69,9 @@ export function initRepoGraphGit() { const html = await response.text(); const div = document.createElement('div'); div.innerHTML = html; - document.getElementById('pagination').innerHTML = div.getElementById('pagination').innerHTML; - document.getElementById('rel-container').innerHTML = div.getElementById('rel-container').innerHTML; - document.getElementById('rev-container').innerHTML = div.getElementById('rev-container').innerHTML; + document.querySelector('#pagination').innerHTML = div.querySelector('#pagination').innerHTML; + document.querySelector('#rel-container').innerHTML = div.querySelector('#rel-container').innerHTML; + document.querySelector('#rev-container').innerHTML = div.querySelector('#rev-container').innerHTML; hideElem('#loading-indicator'); showElem('#rel-container'); showElem('#rev-container'); @@ -82,7 +82,7 @@ export function initRepoGraphGit() { dropdownSelected.splice(0, 0, '...flow-hide-pr-refs'); } - const flowSelectRefsDropdown = document.getElementById('flow-select-refs-dropdown'); + const flowSelectRefsDropdown = document.querySelector('#flow-select-refs-dropdown'); $(flowSelectRefsDropdown).dropdown('set selected', dropdownSelected); $(flowSelectRefsDropdown).dropdown({ clearable: true, @@ -115,7 +115,7 @@ export function initRepoGraphGit() { if (e.target.matches('#rev-list li')) { const flow = e.target.getAttribute('data-flow'); if (flow === '0') return; - document.getElementById(`flow-${flow}`)?.classList.add('highlight'); + document.querySelector(`#flow-${flow}`)?.classList.add('highlight'); e.target.classList.add('hover'); for (const item of document.querySelectorAll(`#rev-list li[data-flow='${flow}']`)) { item.classList.add('highlight'); @@ -136,7 +136,7 @@ export function initRepoGraphGit() { if (e.target.matches('#rev-list li')) { const flow = e.target.getAttribute('data-flow'); if (flow === '0') return; - document.getElementById(`flow-${flow}`)?.classList.remove('highlight'); + document.querySelector(`#flow-${flow}`)?.classList.remove('highlight'); e.target.classList.remove('hover'); for (const item of document.querySelectorAll(`#rev-list li[data-flow='${flow}']`)) { item.classList.remove('highlight'); diff --git a/web_src/js/features/repo-home.js b/web_src/js/features/repo-home.js index 6a5bce826..f48c1b1bb 100644 --- a/web_src/js/features/repo-home.js +++ b/web_src/js/features/repo-home.js @@ -7,11 +7,11 @@ import {showErrorToast} from '../modules/toast.js'; const {appSubUrl} = window.config; export function initRepoTopicBar() { - const mgrBtn = document.getElementById('manage_topic'); + const mgrBtn = document.querySelector('#manage_topic'); if (!mgrBtn) return; - const editDiv = document.getElementById('topic_edit'); - const viewDiv = document.getElementById('repo-topics'); + const editDiv = document.querySelector('#topic_edit'); + const viewDiv = document.querySelector('#repo-topics'); const topicDropdown = editDiv.querySelector('.ui.dropdown'); let lastErrorToast; @@ -28,7 +28,7 @@ export function initRepoTopicBar() { mgrBtn.focus(); }); - document.getElementById('save_topic').addEventListener('click', async (e) => { + document.querySelector('#save_topic').addEventListener('click', async (e) => { lastErrorToast?.hideToast(); const topics = editDiv.querySelector('input[name=topics]').value; diff --git a/web_src/js/features/repo-issue-edit.js b/web_src/js/features/repo-issue-edit.js index 29b96f512..8d43b6620 100644 --- a/web_src/js/features/repo-issue-edit.js +++ b/web_src/js/features/repo-issue-edit.js @@ -55,7 +55,7 @@ async function onEditContent(event) { dropzone.querySelector('.files').append(input); }); this.on('removedfile', async (file) => { - document.getElementById(file.uuid)?.remove(); + document.querySelector(`#${file.uuid}`)?.remove(); if (disableRemovedfileEvent) return; if (dropzone.getAttribute('data-remove-url') && !fileUuidDict[file.uuid].submitted) { try { @@ -137,7 +137,7 @@ async function onEditContent(event) { } editContentZone.setAttribute('data-content-version', data.contentVersion); if (!data.content) { - renderContent.innerHTML = document.getElementById('no-content').innerHTML; + renderContent.innerHTML = document.querySelector('#no-content').innerHTML; rawContent.textContent = ''; } else { renderContent.innerHTML = data.content; @@ -166,7 +166,7 @@ async function onEditContent(event) { comboMarkdownEditor = getComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor')); if (!comboMarkdownEditor) { - editContentZone.innerHTML = document.getElementById('issue-comment-editor-template').innerHTML; + editContentZone.innerHTML = document.querySelector('#issue-comment-editor-template').innerHTML; comboMarkdownEditor = await initComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor')); comboMarkdownEditor.attachedDropzoneInst = await setupDropzone(editContentZone.querySelector('.dropzone')); editContentZone.querySelector('.ui.cancel.button').addEventListener('click', cancelAndReset); diff --git a/web_src/js/features/repo-issue-list.js b/web_src/js/features/repo-issue-list.js index 5d18a7ff8..c8ae91d45 100644 --- a/web_src/js/features/repo-issue-list.js +++ b/web_src/js/features/repo-issue-list.js @@ -158,7 +158,7 @@ function initRepoIssueListAuthorDropdown() { } function initPinRemoveButton() { - for (const button of document.getElementsByClassName('issue-card-unpin')) { + for (const button of document.querySelectorAll('.issue-card-unpin')) { button.addEventListener('click', async (event) => { const el = event.currentTarget; const id = Number(el.getAttribute('data-issue-id')); @@ -182,7 +182,7 @@ async function pinMoveEnd(e) { } async function initIssuePinSort() { - const pinDiv = document.getElementById('issue-pins'); + const pinDiv = document.querySelector('#issue-pins'); if (pinDiv === null) return; diff --git a/web_src/js/features/repo-issue-pr-form.js b/web_src/js/features/repo-issue-pr-form.js index 7b26e643c..94a285734 100644 --- a/web_src/js/features/repo-issue-pr-form.js +++ b/web_src/js/features/repo-issue-pr-form.js @@ -2,7 +2,7 @@ import {createApp} from 'vue'; import PullRequestMergeForm from '../components/PullRequestMergeForm.vue'; export function initRepoPullRequestMergeForm() { - const el = document.getElementById('pull-request-merge-form'); + const el = document.querySelector('#pull-request-merge-form'); if (!el) return; const view = createApp(PullRequestMergeForm); diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js index 3cbbdc41f..d53c3346f 100644 --- a/web_src/js/features/repo-issue.js +++ b/web_src/js/features/repo-issue.js @@ -44,14 +44,14 @@ export function initRepoIssueTimeTracking() { async function updateDeadline(deadlineString) { hideElem('#deadline-err-invalid-date'); - document.getElementById('deadline-loader')?.classList.add('is-loading'); + document.querySelector('#deadline-loader')?.classList.add('is-loading'); let realDeadline = null; if (deadlineString !== '') { const newDate = Date.parse(deadlineString); if (Number.isNaN(newDate)) { - document.getElementById('deadline-loader')?.classList.remove('is-loading'); + document.querySelector('#deadline-loader')?.classList.remove('is-loading'); showElem('#deadline-err-invalid-date'); return false; } @@ -59,7 +59,7 @@ async function updateDeadline(deadlineString) { } try { - const response = await POST(document.getElementById('update-issue-deadline-form').getAttribute('action'), { + const response = await POST(document.querySelector('#update-issue-deadline-form').getAttribute('action'), { data: {due_date: realDeadline}, }); @@ -70,7 +70,7 @@ async function updateDeadline(deadlineString) { } } catch (error) { console.error(error); - document.getElementById('deadline-loader').classList.remove('is-loading'); + document.querySelector('#deadline-loader').classList.remove('is-loading'); showElem('#deadline-err-invalid-date'); } } @@ -182,7 +182,7 @@ export function initRepoIssueCommentDelete() { counter.textContent = String(num); } - document.getElementById(deleteButton.getAttribute('data-comment-id'))?.remove(); + document.querySelector(`#${deleteButton.getAttribute('data-comment-id')}`)?.remove(); if (conversationHolder && !conversationHolder.querySelector('.comment')) { const path = conversationHolder.getAttribute('data-path'); @@ -298,7 +298,7 @@ export function initRepoPullRequestMergeInstruction() { } export function initRepoPullRequestAllowMaintainerEdit() { - const wrapper = document.getElementById('allow-edits-from-maintainers'); + const wrapper = document.querySelector('#allow-edits-from-maintainers'); if (!wrapper) return; const checkbox = wrapper.querySelector('input[type="checkbox"]'); checkbox.addEventListener('input', async () => { @@ -678,7 +678,7 @@ export function initSingleCommentEditor($commentForm) { // * normal new issue/pr page, no status-button // * issue/pr view page, with comment form, has status-button const opts = {}; - const statusButton = document.getElementById('status-button'); + const statusButton = document.querySelector('#status-button'); if (statusButton) { opts.onContentChanged = (editor) => { const statusText = statusButton.getAttribute(editor.value().trim() ? 'data-status-and-comment' : 'data-status'); diff --git a/web_src/js/features/repo-migrate.js b/web_src/js/features/repo-migrate.js index 490e7df0e..b8157e2da 100644 --- a/web_src/js/features/repo-migrate.js +++ b/web_src/js/features/repo-migrate.js @@ -4,10 +4,10 @@ import {GET, POST} from '../modules/fetch.js'; const {appSubUrl} = window.config; export function initRepoMigrationStatusChecker() { - const repoMigrating = document.getElementById('repo_migrating'); + const repoMigrating = document.querySelector('#repo_migrating'); if (!repoMigrating) return; - document.getElementById('repo_migrating_retry').addEventListener('click', doMigrationRetry); + document.querySelector('#repo_migrating_retry').addEventListener('click', doMigrationRetry); const task = repoMigrating.getAttribute('data-migrating-task-id'); @@ -20,7 +20,7 @@ export function initRepoMigrationStatusChecker() { // for all status if (data.message) { - document.getElementById('repo_migrating_progress_message').textContent = data.message; + document.querySelector('#repo_migrating_progress_message').textContent = data.message; } // TaskStatusFinished @@ -36,7 +36,7 @@ export function initRepoMigrationStatusChecker() { showElem('#repo_migrating_retry'); showElem('#repo_migrating_failed'); showElem('#repo_migrating_failed_image'); - document.getElementById('repo_migrating_failed_error').textContent = data.message; + document.querySelector('#repo_migrating_failed_error').textContent = data.message; return false; } diff --git a/web_src/js/features/repo-migration.js b/web_src/js/features/repo-migration.js index 59e282e4e..7f7aa237e 100644 --- a/web_src/js/features/repo-migration.js +++ b/web_src/js/features/repo-migration.js @@ -1,13 +1,13 @@ import {hideElem, showElem, toggleElem} from '../utils/dom.js'; -const service = document.getElementById('service_type'); -const user = document.getElementById('auth_username'); -const pass = document.getElementById('auth_password'); -const token = document.getElementById('auth_token'); -const mirror = document.getElementById('mirror'); -const lfs = document.getElementById('lfs'); -const lfsSettings = document.getElementById('lfs_settings'); -const lfsEndpoint = document.getElementById('lfs_endpoint'); +const service = document.querySelector('#service_type'); +const user = document.querySelector('#auth_username'); +const pass = document.querySelector('#auth_password'); +const token = document.querySelector('#auth_token'); +const mirror = document.querySelector('#mirror'); +const lfs = document.querySelector('#lfs'); +const lfsSettings = document.querySelector('#lfs_settings'); +const lfsEndpoint = document.querySelector('#lfs_endpoint'); const items = document.querySelectorAll('#migrate_items input[type=checkbox]'); export function initRepoMigration() { @@ -18,16 +18,16 @@ export function initRepoMigration() { pass?.addEventListener('input', () => {checkItems(false)}); token?.addEventListener('input', () => {checkItems(true)}); mirror?.addEventListener('change', () => {checkItems(true)}); - document.getElementById('lfs_settings_show')?.addEventListener('click', (e) => { + document.querySelector('#lfs_settings_show')?.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); showElem(lfsEndpoint); }); lfs?.addEventListener('change', setLFSSettingsVisibility); - const cloneAddr = document.getElementById('clone_addr'); + const cloneAddr = document.querySelector('#clone_addr'); cloneAddr?.addEventListener('change', () => { - const repoName = document.getElementById('repo_name'); + const repoName = document.querySelector('#repo_name'); if (cloneAddr.value && !repoName?.value) { // Only modify if repo_name input is blank repoName.value = cloneAddr.value.match(/^(.*\/)?((.+?)(\.git)?)$/)[3]; } diff --git a/web_src/js/features/repo-projects.js b/web_src/js/features/repo-projects.js index a1cc4b346..706942363 100644 --- a/web_src/js/features/repo-projects.js +++ b/web_src/js/features/repo-projects.js @@ -5,8 +5,8 @@ import {POST, DELETE, PUT} from '../modules/fetch.js'; function updateIssueCount(cards) { const parent = cards.parentElement; - const cnt = parent.getElementsByClassName('issue-card').length; - parent.getElementsByClassName('project-column-issue-count')[0].textContent = cnt; + const cnt = parent.querySelectorAll('.issue-card').length; + parent.querySelectorAll('.project-column-issue-count')[0].textContent = cnt; } async function createNewColumn(url, columnTitle, projectColorInput) { @@ -26,7 +26,7 @@ async function createNewColumn(url, columnTitle, projectColorInput) { } async function moveIssue({item, from, to, oldIndex}) { - const columnCards = to.getElementsByClassName('issue-card'); + const columnCards = to.querySelectorAll('.issue-card'); updateIssueCount(from); updateIssueCount(to); @@ -53,7 +53,7 @@ async function initRepoProjectSortable() { // the HTML layout is: #project-board > .board > .project-column .cards > .issue-card const mainBoard = els[0]; - let boardColumns = mainBoard.getElementsByClassName('project-column'); + let boardColumns = mainBoard.querySelectorAll('.project-column'); createSortable(mainBoard, { group: 'project-column', draggable: '.project-column', @@ -61,7 +61,7 @@ async function initRepoProjectSortable() { delayOnTouchOnly: true, delay: 500, onSort: async () => { - boardColumns = mainBoard.getElementsByClassName('project-column'); + boardColumns = mainBoard.querySelectorAll('.project-column'); const columnSorting = { columns: Array.from(boardColumns, (column, i) => ({ @@ -81,7 +81,7 @@ async function initRepoProjectSortable() { }); for (const boardColumn of boardColumns) { - const boardCardList = boardColumn.getElementsByClassName('cards')[0]; + const boardCardList = boardColumn.querySelectorAll('.cards')[0]; createSortable(boardCardList, { group: 'shared', onAdd: moveIssue, @@ -99,7 +99,7 @@ export function initRepoProject() { const _promise = initRepoProjectSortable(); - for (const modal of document.getElementsByClassName('edit-project-column-modal')) { + for (const modal of document.querySelectorAll('.edit-project-column-modal')) { const projectHeader = modal.closest('.project-column-header'); const projectTitleLabel = projectHeader?.querySelector('.project-column-title-label'); const projectTitleInput = modal.querySelector('.project-column-title-input'); diff --git a/web_src/js/features/repo-release.js b/web_src/js/features/repo-release.js index f3cfa7441..2be1ec58c 100644 --- a/web_src/js/features/repo-release.js +++ b/web_src/js/features/repo-release.js @@ -20,7 +20,7 @@ export function initRepoReleaseNew() { } function initTagNameEditor() { - const el = document.getElementById('tag-name-editor'); + const el = document.querySelector('#tag-name-editor'); if (!el) return; const existingTags = JSON.parse(el.getAttribute('data-existing-tags')); @@ -30,10 +30,10 @@ function initTagNameEditor() { const newTagHelperText = el.getAttribute('data-tag-helper-new'); const existingTagHelperText = el.getAttribute('data-tag-helper-existing'); - const tagNameInput = document.getElementById('tag-name'); + const tagNameInput = document.querySelector('#tag-name'); const hideTargetInput = function(tagNameInput) { const value = tagNameInput.value; - const tagHelper = document.getElementById('tag-helper'); + const tagHelper = document.querySelector('#tag-helper'); if (existingTags.includes(value)) { // If the tag already exists, hide the target branch selector. hideElem('#tag-target-selector'); diff --git a/web_src/js/features/repo-settings.js b/web_src/js/features/repo-settings.js index 652f8ac29..6590c2b56 100644 --- a/web_src/js/features/repo-settings.js +++ b/web_src/js/features/repo-settings.js @@ -44,7 +44,7 @@ export function initRepoSettingsCollaboration() { } export function initRepoSettingSearchTeamBox() { - const searchTeamBox = document.getElementById('search-team-box'); + const searchTeamBox = document.querySelector('#search-team-box'); if (!searchTeamBox) return; $(searchTeamBox).search({ @@ -78,29 +78,29 @@ export function initRepoSettingGitHook() { export function initRepoSettingBranches() { if (!document.querySelector('.repository.settings.branches')) return; - for (const el of document.getElementsByClassName('toggle-target-enabled')) { + for (const el of document.querySelectorAll('.toggle-target-enabled')) { el.addEventListener('change', function () { const target = document.querySelector(this.getAttribute('data-target')); target?.classList.toggle('disabled', !this.checked); }); } - for (const el of document.getElementsByClassName('toggle-target-disabled')) { + for (const el of document.querySelectorAll('.toggle-target-disabled')) { el.addEventListener('change', function () { const target = document.querySelector(this.getAttribute('data-target')); if (this.checked) target?.classList.add('disabled'); // only disable, do not auto enable }); } - document.getElementById('dismiss_stale_approvals')?.addEventListener('change', function () { - document.getElementById('ignore_stale_approvals_box')?.classList.toggle('disabled', this.checked); + document.querySelector('#dismiss_stale_approvals')?.addEventListener('change', function () { + document.querySelector('#ignore_stale_approvals_box')?.classList.toggle('disabled', this.checked); }); // show the `Matched` mark for the status checks that match the pattern const markMatchedStatusChecks = () => { - const patterns = (document.getElementById('status_check_contexts').value || '').split(/[\r\n]+/); + const patterns = (document.querySelector('#status_check_contexts').value || '').split(/[\r\n]+/); const validPatterns = patterns.map((item) => item.trim()).filter(Boolean); - const marks = document.getElementsByClassName('status-check-matched-mark'); + const marks = document.querySelectorAll('.status-check-matched-mark'); for (const el of marks) { let matched = false; @@ -115,5 +115,5 @@ export function initRepoSettingBranches() { } }; markMatchedStatusChecks(); - document.getElementById('status_check_contexts').addEventListener('input', onInputDebounce(markMatchedStatusChecks)); + document.querySelector('#status_check_contexts').addEventListener('input', onInputDebounce(markMatchedStatusChecks)); } diff --git a/web_src/js/features/sshkey-helper.js b/web_src/js/features/sshkey-helper.js index 3960eefe8..5531c1845 100644 --- a/web_src/js/features/sshkey-helper.js +++ b/web_src/js/features/sshkey-helper.js @@ -1,8 +1,8 @@ export function initSshKeyFormParser() { // Parse SSH Key - document.getElementById('ssh-key-content')?.addEventListener('input', function () { + document.querySelector('#ssh-key-content')?.addEventListener('input', function () { const arrays = this.value.split(' '); - const title = document.getElementById('ssh-key-title'); + const title = document.querySelector('#ssh-key-title'); if (!title.value && arrays.length === 3 && arrays[2] !== '') { title.value = arrays[2]; } diff --git a/web_src/js/features/user-auth-webauthn.js b/web_src/js/features/user-auth-webauthn.js index 6dfbb4d76..ea26614ba 100644 --- a/web_src/js/features/user-auth-webauthn.js +++ b/web_src/js/features/user-auth-webauthn.js @@ -109,7 +109,7 @@ async function webauthnRegistered(newCredential) { } function webAuthnError(errorType, message) { - const elErrorMsg = document.getElementById(`webauthn-error-msg`); + const elErrorMsg = document.querySelector(`#webauthn-error-msg`); if (errorType === 'general') { elErrorMsg.textContent = message || 'unknown error'; @@ -140,7 +140,7 @@ function detectWebAuthnSupport() { } export function initUserAuthWebAuthnRegister() { - const elRegister = document.getElementById('register-webauthn'); + const elRegister = document.querySelector('#register-webauthn'); if (!elRegister) { return; } @@ -155,7 +155,7 @@ export function initUserAuthWebAuthnRegister() { } async function webAuthnRegisterRequest() { - const elNickname = document.getElementById('nickname'); + const elNickname = document.querySelector('#nickname'); const formData = new FormData(); formData.append('name', elNickname.value); diff --git a/web_src/js/features/user-auth.js b/web_src/js/features/user-auth.js index a871ac471..1ea131e75 100644 --- a/web_src/js/features/user-auth.js +++ b/web_src/js/features/user-auth.js @@ -1,9 +1,9 @@ import {checkAppUrl} from './common-global.js'; export function initUserAuthOauth2() { - const outer = document.getElementById('oauth2-login-navigator'); + const outer = document.querySelector('#oauth2-login-navigator'); if (!outer) return; - const inner = document.getElementById('oauth2-login-navigator-inner'); + const inner = document.querySelector('#oauth2-login-navigator-inner'); checkAppUrl(); diff --git a/web_src/js/features/user-settings.js b/web_src/js/features/user-settings.js index 2d8c53e45..8cb1f0582 100644 --- a/web_src/js/features/user-settings.js +++ b/web_src/js/features/user-settings.js @@ -3,11 +3,11 @@ import {hideElem, showElem} from '../utils/dom.js'; export function initUserSettings() { if (!document.querySelectorAll('.user.settings.profile').length) return; - const usernameInput = document.getElementById('username'); + const usernameInput = document.querySelector('#username'); if (!usernameInput) return; usernameInput.addEventListener('input', function () { - const prompt = document.getElementById('name-change-prompt'); - const promptRedirect = document.getElementById('name-change-redirect-prompt'); + const prompt = document.querySelector('#name-change-prompt'); + const promptRedirect = document.querySelector('#name-change-redirect-prompt'); if (this.value.toLowerCase() !== this.getAttribute('data-name').toLowerCase()) { showElem(prompt); showElem(promptRedirect); diff --git a/web_src/js/markup/anchors.js b/web_src/js/markup/anchors.js index 0e2c92713..6f36d0968 100644 --- a/web_src/js/markup/anchors.js +++ b/web_src/js/markup/anchors.js @@ -9,19 +9,16 @@ function scrollToAnchor(encodedId) { if (!encodedId) return; const id = decodeURIComponent(encodedId); const prefixedId = addPrefix(id); - let el = document.getElementById(prefixedId); + let el = document.querySelector(`#${prefixedId}`); // check for matching user-generated `a[name]` if (!el) { - const nameAnchors = document.getElementsByName(prefixedId); - if (nameAnchors.length) { - el = nameAnchors[0]; - } + el = document.querySelector(`a[name="${CSS.escape(prefixedId)}"]`); } // compat for links with old 'user-content-' prefixed hashes if (!el && hasPrefix(id)) { - return document.getElementById(id)?.scrollIntoView(); + return document.querySelector(`#${id}`)?.scrollIntoView(); } el?.scrollIntoView(); diff --git a/web_src/js/standalone/devtest.js b/web_src/js/standalone/devtest.js index d0ca511c0..8dbba554a 100644 --- a/web_src/js/standalone/devtest.js +++ b/web_src/js/standalone/devtest.js @@ -1,11 +1,11 @@ import {showInfoToast, showWarningToast, showErrorToast} from '../modules/toast.js'; -document.getElementById('info-toast').addEventListener('click', () => { +document.querySelector('#info-toast').addEventListener('click', () => { showInfoToast('success 😀'); }); -document.getElementById('warning-toast').addEventListener('click', () => { +document.querySelector('#warning-toast').addEventListener('click', () => { showWarningToast('warning 😐'); }); -document.getElementById('error-toast').addEventListener('click', () => { +document.querySelector('#error-toast').addEventListener('click', () => { showErrorToast('error 🙁'); }); diff --git a/web_src/js/standalone/swagger.js b/web_src/js/standalone/swagger.js index 00854ef5d..292881316 100644 --- a/web_src/js/standalone/swagger.js +++ b/web_src/js/standalone/swagger.js @@ -2,7 +2,7 @@ import SwaggerUI from 'swagger-ui-dist/swagger-ui-es-bundle.js'; import 'swagger-ui-dist/swagger-ui.css'; window.addEventListener('load', async () => { - const url = document.getElementById('swagger-ui').getAttribute('data-source'); + const url = document.querySelector('#swagger-ui').getAttribute('data-source'); const res = await fetch(url); const spec = await res.json();