Forbid jQuery `.prop` and fix related issues (#29832)

The issue checkbox code received a few more cleanups and I specifically
tested it. The other changes are trivial. Also, I checked the cases for
how many elements match the jQuery selection to determine querySelector
vs. querySelectorAll.

---------

Co-authored-by: Giteabot <teabot@gitea.io>
pull/28024/head^2
silverwind 8 months ago committed by GitHub
parent cb78648ad9
commit 21fe512aac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      .eslintrc.yaml
  2. 2
      web_src/js/features/admin/common.js
  3. 6
      web_src/js/features/comp/LabelEdit.js
  4. 14
      web_src/js/features/repo-editor.js
  5. 36
      web_src/js/features/repo-issue-list.js
  6. 2
      web_src/js/features/repo-legacy.js

@ -315,7 +315,7 @@ rules:
jquery/no-parent: [0] jquery/no-parent: [0]
jquery/no-parents: [0] jquery/no-parents: [0]
jquery/no-parse-html: [2] jquery/no-parse-html: [2]
jquery/no-prop: [0] jquery/no-prop: [2]
jquery/no-proxy: [2] jquery/no-proxy: [2]
jquery/no-ready: [2] jquery/no-ready: [2]
jquery/no-serialize: [2] jquery/no-serialize: [2]
@ -466,7 +466,7 @@ rules:
no-jquery/no-parse-html: [2] no-jquery/no-parse-html: [2]
no-jquery/no-parse-json: [2] no-jquery/no-parse-json: [2]
no-jquery/no-parse-xml: [2] no-jquery/no-parse-xml: [2]
no-jquery/no-prop: [0] no-jquery/no-prop: [2]
no-jquery/no-proxy: [2] no-jquery/no-proxy: [2]
no-jquery/no-ready-shorthand: [2] no-jquery/no-ready-shorthand: [2]
no-jquery/no-ready: [2] no-jquery/no-ready: [2]

@ -49,7 +49,7 @@ export function initAdminCommon() {
} }
function onUsePagedSearchChange() { function onUsePagedSearchChange() {
if ($('#use_paged_search').prop('checked')) { if (document.getElementById('use_paged_search').checked) {
showElem('.search-page-size'); showElem('.search-page-size');
$('.search-page-size').find('input').attr('required', 'required'); $('.search-page-size').find('input').attr('required', 'required');
} else { } else {

@ -14,7 +14,7 @@ function updateExclusiveLabelEdit(form) {
if (isExclusiveScopeName($nameInput.val())) { if (isExclusiveScopeName($nameInput.val())) {
$exclusiveField.removeClass('muted'); $exclusiveField.removeClass('muted');
$exclusiveField.removeAttr('aria-disabled'); $exclusiveField.removeAttr('aria-disabled');
if ($exclusiveCheckbox.prop('checked') && $exclusiveCheckbox.data('exclusive-warn')) { if ($exclusiveCheckbox[0].checked && $exclusiveCheckbox.data('exclusive-warn')) {
$exclusiveWarning.removeClass('gt-hidden'); $exclusiveWarning.removeClass('gt-hidden');
} else { } else {
$exclusiveWarning.addClass('gt-hidden'); $exclusiveWarning.addClass('gt-hidden');
@ -50,10 +50,10 @@ export function initCompLabelEdit(selector) {
$nameInput.val($(this).data('title')); $nameInput.val($(this).data('title'));
const $isArchivedCheckbox = $('.edit-label .label-is-archived-input'); const $isArchivedCheckbox = $('.edit-label .label-is-archived-input');
$isArchivedCheckbox.prop('checked', this.hasAttribute('data-is-archived')); $isArchivedCheckbox[0].checked = this.hasAttribute('data-is-archived');
const $exclusiveCheckbox = $('.edit-label .label-exclusive-input'); const $exclusiveCheckbox = $('.edit-label .label-exclusive-input');
$exclusiveCheckbox.prop('checked', this.hasAttribute('data-exclusive')); $exclusiveCheckbox[0].checked = this.hasAttribute('data-exclusive');
// Warn when label was previously not exclusive and used in issues // Warn when label was previously not exclusive and used in issues
$exclusiveCheckbox.data('exclusive-warn', $exclusiveCheckbox.data('exclusive-warn',
$(this).data('num-issues') > 0 && $(this).data('num-issues') > 0 &&

@ -67,10 +67,10 @@ export function initRepoEditor() {
$('.js-quick-pull-choice-option').on('change', function () { $('.js-quick-pull-choice-option').on('change', function () {
if ($(this).val() === 'commit-to-new-branch') { if ($(this).val() === 'commit-to-new-branch') {
showElem($('.quick-pull-branch-name')); showElem($('.quick-pull-branch-name'));
$('.quick-pull-branch-name input').prop('required', true); document.querySelector('.quick-pull-branch-name input').required = true;
} else { } else {
hideElem($('.quick-pull-branch-name')); hideElem($('.quick-pull-branch-name'));
$('.quick-pull-branch-name input').prop('required', false); document.querySelector('.quick-pull-branch-name input').required = false;
} }
$('#commit-button').text($(this).attr('button_text')); $('#commit-button').text($(this).attr('button_text'));
}); });
@ -135,13 +135,13 @@ export function initRepoEditor() {
// Using events from https://github.com/codedance/jquery.AreYouSure#advanced-usage // Using events from https://github.com/codedance/jquery.AreYouSure#advanced-usage
// to enable or disable the commit button // to enable or disable the commit button
const $commitButton = $('#commit-button'); const commitButton = document.getElementById('commit-button');
const $editForm = $('.ui.edit.form'); const $editForm = $('.ui.edit.form');
const dirtyFileClass = 'dirty-file'; const dirtyFileClass = 'dirty-file';
// Disabling the button at the start // Disabling the button at the start
if ($('input[name="page_has_posted"]').val() !== 'true') { if ($('input[name="page_has_posted"]').val() !== 'true') {
$commitButton.prop('disabled', true); commitButton.disabled = true;
} }
// Registering a custom listener for the file path and the file content // Registering a custom listener for the file path and the file content
@ -151,7 +151,7 @@ export function initRepoEditor() {
fieldSelector: ':input:not(.commit-form-wrapper :input)', fieldSelector: ':input:not(.commit-form-wrapper :input)',
change() { change() {
const dirty = $(this).hasClass(dirtyFileClass); const dirty = $(this).hasClass(dirtyFileClass);
$commitButton.prop('disabled', !dirty); commitButton.disabled = !dirty;
}, },
}); });
@ -163,7 +163,7 @@ export function initRepoEditor() {
editor.setValue(value); editor.setValue(value);
} }
$commitButton.on('click', (event) => { commitButton?.addEventListener('click', (e) => {
// A modal which asks if an empty file should be committed // A modal which asks if an empty file should be committed
if ($editArea.val().length === 0) { if ($editArea.val().length === 0) {
$('#edit-empty-content-modal').modal({ $('#edit-empty-content-modal').modal({
@ -171,7 +171,7 @@ export function initRepoEditor() {
$('.edit.form').trigger('submit'); $('.edit.form').trigger('submit');
}, },
}).modal('show'); }).modal('show');
event.preventDefault(); e.preventDefault();
} }
}); });
})(); })();

@ -1,6 +1,6 @@
import $ from 'jquery'; import $ from 'jquery';
import {updateIssuesMeta} from './repo-issue.js'; import {updateIssuesMeta} from './repo-issue.js';
import {toggleElem, hideElem} from '../utils/dom.js'; import {toggleElem, hideElem, isElemHidden} from '../utils/dom.js';
import {htmlEscape} from 'escape-goat'; import {htmlEscape} from 'escape-goat';
import {confirmModal} from './comp/ConfirmModal.js'; import {confirmModal} from './comp/ConfirmModal.js';
import {showErrorToast} from '../modules/toast.js'; import {showErrorToast} from '../modules/toast.js';
@ -8,32 +8,42 @@ import {createSortable} from '../modules/sortable.js';
import {DELETE, POST} from '../modules/fetch.js'; import {DELETE, POST} from '../modules/fetch.js';
function initRepoIssueListCheckboxes() { function initRepoIssueListCheckboxes() {
const $issueSelectAll = $('.issue-checkbox-all'); const issueSelectAll = document.querySelector('.issue-checkbox-all');
const $issueCheckboxes = $('.issue-checkbox'); const issueCheckboxes = document.querySelectorAll('.issue-checkbox');
const syncIssueSelectionState = () => { const syncIssueSelectionState = () => {
const $checked = $issueCheckboxes.filter(':checked'); const checkedCheckboxes = Array.from(issueCheckboxes).filter((el) => el.checked);
const anyChecked = $checked.length !== 0; const anyChecked = Boolean(checkedCheckboxes.length);
const allChecked = anyChecked && $checked.length === $issueCheckboxes.length; const allChecked = anyChecked && checkedCheckboxes.length === issueCheckboxes.length;
if (allChecked) { if (allChecked) {
$issueSelectAll.prop({'checked': true, 'indeterminate': false}); issueSelectAll.checked = true;
issueSelectAll.indeterminate = false;
} else if (anyChecked) { } else if (anyChecked) {
$issueSelectAll.prop({'checked': false, 'indeterminate': true}); issueSelectAll.checked = false;
issueSelectAll.indeterminate = true;
} else { } else {
$issueSelectAll.prop({'checked': false, 'indeterminate': false}); issueSelectAll.checked = false;
issueSelectAll.indeterminate = false;
} }
// if any issue is selected, show the action panel, otherwise show the filter panel // if any issue is selected, show the action panel, otherwise show the filter panel
toggleElem($('#issue-filters'), !anyChecked); toggleElem($('#issue-filters'), !anyChecked);
toggleElem($('#issue-actions'), anyChecked); toggleElem($('#issue-actions'), anyChecked);
// there are two panels but only one select-all checkbox, so move the checkbox to the visible panel // there are two panels but only one select-all checkbox, so move the checkbox to the visible panel
$('#issue-filters, #issue-actions').filter(':visible').find('.issue-list-toolbar-left').prepend($issueSelectAll); const panels = document.querySelectorAll('#issue-filters, #issue-actions');
const visiblePanel = Array.from(panels).find((el) => !isElemHidden(el));
const toolbarLeft = visiblePanel.querySelector('.issue-list-toolbar-left');
toolbarLeft.prepend(issueSelectAll);
}; };
$issueCheckboxes.on('change', syncIssueSelectionState); for (const el of issueCheckboxes) {
el.addEventListener('change', syncIssueSelectionState);
}
$issueSelectAll.on('change', () => { issueSelectAll.addEventListener('change', () => {
$issueCheckboxes.prop('checked', $issueSelectAll.is(':checked')); for (const el of issueCheckboxes) {
el.checked = issueSelectAll.checked;
}
syncIssueSelectionState(); syncIssueSelectionState();
}); });

@ -533,7 +533,7 @@ export function initRepository() {
const gitignores = $('input[name="gitignores"]').val(); const gitignores = $('input[name="gitignores"]').val();
const license = $('input[name="license"]').val(); const license = $('input[name="license"]').val();
if (gitignores || license) { if (gitignores || license) {
$('input[name="auto_init"]').prop('checked', true); document.querySelector('input[name="auto_init"]').checked = true;
} }
}); });
} }

Loading…
Cancel
Save