From e0b018706fa7703ef1759d9a75a1399383715808 Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Tue, 26 Mar 2024 21:33:32 +0200 Subject: [PATCH] Remove jQuery `.attr` from the common issue page functions (#30083) - Switched from jQuery `attr` to plain javascript `getAttribute` and `setAttribute` - Tested most of the functions and they work as before --------- Signed-off-by: Yarden Shoham Co-authored-by: silverwind Co-authored-by: delvh --- web_src/js/features/repo-issue.js | 156 ++++++++++++++++-------------- 1 file changed, 83 insertions(+), 73 deletions(-) diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js index 20a854fb47..47b4d5f71c 100644 --- a/web_src/js/features/repo-issue.js +++ b/web_src/js/features/repo-issue.js @@ -42,23 +42,23 @@ export function initRepoIssueTimeTracking() { } async function updateDeadline(deadlineString) { - hideElem($('#deadline-err-invalid-date')); - $('#deadline-loader').addClass('is-loading'); + hideElem('#deadline-err-invalid-date'); + document.getElementById('deadline-loader')?.classList.add('is-loading'); let realDeadline = null; if (deadlineString !== '') { const newDate = Date.parse(deadlineString); if (Number.isNaN(newDate)) { - $('#deadline-loader').removeClass('is-loading'); - showElem($('#deadline-err-invalid-date')); + document.getElementById('deadline-loader')?.classList.remove('is-loading'); + showElem('#deadline-err-invalid-date'); return false; } realDeadline = new Date(newDate); } try { - const response = await POST($('#update-issue-deadline-form').attr('action'), { + const response = await POST(document.getElementById('update-issue-deadline-form').getAttribute('action'), { data: {due_date: realDeadline}, }); @@ -69,8 +69,8 @@ async function updateDeadline(deadlineString) { } } catch (error) { console.error(error); - $('#deadline-loader').removeClass('is-loading'); - showElem($('#deadline-err-invalid-date')); + document.getElementById('deadline-loader').classList.remove('is-loading'); + showElem('#deadline-err-invalid-date'); } } @@ -87,6 +87,19 @@ export function initRepoIssueDue() { }); } +/** + * @param {HTMLElement} item + */ +function excludeLabel(item) { + const href = item.getAttribute('href'); + const id = item.getAttribute('data-label-id'); + + const regStr = `labels=((?:-?[0-9]+%2c)*)(${id})((?:%2c-?[0-9]+)*)&`; + const newStr = 'labels=$1-$2$3&'; + + window.location = href.replace(new RegExp(regStr), newStr); +} + export function initRepoIssueSidebarList() { const repolink = $('#repolink').val(); const repoId = $('#repoId').val(); @@ -123,16 +136,6 @@ export function initRepoIssueSidebarList() { fullTextSearch: true, }); - function excludeLabel(item) { - const href = $(item).attr('href'); - const id = $(item).data('label-id'); - - const regStr = `labels=((?:-?[0-9]+%2c)*)(${id})((?:%2c-?[0-9]+)*)&`; - const newStr = 'labels=$1-$2$3&'; - - window.location = href.replace(new RegExp(regStr), newStr); - } - $('.menu a.label-filter-item').each(function () { $(this).on('click', function (e) { if (e.altKey) { @@ -144,9 +147,9 @@ export function initRepoIssueSidebarList() { $('.menu .ui.dropdown.label-filter').on('keydown', (e) => { if (e.altKey && e.keyCode === 13) { - const $selectedItems = $('.menu .ui.dropdown.label-filter .menu .item.selected'); - if ($selectedItems.length > 0) { - excludeLabel($($selectedItems[0])); + const selectedItem = document.querySelector('.menu .ui.dropdown.label-filter .menu .item.selected'); + if (selectedItem) { + excludeLabel(selectedItem); } } }); @@ -166,11 +169,11 @@ export function initRepoIssueCommentDelete() { const $parentTimelineGroup = $this.closest('.timeline-item-group'); // Check if this was a pending comment. if ($conversationHolder.find('.pending-label').length) { - const $counter = $('#review-box .review-comments-counter'); - let num = parseInt($counter.attr('data-pending-comment-number')) - 1 || 0; + const counter = document.querySelector('#review-box .review-comments-counter'); + let num = parseInt(counter?.getAttribute('data-pending-comment-number')) - 1 || 0; num = Math.max(num, 0); - $counter.attr('data-pending-comment-number', num); - $counter.text(num); + counter.setAttribute('data-pending-comment-number', num); + counter.textContent = String(num); } $(`#${$this.data('comment-id')}`).remove(); @@ -279,14 +282,16 @@ export function initRepoPullRequestMergeInstruction() { } export function initRepoPullRequestAllowMaintainerEdit() { - const $checkbox = $('#allow-edits-from-maintainers'); - if (!$checkbox.length) return; + const checkbox = document.getElementById('allow-edits-from-maintainers'); + if (!checkbox) return; - const promptError = $checkbox.attr('data-prompt-error'); + const $checkbox = $(checkbox); + + const promptError = checkbox.getAttribute('data-prompt-error'); $checkbox.checkbox({ 'onChange': async () => { const checked = $checkbox.checkbox('is checked'); - let url = $checkbox.attr('data-url'); + let url = checkbox.getAttribute('data-url'); url += '/set_allow_maintainer_edit'; $checkbox.checkbox('set disabled'); try { @@ -298,7 +303,7 @@ export function initRepoPullRequestAllowMaintainerEdit() { } } catch (error) { console.error(error); - showTemporaryTooltip($checkbox[0], promptError); + showTemporaryTooltip(checkbox, promptError); } finally { $checkbox.checkbox('set enabled'); } @@ -325,7 +330,9 @@ export function initRepoIssueReferenceRepositorySearch() { }, onChange(_value, _text, $choice) { const $form = $choice.closest('form'); - $form.attr('action', `${appSubUrl}/${_text}/issues/new`); + if (!$form.length) return; + + $form[0].setAttribute('action', `${appSubUrl}/${_text}/issues/new`); }, fullTextSearch: true, }); @@ -375,17 +382,16 @@ export function initRepoIssueComments() { window.location.reload(); }); - $(document).on('click', (event) => { - const $urlTarget = $(':target'); - if (!$urlTarget.length) return; + document.addEventListener('click', (e) => { + const urlTarget = document.querySelector(':target'); + if (!urlTarget) return; - const urlTargetId = $urlTarget.attr('id'); + const urlTargetId = urlTarget.id; if (!urlTargetId) return; + if (!/^(issue|pull)(comment)?-\d+$/.test(urlTargetId)) return; - const $target = $(event.target); - - if (!$target.closest(`#${urlTargetId}`).length) { + if (!e.target.closest(`#${urlTargetId}`)) { const scrollPosition = $(window).scrollTop(); window.location.hash = ''; $(window).scrollTop(scrollPosition); @@ -419,30 +425,33 @@ export function initRepoPullRequestReview() { if (window.history.scrollRestoration !== 'manual') { window.history.scrollRestoration = 'manual'; } - const $commentDiv = $(window.location.hash); - if ($commentDiv) { + const commentDiv = document.querySelector(window.location.hash); + if (commentDiv) { // get the name of the parent id - const groupID = $commentDiv.closest('div[id^="code-comments-"]').attr('id'); + const groupID = commentDiv.closest('div[id^="code-comments-"]')?.getAttribute('id'); if (groupID && groupID.startsWith('code-comments-')) { const id = groupID.slice(14); - const $ancestorDiffBox = $commentDiv.closest('.diff-file-box'); + const ancestorDiffBox = commentDiv.closest('.diff-file-box'); // on pages like conversation, there is no diff header - const $diffHeader = $ancestorDiffBox.find('.diff-file-header'); + const diffHeader = ancestorDiffBox?.querySelector('.diff-file-header'); + // offset is for scrolling let offset = 30; - if ($diffHeader[0]) { - offset += $('.diff-detail-box').outerHeight() + $diffHeader.outerHeight(); + if (diffHeader) { + offset += $('.diff-detail-box').outerHeight() + $(diffHeader).outerHeight(); } - $(`#show-outdated-${id}`).addClass('tw-hidden'); - $(`#code-comments-${id}`).removeClass('tw-hidden'); - $(`#code-preview-${id}`).removeClass('tw-hidden'); - $(`#hide-outdated-${id}`).removeClass('tw-hidden'); + + document.getElementById(`show-outdated-${id}`).classList.add('tw-hidden'); + document.getElementById(`code-comments-${id}`).classList.remove('tw-hidden'); + document.getElementById(`code-preview-${id}`).classList.remove('tw-hidden'); + document.getElementById(`hide-outdated-${id}`).classList.remove('tw-hidden'); // if the comment box is folded, expand it - if ($ancestorDiffBox.attr('data-folded') && $ancestorDiffBox.attr('data-folded') === 'true') { - setFileFolding($ancestorDiffBox[0], $ancestorDiffBox.find('.fold-file')[0], false); + if (ancestorDiffBox.getAttribute('data-folded') === 'true') { + setFileFolding(ancestorDiffBox, ancestorDiffBox.querySelector('.fold-file'), false); } + window.scrollTo({ - top: $commentDiv.offset().top - offset, + top: $(commentDiv).offset().top - offset, behavior: 'instant', }); } @@ -529,7 +538,7 @@ export function initRepoPullRequestReview() { const $commentCloud = $td.find('.comment-code-cloud'); if (!$commentCloud.length && !$ntr.find('button[name="pending_review"]').length) { try { - const response = await GET($(this).closest('[data-new-comment-url]').attr('data-new-comment-url')); + const response = await GET(this.closest('[data-new-comment-url]')?.getAttribute('data-new-comment-url')); const html = await response.text(); $td.html(html); $td.find("input[name='line']").val(idx); @@ -585,6 +594,22 @@ export function initRepoIssueWipToggle() { }); } +async function pullrequest_targetbranch_change(update_url) { + const targetBranch = $('#pull-target-branch').data('branch'); + const $branchTarget = $('#branch_target'); + if (targetBranch === $branchTarget.text()) { + window.location.reload(); + return false; + } + try { + await POST(update_url, {data: new URLSearchParams({target_branch: targetBranch})}); + } catch (error) { + console.error(error); + } finally { + window.location.reload(); + } +} + export function initRepoIssueTitleEdit() { // Edit issue title const $issueTitle = $('#issue-title'); @@ -607,23 +632,7 @@ export function initRepoIssueTitleEdit() { $('#edit-title').on('click', editTitleToggle); $('#cancel-edit-title').on('click', editTitleToggle); $('#save-edit-title').on('click', editTitleToggle).on('click', async function () { - const pullrequest_targetbranch_change = async function (update_url) { - const targetBranch = $('#pull-target-branch').data('branch'); - const $branchTarget = $('#branch_target'); - if (targetBranch === $branchTarget.text()) { - window.location.reload(); - return false; - } - try { - await POST(update_url, {data: new URLSearchParams({target_branch: targetBranch})}); - } catch (error) { - console.error(error); - } finally { - window.location.reload(); - } - }; - - const pullrequest_target_update_url = $(this).attr('data-target-update-url'); + const pullrequest_target_update_url = this.getAttribute('data-target-update-url'); if (!$editInput.val().length || $editInput.val() === $issueTitle.text()) { $editInput.val($issueTitle.text()); await pullrequest_targetbranch_change(pullrequest_target_update_url); @@ -631,7 +640,7 @@ export function initRepoIssueTitleEdit() { try { const params = new URLSearchParams(); params.append('title', $editInput.val()); - const response = await POST($(this).attr('data-update-url'), {data: params}); + const response = await POST(this.getAttribute('data-update-url'), {data: params}); const data = await response.json(); $editInput.val(data.title); $issueTitle.text(data.title); @@ -671,10 +680,11 @@ 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 = $('#status-button'); - if ($statusButton.length) { + const statusButton = document.getElementById('status-button'); + if (statusButton) { opts.onContentChanged = (editor) => { - $statusButton.text($statusButton.attr(editor.value().trim() ? 'data-status-and-comment' : 'data-status')); + const statusText = statusButton.getAttribute(editor.value().trim() ? 'data-status-and-comment' : 'data-status'); + statusButton.textContent = statusText; }; } initComboMarkdownEditor($commentForm.find('.combo-markdown-editor'), opts);