// ==UserScript== // @version 2.0.1 // @include *.fanfiction.net/s/* // @namespace ffnet // @name Fanfiction.net story export script. // @author Alssn // @description Writes all chapters of the story on one page. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js // @grant GM.setClipboard // @grant GM_xmlhttpRequest // @connect fanfiction.net // @downloadURL none // ==/UserScript== //Chapters are downloaded with a delay to prevent ff.net from limiting connections var chapters=[]; var settings; var style = $(``) $('body').append(style); loadSettings(); drawUI(); function drawUI(){ var storyLength = getLength(); var currentChapter = document.getElementById('chap_select').value; // creating links var node = $('.lc').first(); var exportMenu = $('fE'); var exportContainer = $(''); var addIndexButton = $('Index'); var expAllButton = $('Export'); var expButton = $('Text'); var copyButton = $('Copy'); //Settings var settingsSection = $(''); var settingsToggle = $('Options'); var settingsContainer = $('
'); var settingsDelay = $(''); var headersSwitch = $(``); var chapterSelection = $(` - `); settingsSection.append(settingsToggle); settingsContainer.append(headersSwitch, settingsDelay, chapterSelection); //Draw exportMenu.append(exportContainer); exportContainer.append(expAllButton,'| ',addIndexButton,'| ',expButton, copyButton,'| ', settingsSection); node.append(exportMenu); settingsContainer.insertAfter(node.parent()); //Event handlers var chaptersCheckbox = $('#ffneCheckboxChapters')[0]; chaptersCheckbox.addEventListener('change',function(){setSetting('limitChapters',chaptersCheckbox.checked);}); var headersCheckbox = $('#ffneCheckboxHeaders')[0]; headersCheckbox.addEventListener('change',function(){setSetting('addHeaders',headersCheckbox.checked);}); var delayInput = $('#ffneInputDelay')[0]; delayInput.addEventListener('change',function(){setSetting('delay',delayInput.value);}); expAllButton.click(exportStory); expButton.click(exportCh); settingsToggle.click(toggleSettingsDisplay); addIndexButton.click(addIndex); copyButton.click(copyText); $('#ffne_button').click(function(){ var cont = $('#ffne_export'); if (cont.hasClass('ffne_hidden')){cont.removeClass('ffne_hidden');}else{cont.addClass('ffne_hidden')} }); showSettings(settings.displaySettings); } //Add table of contents function addIndex(){ var chapters = $('div[name="ffnee_chapter"]'); var index = $('

Table of contents

'); var toC = $('
    '); index.append(toC); for (var i=0;i'+item.attr('title')+'')); } $('#storytext').prepend(index); } //adding headers, as entered by author function addHeaders(){ var chapters = document.getElementsByName('ffnee_chapter'); for (var i=0;i'; item.insertBefore(header,item.firstChild); } } function addTitle(){ var titleText = $('b.xcontrast_txt','#profile_top').first().html(); var title = $('

    '+titleText+'

    '); var authorText = $('a.xcontrast_txt[href^="/u/"]','#profile_top').first().html(); var author = $('

    '+authorText+'

    '); var storytext = $('#storytext'); storytext.prepend(title, author); } function exportCh(){ document.body.innerHTML='
    '+document.getElementById('storytextp').innerHTML+'
    '; } function copyText(){ GM.setClipboard(document.getElementById('storytextp').innerText); } function exportStory(e){ var limitChapters = document.getElementById('ffneCheckboxChapters').checked; var storyLength=getLength(); if (storyLength == 1){ expText.nodeValue = 'Oneshot'; return; } let startChapter = 0; let endChapter = storyLength; if (limitChapters){ startChapter = document.getElementById('ffneInputChapterStart').value-1; endChapter = Math.max(document.getElementById('ffneInputChapterEnd').value, startChapter+1); } exportChapters(e, startChapter, endChapter); } function exportChapters(e,start,end){ // Main actions // Progress indicator settings.delay = document.getElementById('ffneInputDelay').value; var expDiv = document.getElementById('exportAllButton'); var expText = expDiv.childNodes[0]; var hr=location.href; var chapterNumIndex=hr.search(/\/\d{1,3}\//); //Getting number of chapters var storyLength = end-start; let i = start; var totalStoryLength = storyLength;//reference console.log('retrieving '+totalStoryLength+' chapters'); console.log('start index is: '+(start+1)+', end is: '+end); setTimeout(function tick(){ console.log(`Starting to load chapter ${i+1}`); loadChapter(i+1,function(response,num){ console.log('Loaded chapter '+(num+1)); chapters[num]=parseChapter(response, num+1); expText.nodeValue = 'Export: Chapter '+String(totalStoryLength-storyLength+1)+' out of '+totalStoryLength; storyLength--; if (storyLength==0){ console.log(chapters); parseStory(chapters); expText.nodeValue='Story (again)'; } }); i++; if (i