PageSourceSearch

https://fhr2048.github.io/js/anzhiyu/comment_barrage.js

js fhr2048.github.io collected 2026-10-03 09:11:52 UTC 6,529 bytes, 179 lines download raw bytes

1if (document.querySelector(".comment-barrage")) {
2  var commentBarrageConfig = {
3    maxBarrage: GLOBAL_CONFIG.commentBarrageConfig.maxBarrage,
4    barrageTime: GLOBAL_CONFIG.commentBarrageConfig.barrageTime,
5    twikooUrl: GLOBAL_CONFIG.twikooEnvId,
6    accessToken: GLOBAL_CONFIG.commentBarrageConfig.accessToken,
7    mailMd5: GLOBAL_CONFIG.commentBarrageConfig.mailMd5,
8    pageUrl: window.location.pathname,
9    barrageTimer: [],
10    barrageList: [],
11    barrageIndex: 0,
12    dom: document.querySelector(".comment-barrage"),
13  };
14  var commentInterval = null;
15  var hoverOnCommentBarrage = false;
16
17  document.querySelector(".comment-barrage").addEventListener("mouseenter", function () {
18    hoverOnCommentBarrage = true;
19  });
20  document.querySelector(".comment-barrage").addEventListener("mouseleave", function () {
21    hoverOnCommentBarrage = false;
22  });
23
24  function initCommentBarrage() {
25    if (!commentBarrageConfig.dom) return;
26
27    var data = JSON.stringify({
28      event: "COMMENT_GET",
29      "commentBarrageConfig.accessToken": commentBarrageConfig.accessToken,
30      url: commentBarrageConfig.pageUrl,
31    });
32    var xhr = new XMLHttpRequest();
33    xhr.withCredentials = true;
34    xhr.addEventListener("readystatechange", function () {
35      if (this.readyState === 4 && this.responseText) {
36        commentBarrageConfig.barrageList = commentLinkFilter(JSON.parse(this.responseText).data);
37        commentBarrageConfig.dom.innerHTML = "";
38      }
39    });
40    xhr.open("POST", commentBarrageConfig.twikooUrl);
41    xhr.setRequestHeader("Content-Type", "application/json");
42    xhr.send(data);
43
44    clearInterval(commentInterval);
45    commentInterval = null;
46
47    commentInterval = setInterval(() => {
48      if (commentBarrageConfig.barrageList.length && !hoverOnCommentBarrage) {
49        popCommentBarrage(commentBarrageConfig.barrageList[commentBarrageConfig.barrageIndex]);
50        commentBarrageConfig.barrageIndex += 1;
51        commentBarrageConfig.barrageIndex %= commentBarrageConfig.barrageList.length;
52      }
53      if (
54        commentBarrageConfig.barrageTimer.length >
55          (commentBarrageConfig.barrageList.length > commentBarrageConfig.maxBarrage
56            ? commentBarrageConfig.maxBarrage
57            : commentBarrageConfig.barrageList.length) &&
58        !hoverOnCommentBarrage
59      ) {
60        removeCommentBarrage(commentBarrageConfig.barrageTimer.shift());
61      }
62    }, commentBarrageConfig.barrageTime);
63  }
64
65  function commentLinkFilter(data) {
66    data.sort((a, b) => {
67      return a.created - b.created;
68    });
69    let newData = [];
70    data.forEach(item => {
71      newData.push(...getCommentReplies(item));
72    });
73    return newData;
74  }
75
76  function getCommentReplies(item) {
77    if (item.replies) {
78      let replies = [item];
79      item.replies.forEach(item => {
80        replies.push(...getCommentReplies(item));
81      });
82      return replies;
83    } else {
84      return [];
85    }
86  }
87
88  function popCommentBarrage(data) {
89    let barrage = document.createElement("div");
90    barrage.className = "comment-barrage-item";
91    barrage.innerHTML = `
92          <div class="barrageHead">
93            <a class="barrageTitle ${
94              data.mailMd5 === commentBarrageConfig.mailMd5 ? "barrageBloggerTitle" : ""
95            }" href="javascript:anzhiyu.scrollTo('#post-comment')"">
96              ${data.mailMd5 === commentBarrageConfig.mailMd5 ? "博主" : "热评"}
97            </a>
98            <div class="barrageNick">${data.nick}</div>
99            <img class="nolazyload barrageAvatar" src="https://cravatar.cn/avatar/${data.mailMd5}"/>
100            <a class="comment-barrage-close" href="javascript:anzhiyu.switchCommentBarrage()"><i class="anzhiyufont anzhiyu-icon-xmark"></i></a>
101          </div>
102          <anzhiyu class="barrageContent" onClick="window.location.hash = '${data.id}'">
103            ${data.comment}
104          </anzhiyu>
105        `;
106
107    // 获取anzhiyu标签内的所有pre元素
108    let anzhiyuPres = barrage.querySelectorAll("anzhiyu pre");
109
110    // 遍历每个pre元素,将其替换为"【代码】"
111    anzhiyuPres.forEach(pre => {
112      let codePlaceholder = document.createElement("span");
113      codePlaceholder.innerText = "【代码】";
114      pre.parentNode.replaceChild(codePlaceholder, pre);
115    });
116
117    // 获取anzhiyu标签内的所有图片元素
118    let anzhiyuImages = barrage.querySelectorAll("anzhiyu img");
119
120    // 遍历每个图片元素,将其替换为"【图片】",但排除带有class=tk-owo-emotion的图片
121    anzhiyuImages.forEach(image => {
122      if (!image.classList.contains("tk-owo-emotion")) {
123        image.style.display = "none"; // 隐藏图片
124        let placeholder = document.createElement("span");
125        placeholder.innerText = "【图片】";
126        image.parentNode.replaceChild(placeholder, image);
127      }
128    });
129    commentBarrageConfig.barrageTimer.push(barrage);
130    commentBarrageConfig.dom.append(barrage);
131  }
132
133  function removeCommentBarrage(barrage) {
134    barrage.className = "comment-barrage-item out";
135
136    setTimeout(() => {
137      if (commentBarrageConfig.dom && commentBarrageConfig.dom.contains(barrage)) {
138        commentBarrageConfig.dom.removeChild(barrage);
139      }
140    }, 1000);
141  }
142
143  // 自动隐藏
144  const commentEntryCallback = entries => {
145    const commentBarrage = document.querySelector(".comment-barrage");
146    const postComment = document.getElementById("post-comment");
147
148    entries.forEach(entry => {
149      if (postComment && commentBarrage && document.body.clientWidth > 768) {
150        commentBarrage.style.bottom = entry.isIntersecting ? `-${commentBarrageConfig.maxBarrage * 200}px` : "0";
151      }
152    });
153  };
154  // 创建IntersectionObserver实例
155  const observer = new IntersectionObserver(commentEntryCallback, {
156    root: null,
157    rootMargin: "0px",
158    threshold: 0,
159  });
160  // 监视目标元素
161  const postCommentTarget = document.getElementById("post-comment");
162  if (postCommentTarget) {
163    observer.observe(postCommentTarget);
164  }
165
166  initCommentBarrage();
167
168  if (localStorage.getItem("commentBarrageSwitch") !== "false") {
169    document.querySelector(".comment-barrage").style.display = "flex";
170    document.querySelector(".menu-commentBarrage-text").textContent = "关闭热评";
171  } else {
172    document.querySelector(".comment-barrage").style.display = "none";
173    document.querySelector(".menu-commentBarrage-text").textContent = "显示热评";
174  }
175
176  document.addEventListener("pjax:send", function () {
177    clearInterval(commentInterval);
178  });
179}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.