Endless Pixiv Pages

Loads more pixiv pages as you scroll down.

目前為 2017-04-18 提交的版本,檢視 最新版本

// ==UserScript==
// @name           Endless Pixiv Pages
// @namespace      https://greasyfork.org/scripts/3254
// @include        http://www.pixiv.net/*
// @include        https://www.pixiv.net/*
// @description    Loads more pixiv pages as you scroll down.
// @version        2017.04.18
// @grant          none
// ==/UserScript==

var iframeLoader = false;//If true, load pages inside a hidden iframe instead of with XMLHttpRequest--other pixiv scripts might work better with this on. 
var scrollBuffer = 500;//Minimum height remaining to scroll before loading the next page.
var timeToFailure = 30;//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;

//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 = getMainTable(document)) != null && (bottomDoc = getBottomPager(document)) != null && (nextPage = getNextPage(bottomDoc)) != null )
{
	//Move bottom pager out of where additional content will be loaded
	bottomDoc.parentNode.removeChild(bottomDoc);
	mainTable.parentNode.parentNode.appendChild(bottomDoc);
	
	if( iframeLoader )
	{
		//iframe to load pages
		iframeLoader = document.createElement("iframe");
		iframeLoader.addEventListener("load", function(){ processPage( iframeLoader.contentDocument ); }, false);
		iframeLoader.width = iframeLoader.height = 0;
		iframeLoader.style.visibility = "hidden";
		document.body.appendChild(iframeLoader);
	}
	
	//Adjust buffer height
	scrollBuffer += window.innerHeight;

	//Watch scrolling
	window.addEventListener("scroll", testScrollPosition, false);
	testScrollPosition();
}

function getMainTable(source)
{
	var result = null, tableFun =
	[	
		//bookmarks: user
		function(src){ src = src.getElementById("search-result"); return src ? src.getElementsByTagName("ul")[0] : null; },
		
		//search
		//new_illust
		//member_illust.php?id=####
		function(src){ src = src.getElementsByClassName("image-item")[0]; return src ? src.parentNode : null; },
		
		//search: group/novel
		function(src){ return src.getElementsByClassName("autopagerize_page_element")[0]; },
		
		//search: users
		////function(src){ return src.getElementsByClassName("user-recommendation-items")[0]; },//lazy-loading issue
		
		//default
		function(src){ src = src.getElementsByClassName("linkStyleWorks")[0]; return src ? src.getElementsByTagName("ul")[0] : 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 =
	[
		//most things
		function(src){ src = src.getElementsByClassName("pager-container"); return src.length ? src[src.length - 1].parentNode : null; },
		
		//image responses, bookmarked users
		function(src){ src = src.getElementsByClassName("_pager-complex"); return src.length ? src[src.length - 1] : null; }
	];
	
	for( var i = 0; i < pagerFun.length; i++ )
	{
		getBottomPager = pagerFun[i];
		if( (result = getBottomPager(source)) != null )
			return result;
	}
	
	return null;
}

function getNextPage(pager)
{
	var links = pager.getElementsByTagName("a");
	if( links.length == 0 || links[links.length-1].getAttribute("rel") != "next" )
		return null;//No more pages
	else if( links[links.length-1].href.indexOf("http://www.pixiv.net/") < 0 )
		return "http://www.pixiv.net/"+links[links.length-1].href;
	else
		return links[links.length-1].href;
}

function testScrollPosition()
{
	if( !pending && window.pageYOffset + scrollBuffer > bottomDoc.offsetTop )
	{
		pending = true;
		timeout = setTimeout( function(){ pending = false; testScrollPosition(); }, timeToFailure*1000 );
		
		if( iframeLoader )
			iframeLoader.contentDocument.location.replace(nextPage);
		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;
	}
	
	//Disable lazy loading to fix pages like /new_illust.php
	var image = newTable.getElementsByTagName("img");
	for( var i = 0; i < image.length; i++ )
	  if( image[i].getAttribute("data-src") )
	    image[i].src = image[i].getAttribute("data-src");
	
	//Add page link
	var pageLink = mainTable.parentNode.appendChild( document.createElement("div") );
	pageLink.setAttribute("style","font-size:large; text-align:left; margin-left: 10px");
	pageLink.setAttribute("class","clear");
	pageLink.innerHTML = '<hr style="clear: both;"><a href="'+nextPage+'">Page '+nextPage.replace(/.*(\?|&)p=([0-9]+).*/,'$2')+'</a>';
	
	//Update the visible bottom paginator.
	var bottomPage = getBottomPager( newDoc );
	bottomDoc.innerHTML = bottomPage.innerHTML;
	
	//Append new page
	mainTable.parentNode.appendChild( document.adoptNode(newTable) );
	
	//Check for the next page, and disable the script if there isn't one.
	if( nextPage = getNextPage(bottomPage) )
	{
		pending = false;
		testScrollPosition();
	}
	else
	{
		pageLink = mainTable.parentNode.appendChild( document.createElement("div") );
		pageLink.setAttribute("class","clear");
	}
};

//So as I pray, Unlimited Pixiv Works.