// ==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/*/*
// @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.20150619184945
// ==/UserScript==
// javascript:var script=document.createElement("script");script.src="https://greasyfork.org/en/scripts/10182-fanfictionqomplete/code/fanfictionqomplete.js";document.body.appendChild(script);window.setTimeout(function(){document.runFFQomplete();},500);
// document.styleSheets[0].cssText = "";
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.runFFQomplete = function() {
window.onload = function() {
var a = document.getElementsByClassName('skiptranslate')
for (; a.length;) {
a[0].remove()
}
var c = document.body.style.backgroundColor
document.body.removeAttribute('style')
document.body.style.backgroundColor = c // data race but whatever.
}
var re = /(^.*?fanfiction\.net\/s\/\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, '<span style="color:hsl(' + d + ' ,100%, 50%);">$1</span>')
// 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')
chaptitle.innerHTML = 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 chap_select = document.getElementById('chap_select')
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:lime;color:#ccc;margin:0;padding:0;font-family:"Verdana";}\n\
div.loading{}\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:first-child{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:#a05;}a:visited{color:#555;}a:hover{color:#fff;}a:active{color:#a05;}\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)
document.head.appendChild(title)
var profile = document.createElement('div')
profile.setAttribute('class', 'wrap profile')
profile.setAttribute('id', 'profile')
var pad = document.createElement('div')
pad.setAttribute('class', 'pad')
pad.appendChild(profile_top)
profile.appendChild(pad)
document.body.appendChild(profile)
var panel = document.createElement('div')
panel.setAttribute('class', 'panel')
var posbtn = document.createElement('button')
posbtn.setAttribute('id', 'posbtn')
posbtn.setAttribute('onclick',
"function() {\n\
var e = document.getElementById('position-style')\n\
if (e) {\n\
if (e.innerHTML == 'div.wrap{margin-left:0px;}') {\n\
e.innerHTML = 'div.wrap{margin-right:0px;}'\n\
document.getElementById('posbtn').innerHTML = 'Position: Right'\n\
} else {\n\
e.remove()\n\
document.getElementById('posbtn').innerHTML = 'Position: Center'\n\
}\n\
} else {\n\
var s = document.createElement('style')\n\
s.setAttribute('id', 'position-style')\n\
s.innerHTML = 'div.wrap{margin-left:0px;}'\n\
document.head.appendChild(s)\n\
document.getElementById('posbtn').innerHTML = 'Position: Left'\n\
}\n\
}")
posbtn.setAttribute('style', 'float:left;')
posbtn.innerHTML = 'Position: Center'
var colschemebtn = document.createElement('button')
colschemebtn.setAttribute('id', 'colschemebtn')
colschemebtn.setAttribute('onclick',
"window.toggleColScheme = function() {\n\
var e = document.getElementById('colscheme-style')\n\
if (e) {\n\
if (e.innerHTML == 'body{color:#000;}\na:hover{color:#000;}\ndiv.pad{background-color:#fff;}\n') {\n\
e.innerHTML = 'body{color:#fff;}\ndiv.pad{background-color:#000;}\n'\n\
document.getElementById('colschemebtn').innerHTML = 'Color Scheme: Black'\n\
} else {\n\
e.remove()\n\
document.getElementById('colschemebtn').innerHTML = 'Color Scheme: Dark'\n\
}\n\
} else {\n\
var s = document.createElement('style')\n\
s.setAttribute('id', 'colscheme-style')\n\
s.innerHTML = 'body{color:#000;}\na:hover{color:#000;}\ndiv.pad{background-color:#fff;}\n'\n\
document.head.appendChild(s)\n\
document.getElementById('colschemebtn').innerHTML = 'Color Scheme: White'\n\
}\n\
}()")
colschemebtn.setAttribute('style', 'float:left;')
colschemebtn.innerHTML = 'Color Scheme: Dark'
var widthbtn = document.createElement('button')
widthbtn.setAttribute('id', 'widthbtn')
widthbtn.setAttribute('onclick',
"function() {\n\
var e = document.getElementById('width-style')\n\
if (e) {\n\
if (e.innerHTML == 'div.wrap{max-width:100%;}') {\n\
e.innerHTML = 'div.wrap{max-width:777px;}'\n\
document.getElementById('widthbtn').innerHTML = 'Page Width: Narrow'\n\
} else {\n\
e.remove()\n\
document.getElementById('widthbtn').innerHTML = 'Page Width: Default'\n\
}\n\
} else {\n\
var s = document.createElement('style')\n\
s.setAttribute('id', 'width-style')\n\
s.innerHTML = 'div.wrap{max-width:100%;}'\n\
document.head.appendChild(s)\n\
document.getElementById('widthbtn').innerHTML = 'Page Width: Wide'\n\
}\n\
}()")
widthbtn.setAttribute('class', 'center')
widthbtn.innerHTML = 'Page Width: Default'
panel.appendChild(widthbtn)
panel.appendChild(posbtn)
panel.appendChild(colschemebtn)
if (chap_select) {
chap_select.setAttribute('onchange', 'if(this.options[this.selectedIndex].value < ' + urlGetChap(document.location.href) + '){' +
chap_select.getAttribute('onchange') +
'}' + ' else {document.getElementById(\'\'+this.options[this.selectedIndex].value).scrollIntoView();}'
)
chap_select.setAttribute('style', 'float:right;')
var os = chap_select.getElementsByTagName('option')
for (i = 0; i < urlGetChap(document.location) - 1; i += 1) {
os[i].setAttribute('class', 'external')
}
panel.appendChild(chap_select)
}
document.getElementById('profile').firstChild.appendChild(panel)
// document.body.insertBefore(panel, document.body.firstChild)
document.body.appendChild(chap)
function loadQomplete() {
var a = document.getElementsByClassName('skiptranslate')
for (; a.length;) {
a[0].remove()
}
document.body.removeAttribute('style')
document.body.style.backgroundColor = '#000'
}
function appendChapterFromURL(url) {
var oReq = new XMLHttpRequest();
oReq.onload = function() {
var xmlDoc = new DOMParser().parseFromString(this.responseText, "text/html")
var url = this.responseURL ? this.responseURL : this.responseURLfallback
if (!url) {
console.log('Error: Response has no responseURL field!')
}
var chap = chapFromPage(url, xmlDoc)
if (chap) {
document.body.appendChild(chap)
window.setTimeout(function() {
appendChapterFromURL(inc(url))
}, 0)
} else loadQomplete()
}
oReq.responseURLfallback = url
oReq.open("get", url, true)
oReq.send()
}
appendChapterFromURL(inc(document.location.href))
}
// document.runFFQomplete()