Duolingo Table Header Tooltips

Adds tooltips for table header columns on Duolingo tables and make them sticky.

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Duolingo Table Header Tooltips
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Adds tooltips for table header columns on Duolingo tables and make them sticky.
// @author       BErnd14
// @match        https://duolingodata.com/*
// @grant        GM_addStyle
// @license MIT
// ==/UserScript==

(function () {
    'use strict';

    const tooltips = {
        'Learning': 'Link to course structure (CEFR levels in red)',
        'from': "'from' links to a technical JSON file",
        'U': 'Units - Links to an image of the Path structure',
        'Lr': 'Learners - Number of learners (in millions), links to DuoRadios when green',
        'Ls': 'Lessons - Purple = Adventures, links to these',
        'S': 'Stories - Links to official or unofficial stories',
        'W': 'Words - Word list (if available)',
        'R': 'Release Date - Format: Year.Month, links to course versions',
        'D': 'Different Lessons - Ranking, links to alternative versions'
    };

    function addTooltips() {
        const headers = document.querySelectorAll('#DuolingoData thead th');
        if (!headers.length) return;

        headers.forEach(th => {
            const key = th.textContent.trim();
            if (tooltips[key]) {
                if (th.title !== tooltips[key]) {
                    th.title = tooltips[key];
                }
            }
        });
    }

    const observer = new MutationObserver(mutations => {
        for (const mutation of mutations) {
            if (mutation.type === 'childList' || mutation.type === 'subtree' || mutation.type === 'characterData') {
                addTooltips();
                break;
            }
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true,
        characterData: true
    });

    setTimeout(addTooltips, 1000);

    GM_addStyle(`
        #DuolingoData thead th {
            position: sticky !important;
            top: 0;
            background: white;
            z-index: 1000;
        }
    `);
})();