AO3: Glossary term descriptions as popups

On mouse hover, opens a popup/tooltip with a preview of the linked glossary term's definition

目前為 2022-08-28 提交的版本,檢視 最新版本

// ==UserScript==
// @name         AO3: Glossary term descriptions as popups
// @namespace    https://gf.qytechs.cn/en/users/906106-escctrl
// @description  On mouse hover, opens a popup/tooltip with a preview of the linked glossary term's definition
// @author       escctrl
// @version      1.0
// @match        *://*.archiveofourown.org/faq/*
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @license      MIT
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// ==/UserScript==

(function($) {
    'use strict';

    var gloss_ref = new Object;
    var gloss_date = new Date(GM_getValue("gloss_date"));

    var compare_date = createDate(0, -1, 0); // a month before

    // if the glossary reference was never read, or it is already more than a month old
    if (GM_getValue("gloss_date") === undefined || GM_getValue("gloss_date") < gloss_date) {

        // then read the english glossary page and load the descriptions
        $.get('https://archiveofourown.org/faq/glossary?language_id=en', function(response) {
            // nothing to do here, all interactions are in done() and failed()

        }).done(function(response) {
            // pull all the headings and their anchors
            const glossary = $(response).find('div#faq');

            $(glossary).find('h3').each(function() {
                let content = "";
                $(this).nextUntil('h3').each(function() {
                    content += this.outerHTML;
                });

                // convert it into an object we can store
                gloss_ref[ $(this).attr('id') ] = content;
            });

            // store the results
            GM_setValue("gloss_ref", gloss_ref);
            GM_setValue("gloss_date", new Date().toString());

            // thanks to Przemysław Sienkiewicz on Stackoverflow for the code to catch error responses https://stackoverflow.com/a/40256829
        }).fail(function(data, textStatus, xhr) {
            //This shows status code eg. 429
            console.log("error", data.status);
        });

    }

    else {
        gloss_ref = GM_getValue("gloss_ref");
    }

    // some CSS styling for the popup modal
    document.getElementsByTagName('head')[0].innerHTML += `<style type="text/css">
    #glossary-popup {
      width: 50%; z-index: 1; position: absolute; top: 0; left: 0; right: 0; margin: 0px auto;
      background-color: #fffab0; padding: 1em; border: 0.3em dashed white; }
    </style>`;

    // build a popup modal dialog
    const gloss_popup = document.createElement('div');
    gloss_popup.id = 'glossary-popup';
    $(gloss_popup).hide().appendTo('div#main');

    // find all the glossary links on the faq page
    $('a[href*="glossary"]').add('a[href^="#"]').hover(function() { // mouse over

        // find the corresponding glossary term
        let term = $(this).attr('href').match(/#\w*/ig);
        term = term[0].slice(1);

        // populate the modal dialog
        $(gloss_ref[term]).appendTo(gloss_popup);

        $('<p style="font-size: smaller; font-style: italic; margin-top: 2em;">This is a preview of the Glossary entry. To visit any of the links mentioned in the preview, please go to the Glossary entry itself by following its link.</p>').appendTo(gloss_popup);

        // display the modal dialog
        var e = window.event;
        var y = e.pageY-90;
        gloss_popup.style.setProperty('top', y + "px");
        $(gloss_popup).show();

    }, function() { // mouse out

        // hide the modal dialog again and empty it out for next use
        $(gloss_popup).hide().html("");
    });

})(jQuery);

// convenience function to be able to pass minus values into a Date, so JS will automatically shift correctly over month/year boundaries
// thanks to Phil on Stackoverflow for the code snippet https://stackoverflow.com/a/37003268
function createDate(days, months, years) {
    var date = new Date();
    date.setFullYear(date.getFullYear() + years);
    date.setMonth(date.getMonth() + months);
    date.setDate(date.getDate() + days);
    return date;
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址