Facebook
From LO, 3 Years ago, written in JavaScript.
Embed
Download Paste or View Raw
Hits: 214
  1. // ==UserScript==
  2. // @name        Arca.RevampedCommentSection
  3. // @namespace   Arca.RevampedCommentSection
  4. // @author      자바
  5. // @description 아카라이브 댓글 목록 개선 프로젝트
  6. // @version     1.0.3
  7. // @include     https://arca.live/*
  8. // @include     https://*.arca.live/*
  9. // @run-at      document-ready
  10. // @grant       GM_addStyle
  11. // ==/UserScript==
  12.  
  13. GM_addStyle(/*css*/`
  14.   .comment-wrapper.fold > .comment-wrapper {
  15.     display: none;
  16.   }
  17.  
  18.   .comment-wrapper.foldable > .comment-item .info-row {
  19.     cursor: pointer;
  20.   }
  21.  
  22.   .comment-wrapper.foldable > .comment-item .folder {
  23.     font-family: monospace;
  24.     font-weight: bold;
  25.   }
  26.   .comment-wrapper.foldable > .comment-item .folder:after {
  27.     content: "[-]";
  28.   }
  29.   .comment-wrapper.fold > .comment-item .folder:after {
  30.     content: "[+]";
  31.   }
  32. `)
  33.  
  34. /**
  35.  * 댓글 요소에서 삭제 버튼을 찾습니다
  36.  * @param {HTMLElement} comment
  37.  * @returns {HTMLElement}
  38.  */
  39. function findDeleteAnchor (comment) {
  40.   for (let anchor of comment.querySelectorAll('a')) {
  41.     if (anchor.textContent.trim() === '삭제') {
  42.       return anchor
  43.     }
  44.   }
  45. }
  46.  
  47. /**
  48.  * 타래 삭제 버튼을 눌렀을 때 실행될 메소드
  49.  * @this {HTMLElement}
  50.  * @param {MouseEvent} e
  51.  */
  52. function onDeleteClick (e) {
  53.   e.preventDefault()
  54.  
  55.   // 삭제할 댓글 아이디 가져오기
  56.   const parent = this.closest('.comment-wrapper')
  57.   const comments = [ parent, ...parent.querySelectorAll('.comment-wrapper') ]
  58.  
  59.   // 정말 삭제할건지 물어보기
  60.   if (!confirm(`정말 해당 댓글과 답글 ${comments.length - 1}개를 제거하시겠습니까?`)) {
  61.     return
  62.   }
  63.  
  64.   const promises = []
  65.   const errors = []
  66.  
  67.   for (let comment of comments) {
  68.     const anchor = findDeleteAnchor(comment)
  69.  
  70.     if (anchor) {
  71.       promises.push(
  72.         fetch(anchor.href, {
  73.           method: 'POST',
  74.           headers: {'Content-type': 'application/x-www-form-urlencoded'},
  75.           body: `_csrf=${document.querySelector('input[name=_csrf]').value}`
  76.         }).catch(e => errors.push(e))
  77.       )
  78.     }
  79.   }
  80.  
  81.   return Promise.all(promises)
  82.     .finally(() => {
  83.       if (errors.length) {
  84.         const error = errors.map((e, idx) => ` ${idx}: ${e.message}`).join('\n')
  85.         alert(`댓글 삭제 중 ${errors.length}개의 오류가 발생했습니다\n${error}`)
  86.       }
  87.  
  88.       location.reload()
  89.     })
  90. }
  91.  
  92. /**
  93.  * 타래 접기 버튼을 눌렀을 때 실행될 메소드
  94.  * @this {HTMLElement}
  95.  * @param {MouseEvent} e
  96.  */
  97. function onFolderClick (e) {
  98.   if (!e.target.matches('a, button')) {
  99.     const command = this.closest('.comment-wrapper')
  100.     command.classList.toggle('fold')
  101.   }
  102. }
  103.  
  104. const deleteBtnTemplate = document.createElement('a')
  105. deleteBtnTemplate.href = '#'
  106. deleteBtnTemplate.innerHTML = `
  107.   <span class="icon ion-trash-b"></span>
  108.   전체삭제
  109. `
  110.  
  111. const folderBtnTemplate = document.createElement('span')
  112. folderBtnTemplate.classList.add('folder')
  113.  
  114. // 답글이 있는 댓글만 모두 불러오기
  115. for (let comment of document.querySelectorAll('.comment-wrapper')) {
  116.   if (!comment.querySelector(':scope > .comment-wrapper')) {
  117.     continue
  118.   }
  119.  
  120.   // 삭제 권한이 있다면 전체 삭제 버튼 추가하기
  121.   const anchor = findDeleteAnchor(comment)
  122.   if (anchor) {
  123.     const button = deleteBtnTemplate.cloneNode(true)
  124.     button.addEventListener('click', onDeleteClick)
  125.  
  126.     anchor.parentElement.insertBefore(button, anchor)
  127.     anchor.parentElement.insertBefore(
  128.       document.createTextNode('\u00A0|\u00A0'), anchor)
  129.   }
  130.  
  131.   // 댓글 접는 버튼 추가하기
  132.   const folder = folderBtnTemplate.cloneNode(true)
  133.   const info = comment.querySelector('.info-row')
  134.   info.prepend(folder)
  135.   info.addEventListener('click', onFolderClick)
  136.   comment.classList.add('foldable')
  137.  
  138.   // 3개 이상 댓글이 있다면 접은 상태로 만들기
  139.   if (comment.querySelectorAll('.comment-wrapper').length > 3) {
  140.     folder.click()
  141.   }
  142. }
  143.  
  144. // 선택된 댓글이 있다면 모두 펼치기
  145. if (location.hash) {
  146.   for (let comment of document.querySelectorAll(`${location.hash}, ${location.hash} .comment-wrapper`)) {
  147.     comment.classList.remove('fold')
  148.   }
  149. }

Replies to RevampedComment rss

Title Name Language When
Re: RevampedComment Lousy Capybara javascript 2 Years ago.