小天管理 发表于 10月11日 发表于 10月11日 1. 具体问题简述 我开发了一个 Tampermonkey 脚本,但是往往需要手动刷新页面才能触发。请教该如何优化。(代码附在最后面) 2. 脚本功能描述 inSpirehep.net这个网站可以复制文献的BibTeX引文信息(通过点击文献左下角的cite实现),现在我想在BibTeX内容中加入一个inSpirehep.net网站的编号。为此我使用 Tampermonkey 脚本在文献的右下角添加了一个Copy BibTeX to Clipboard的按钮,点击按钮可以将加入编号的BibTeX内容复制到系统剪贴板。 现在的问题是,这个脚本往往需要重新刷新页面才能触发,在第一次展示文献列表的时候不会出现。不知道该如何修复。PS ,这份代码也是在 ChatGPT 协助下完成的,本人完全没有 JS 开发经验。希望能有高手指点一二。 3. 我的原始代码 // ==UserScript== // @name Copy BibTeX to Clipboard-v2 // @version 2.0 // @description Adds a button to fetch data and copy it to clipboard // @author Chipmunker // @match https://inspirehep.net/literature* // @run-at document-end // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_notification // ==/UserScript== (function () { 'use strict'; var maxAttempts = 200; // 最大尝试次数 var attempts = 0; // 当前尝试次数 var copyBtnText = "Copy BibTeX to Clipboard"; var copyBtnColor = "#000008"; var copiedBtnText = "Data Copied to Clipboard"; var copiedBtnColor = "#f44336"; var showDuration = 5000; // ms var regexPattern = /^https:\/\/inspirehep.net\/literature\/(\d+)$/; // 按钮的点击事件处理函数 function CopyToClipOnClick(button, inspireID) { // 发送 GET 请求 GM_xmlhttpRequest({ method: 'GET', url: 'https://inspirehep.net/api/literature/' + inspireID, // 替换为你要请求的 API URL headers: { 'authority': 'inspirehep.net', 'accept': 'application/x-bibtex' }, onload: function (response) { // 获取响应数据 var data = response.responseText; // console.log("|" + data + "|"); // 为 BibTeX 添加 inspireID let BibInspireID = data.replace(/\n\}\n$/, ",\n inspirehepID = \"" + inspireID + "\"\n}\n"); // 将数据写入系统剪贴板 GM_setClipboard(BibInspireID); // 修改复制按钮并在一秒后修复 var textSpan = button.querySelector('.v-top, #span-' + inspireID); textSpan.innerText = copiedBtnText; textSpan.style.color = copiedBtnColor; setTimeout(function () { textSpan.innerText = copyBtnText; textSpan.style.color = copyBtnColor; }, showDuration); // 提示用户数据已复制 // alert('Data copied to clipboard: \n' + BibInspireID); GM_notification({ text: BibInspireID, title: copiedBtnText, // url: 'https:/example.com/', onclick: (event) => { // The userscript is still running, so don't open example.com // event.preventDefault(); // Display an alert message instead // alert('I was clicked!') console.log('NotificationClick') } }); } }); } function findRefSearchBtnAll() { var intervalId = setInterval(function () { // 查找 ref Search button var refSearchBtnAll = document.querySelectorAll('[data-test-id="reference-search-button"]'); if (refSearchBtnAll.length > 0) { // 找到了 ref Search button 元素,可以执行相应的操作 clearInterval(intervalId); // 停止轮询 console.log('找到了 ref Search button 元素'); var Btn = document.querySelector('.CopyBtn'); if (Btn) { return; } for (var refSearchBtn of refSearchBtnAll) { var button = createCopyBtn(refSearchBtn, copyBtnText); // 按钮点击事件处理函数 button.addEventListener('click', function () { var inspireID = this.id; CopyToClipOnClick(this, inspireID); }); } } else { attempts++; // 增加尝试次数 // console.log('未找到 ref Search button 元素'); if (attempts >= maxAttempts) { clearInterval(intervalId); // 达到最大尝试次数,停止轮询 console.log('未找到 ref Search button 元素, 达到最大尝试次数'); } } }, 100); // 每隔 100 毫秒钟检查一次 } const observer = new MutationObserver(function (mutationsList, observer) { // 在 div 变化时重新运行脚本的代码 // 例如,重新加载页面 // location.reload(); findRefSearchBtnAll(); }); var currentURL = window.location.href; if (regexPattern.test(currentURL)) { findRefSearchBtnAll(); } else { findRefSearchBtnAll(); // 监听目标 div 的变化 const targetDiv = document.querySelector('[class="ant-col ant-col-xs-24 ant-col-lg-17"]');//'[data-test-id="search-results"]'); if (targetDiv) { observer.observe(targetDiv, { attributes: false, childList: true, subtree: true }); } } })(); function createCopyBtn(refSearchBtn, copyBtnText) { var refSearchSpan = refSearchBtn.parentNode; // 构造 copy icon var copyImgSpan = document.createElement('span'); copyImgSpan.role = "img"; copyImgSpan.innerHTML = '<svg viewBox="64 64 896 896" focusable="false" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg>'; // 构造 icon span var iconSpan = document.createElement('span'); iconSpan.className = "icon"; iconSpan.appendChild(copyImgSpan); // 获取文献 ID var inspireMatch = refSearchBtn.href.match(/citedby:recid:(\d+)$/); var inspireID = inspireMatch[1]; // 构造 __IconText__ var IconTextSpan = document.createElement("span"); IconTextSpan.className = "__IconText__"; var textSpan = document.createElement("span"); textSpan.className = "v-top"; textSpan.innerText = copyBtnText; // "Copy BibTeX to Clipboard"; textSpan.id = "span-" + inspireID; IconTextSpan.appendChild(iconSpan); IconTextSpan.appendChild(textSpan); // 构造 Button var button = document.createElement('button'); button.type = "button"; button.id = inspireID; button.className = "CopyBtn"; button.appendChild(IconTextSpan); var UserActionSpan = document.createElement("span"); UserActionSpan.className = "__UserAction__"; UserActionSpan.appendChild(button); refSearchSpan.parentElement.insertBefore(UserActionSpan, refSearchSpan); return button; }
已推荐帖子
创建帐户或登录来提出意见
您需要成为会员才能提出意见
创建帐户
注册成为会员.只要几个简单步骤!
注册帐户登录
已经有帐户? 请在此处登录.
现在登录