Greasy Fork is available in English.

探索者视角MOD

Preview links by hovering and pressing 'F' on Discourse forums

// ==UserScript==
// @name         探索者视角MOD
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  Preview links by hovering and pressing 'F' on Discourse forums
// @author       Your Name
// @match        https://linux.do/*
// @grant        none
// @license MIT
// ==/UserScript==
 
(function() {
    'use strict';
 
    const iframeContainer = document.createElement('div');
    iframeContainer.style.cssText = 'position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; display: none; align-items: center; justify-content: center; background: rgba(0, 0, 0, 0.5); z-index: 9999;';
    const iframe = document.createElement('iframe');
    iframe.style.cssText = 'width: 70vw; height: 70vh; border: none; background: white;';
    iframeContainer.appendChild(iframe);
    document.body.appendChild(iframeContainer);
 
    let currentHoveredLink = null;
    let keyDown = false;
    let longPressTimer = null;
    const longPressDuration = 500; // Time in milliseconds to qualify as a long press
 
    document.addEventListener('keydown', function(event) {
        if (event.key === 'F' || event.key === 'f') { // Only activate if 'F' key is pressed
            keyDown = true;
            if (currentHoveredLink) {
                iframe.src = currentHoveredLink.href;
                iframeContainer.style.display = 'flex';
            }
        }
    });
 
    document.addEventListener('keyup', function(event) {
        if (event.key === 'F' || event.key === 'f') { // Only deactivate if 'F' key is released
            keyDown = false;
        }
    });
 
    document.body.addEventListener('mousedown', function(event) {
        if (event.button === 0) { // Check if left mouse button is pressed
            const aTag = event.target.closest('a[href]');
            if (!aTag || aTag.href.startsWith('javascript:')) return;
 
            longPressTimer = setTimeout(() => {
                iframe.src = aTag.href;
                iframeContainer.style.display = 'flex';
            }, longPressDuration);
        }
    });
 
    document.body.addEventListener('mouseup', function(event) {
        clearTimeout(longPressTimer); // Cancel the timer when the mouse button is released
    });
 
    document.body.addEventListener('mouseover', function(event) {
        const aTag = event.target.closest('a[href]');
        if (!aTag || aTag.href.startsWith('javascript:')) return;
 
        currentHoveredLink = aTag; // Update currently hovered link
        if (keyDown) { // Check if 'F' key is still pressed
            iframe.src = currentHoveredLink.href;
            iframeContainer.style.display = 'flex';
        }
    }, { passive: true });
 
    document.body.addEventListener('mouseout', function(event) {
        if (event.target.closest('a[href]')) {
            currentHoveredLink = null; // Clear hovered link on mouseout
        }
    });
 
    iframeContainer.addEventListener('click', function(event) {
        if (event.target === iframeContainer) {
            iframeContainer.style.display = 'none';
            iframe.src = '';
        }
    });
 
    // 添加预览按钮的函数
    function addPreviewButtons() {
        const posts = document.querySelectorAll('.link-top-line'); // 选择所有 .link-top-line 元素

        posts.forEach(post => {
            // 检查按钮是否已存在
            if (!post.querySelector('.topicpreview-btn')) {
                const button = document.createElement('button');
                button.innerText = '预览'; // 按钮文本改为“预览”
                button.className = 'btn btn-icon-text btn-default topicpreview-btn'; // 添加类名以匹配样式
                button.style.cssText = 'margin-left: 10px; padding: 6px 12px; background-color: #f0f0f0; color: black; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; display: none;'; // 去掉边框,字体颜色为黑色

                post.appendChild(button); // 将按钮添加到 .link-top-line 元素下

                // 鼠标悬停时显示按钮
                const mainLink = post.closest('.main-link.clearfix.topic-list-data');
                if (mainLink) {
                    mainLink.addEventListener('mouseenter', () => {
                        button.style.display = 'inline-block'; // 悬停时显示按钮
                    });
                    mainLink.addEventListener('mouseleave', () => {
                        button.style.display = 'none'; // 离开时隐藏按钮
                    });
                }

                // 绑定点击事件
                button.addEventListener('click', function() {
                    const link = post.querySelector('a[href]'); // 获取帖子链接
                    if (link) {
                        iframe.src = link.href; // 设置 iframe 的 src 为帖子链接
                        iframeContainer.style.display = 'flex'; // 显示弹框
                    } else {
                        console.error('未找到帖子链接');
                    }
                });
            }
        });
    }

    // 初始调用
    addPreviewButtons();

    // 监听动态加载内容的事件(假设使用 MutationObserver)
    const observer = new MutationObserver(() => {
        addPreviewButtons(); // 每次内容变化时调用
    });

    // 观察目标节点(假设是帖子列表的父元素)
    const targetNode = document.querySelector('.topic-list'); // 根据实际情况选择
    if (targetNode) {
        observer.observe(targetNode, { childList: true, subtree: true });
    }
})();