自动加载下页
// ==UserScript==
// @name Bangumi Unlimited Pages
// @namespace https://github.com/bangumi/scripts/liaune
// @version 0.4
// @description 自动加载下页
// @author Liaune
// @include /^https?://(bangumi\.tv|bgm\.tv|chii\.in)/.*
// @grant GM_addStyle
// ==/UserScript==
(function() {
var iframeLoader = false;//If true, load pages inside a hidden iframe instead of with XMLHttpRequest--other bgm scripts might work better with this on.
var scrollBuffer = 100;//Minimum height remaining to scroll before loading the next page.
var timeToFailure = 10;//Seconds to wait for a response from the next page before attempting to fetch the page again.
var mainTable, bottomDoc, nextPage, timeout = 0, pending = false, totalPages = 0, loadAll = 0, Autoload = false, loadAllLink=null;
mainTable = getMainTable(document);
bottomDoc = getBottomPager(document);
nextPage = getNextPage(bottomDoc);
//Run if this window isn't inside an iframe and we've found the thumbnail container, bottom pager, and next page
if( window == window.top && mainTable && bottomDoc && nextPage )
{
//Move bottom pager out of where additional content will be loaded
//bottomDoc.parentNode.removeChild(bottomDoc);
//mainTable.parentNode.appendChild(bottomDoc);
var resultBadge = document.querySelector(".page_inner a:last-child");
var resultMatcher;
totalPages = resultBadge? resultBadge.href.replace(/.*(\?|&)page=([0-9]+).*/,'$2'): null;
let AutoloadLink = document.createElement("a");
mainTable.parentNode.appendChild(AutoloadLink);
AutoloadLink.className = "p";
AutoloadLink.style = 'float:right';
AutoloadLink.textContent = "Auto Load Pages";
AutoloadLink.onclick = function(){
Autoload = true;
AutoloadLink.style.display='none';
testScrollPosition();
};
loadAllLink = document.createElement("a");
mainTable.parentNode.appendChild(loadAllLink);
loadAllLink.className = "p";
loadAllLink.style = 'float:right';
loadAllLink.textContent = "Load All Pages";
loadAllLink.onclick = function(){
loadAll = (loadAll==1)? 0 :1;
loadAllLink.textContent = (loadAll==1) ? "Stop Loading All Pages" : "Load All Pages";
loadAllLink.setAttribute("style"," position: fixed;top: 500px;left: 50px");
testScrollPosition();
};
//Adjust buffer height
scrollBuffer += window.innerHeight;
//Watch scrolling
window.addEventListener("scroll", testScrollPosition, false);
testScrollPosition();
}
function getMainTable(source){
var result = null, tableFun =
[
//user/mono
function(src){ src = src.querySelector('ul.coversSmall'); return src ? src : null; },
//subject/browser
function(src){ src = src.querySelector('#browserItemList'); return src ? src : null; },
//subject/collections
function(src){ src = src.querySelector('ul#memberUserList'); return src ? src : null; },
///group/forum
function(src){ src = src.querySelectorAll('#columnA .topic_list tbody')[1]; return src ? src : null; },
//blog
function(src){ src = src.querySelector('#news_list'); return src ? src : null; },
//timeline
function(src){ src = src.querySelector('#tmlContent #timeline'); return src ? src : null; },
//index
function(src){ src = src.querySelector('#timeline ul'); return src ? src : null; },
//group/all
function(src){ src = src.querySelector('#memberGroupList'); return src ? src : null; },
//tags
function(src){ src = src.querySelector('#tagList'); return src ? src : null; },
//subject/reviews
function(src){ src = src.querySelector('#entry_list'); return src ? src : null; },
//comments
function(src){ src = src.querySelector('#comment_box'); return src ? src : null; },
];
for( var i = 0; i < tableFun.length; i++ )
{
getMainTable = tableFun[i];
if( (result = getMainTable(source)) != null )
return result;
}
return null;
}
function getBottomPager(source){
var result = null, pagerFun =
[
function(src){ src = src.querySelector(".page_inner"); return src ? src : null; },
];
for( var i = 0; i < pagerFun.length; i++ )
{
getBottomPager = pagerFun[i];
if( (result = getBottomPager(source)) != null )
return result;
}
return null;
}
function getNextPage(pager){
if(!pager) return null;
let current = pager.querySelector('.p_cur');
if(current)
return $(current).next('a.p') ? $(current).next('a.p').attr('href'):null;
let next = pager.querySelectorAll('a.p')[1] ? pager.querySelectorAll('a.p')[1] : pager.querySelectorAll('a.p')[0];
if(next)
return next.href;
}
function testScrollPosition(){
if( !pending && (loadAll || (Autoload && window.pageYOffset + scrollBuffer > bottomDoc.offsetTop)) )
{
pending = true;
timeout = setTimeout( function(){ pending = false; testScrollPosition(); }, timeToFailure*1000 );
//If the page about to be loaded is the last, hide the "Load All Pages" link.
if( loadAllLink && nextPage.replace(/.*(\?|&)page=([0-9]+).*/,'$2') == totalPages && totalPages>2 )
loadAllLink.style.display = "none";
else
{
var xhr = new XMLHttpRequest();
xhr.open( "GET", nextPage );
xhr.onabort = xhr.onabort = xhr.onerror = function(){ clearTimeout(timeout); pending = false; };
xhr.onload = function(){ processPage( xhr.responseXML ); };
xhr.responseType = "document";
xhr.send();
}
}
}
function processPage( newDoc ){
clearTimeout(timeout);
var newTable = getMainTable(newDoc);
//Make sure page loaded properly
if( !newTable )
{
pending = false;
return;
}
//Update the visible bottom paginator.
var bottomPage = getBottomPager( newDoc );
bottomDoc.innerHTML = bottomPage.innerHTML;
//Append new page
//mainTable.innerHTML+= newTable.innerHTML;
$(mainTable).append(newTable.innerHTML);
//Check for the next page, and disable the script if there isn't one.
nextPage = getNextPage(bottomPage);
if(nextPage)
{
pending = false;
testScrollPosition();
}
}
})();