BangumiLazyPreview

Lazy load links and show their titles with caching using IndexedDB

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         BangumiLazyPreview
// @namespace    https://github.com/Adachi-Git/BangumiLazyPreviewLink
// @version      0.30
// @description  Lazy load links and show their titles with caching using IndexedDB
// @author       Jirehlov (Original Author), Adachi (Current Author)
// @include      /^https?://(bangumi\.tv|bgm\.tv|chii\.in)/.*
// @grant        none
// @license      MIT
// @require      https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js
// ==/UserScript==

(function () {
    "use strict";

    // 确保页面完全加载后再执行脚本
    window.addEventListener('load', async () => {
        try {
            // 初始化 localForage
            await localforage.ready();

            // 替换链接文本为链接指向页面的标题
            const replaceLinkText = async (link) => {
                // 检查链接是否在当前视图内
                const rect = link.getBoundingClientRect();
                if (rect.top >= 0 && rect.bottom <= window.innerHeight) {
                    let linkURL = link.href;
                    if (window.location.href.includes('bangumi.tv')) {
                        linkURL = linkURL.replace('bgm.tv', 'bangumi.tv');
                    } else if (window.location.href.includes('chii.in')) {
                        linkURL = linkURL.replace(/bangumi\.tv|bgm\.tv/, 'chii.in');
                    }
                    if (link.textContent === link.href) {
                        // 检查是否有缓存
                        const cachedTitle = await localforage.getItem(linkURL);
                        if (cachedTitle) {
                            // 如果有缓存,直接使用缓存中的标题
                            link.textContent = cachedTitle;
                            console.log(`Title for ${linkURL} retrieved from cache: ${cachedTitle}`);
                        } else {
                            // 如果没有缓存,发起网络请求获取标题
                            fetch(linkURL)
                                .then(response => response.text())
                                .then(data => {
                                    const parser = new DOMParser();
                                    const htmlDoc = parser.parseFromString(data, 'text/html');
                                    const title = htmlDoc.querySelector('h1.nameSingle a');
                                    const blogtitle = htmlDoc.querySelector('h1');
                                    let titleText = title ? title.textContent : '';
                                    let blogtitleText = blogtitle ? blogtitle.textContent : '';
                                    if (link.href.includes('subject') || link.href.includes('ep')) {
                                        const chineseName = title ? title.getAttribute('title') : '';
                                        if (chineseName) {
                                            if (titleText) {
                                                titleText += ' | ' + chineseName;
                                            } else {
                                                titleText = chineseName;
                                            }
                                        }
                                    }
                                    if (link.href.includes('ep')) {
                                        const epTitle = htmlDoc.querySelector('h2.title');
                                        if (epTitle) {
                                            epTitle.querySelectorAll('small').forEach(small => small.remove());
                                            const epTitleText = epTitle.textContent;
                                            if (epTitleText) {
                                                if (titleText) {
                                                    titleText += ' | ' + epTitleText;
                                                } else {
                                                    titleText = epTitleText;
                                                }
                                            }
                                        }
                                    }
                                    if ((link.href.includes('blog') || link.href.includes('topic') || link.href.includes('index')) && blogtitleText) {
                                        titleText = blogtitleText;
                                    }
                                    if (titleText) {
                                        link.textContent = titleText;
                                        // 将标题存储到 IndexedDB 中
                                        localforage.setItem(linkURL, titleText);
                                        console.log(`Title for ${linkURL} retrieved from network and cached: ${titleText}`);
                                    }
                                })
                                .catch(error => {
                                    console.error('Error fetching data:', error);
                                });
                        }
                    }
                }
            };

            // 获取页面上的所有链接
            const allLinks = document.querySelectorAll('a[href^="https://bgm.tv/subject/"], a[href^="https://chii.in/subject/"], a[href^="https://bangumi.tv/subject/"], a[href^="https://bgm.tv/ep/"], a[href^="https://chii.in/ep/"], a[href^="https://bangumi.tv/ep/"], a[href^="https://bgm.tv/character/"], a[href^="https://chii.in/character/"], a[href^="https://bangumi.tv/character/"], a[href^="https://bgm.tv/person/"], a[href^="https://chii.in/person/"], a[href^="https://bangumi.tv/person/"], a[href^="https://bgm.tv/blog/"], a[href^="https://chii.in/blog/"], a[href^="https://bangumi.tv/blog/"], a[href^="https://bgm.tv/group/topic/"], a[href^="https://chii.in/group/topic/"], a[href^="https://bangumi.tv/group/topic/"], a[href^="https://bgm.tv/index/"], a[href^="https://chii.in/index/"], a[href^="https://bangumi.tv/index/"]');

            // 设置定时器变量
            let timer;

            let lazyLinks = Array.from(allLinks);

            const lazyLoadLinks = () => {
                lazyLinks.forEach(link => {
                    replaceLinkText(link);
                });
                // 清空已处理的链接
                lazyLinks = [];
            };

            // 检查滚动事件来触发懒加载
            window.addEventListener('scroll', () => {
                // 在滚动事件中,检查链接是否在视口中,并将未处理的链接添加到待处理列表
                allLinks.forEach(link => {
                    const rect = link.getBoundingClientRect();
                    if (rect.top >= 0 && rect.bottom <= window.innerHeight) {
                        lazyLinks.push(link);
                    }
                });
                // 当页面滚动停止一段时间后再执行懒加载
                clearTimeout(timer);
                timer = setTimeout(lazyLoadLinks, 200); // 等待200毫秒
            });

            // 页面加载完成时立即执行一次懒加载
            window.addEventListener('DOMContentLoaded', lazyLoadLinks);
        } catch (error) {
            console.error('Error in BangumiLazyPreview script:', error);
        }
    });
})();