您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Loads all following chapters on fanfiction.net and strips off bloat.
当前为
// ==UserScript== // @name FanfictionQomplete // @description Loads all following chapters on fanfiction.net and strips off bloat. // @namespace http://greasyfork.icu/en/users/11891-qon // @author Qon // @include https://www.fanfiction.net/s/*/* // @include https://www.fictionpress.com/s/*/* // @include https://www.fimfiction.net/story/*/* // @include http://www.fimfiction.net/story/*/* // @compatible firefox // @compatible chrome // @noframes // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @run-at document-start // @license Simple Public License 2.0 (SimPL) https://tldrlegal.com/license/simple-public-license-2.0-%28simpl%29 // @version 0.0.1.20151106155133 // ==/UserScript== // javascript:var script=document.createElement("script");var t=new Date(Date());script.src="http://greasyfork.icu/en/scripts/10182-fanfictionqomplete/code/fanfictionqomplete.js?"+t.getFullYear()+t.getMonth()+t.getDate();document.body.appendChild(script);window.setTimeout(function(){document.runFFQomplete();},500); /* TODO !checkForBadJavascripts! (remove addJS_Node ?) Add support for other sites WIP https://www.fictionpress.com WIP fimfiction.com Change width by dragging the border? and position? Add copies of all links at the end of a fanfic. Save scroll, because the browser built in one doesn't work between browser restarts */ // Source for checkForBadJavascripts: https://gist.github.com/BrockA/2620135 /*--- checkForBadJavascripts() This is a utility function, meant to be used inside a Greasemonkey script that has the "@run-at document-start" directive set. It Checks for and deletes or replaces specific <script> tags. */ function checkForBadJavascripts(controlArray) { /*--- Note that this is a self-initializing function. The controlArray parameter is only active for the FIRST call. After that, it is an event listener. The control array row is defines like so: [bSearchSrcAttr, identifyingRegex, callbackFunction] Where: bSearchSrcAttr True to search the SRC attribute of a script tag false to search the TEXT content of a script tag. identifyingRegex A valid regular expression that should be unique to that particular script tag. callbackFunction An optional function to execute when the script is found. Use null if not needed. Usage example: checkForBadJavascripts ( [ [false, /old, evil init()/, function () {addJS_Node (init);} ], [true, /evilExternalJS/i, null ] ] ); */ if (!controlArray.length) return null; checkForBadJavascripts = function(zEvent) { for (var J = controlArray.length - 1; J >= 0; --J) { var bSearchSrcAttr = controlArray[J][0]; var identifyingRegex = controlArray[J][1]; if (bSearchSrcAttr) { if (identifyingRegex.test(zEvent.target.src)) { stopBadJavascript(J); return false; } } else { if (identifyingRegex.test(zEvent.target.textContent)) { stopBadJavascript(J); return false; } } } function stopBadJavascript(controlIndex) { zEvent.stopPropagation(); zEvent.preventDefault(); var callbackFunction = controlArray[J][2]; if (typeof callbackFunction == "function") callbackFunction(zEvent.target); //--- Remove the node just to clear clutter from Firebug inspection. zEvent.target.parentNode.removeChild(zEvent.target); //--- Script is intercepted, remove it from the list. controlArray.splice(J, 1); if (!controlArray.length) { //--- All done, remove the listener. window.removeEventListener( 'beforescriptexecute', checkForBadJavascripts, true ); } } } /*--- Use the "beforescriptexecute" event to monitor scipts as they are loaded. See https://developer.mozilla.org/en/DOM/element.onbeforescriptexecute Note seems to work on scripts that are dynamically created, despite what the spec says. */ window.addEventListener('beforescriptexecute', checkForBadJavascripts, true); return checkForBadJavascripts; } function addJS_Node(text, s_URL, funcToRun) { var D = document; var scriptNode = D.createElement('script'); scriptNode.type = "text/javascript"; if (text) scriptNode.textContent = text; if (s_URL) scriptNode.src = s_URL; if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()'; var targ = D.getElementsByTagName('head')[0] || D.body || D.documentElement; //--- Don't error check here. if DOM not available, should throw error. targ.appendChild(scriptNode); } if (Element.prototype.remove == undefined) { Element.prototype.remove = function() { this.parentNode.removeChild(this) } } function injectQompleteButton() { var lc = document.getElementsByClassName('lc') if (!lc.length) { lc = document.getElementById('chapter_title') lc = lc&&lc.parentNode lc = lc&&lc.getElementsByClassName('button-group')[0] console.log(lc) var btn = document.createElement('a') btn.addEventListener('click', runFFQomplete) btn.setAttribute('class', 'styled_button styled_button_grey button-icon-only') btn.setAttribute('title', 'Append all following chapters and remove unecessary bloat.') btn.innerHTML = 'Qomplete!' console.log(lc.lastChild.previousSibling) lc.insertBefore(btn,lc.lastChild.previousSibling) } else { lc = lc[0] var btn = document.createElement('button') // btn.setAttribute('onclick', 'runFFQomplete();') btn.addEventListener('click', 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)}} window.addEventListener('load', injectQompleteButton) // document.styleSheets[0].cssText = ""; var hash_settings = document.location.hash.slice(1).split('&') for(var i=0; i<hash_settings.length; ++i){ var kv = hash_settings[i].split('=') if(kv[0]==='Qomplete') { checkForBadJavascripts ([ [true, /static\.fimfiction\.net\/js\/scripts\.js\?uupAcQPf/, null], [false, /\$\(window\)\.scroll\( function\(e\)/ /*)*/, null] ]) window.addEventListener('load', runFFQomplete)}} var live = true function readSettings() { var settings = {Qomplete:1} if(live){ settings.center = GM_getValue('center',0) settings.bgcol = GM_getValue('bgcol',0) settings.edge = GM_getValue('edge',0) settings.width = GM_getValue('width',0) } var hash_settings = document.location.hash.slice(1).split('&') for(var i=0; i<hash_settings.length; ++i){ var kv = hash_settings[i].split('=') switch(kv[0]){ case 'center': settings.center = parseInt(kv[1]) break; case 'bgcol': settings.bgcol = parseInt(kv[1]) break; case 'edge': settings.edge = parseInt(kv[1]) break; case 'width': settings.width = parseInt(kv[1]) break; } } return settings } function saveSettings(o) { var q = [] for(var k in o) { if(o.hasOwnProperty(k)) { if(live) {GM_setValue(k,o[k])} q.push(k+'='+o[k])}} window.location = '#'+q.join('&')} var settings = readSettings() console.log(settings) function runFFQomplete() { saveSettings(settings) 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 + ((/fimfiction\.net/.exec(document.location)==null) ? arr[3] : arr[3].replace(/\/[^\/]*$/, ""))} function inc(url) { var arr = re.exec(url) return arr[1] + (parseInt(arr[2]) + 1) + ((/fimfiction\.net/.exec(document.location)==null) ? arr[3] : arr[3].replace(/\/[^\/]*$/, ""))} function chapFromPage(url, page) { var storytext = page.getElementById('storytext') // fanfiction.net if(!storytext) { // fimfiction.net if(latestChap==1) { try { latestChap = page.getElementById('chapter_format').getElementsByClassName('title')[0].getElementsByTagName('ul')[0].getElementsByTagName('li').length } catch (e) {}} storytext = page.getElementsByClassName('chapter_content')[0] storytext.style = '' var styles = storytext.getElementsByTagName('style') for(style of styles) { style.remove()}} if (storytext) { // var ps = storytext.getElementsByTagName('p'), 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') 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') if(/fimfiction\.net/.exec(document.location)==null) { var cut = /(.*(| [Cc]hapter [^:]+: .*)), a .* fanfic \| FanFiction/ var newChapTitle = cut.exec(title.innerHTML)} else { var cut = /(.*) - FIMFiction.net/ 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') if(!profile_top) profile_top = document.getElementsByClassName('inner')[0] // fimfiction, TODO make better 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 aaa=0 var bbb=1 if(/fimfiction\.net/.exec(document.location)==null) {aaa=2; bbb=5;} // else {aaa=0; bbb=1;} var favicon = [].slice.call(document.head.getElementsByTagName('link')).slice(aaa,bbb) 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') /* def gencss(): css = '' wps = 5 wpe = 1 pps = 50 ppe = 5 mwe = 650 wpr = wpl = wpe ppr = ppl = ppe mw = mwe while ppl+ppr<=pps*2 or wpl+wpr<=wps*2: if ppl+ppr<=pps*2: cs = r'@media (max-width: '+str( mw) +r'px) {div.pad{padding-left:'+str(ppl)+r'px;padding-right:'+str(ppr)+'px;}}\\n\\\n' #' if ppl<=ppr: ppl += 1 else: ppr += 1 elif wpl+wpr<=wps*2: cs = r'@media (max-width: '+str( mw) +r'px) {div.wrap{padding-left:'+str(wpl)+r'px;padding-right:'+str(wpr)+'px;}}\\n\\\n' #' if wpl<=wpr: wpl += 1 else: wpr += 1 css = cs+css mw = mw+1 return css */ console.log(activeChap) style.innerHTML = 'body{background-color:#000;color:#ccc;margin:0;padding:0;font-family:"Verdana";}\n\ ul.tags > li{display:inline;}\n\ ul.tags > li::before{content:" #"}\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-of-type(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\ option{}\n\ option:nth-of-type(6n+1)::before{content:"";padding-left:3px;margin-left:-3px;margin-right:4px;background:linear-gradient(to bottom, #f00, #ff0);}\n\ option:nth-of-type(6n+2)::before{content:"";padding-left:3px;margin-left:-3px;margin-right:4px;background:linear-gradient(to bottom, #ff0, #0f0);}\n\ option:nth-of-type(6n+3)::before{content:"";padding-left:3px;margin-left:-3px;margin-right:4px;background:linear-gradient(to bottom, #0f0, #0ff);}\n\ option:nth-of-type(6n+4)::before{content:"";padding-left:3px;margin-left:-3px;margin-right:4px;background:linear-gradient(to bottom, #0ff, #00f);}\n\ option:nth-of-type(6n+5)::before{content:"";padding-left:3px;margin-left:-3px;margin-right:4px;background:linear-gradient(to bottom, #00f, #f0f);}\n\ option:nth-of-type(6n+0)::before{content:"";padding-left:3px;margin-left:-3px;margin-right:4px;background:linear-gradient(to bottom, #f0f, #f00);}\n\ .col:nth-of-type(6n+'+ ((4- activeChap+60000)%6) +'){background-color:#f00;background:linear-gradient(to bottom, #f00, #ff0);}\n\ .col:nth-of-type(6n+'+ ((5- activeChap+60000)%6) +'){background-color:#ff0;background:linear-gradient(to bottom, #ff0, #0f0);}\n\ .col:nth-of-type(6n+'+ ((6- activeChap+60000)%6) +'){background-color:#0f0;background:linear-gradient(to bottom, #0f0, #0ff);}\n\ .col:nth-of-type(6n+'+ ((7- activeChap+60000)%6) +'){background-color:#0ff;background:linear-gradient(to bottom, #0ff, #00f);}\n\ .col:nth-of-type(6n+'+ ((8- activeChap+60000)%6) +'){background-color:#00f;background:linear-gradient(to bottom, #00f, #f0f);}\n\ .col:nth-of-type(6n+'+ ((9- activeChap+60000)%6) +'){background-color:#f0f;background:linear-gradient(to bottom, #f0f, #f00);}\n' +'@media (max-width: 700px) {div.wrap{padding-left:1px;padding-right:1px;} div.pad{padding-left:5px;padding-right:5px;}}\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) if(/fimfiction\.net/.exec(document.location)==null) { 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:'')))} } else { var settitle = /.* - (.*) - FIMFiction.net/ var storyname = settitle.exec(title.innerHTML) // console.log(storyname) if(storyname) { title.innerHTML = storyname[1] + (' - chapter '+activeChap+(latestChap!=activeChap?'-'+latestChap:'')) } } document.head.appendChild(title) for (i=0;i<favicon.length;i+=1) {document.head.appendChild(favicon[i])} var ficpic = profile_top.getElementsByTagName('img')[0] if(ficpic){ // http://pastebin.ca/1425789 function mime_from_data(data) // Simple function that checks for JPG, GIF and PNG from image data. Otherwise returns false. { if('GIF'==data.substr(0,3))return 'image/gif'; else if('PNG'==data.substr(1,3))return 'image/png'; else if('JFIF'==data.substr(6,4))return 'image/jpg'; return false; }; function data_string(data) // Generates the binary data string from character / multibyte data { var data_string=''; for(var i=0,il=data.length;i<il;i++)data_string+=String.fromCharCode(data[i].charCodeAt(0)&0xff); return data_string; }; function load_image(tries) { GM_xmlhttpRequest({ method: 'GET', url: ficpic.src, overrideMimeType: 'text/plain; charset=x-user-defined', onload: function(xhr) { var data = data_string(xhr.responseText); if(mime_from_data(data)) { var base64_data = btoa(data); // Encode to base64 string var data_url = 'data:' + mime_from_data(data) + ';base64,' + base64_data; // Make the data url ficpic.src = data_url } else if (tries>0) { load_image(tries-1) } } }); return; }; load_image(5) } // window.addEventListener('load_image',load_image,false); // Make sure image has properly loaded var loadwrap = document.createElement('div') loadwrap.setAttribute('class', 'wrap') loadwrap.style.position = 'sticky' loadwrap.style.top = '0px' var loading = document.createElement('div') loading.style.float = 'left' loading.setAttribute('id', 'loading') // loading.style.margin = '0px' // loading.innerHTML = String.fromCharCode(160) loadwrap.appendChild(loading) document.body.appendChild(loadwrap) function updateLoading(ignore, appended, downloaded, total) { // var loading = document.getElementById('loading') var p0 = parseInt(ignore / total * 100) var p1 = parseInt((appended + ignore) / total * 100) if (p1 == 100) { setTimeout(function() { loading.style.display = 'none' }, (activeChap != latestChap) * 100) } var p2 = parseInt((downloaded + appended + ignore) / total * 100) loading.style.background = 'linear-gradient(to right' + ', white 0%' + ', #555 ' + p0/2 + '%, white ' + p0 + '%, lime ' + p0 + '%, lime ' + p1 + '%, blue ' + p1 + '%, blue ' + p2 + '%, white ' + p2 + '%, white 100%)' } updateLoading(activeChap - 1, appendedNow, notAppendedYet, latestChap) 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') function centerclick() { var settings = readSettings() var e = document.getElementById('position-style') if (e) { if (e.innerHTML == 'div.wrap{margin-left:0px;}') { settings.center = 2 e.innerHTML = 'div.wrap{margin-right:0px;}' document.getElementById('posbtn').innerHTML = 'Right'} else { settings.center = 0 e.remove() document.getElementById('posbtn').innerHTML = 'Centered'}} else { settings.center = 1 var s = document.createElement('style') s.setAttribute('id', 'position-style') s.innerHTML = 'div.wrap{margin-left:0px;}' document.head.appendChild(s) document.getElementById('posbtn').innerHTML = 'Left'} saveSettings(settings)} posbtn.setAttribute('onclick', 'centerclick()') posbtn.setAttribute('class', 'center;') posbtn.innerHTML = 'Centered' var bgcolbtn = document.createElement('button') bgcolbtn.setAttribute('id', 'bgcolbtn') function bgcolclick() { var settings = readSettings() var e = document.getElementById('bgcol-style') if (e) { if (e.innerHTML == 'body{color:#000;}a:hover{color:#000;}div.pad{background-color:#fff;}') { settings.bgcol = 2 e.innerHTML = 'body{color:#fff;}div.pad{background-color:#000;}' document.getElementById('bgcolbtn').innerHTML = 'Background: Black'} else { settings.bgcol = 0 e.remove() document.getElementById('bgcolbtn').innerHTML = 'Background: Dark'}} else { settings.bgcol = 1 var s = document.createElement('style') s.setAttribute('id', 'bgcol-style') s.innerHTML = 'body{color:#000;}a:hover{color:#000;}div.pad{background-color:#fff;}' document.head.appendChild(s) document.getElementById('bgcolbtn').innerHTML = 'Background: White'} saveSettings(settings)} bgcolbtn.setAttribute('onclick', 'bgcolclick()') bgcolbtn.setAttribute('style', 'float:left;') bgcolbtn.innerHTML = 'Background: Dark' var edgebtn = document.createElement('button') edgebtn.setAttribute('id', 'edgebtn') function edgeclick() { var settings = readSettings() var e = document.getElementById('edge-style') if (e) { settings.edge = 0 e.remove() document.getElementById('edgebtn').innerHTML = 'Edge: Rainbow'} else { settings.edge = 1 var s = document.createElement('style') s.setAttribute('id', 'edge-style') s.innerHTML = '.col:nth-of-type(n){background-color:#333;background:#333;}.profile{background-color:#333;background:linear-gradient(to bottom, #fff, #333);}' document.head.appendChild(s) document.getElementById('edgebtn').innerHTML = 'Edge: Gray'} saveSettings(settings)} edgebtn.setAttribute('onclick', 'edgeclick()') edgebtn.setAttribute('style', 'float:left;') edgebtn.innerHTML = 'Edge: Rainbow' var widthbtn = document.createElement('button') widthbtn.setAttribute('id', 'widthbtn') function widthclick() { var settings = readSettings() var e = document.getElementById('width-style') if (e) { if (e.innerHTML == 'div.wrap{max-width:777px;}') { settings.width = 2 e.innerHTML = 'div.wrap{max-width:100%;}' document.getElementById('widthbtn').innerHTML = 'Width: Wide'} else { settings.width = 0 e.remove() document.getElementById('widthbtn').innerHTML = 'Width: Default'}} else { settings.width = 1 var s = document.createElement('style') s.setAttribute('id', 'width-style') s.innerHTML = 'div.wrap{max-width:777px;}' document.head.appendChild(s) document.getElementById('widthbtn').innerHTML = 'Width: Narrow'} saveSettings(settings)} widthbtn.setAttribute('onclick', 'widthclick()') widthbtn.setAttribute('class', 'center') widthbtn.innerHTML = 'Width: Default' function setSettings(){ var live = false if (Element.prototype.remove == undefined) { Element.prototype.remove = function() { this.parentNode.removeChild(this)}} var e,settings = readSettings() if((e=document.getElementById('position-style'))&&settings.center!=null) {e.remove(); document.getElementById('posbtn').innerHTML='Centered'} if((e=document.getElementById('bgcol-style'))&&settings.bgcol!=null) {e.remove(); document.getElementById('bgcolbtn').innerHTML='Background: Dark'} if((e=document.getElementById('edge-style'))&&settings.edge!=null) {e.remove(); document.getElementById('edgebtn').innerHTML='Edge: Rainbow'} if((e=document.getElementById('width-style'))&&settings.width!=null) {e.remove(); document.getElementById('widthbtn').innerHTML='Width: Default'} for(var i=0; i<settings.center; ++i) {setTimeout(centerclick,0)} for(var i=0; i<settings.bgcol; ++i) {setTimeout(bgcolclick,0)} for(var i=0; i<settings.edge; ++i) {setTimeout(edgeclick,0)} for(var i=0; i<settings.width; ++i) {setTimeout(widthclick,0)}} var scripttag = document.createElement('script') scripttag.setAttribute('id','button-helper') scripttag.innerHTML = [ ,setSettings.toString().slice(23,-1) ,readSettings.toString() ,saveSettings.toString() ,centerclick.toString() ,bgcolclick.toString() ,edgeclick.toString() ,widthclick.toString() ].join('\n') posbtn.addEventListener('click',_=>{saveSettings(readSettings())}) widthbtn.addEventListener('click',_=>{saveSettings(readSettings())}) bgcolbtn.addEventListener('click',_=>{saveSettings(readSettings())}) edgebtn.addEventListener('click',_=>{saveSettings(readSettings())}) panel.appendChild(posbtn) panel.appendChild(widthbtn) panel.appendChild(bgcolbtn) panel.appendChild(edgebtn) document.body.appendChild(scripttag) } 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()} a = document.getElementsByClassName('ad_container') for (; a.length;) {a[0].remove()} element.next = function() { if(this.firstChild) return this.firstChild if(this.nextSibling) return this.nextSibling return this.parentNode.nextSibling} // window.parentNode.replaceChild(window.cloneNode(false), window) // var el = document // while(el) { // e.parentNode.replaceChild(el.cloneNode(false), el) // el = el.next()} // document.head.parentNode.replaceChild(document.head.cloneNode(true), document.head) // document.body.parentNode.replaceChild(document.body.cloneNode(true), document.body) // var el = document.body // elClone = el.cloneNode(true); // el.parentNode.replaceChild(elClone, el); document.body.removeAttribute('style') updateLoading(activeChap - 1, latestChap - (activeChap - 1), 0, latestChap)} 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 var chap = chapFromPage(url, xmlDoc) if (chap) { document.body.appendChild(chap) appendedNow += 1 updateLoading(activeChap - 1, appendedNow, notAppendedYet, latestChap) window.setTimeout(function() { appendChapterFromURL(inc(url)) }, 0)} else loadQomplete()} oReq.responseURLfallback = url oReq.open("get", url, true) oReq.send()} function appendChapterFromURL2(url) { var oReq = new XMLHttpRequest(); oReq.onload = function() { // setTimeout(function(this2){ var this2 = this // for debug purposes, use comment above as code to simulate delays (and its matching closing part) var xmlDoc = new DOMParser().parseFromString(this2.responseText, "text/html") var url = this2.responseURL ? this2.responseURL : this2.responseURLfallback var chap = chapFromPage(url, xmlDoc) if (chap) { chapArr[parseInt(urlGetChap(url))] = chap notAppendedYet += 1 updateLoading(activeChap - 1, appendedNow, notAppendedYet, latestChap) if (appendedNow + notAppendedYet + activeChap - 1 == latestChap) { // consolog("all downloaded", performance.now()) } } // }, Math.random()*8000+50*urlGetChap(this.responseURL), this) } oReq.responseURLfallback = url oReq.open("get", url, true) oReq.send()} function appendNextChap(n) { if (chapArr[n]) { document.body.appendChild(chapArr[n]) appendedNow += 1 notAppendedYet -= 1 updateLoading(activeChap - 1, appendedNow, notAppendedYet, latestChap) if (n < latestChap) { appendNextChap(n + 1)} else { loadQomplete() }} else { window.setTimeout(function() { appendNextChap(n) }, 50) }} if (true) { // Asynchronous chapter load. Very fast for big fanfics. for (i = activeChap; i < latestChap; i += 1) appendChapterFromURL2(urlSetChap(document.location.href, i + 1)); if (activeChap == latestChap) { loadQomplete()} else { appendNextChap(activeChap + 1)}} else { // Synchronous chapter load. Slow for big fanfics but doesn't hit the server as hard. appendChapterFromURL(inc(document.location.href))} }