// ==UserScript==
// @name FanfictionQomplete
// @description Loads all following chapters on fanfiction.net and strips off bloat.
// @namespace https://greasyfork.org/en/users/11891-qon
// @author Qon
// @include https://www.fanfiction.net/s/*/*
// @compatible firefox
// @compatible chrome
// @noframes
// @grant none
// @license Simple Public License 2.0 (SimPL) https://tldrlegal.com/license/simple-public-license-2.0-%28simpl%29
// @version 0.0.1.20150726044616
// @downloadURL none
// ==/UserScript==
/*
TODO
Add support for other sites
https://www.fictionpress.com
Already done, but I haven't put this site among the include rules for now. Don't know if anyone cares about it...
If you want it you can add "https://www.fanfiction.net/s/* /*" (without "" and without the space) to the inclusion rules yourself in the script settings
fimfiction.com
Will take more work but it's more popular site and I do read fics there myself sometimes.
Change width by dragging the border? and position?
Convert images to data url.
Automatically qomplete fanfics?
Not sure it's a good idea, even as an option for several reasons.
Might crash browsers at startup, strain servers a whole lot and make it harder to access features like chapters reviewing, fav and follow fics and other issues.
Save settings?
Like background color and page with, so that you don't have to change them every time to your preferences.
Not sure if this should be implemented or not. If fics are automatically qompleted this would be needed for brosers to remember your previous scroll position.
*/
// javascript:var script=document.createElement("script");var t=new Date(Date());script.src="https://greasyfork.org/en/scripts/10182-fanfictionqomplete/code/fanfictionqomplete.js?"+t.getFullYear()+t.getMonth()+t.getDate();document.body.appendChild(script);window.setTimeout(function(){document.runFFQomplete();},500);
if (Element.prototype.remove == undefined) {
Element.prototype.remove = function() {
this.parentNode.removeChild(this)
}
}
function injectRunButton() {
var lc = document.getElementsByClassName('lc')
if (lc.length) {
lc = lc[0]
var btn = document.createElement('button')
btn.setAttribute('onclick', 'document.runFFQomplete();')
btn.setAttribute('class', 'btn')
btn.setAttribute('style', 'margin-left:12px;margin-right:2px;')
btn.setAttribute('title', 'Append all following chapters and remove unecessary bloat.')
btn.innerHTML = 'Qomplete!'
lc.appendChild(btn)
}
}
injectRunButton()
// document.styleSheets[0].cssText = "";
document.runFFQomplete = function() {
window.onload = function() {
var a = document.getElementsByClassName('skiptranslate')
for (; a.length;) {
a[0].remove()
}
document.body.removeAttribute('style')
}
var re = /(^.*?(?:fan|fim)?fiction(?:press\.com|\.net)\/s(?:tory)?\/\d+\/)(\d+)(\/?[^#]*)/
function urlGetChap(url) {
var arr = re.exec(url)
return arr[2]
}
function urlSetChap(url, n) {
var arr = re.exec(url)
return arr[1] + n + arr[3]
}
function inc(url) {
var arr = re.exec(url)
return arr[1] + (parseInt(arr[2]) + 1) + arr[3]
}
function chapFromPage(url, page) {
var storytext = page.getElementById('storytext')
if (storytext) {
// var ps = storytext.getElementsByTagName('p')
// var d = 0
// for (q of ps) {
// q.style.color = 'hsl(' + d + ' ,20%, 80%)'
// // q.innerHTML = q.innerHTML.replace(/([\.,?!])/g, '$1')
// d = (d + 1 / ps.length * 360) % 360
// }
var wrap = page.createElement('div')
wrap.setAttribute('class', 'wrap col' + (urlGetChap(url) % 6))
wrap.setAttribute('id', urlGetChap(url))
var pad = page.createElement('div')
pad.setAttribute('class', 'pad')
var chapdiv = page.createElement('div')
chapdiv.setAttribute('class', 'chapter')
var chapspan = page.createElement('span')
chapspan.innerHTML = urlGetChap(url) + '. '
var title = page.getElementsByTagName('title')[0]
var chaptitle = page.createElement('a')
chaptitle.setAttribute('href', url.replace(/#.*$/, ""))
chaptitle.setAttribute('class', 'external')
var cut = /(.*(| [Cc]hapter [^:]+: .*)), a .* fanfic \| FanFiction/
var newChapTitle = cut.exec(title.innerHTML)
chaptitle.innerHTML = newChapTitle ? newChapTitle[1] : title.innerHTML
chapdiv.appendChild(chapspan)
chapdiv.appendChild(chaptitle)
chapdiv.appendChild(document.createElement('hr'))
chapdiv.appendChild(storytext)
pad.appendChild(chapdiv)
wrap.appendChild(pad)
return wrap
} else return null
}
document.body.setAttribute('style', '')
var title = document.getElementsByTagName('title')[0]
var profile_top = document.getElementById('profile_top')
var statusCompleteRE = /Status: Complete/
var statusComplete = statusCompleteRE.exec(profile_top.innerHTML) ? true : false
var chap_select = document.getElementById('chap_select')
var latestChap = chap_select ? chap_select.children.length : 1
var activeChap = parseInt(urlGetChap(document.location))
var appendedNow = 1
var notAppendedYet = 0
var chapArr = []
var favicon = [].slice.call(document.head.getElementsByTagName('link')).slice(2,5)
var chap = chapFromPage(document.location.href, document)
var ptbuttons = profile_top.getElementsByTagName('button')
if (ptbuttons.length) {
ptbuttons[0].remove()
for (; document.head.firstElementChild;) document.head.firstElementChild.remove();
for (; document.body.firstElementChild;) document.body.firstElementChild.remove();
}
document.body.removeAttribute('style')
var style = document.createElement('style')
style.setAttribute('type', 'text/css')
style.innerHTML =
'body{background-color:#000;color:#ccc;margin:0;padding:0;font-family:"Verdana";}\n\
#loading{position:inherit;width:100%;height:5px;}\n\
button, select{border-radius:4px;padding:4px 12px;background: linear-gradient(to bottom, #333, #000);border-width: 1px;color:#ccc;background-color:#000;}\n\
button:hover{background-image:none;}\n\
.panel{text-align:center;}\n\
a.external, option.external{background: transparent url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGXRFWHRTb2Z0d2FyZQBBZ\
G9iZSBJbWFnZVJlYWR5ccllPAAAAFZJREFUeF59z4EJADEIQ1F36k7u5E7ZKXeUQPACJ3wK7UNokVxVk9kHnQH7bY9hbDyDhNXgjpRLqFlo4M2GgfyJHhjq8V4agfrgPQX3JtJQGbofmCHgA/nAKks+JAjFA\
AAAAElFTkSuQmCC") no-repeat scroll right center;padding-right: 13px;}\n\
div.wrap{max-width:1300px;margin:auto;padding:0px 5px 0px 5px;}\n\
div.wrap:nth-child(2){padding-top:5px;margin-top:50px;}\n\
div.wrap:last-child{padding-bottom:5px;margin-bottom:50px;}\n\
div.pad{background-color:#222;padding:50px;}\n\
.chapter{}#profile_top{}img{float:left;}canvas{float:left;}\n\
a:link{color:#555;}a:visited{color:#555;}a:hover{color:#aaa;}a:active{color:#aaa;}\n\
.col1{background-color:#f00;background:linear-gradient(to bottom, #f00, #ff0);}\n\
.col2{background-color:#ff0;background:linear-gradient(to bottom, #ff0, #0f0);}\n\
.col3{background-color:#0f0;background:linear-gradient(to bottom, #0f0, #0ff);}\n\
.col4{background-color:#0ff;background:linear-gradient(to bottom, #0ff, #00f);}\n\
.col5{background-color:#00f;background:linear-gradient(to bottom, #00f, #f0f);}\n\
.col0{background-color:#f0f;background:linear-gradient(to bottom, #f0f, #f00);}\n'
switch ((urlGetChap(document.location.href) % 6)) {
case 0:
style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #f0f);}\n'
break;
case 1:
style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #f00);}\n'
break;
case 2:
style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #ff0);}\n'
break;
case 3:
style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #0f0);}\n'
break;
case 4:
style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #0ff);}\n'
break;
case 5:
style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #00f);}\n'
break;
}
document.head.appendChild(style)
var settitle = /(.*)[Cc]hapter .*, a (.*) fanfic \| FanFiction/
var storyname = settitle.exec(title.innerHTML)
if(!storyname) {
var settitle = /(.*), a (.*) fanfic \| FanFiction/
var storyname = settitle.exec(title.innerHTML)
}
if(storyname) {
title.innerHTML = storyname[1]+' - '+storyname[2]+(statusComplete && activeChap==1 ? ' - Qomplete' : (' - chapter '+activeChap+(latestChap!=activeChap?'-'+latestChap:'')))
}
document.head.appendChild(title)
for (i=0;i