Greasy Fork

AO3: Fic's style

Tweaks for the fic's style. You can change font, size, width... + full screen mode + estimated reading time

目前为 2015-07-31 提交的版本。查看 最新版本

// ==UserScript==
// @name         AO3: Fic's style
// @namespace    https://greasyfork.org/it/users/12632-schegge
// @version      1.1.5
// @description  Tweaks for the fic's style. You can change font, size, width... + full screen mode + estimated reading time
// @author       Schegge
// @match        http*://archiveofourown.org*/works/*
// @exclude      http*://archiveofourown.org/works/search?*
// @require      https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @grant        GM_addStyle
// ==/UserScript==

(function($) {

    fontNameDefault = $("body").css("font-family");
//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//* OPTIONS *//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//

    var Options = {
        fontName: [fontNameDefault, "Georgia", "Garamond", "Book Antiqua", "Verdana", "Segoe UI"],
        fontSize: 100, //%
        fontColor: "#000",
        chapterWidth: 90, //% ( min = 10; max = 90 )
        showBackground: "no", //or "yes"
        backgroundColor: "#f6f6f6"
    };

//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//

    var chaptersCSS;
    numChapters = $("#chapters > .chapter").length; // it counts how many chapters the fic has
    if (numChapters) { // if the fic has several chapters, even if only one chapter is displayed
        chapters = $("#chapters > .chapter");
        chaptersCSS = "#chapters > .chapter";
    } else { // if the fic is a one-shot
        chapters = $("#chapters");
        chaptersCSS = "#chapters";
    }

    // general CSS changes
    GM_addStyle(
        chaptersCSS + " { " +
        "color: " + Options.fontColor + "; " +
        "margin: auto; " +
        "text-align: justify; " +
        "padding-top: 30px; " +
        "padding-bottom: 30px; " +
        "border-radius: 100% / 60px; " +
        "margin-bottom: 20px; " +
        "padding-right: 3%; " +
        "padding-left: 3%; " +
        "} " +
        ".chapter .preface { " +
        "margin-bottom: 0; " +
        "} " +
        ".chapter .preface[role='complementary'] { " +
        "margin-top: 0; " +
        "padding-top: 0; " +
        "} " +
        "#workskin .notes, #workskin .summary { " +
        "font-size: .91rem; " +
        "} " +
        "#chapters .userstuff p { " +
        "margin: 0.6em auto; " +
        "text-align: justify; " +
        "} " +
        "#chapters .userstuff blockquote { " +
        "font-family: inherit; " +
        "padding-top: 1px; " +
        "padding-bottom: 1px; " +
        "margin: 0 .5em; " +
        "} " +
        ".userstuff hr { " +
        "width: 100%; " +
        "height: 1px; " +
        "border: 0; " +
        "background-image: linear-gradient(to right, transparent, rgba(0, 0, 0, .2), transparent); " +
        "} " +
        ".userstuff img { " +
        "max-width: 100%; " +
        "height: auto; " +
        "} " +
        "#options, #arrow { " +
        "position: fixed; " +
        "bottom: 15px; " +
        "margin: 0; " +
        "padding: 0; " +
        "font-family: Consolas, monospace; " +
        "font-size: 16px; " +
        "color: #000; " +
        "text-shadow: 0 0 2px rgba(0, 0, 0, .4); " +
        "z-index: 999; " +
        "} " +
        "#options { " +
        "right: 15px; " +
        "} " +
        "#arrow { " +
        "left: 15px; " +
        "cursor: pointer; " +
        "} " +
        "#options > div { " +
        "margin: 5px 0 0 0; " +
        "padding: 0 5px; " +
        "cursor: pointer; " +
        "} " +
        "#options > div:last-child { " +
        "padding: 2px 5px; " +
        "color: #fff; " +
        "background-color: rgba(0, 0, 0, .2); " +
        "} "
    );

    // CSS changes depending by the user
    var Variables = {
        fontName: function() {
            var fontName = localStorage.getItem("ficstyle_fontName");
            if (!fontName) {
                fontName = Options.fontName[0];
                localStorage.setItem("ficstyle_fontName", fontName);
            }
            return fontName;
        },      
        fontSize: function() {
            var fontSize = localStorage.getItem("ficstyle_fontSize");
            if (!fontSize) {
                fontSize = Options.fontSize;
                localStorage.setItem("ficstyle_fontSize", fontSize);
            }
            return fontSize;
        },        
        chapterWidth: function() {
            var chapterWidth = localStorage.getItem("ficstyle_chapterWidth");
            if (!chapterWidth) {
                chapterWidth = Options.chapterWidth;
                localStorage.setItem("ficstyle_chapterWidth", chapterWidth);
            }
            return chapterWidth;
        },        
        showBackground: function() {
            var showBackground = localStorage.getItem("ficstyle_showBackground");
            if(!showBackground) {
                showBackground = Options.showBackground;
                localStorage.setItem("ficstyle_showBackground", showBackground);
            }
            return showBackground;
        },        
        hide: function() {
            var hide = localStorage.getItem("ficstyle_hide");
            if (!hide) {
                hide = "no";
                localStorage.setItem("ficstyle_hide", hide);
            }
            return hide;
        },        
        background: function() {
            chapters.css({
                "background-color": Options.backgroundColor,
                "box-shadow": "inset 0 0 8px 0 rgba(0, 0, 0, .2)"                           
            });
            $(".chapter .preface[role='complementary']").css("border-top-width", "0"); // the chapter title
            $("#chapters .userstuff blockquote").css({
                "background-image": "linear-gradient(to right, rgba(0, 0, 0, .035), transparent)",
                "border-width": "0"
            });
        },
        noBackground: function() {
            chapters.css({
                "background-color": "transparent",
                "box-shadow": "none"
            });
            $(".chapter .preface[role='complementary']").css("border-top-width", "1px"); // the chapter title
            $("#chapters .userstuff blockquote").css({
                "background-image": "none",
                "border-width": "2px",
                "border-color": "rgba(0, 0, 0, .1)"
            });
        },
        changingCSS: function(a, b) { // a = "Variables" (user changes) or "Options" (default); b = "no" background or "yes"
            var chapterWidth, fontName, fontSize;
            if (a == "Variables") {
                chapterWidth = this.chapterWidth();
                fontName = this.fontName();
                fontSize = this.fontSize();
            } else { // a = "Options"       
                chapterWidth = Options.chapterWidth;
                fontName = Options.fontName[0];
                fontSize = Options.fontSize;
            }
            chapters.css({
                "width": chapterWidth + "%",
                "font-family": fontName,
                "font-size": fontSize + "%"
            });
            if (b == "no") {
                this.noBackground();
            } else { // b = "yes"
                this.background();
            }
        }
    };

    // more CSS changes
    Variables.changingCSS("Variables", Variables.showBackground());
    $("#chapters .userstuff p").each(function(){ if(!$(this).text().trim().length){$(this).remove();} }); // it removes empty paragraphs
    $("#chapters .userstuff br").after("<p>").remove(); // replace '<br>' with paragraphs
    
    // add estimated reading time
    $words = $("#main .wrapper dd.stats dd.words");
    var time;
    var numWords = $words.text();
    var timeReading = parseInt(numWords) / 200;
    if ( timeReading <= 60 ) {
        timeReading = Math.round( timeReading );
        time = "Minutes";
    } else {
        timeReading = Math.round( timeReading / 60 );
        time = "Hours";  
    }
    $words.after("<dt>" + time + ":</dt><dd>" + timeReading + "</dd>");

    // the options displayed on the page
    $fullScreen = $("<div>", {id: "full-screen", class: "actions", html: "<a>Full Screen Mode</a>"});
    $("#main > ul.work.navigation.actions").prepend($fullScreen);

    $options = $("<div>", {id: "options"})
    .append( $("<div>", {html: "«", id: "font-name-minus", attr: {"title": "previous font"} }) )
    .append( $("<div>", {html: "»", id: "font-name-plus", attr: {"title": "next font"} }) )
    .append( $("<div>", {html: "-", id: "font-size-minus", attr: {"title": "decrease font size"} }) )
    .append( $("<div>", {html: "+", id: "font-size-plus", attr: {"title": "increase font size"} }) )
    .append( $("<div>", {html: "▫", id: "chapter-width-minus", attr: {"title": "decrease width"} }) )
    .append( $("<div>", {html: "□", id: "chapter-width-plus", attr: {"title": "increase width"} }) )
    .append( $("<div>", {html: "b", id: "chapter-background", attr: {"title": "add/remove background"} }) )
    .append( $("<div>", {html: "r", id: "reset-local-storage", attr: {"title": "reset"} }) )
    .append( $("<div>", {html: "&#9776;", id: "show-hide", attr: {"title": "show/hide menu"} }) );
    $("body").append($options);

    if(Variables.hide() == "no") {
        $("#options > div").css("display", "block");
    } else {
        $("#options > div:nth-last-child(n+2)").css("display", "none");
    }

    var percent;
    function checkPosition() {
        documentTopB = $(document).scrollTop();
        documentHeightB = $(document).height();
        percent = documentTopB / documentHeightB;
    }
    function returnBack() {
        documentHeightA = $(document).height();
        var r = percent * documentHeightA;
        $(document).scrollTop(r);
    }

    // changes triggered by the user    
    $("#show-hide").click(function() {
        $("#options > div:nth-last-child(n+2)").slideToggle("300");
        if(localStorage.getItem("ficstyle_hide") == "no") {
            localStorage.setItem("ficstyle_hide", "yes");
        } else { localStorage.setItem("ficstyle_hide", "no"); }
    });

    $("#reset-local-storage").click(function() {
        checkPosition();
        localStorage.setItem("ficstyle_fontName", Options.fontName[0]);
        localStorage.setItem("ficstyle_fontSize", Options.fontSize);
        localStorage.setItem("ficstyle_chapterWidth", Options.chapterWidth);        
        localStorage.setItem("ficstyle_showBackground", Options.showBackground);
        Variables.changingCSS("Options", Options.showBackground);
        returnBack();
    });

    $("#chapter-background").click(function() {
        if(localStorage.getItem("ficstyle_showBackground") == "no") {
            localStorage.setItem("ficstyle_showBackground", "yes");
            Variables.background();
        } else {
            localStorage.setItem("ficstyle_showBackground", "no");
            Variables.noBackground();
        }
    });

    var curFont, curFontIncr;
    $("#font-name-minus").click(function() {
        checkPosition();
        curFont = localStorage.getItem("ficstyle_fontName");    
        for(var i = 0; i < Options.fontName.length; i++) {
            if(curFont == Options.fontName[i]) {
                var j = i - 1;
                if(j === -1) {
                    var u = Options.fontName.length - 1;
                    curFontIncr = Options.fontName[u];
                } else {
                    curFontIncr = Options.fontName[j];
                }
                $(chapters).css("font-family", curFontIncr);
                localStorage.setItem("ficstyle_fontName", curFontIncr);
            }
        }
        returnBack();
    });
    $("#font-name-plus").click(function() {
        checkPosition();
        curFont = localStorage.getItem("ficstyle_fontName");    
        for(var i = 0; i < Options.fontName.length; i++) {
            if(curFont == Options.fontName[i]) {
                var j = i + 1;
                if(j === Options.fontName.length) {                                        
                    curFontIncr = Options.fontName[0];
                } else {
                    curFontIncr = Options.fontName[j];
                }
                $(chapters).css("font-family", curFontIncr);
                localStorage.setItem("ficstyle_fontName", curFontIncr);
            }
        }
        returnBack();
    });

    var curSize;
    $("#font-size-minus").click(function() {
        checkPosition();
        curSize = parseFloat(localStorage.getItem("ficstyle_fontSize")) - 2.5;
        $(chapters).css("font-size", curSize+"%");
        localStorage.setItem("ficstyle_fontSize", curSize);
        returnBack();
    });
    $("#font-size-plus").click(function() { 
        checkPosition();       
        curSize = parseFloat(localStorage.getItem("ficstyle_fontSize")) + 2.5;
        $(chapters).css("font-size", curSize+"%");
        localStorage.setItem("ficstyle_fontSize", curSize);
        returnBack();
    });

    var curWidth;
    $("#chapter-width-minus").click(function() {
        checkPosition();
        curWidth = parseInt(localStorage.getItem("ficstyle_chapterWidth")) - 10;
        if(curWidth < 10) { curWidth = 10; }
        $(chapters).css("width", curWidth+"%");
        localStorage.setItem("ficstyle_chapterWidth", curWidth);
        returnBack();
    });
    $("#chapter-width-plus").click(function() {
        checkPosition();
        curWidth = parseInt(localStorage.getItem("ficstyle_chapterWidth")) + 10;
        if(curWidth > 90) { curWidth = 90; }
        $(chapters).css("width", curWidth+"%");
        localStorage.setItem("ficstyle_chapterWidth", curWidth);
        returnBack();
    });
    
    
    // full screen mode
    $scroll = $("<div id='arrow' style='display: none'>&#8593;</div>");
    $("body").append($scroll.hide());
    
    $workskin = $("#workskin");
    if ( $("#main > div.work > div.wrapper").length ) {
        $wrapper = $("#main > div.work > div.wrapper");
    } else { $wrapper = $("#main > div.wrapper"); }
    
    sessionStorage.setItem("onlyChapters", "no");
    
    $("#full-screen").click(function() {
        if ( sessionStorage.getItem("onlyChapters") == "no" ) {
            $("#outer").children().hide();
            $("#workskin > div:nth-child(1)").prepend($fullScreen);
            $("body").append($workskin);
            $scroll.show();
            $(document).scrollTop(0);
            sessionStorage.setItem("onlyChapters", "yes");
        } else {
            $("#outer").children().removeAttr("style");
            $wrapper.after($workskin);            
            $scroll.hide();
            $("#main > ul.work.navigation.actions").prepend($fullScreen);
            sessionStorage.setItem("onlyChapters", "no");
        }
    });
    
    $("#arrow").click(function() {
        $(document).scrollTop(0);
    });

})(window.jQuery);