loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Remove jQuery class from the `repo-issue.js` file (#30192)

Switched from jQuery class functions to plain JavaScript `classList`.

Tested the following functionalities and they work as before:
- delete issue comment
- cancel code comment
- update (merge or rebase) pull request
- re-request review
- reply to code comment
- show/hide outdated comments
- add code comment
- edit issue title

---------

Signed-off-by: Yarden Shoham <git@yardenshoham.com>
Co-authored-by: silverwind <me@silverwind.io>
(cherry picked from commit ef5892d988f71743c7f5446bc6ce69cb4384455b)

authored by

Yarden Shoham
silverwind
and committed by
Gergely Nagy
998f4dc3 29a8be7c

+85 -70
+85 -70
web_src/js/features/repo-issue.js
··· 158 158 159 159 export function initRepoIssueCommentDelete() { 160 160 // Delete comment 161 - $(document).on('click', '.delete-comment', async function () { 162 - const $this = $(this); 163 - if (window.confirm($this.data('locale'))) { 161 + document.addEventListener('click', async (e) => { 162 + if (!e.target.matches('.delete-comment')) return; 163 + e.preventDefault(); 164 + 165 + const deleteButton = e.target; 166 + if (window.confirm(deleteButton.getAttribute('data-locale'))) { 164 167 try { 165 - const response = await POST($this.data('url')); 168 + const response = await POST(deleteButton.getAttribute('data-url')); 166 169 if (!response.ok) throw new Error('Failed to delete comment'); 167 - const $conversationHolder = $this.closest('.conversation-holder'); 168 - const $parentTimelineItem = $this.closest('.timeline-item'); 169 - const $parentTimelineGroup = $this.closest('.timeline-item-group'); 170 + 171 + const conversationHolder = deleteButton.closest('.conversation-holder'); 172 + const parentTimelineItem = deleteButton.closest('.timeline-item'); 173 + const parentTimelineGroup = deleteButton.closest('.timeline-item-group'); 174 + 170 175 // Check if this was a pending comment. 171 - if ($conversationHolder.find('.pending-label').length) { 176 + if (conversationHolder?.querySelector('.pending-label')) { 172 177 const counter = document.querySelector('#review-box .review-comments-counter'); 173 178 let num = parseInt(counter?.getAttribute('data-pending-comment-number')) - 1 || 0; 174 179 num = Math.max(num, 0); ··· 176 181 counter.textContent = String(num); 177 182 } 178 183 179 - $(`#${$this.data('comment-id')}`).remove(); 180 - if ($conversationHolder.length && !$conversationHolder.find('.comment').length) { 181 - const path = $conversationHolder.data('path'); 182 - const side = $conversationHolder.data('side'); 183 - const idx = $conversationHolder.data('idx'); 184 - const lineType = $conversationHolder.closest('tr').data('line-type'); 184 + document.getElementById(deleteButton.getAttribute('data-comment-id'))?.remove(); 185 + 186 + if (conversationHolder && !conversationHolder.querySelector('.comment')) { 187 + const path = conversationHolder.getAttribute('data-path'); 188 + const side = conversationHolder.getAttribute('data-side'); 189 + const idx = conversationHolder.getAttribute('data-idx'); 190 + const lineType = conversationHolder.closest('tr').getAttribute('data-line-type'); 191 + 185 192 if (lineType === 'same') { 186 - $(`[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`).removeClass('tw-invisible'); 193 + document.querySelector(`[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`).classList.remove('tw-invisible'); 187 194 } else { 188 - $(`[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`).removeClass('tw-invisible'); 195 + document.querySelector(`[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`).classList.remove('tw-invisible'); 189 196 } 190 - $conversationHolder.remove(); 197 + 198 + conversationHolder.remove(); 191 199 } 200 + 192 201 // Check if there is no review content, move the time avatar upward to avoid overlapping the content below. 193 - if (!$parentTimelineGroup.find('.timeline-item.comment').length && !$parentTimelineItem.find('.conversation-holder').length) { 194 - const $timelineAvatar = $parentTimelineGroup.find('.timeline-avatar'); 195 - $timelineAvatar.removeClass('timeline-avatar-offset'); 202 + if (!parentTimelineGroup?.querySelector('.timeline-item.comment') && !parentTimelineItem?.querySelector('.conversation-holder')) { 203 + const timelineAvatar = parentTimelineGroup?.querySelector('.timeline-avatar'); 204 + timelineAvatar?.classList.remove('timeline-avatar-offset'); 196 205 } 197 206 } catch (error) { 198 207 console.error(error); 199 208 } 200 209 } 201 - return false; 202 210 }); 203 211 } 204 212 ··· 222 230 223 231 export function initRepoIssueCodeCommentCancel() { 224 232 // Cancel inline code comment 225 - $(document).on('click', '.cancel-code-comment', (e) => { 226 - const $form = $(e.currentTarget).closest('form'); 227 - if ($form.length > 0 && $form.hasClass('comment-form')) { 228 - $form.addClass('tw-hidden'); 229 - showElem($form.closest('.comment-code-cloud').find('button.comment-form-reply')); 233 + document.addEventListener('click', (e) => { 234 + if (!e.target.matches('.cancel-code-comment')) return; 235 + 236 + const form = e.target.closest('form'); 237 + if (form?.classList.contains('comment-form')) { 238 + hideElem(form); 239 + showElem(form.closest('.comment-code-cloud')?.querySelectorAll('button.comment-form-reply')); 230 240 } else { 231 - $form.closest('.comment-code-cloud').remove(); 241 + form.closest('.comment-code-cloud')?.remove(); 232 242 } 233 243 }); 234 244 } 235 245 236 246 export function initRepoPullRequestUpdate() { 237 247 // Pull Request update button 238 - const $pullUpdateButton = $('.update-button > button'); 239 - $pullUpdateButton.on('click', async function (e) { 248 + const pullUpdateButton = document.querySelector('.update-button > button'); 249 + if (!pullUpdateButton) return; 250 + 251 + pullUpdateButton.addEventListener('click', async function (e) { 240 252 e.preventDefault(); 241 - const $this = $(this); 242 - const redirect = $this.data('redirect'); 243 - $this.addClass('is-loading'); 253 + const redirect = this.getAttribute('data-redirect'); 254 + this.classList.add('is-loading'); 244 255 let response; 245 256 try { 246 - response = await POST($this.data('do')); 257 + response = await POST(this.getAttribute('data-do')); 247 258 } catch (error) { 248 259 console.error(error); 249 260 } finally { 250 - $this.removeClass('is-loading'); 261 + this.classList.remove('is-loading'); 251 262 } 252 263 let data; 253 264 try { ··· 266 277 267 278 $('.update-button > .dropdown').dropdown({ 268 279 onChange(_text, _value, $choice) { 269 - const $url = $choice.data('do'); 270 - if ($url) { 271 - $pullUpdateButton.find('.button-text').text($choice.text()); 272 - $pullUpdateButton.data('do', $url); 280 + const url = $choice[0].getAttribute('data-do'); 281 + if (url) { 282 + const buttonText = pullUpdateButton.querySelector('.button-text'); 283 + if (buttonText) { 284 + buttonText.textContent = $choice.text(); 285 + } 286 + pullUpdateButton.setAttribute('data-do', url); 273 287 } 274 288 }, 275 289 }); ··· 367 381 368 382 $('.re-request-review').on('click', async function (e) { 369 383 e.preventDefault(); 370 - const url = $(this).data('update-url'); 371 - const issueId = $(this).data('issue-id'); 372 - const id = $(this).data('id'); 373 - const isChecked = $(this).hasClass('checked'); 384 + const url = this.getAttribute('data-update-url'); 385 + const issueId = this.getAttribute('data-issue-id'); 386 + const id = this.getAttribute('data-id'); 387 + const isChecked = this.classList.contains('checked'); 374 388 375 389 await updateIssuesMeta(url, isChecked ? 'detach' : 'attach', issueId, id); 376 390 window.location.reload(); ··· 397 411 export async function handleReply($el) { 398 412 hideElem($el); 399 413 const $form = $el.closest('.comment-code-cloud').find('.comment-form'); 400 - $form.removeClass('tw-hidden'); 414 + showElem($form); 401 415 402 416 const $textarea = $form.find('textarea'); 403 417 let editor = getComboMarkdownEditor($textarea); ··· 454 468 455 469 $(document).on('click', '.show-outdated', function (e) { 456 470 e.preventDefault(); 457 - const id = $(this).data('comment'); 458 - $(this).addClass('tw-hidden'); 459 - $(`#code-comments-${id}`).removeClass('tw-hidden'); 460 - $(`#code-preview-${id}`).removeClass('tw-hidden'); 461 - $(`#hide-outdated-${id}`).removeClass('tw-hidden'); 471 + const id = this.getAttribute('data-comment'); 472 + hideElem(this); 473 + showElem(`#code-comments-${id}`); 474 + showElem(`#code-preview-${id}`); 475 + showElem(`#hide-outdated-${id}`); 462 476 }); 463 477 464 478 $(document).on('click', '.hide-outdated', function (e) { 465 479 e.preventDefault(); 466 - const id = $(this).data('comment'); 467 - $(this).addClass('tw-hidden'); 468 - $(`#code-comments-${id}`).addClass('tw-hidden'); 469 - $(`#code-preview-${id}`).addClass('tw-hidden'); 470 - $(`#show-outdated-${id}`).removeClass('tw-hidden'); 480 + const id = this.getAttribute('data-comment'); 481 + hideElem(this); 482 + hideElem(`#code-comments-${id}`); 483 + hideElem(`#code-preview-${id}`); 484 + showElem(`#show-outdated-${id}`); 471 485 }); 472 486 473 487 $(document).on('click', 'button.comment-form-reply', async function (e) { ··· 504 518 } 505 519 506 520 $(document).on('click', '.add-code-comment', async function (e) { 507 - if ($(e.target).hasClass('btn-add-single')) return; // https://github.com/go-gitea/gitea/issues/4745 521 + if (e.target.classList.contains('btn-add-single')) return; // https://github.com/go-gitea/gitea/issues/4745 508 522 e.preventDefault(); 509 523 510 - const isSplit = $(this).closest('.code-diff').hasClass('code-diff-split'); 511 - const side = $(this).data('side'); 512 - const idx = $(this).data('idx'); 513 - const path = $(this).closest('[data-path]').data('path'); 514 - const $tr = $(this).closest('tr'); 515 - const lineType = $tr.data('line-type'); 524 + const isSplit = this.closest('.code-diff')?.classList.contains('code-diff-split'); 525 + const side = this.getAttribute('data-side'); 526 + const idx = this.getAttribute('data-idx'); 527 + const path = this.closest('[data-path]')?.getAttribute('data-path'); 528 + const tr = this.closest('tr'); 529 + const lineType = tr.getAttribute('data-line-type'); 516 530 517 - let $ntr = $tr.next(); 518 - if (!$ntr.hasClass('add-comment')) { 531 + const ntr = tr.nextElementSibling; 532 + let $ntr = $(ntr); 533 + if (!ntr?.classList.contains('add-comment')) { 519 534 $ntr = $(` 520 535 <tr class="add-comment" data-line-type="${lineType}"> 521 536 ${isSplit ? ` ··· 525 540 <td class="add-comment-left add-comment-right" colspan="5"></td> 526 541 `} 527 542 </tr>`); 528 - $tr.after($ntr); 543 + $(tr).after($ntr); 529 544 } 530 545 531 546 const $td = $ntr.find(`.add-comment-${side}`); ··· 611 626 612 627 const editTitleToggle = function () { 613 628 toggleElem($issueTitle); 614 - toggleElem($('.not-in-edit')); 615 - toggleElem($('#edit-title-input')); 616 - toggleElem($('#pull-desc')); 617 - toggleElem($('#pull-desc-edit')); 618 - toggleElem($('.in-edit')); 619 - toggleElem($('.new-issue-button')); 620 - $('#issue-title-wrapper').toggleClass('edit-active'); 629 + toggleElem('.not-in-edit'); 630 + toggleElem('#edit-title-input'); 631 + toggleElem('#pull-desc'); 632 + toggleElem('#pull-desc-edit'); 633 + toggleElem('.in-edit'); 634 + toggleElem('.new-issue-button'); 635 + document.getElementById('issue-title-wrapper')?.classList.toggle('edit-active'); 621 636 $editInput[0].focus(); 622 637 $editInput[0].select(); 623 638 return false;