共计 4335 个字符,预计需要花费 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 = '';
// 构造 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;
}
正文完