CSDN辅助

用鼠标选中你要复制的文本内容, 会弹出一个提示条, 点击第一个复制, 如果提示条关闭了说明复制成功

  1. // ==UserScript==
  2. // @name CSDN辅助
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.3.0
  5. // @description 用鼠标选中你要复制的文本内容, 会弹出一个提示条, 点击第一个复制, 如果提示条关闭了说明复制成功
  6. // @author HUIHONG
  7. // @match https://blog.csdn.net/**
  8. // @icon https://g.csdnimg.cn/static/logo/favicon32.ico
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15.  
  16.  
  17. // 将代码设置为可编辑状态
  18. for (const code of document.querySelectorAll("code")) {
  19. code.contentEditable = "true";
  20. }
  21.  
  22. // 当鼠标抬起的时候, 监听是否有元素#articleSearchTip
  23. document.addEventListener("mouseup", function (e) {
  24. // 检查是否有这个提示条, 有的话就更新这个提示条
  25. checkArticleSearchTip();
  26. });
  27.  
  28. // 每隔500毫秒查找一次, 一共查找5次
  29. function checkArticleSearchTip(i) {
  30. i = i || 1;
  31. // 是否有元素#articleSearchTip
  32. const articleSearchTip = document.querySelector("#articleSearchTip");
  33. if (articleSearchTip == null) {
  34. // 是否结束查找
  35. if (i <= 5) {
  36. setTimeout(() => checkArticleSearchTip(i + 1), 500);
  37. }
  38. return;
  39. }
  40. // 添加一个复制选项框
  41. updateArticleSearchTip(articleSearchTip);
  42. }
  43.  
  44. // 向提示框中添加一个复制项
  45. function updateArticleSearchTip(tip) {
  46. // 是否已经将节点插入进去了
  47. if (tip == null || document.getElementById("newCopyNode")) {
  48. return;
  49. }
  50.  
  51. // 创建节点
  52. const copyNode = document.createElement("a");
  53. copyNode.innerHTML = '<img src="https://csdnimg.cn/release/blogv2/dist/pc/img/newcNoteWhite.png"><span class="article-text">复制</span>';
  54. copyNode.setAttribute("class", "article-href cnote");
  55. copyNode.setAttribute("href", "javascript:void(0);");
  56. copyNode.id = "newCopyNode";
  57.  
  58. // 为节点添加点击事件
  59. copyNode.addEventListener("click", copySelectedContent);
  60.  
  61. // 将节点插入到提示条中
  62. tip.insertBefore(copyNode, tip.children[0]);
  63. }
  64.  
  65. // 复制被选中的内容到剪切板
  66. function copySelectedContent() {
  67. // 获取选中内容
  68. const selection = window.getSelection().toString();
  69. // 将选中内容写入到剪切板中, 成功就关闭提示框
  70. navigator && navigator.clipboard.writeText(selection).then(function () {
  71. // 关闭提示框
  72. document.querySelector("#articleSearchTip").remove();
  73. // 清空选中内容
  74. window.getSelection().empty();
  75. });
  76. }
  77.  
  78. if (/https:\/\/blog.csdn.net\/[^\/]+\/category_[0-9_]+\.html/.test(window.location.href)) {
  79.  
  80. function getScrollTop() {
  81. let scrollTop = 0
  82. if (document.documentElement && document.documentElement.scrollTop) {
  83. scrollTop = document.documentElement.scrollTop
  84. } else if (document.body) {
  85. scrollTop = document.body.scrollTop
  86. }
  87. return scrollTop
  88. }
  89.  
  90. function getClientHeight() {
  91. var clientHeight = 0
  92. if (document.body.clientHeight && document.documentElement.clientHeight) {
  93. clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight)
  94. } else {
  95. clientHeight = Math.max(document.body.clientHeight, document.documentElement.clientHeight)
  96. }
  97. return clientHeight
  98. }
  99.  
  100. function getScrollHeight() {
  101. return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)
  102. }
  103.  
  104. function isScrollBottom() {
  105. return getScrollTop() + getClientHeight() == getScrollHeight();
  106. }
  107.  
  108. function hidden(clsList) {
  109. for (const cls of clsList) {
  110. const fixed = document.querySelector(cls);
  111. fixed && fixed.setAttribute("style", "display:none;" + fixed.getAttribute("style"));
  112. }
  113. }
  114.  
  115. // 隐藏顶部固定栏
  116. hidden([".column_info_box", ".column_person_box"]);
  117. // 滚动到底部, 加载下一页数据
  118. window.hasNextPage = true;
  119. window.addEventListener("scroll", (e) => {
  120. // 是否滚动到底部
  121. if (isScrollBottom() && window.hasNextPage) {
  122. // 获取下一页标签
  123. const nextPage = window.currentPage + 1;
  124.  
  125. // 获取下一页的链接地址, 并请求下一页
  126. const nextUrl = getAllUrl(nextPage);
  127. fetch(nextUrl)
  128. .then(res => res.text())
  129. .then(html => {
  130. // 解析html
  131. const parser = new DOMParser();
  132. const doc = parser.parseFromString(html, 'text/html');
  133. // 获取列表目录
  134. const columnList = document.querySelector("ul.column_article_list");
  135. // 扩展到当前目录
  136. for (const column of doc.querySelectorAll("ul.column_article_list > li")) {
  137. columnList.appendChild(column);
  138. }
  139. // 更新当前页
  140. window.currentPage = nextPage;
  141. })
  142. .catch(e => {
  143. window.hasNextPage = false;
  144. console.log("下一页获取失败: ", e);
  145. });
  146. }
  147. });
  148. }
  149.  
  150.  
  151. // 不需要关注也能加载全文
  152. $('btn-readmore').hasClass("no-login") || ($("div.article_content").removeAttr("style"), 0 == $(".column-mask").length && $(".hide-article-box").hide(), $('btn-readmore').hasClass("fans_read_more") && ($("#btnAttent").hasClass("attented") || $(".tool-attend").trigger("click")))
  153. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址