// ==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.20150611013408 // @downloadURL none // ==/UserScript== // javascript:var script=document.createElement("script");script.src="https://greasyfork.org/en/scripts/10182-fanfictionqomplete/code/fanfictionqomplete.js";document.body.appendChild(script); // 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() { function urlGetChap(url) { var re = /(^.*?fanfiction\.net\/s\/\d+\/)(\d+)(?:\/?.*$)/ var arr = re.exec(url) return arr[2] } function urlSetChap(url, n) { var re = /(^.*?fanfiction\.net\/s\/\d+\/)(\d+)(?:\/?.*$)/ var arr = re.exec(url) return arr[1] + n } function inc(url) { var re = /(^.*?fanfiction\.net\/s\/\d+\/)(\d+)(?:\/?.*$)/ var arr = re.exec(url) return arr[1] + (parseInt(arr[2]) + 1) } function chapFromPage(url, page) { var storytext = page.getElementById('storytext') if (storytext) { 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.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 } body = document.getElementsByTagName('body')[0] var head = document.getElementsByTagName('head')[0] var title = document.getElementsByTagName('title')[0] var profile_top = document.getElementById('profile_top') var chap = chapFromPage(document.location.href, document) var ptbuttons = profile_top.getElementsByTagName('button') if (ptbuttons.length) { ptbuttons[0].remove() for (; head.firstElementChild;) head.firstElementChild.remove(); for (; body.firstElementChild;) body.firstElementChild.remove(); } 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\ div.wrap{max-width:1300px;margin-left:auto;margin-right: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:#f0f;background:linear-gradient(to bottom, #f0f, #f00);}\n\ .col2{background-color:#f00;background:linear-gradient(to bottom, #f00, #ff0);}\n\ .col3{background-color:#ff0;background:linear-gradient(to bottom, #ff0, #0f0);}\n\ .col4{background-color:#0f0;background:linear-gradient(to bottom, #0f0, #0ff);}\n\ .col5{background-color:#0ff;background:linear-gradient(to bottom, #0ff, #00f);}\n\ .col0{background-color:#00f;background:linear-gradient(to bottom, #00f, #f0f);}\n' switch ((urlGetChap(document.location.href) % 6)) { case 1: style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #f0f);}\n' break; case 2: style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #f00);}\n' break; case 3: style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #ff0);}\n' break; case 4: style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #0f0);}\n' break; case 5: style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #0ff);}\n' break; case 0: style.innerHTML += '.profile{background-color:#777;background:linear-gradient(to bottom, #fff, #00f);}\n' break; } head.appendChild(style) 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) body.appendChild(profile) var btn = document.createElement('button') btn.setAttribute('id', 'toc-btn') btn.setAttribute('onclick', 'window.toggleToc();') btn.innerHTML = 'Table of Contents' document.getElementById('profile').firstChild.appendChild(btn) window.toggleToc = function() { var toc = document.getElementById('toc') if (toc.style.display == 'none') { toc.style.display = 'block' } else { toc.style.display = 'none' } } var toc = document.createElement('div') toc.setAttribute('class', 'pad') toc.setAttribute('id', 'toc') toc.style.display = 'none' toc.style.paddingTop = '0px' document.getElementById('profile').appendChild(toc) function tocAppend(s, n) { var toc = document.getElementById('toc') var a = document.createElement('a') a.setAttribute('href', '#' + n) a.innerHTML = s toc.appendChild(document.createElement('br')) toc.appendChild(a) } tocAppend('Chapter ' + urlGetChap(document.location.href) + '.', urlGetChap(document.location.href)) body.appendChild(chap) function loadQomplete() { var a = document.getElementsByClassName('skiptranslate') for (; a.length;) { a[0].remove() } document.getElementsByTagName('body')[0].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) { body.appendChild(chap) tocAppend('Chapter ' + urlGetChap(url) + '.', urlGetChap(url)) 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()