油猴脚本碰到ajax如何实现无刷新多次执行 _
前言
话分两头讲,首先是因为蝴蝶关闭比较久,然后断种比较多,虽然最近IYUU已经开始支持了,但是保种实在是不理想,所以我们希望借鉴其他站点的管理思路,对旧的、断种严重的、续种困难的种子进行清理。
其次眼看着七万多的种子,每次删一个种子要弄好几次,任谁都迷糊。。。所以,决定写个脚本,一页一页弄~
过程
首先按照以往的经验,删除如果要点击好几次我就直接把它的请求拉过来,然后重写点击事件完事了~
// ==UserScript==
// @name hudbt-delete
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://hudbt.hust.edu.cn/torrents.php?inclbookmarked=0&incldead=1&spstate=0&page=*
// @icon https://www.google.com/s2/favicons?domain=hust.edu.cn
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function() {
// 首先NP架构下都需要一定权限才会展示删除按钮,所以一般人应该是找不到滴~
$('#torrents').find('tr:gt(0)').each((index, e)=>{
var id = $(e).find('a.staff-quick-delete').attr('href').match(/id=(\d+)/)[1];
// 去除跳转按钮,关掉需要点击好几次的面板直接添加点击事件
$(e).find('a.staff-quick-delete').attr('href', '').click(function(event){
event.preventDefault();
//提交请求并解析返回结果
var url = `https://hudbt.hust.edu.cn/cake/torrents/delete/${id}.json`;
GM_xmlhttpRequest({
"method": "POST",
"url": url,
"data": encodeURI('_method=DELETE&data%5BreasonType%5D=0&data%5BreasonDetail%5D='),
'headers':{
"Content-Type": 'application/x-www-form-urlencoded; charset=UTF-8',
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
},
"onload": function(res) {
var result = JSON.parse(res.responseText);
if (result.success) {
location.reload();
} else {
alert('删种失败!!')
}
}
});
});
});
})();
乍一看,没什么毛病,很简单。但是在跑的过程中,遇到了一些bug,蝴蝶上一页下一页用的是ajax,无刷新页面,内容却换了。我们的脚本就第一次执行,后来出来的内容该点击几次还是点击几次。
经过几天的搜索尝试:
window.onhashchange=function(event){
console.log(event);
}
//或者
window.addEventListener('hashchange',function(event){
console.log(event);
})
// ==UserScript==
// @name _Amazon Search, alter results
// @include http://www.amazon.com/s/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
introduced in GM 1.0. It restores the sandbox.
*/
function addCustomSearchResult (jNode) {
//***** YOUR CODE HERE *****
jNode.prepend (
'Buy my stuff, instead!'
);
}
waitForKeyElements ("#atfResults", addCustomSearchResult);
上述借鉴下来,都不好使,但是明确了一个想法,就是必须要添加事件监听,捕捉到ajax发生了,然后将删除按钮的点击事件覆盖掉。
猛然间看到一个:document.addEventListener(‘DOMNodeInserted’, function() { alert(‘hi’) }, false); 请注意,该事件将由页面结构中的任何更改触发,因此您必须检查自己是否定位了正确的更改。
直接试了一下,给我一直反复的输出hi。。。不过也证明有用,因为我要做的就是这个,ajax导致页面改变,我就判断页面改变了,执行一次脚本。那么如何判断呢?也就是页面刷新之后的差异是什么呢?
// ==UserScript==
// @name hudbt-delete
// @namespace http://tampermonkey.net/
// @version 0.2
// @description try to take over the world!
// @author tomorrow505
// @match https://hudbt.hust.edu.cn/torrents.php*
// @icon https://www.google.com/s2/favicons?domain=hust.edu.cn
// @grant GM_xmlhttpRequest
// ==/UserScript==
//首先将函数封装起来,每次执行就是把页面删除按钮的点击事件覆盖掉
function add_click_function(){
$('#torrents').find('tr:gt(0)').each((index, e)=>{
var id = $(e).find("a.staff-quick-delete").attr('href').match(/id=(\d+)/)[1];
$(e).find('a.staff-quick-delete').attr('href', '').addClass('select_torrent').click(function(ee){
ee.preventDefault();
var url = `https://hudbt.hust.edu.cn/cake/torrents/delete/${id}.json`;
GM_xmlhttpRequest({
"method": "POST",
"url": url,
"data": encodeURI('_method=DELETE&data%5BreasonType%5D=0&data%5BreasonDetail%5D='),
'headers':{
"Content-Type": 'application/x-www-form-urlencoded; charset=UTF-8',
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
},
"onload": function(res) {
var result = JSON.parse(res.responseText);
if (result.success) {
location.reload();
} else {
alert('删种失败!!')
}
}
});
});
});
}
// 判断什么时候执行?我做了一个设计,就是执行一次我将页面的删除按钮添加一个class,如果没有这个class的元素,我就执行一遍,有了就不执行了。
document.addEventListener('DOMNodeInserted', function() {
if($('.select_torrent').length == 0){
add_click_function();
}
}, false);
衍生需求
一次性点击一个删除仿佛不太够,那么我们需要增加批量删除按钮。往上再写一个版本:
// ==UserScript==
// @name hudbt-delete
// @namespace http://tampermonkey.net/
// @version 0.3
// @description try to take over the world!
// @author tomorrow505
// @match https://hudbt.hust.edu.cn/torrents.php*
// @icon https://www.google.com/s2/favicons?domain=hust.edu.cn
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function() {
// 页面增加一列,列首删除按钮可以点击进行删种
$('#torrents').find('thead').find('tr:first').append(`<th class="unsortable"><a id="delete_torrents">删种</a></th>`);
$('#delete_torrents').click(function(){
$('input.select_torrent:checked').each((index, e)=>{
var torrent_id = $(e).attr('title');
delete_torrent(torrent_id);
})
});
// 封装删种操作,传入参数为种子id
function delete_torrent(torrent_id) {
var url = `https://hudbt.hust.edu.cn/cake/torrents/delete/${torrent_id}.json`;
GM_xmlhttpRequest({
"method": "POST",
"url": url,
"data": encodeURI('_method=DELETE&data%5BreasonType%5D=0&data%5BreasonDetail%5D='),
'headers':{
"Content-Type": 'application/x-www-form-urlencoded; charset=UTF-8',
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
},
"onload": function(res) {
var result = JSON.parse(res.responseText);
if (result.success) {
// 执行成功之后将种子id对应的行删除掉
$(`input[title=${torrent_id}]`).parent().remove();
console.log(`种子${torrent_id}已经成功删除!!!`);
} else {
console.log(`种子${torrent_id}删除失败!!!`);
console.log(result);
}
}
});
}
// 每一行的最后一列增加一个复选框,勾选之后点击删除即执行删除操作
function fireOnNewPage () {
$('#torrents').find('tr:gt(0)').each((index, e)=>{
var id = $(e).find('a.staff-quick-delete').attr('href').match(/id=(\d+)/)[1];
$(e).append(`<input type="checkbox" title=${id} value="yes" class="select_torrent" style="margin-top: 50%;" >`)
});
}
// 页面监听,主要针对ajax来的
document.addEventListener('DOMNodeInserted', function() {
if($('.select_torrent').length == 0){
fireOnNewPage();
}
}, false);
})();
结束语
如此就实现了一个简单的ajax下,油猴无刷新脚本多次执行了,have fun!!!
参考
[油猴脚本碰到ajax如何实现无刷新多次执行 – Tomorrow’s blog](https://tomorrow505.xyz/%E6%B2%B9%E7%8C%B4%E8%84%9A%E6%9C%AC%E7%A2%B0%E5%88%B0ajax%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E6%97%A0%E5%88%B7%E6%96%B0%E5%A4%9A%E6%AC%A1%E6%89%A7%E8%A1%8C/)