wordpress 右键菜单修改

前言

此前看到Anheyu 的右键菜单样式,因此仿照该主题对Wordpress进行适配。

样式展示

修改正文

JS部分

新建JS文件(无子主题或者不想修改文件的话可以在主题中添加自定义JS代码

[blogRoot]/wp-content/themes/AeroCore-Child/js/rightmenu.js

/**
 * 右键菜单 - AeroCore 适配版
 *
 * 功能:
 * - 右键弹出自定义菜单,替换浏览器默认菜单
 * - Ctrl + 右键 恢复浏览器默认菜单
 * - 根据右键目标智能显示对应菜单项(文字选中/链接/图片/输入框)
 * - 边界检测,菜单不超出视口
 * - 适配 AeroCore 深色模式切换
 */

(function () {
    'use strict';

    // ==================== 菜单 HTML 模板 ====================
    var menuHTML = '<div id="rightMenu">' +
        // 导航操作
        '<div class="rm-group">' +
            '<a class="rm-item" data-action="back"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>后退</a>' +
            '<a class="rm-item" data-action="forward"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>前进</a>' +
            '<a class="rm-item" data-action="reload"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="1 4 1 10 7 10"/><polyline points="23 20 23 14 17 14"/><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"/></svg>刷新</a>' +
            '<a class="rm-item" data-action="scrollTop"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"/></svg>回顶部</a>' +
        '</div>' +
        // 选中文字
        '<div class="rm-group hidden" data-show="text">' +
            '<div class="rm-divider"></div>' +
            '<a class="rm-item" data-action="copy"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>复制</a>' +
            '<a class="rm-item" data-action="searchBaidu"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>百度搜索</a>' +
        '</div>' +
        // 链接
        '<div class="rm-group hidden" data-show="link">' +
            '<div class="rm-divider"></div>' +
            '<a class="rm-item" data-action="openLink"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>打开链接</a>' +
            '<a class="rm-item" data-action="openLinkNew"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="5" y="5" width="14" height="14" rx="2"/><path d="M12 5v14M5 12h14"/></svg>新窗口打开</a>' +
            '<a class="rm-item" data-action="copyLink"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>复制链接</a>' +
        '</div>' +
        // 图片
        '<div class="rm-group hidden" data-show="image">' +
            '<div class="rm-divider"></div>' +
            '<a class="rm-item" data-action="openImage"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>查看图片</a>' +
            '<a class="rm-item" data-action="copyImageLink"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>复制图片链接</a>' +
        '</div>' +
        // 输入框
        '<div class="rm-group hidden" data-show="input">' +
            '<div class="rm-divider"></div>' +
            '<a class="rm-item" data-action="paste"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><rect x="8" y="2" width="8" height="4" rx="1" ry="1"/></svg>粘贴</a>' +
        '</div>' +
        // 文章页
        '<div class="rm-group hidden" data-show="post">' +
            '<div class="rm-divider"></div>' +
            '<a class="rm-item" data-action="copyPageUrl"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>复制本文地址</a>' +
        '</div>' +
        // 通用操作
        '<div class="rm-divider"></div>' +
        '<a class="rm-item" data-action="randomPost"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>随便逛逛</a>' +
        '<a class="rm-item" data-action="toggleDark"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>昼夜切换</a>' +
    '</div>';

    // ==================== 注入 DOM ====================
    document.body.insertAdjacentHTML('beforeend', menuHTML);

    var $menu = document.getElementById('rightMenu');
    if (!$menu) return;

    // ==================== 工具函数 ====================
    function copyText(text) {
        if (navigator.clipboard && navigator.clipboard.writeText) {
            navigator.clipboard.writeText(text).then(function () {
                showToast('已复制');
            }).catch(function () {
                fallbackCopy(text);
            });
        } else {
            fallbackCopy(text);
        }
    }

    function fallbackCopy(text) {
        var ta = document.createElement('textarea');
        ta.value = text;
        ta.style.position = 'fixed';
        ta.style.left = '-9999px';
        ta.style.top = '-9999px';
        document.body.appendChild(ta);
        ta.focus();
        ta.select();
        try { document.execCommand('copy'); showToast('已复制'); } catch (e) {}
        document.body.removeChild(ta);
    }

    function showToast(msg) {
        var toast = document.createElement('div');
        toast.textContent = msg;
        toast.style.cssText = 'position:fixed;top:20px;left:50%;transform:translateX(-50%);' +
            'background:var(--theme-color,#3b82f6);color:#fff;padding:8px 20px;border-radius:8px;' +
            'font-size:14px;z-index:10000;pointer-events:none;transition:opacity 0.3s;';
        document.body.appendChild(toast);
        setTimeout(function () {
            toast.style.opacity = '0';
            setTimeout(function () { document.body.removeChild(toast); }, 300);
        }, 1500);
    }

    function scrollToTop() {
        var start = window.scrollY;
        var duration = 500;
        var startTime = null;
        function step(timestamp) {
            if (!startTime) startTime = timestamp;
            var progress = Math.min((timestamp - startTime) / duration, 1);
            var ease = 1 - Math.pow(1 - progress, 3);
            window.scrollTo(0, start * (1 - ease));
            if (progress < 1) requestAnimationFrame(step);
        }
        requestAnimationFrame(step);
    }

    function toggleDarkMode() {
        // 直接点击 AeroCore 主题切换按钮,由主题自身处理 data-theme / localStorage / 图标切换
        var toggleBtn = document.querySelector('.theme-toggle') || document.querySelector('.theme-toggle--nav');
        if (toggleBtn) {
            toggleBtn.click();
        } else {
            // 降级:手动切换
            var html = document.documentElement;
            if (html.getAttribute('data-theme') === 'dark') {
                html.removeAttribute('data-theme');
                try { localStorage.setItem('theme', 'light'); } catch (e) {}
            } else {
                html.setAttribute('data-theme', 'dark');
                try { localStorage.setItem('theme', 'dark'); } catch (e) {}
            }
        }
    }

    // ==================== 菜单显示/隐藏 ====================
    function showMenu(x, y) {
        $menu.style.display = 'block';
        // 先显示才能获取尺寸
        var menuW = $menu.offsetWidth;
        var menuH = $menu.offsetHeight;
        var winW = window.innerWidth;
        var winH = window.innerHeight;

        if (x + menuW > winW) x = x - menuW;
        if (y + menuH > winH) y = y - menuH;
        if (x < 0) x = 5;
        if (y < 0) y = 5;

        $menu.style.left = x + 'px';
        $menu.style.top = y + 'px';
    }

    function hideMenu() {
        $menu.style.display = 'none';
        // 隐藏所有条件分组
        var groups = $menu.querySelectorAll('.rm-group[data-show]');
        for (var i = 0; i < groups.length; i++) {
            groups[i].classList.add('hidden');
        }
    }

    // ==================== 右键事件 ====================
    document.addEventListener('contextmenu', function (e) {
        // Ctrl + 右键 → 显示浏览器默认菜单
        if (e.ctrlKey || e.metaKey) return;

        e.preventDefault();
        hideMenu();

        var target = e.target;
        var selection = window.getSelection().toString().trim();

        // 选中文字 → 显示文字菜单
        if (selection) {
            var textGroup = $menu.querySelector('[data-show="text"]');
            if (textGroup) textGroup.classList.remove('hidden');
            // 检查选中内容是否为 URL
            if (/^https?:\/\/[^\s]+$/.test(selection)) {
                var linkGroup = $menu.querySelector('[data-show="link"]');
                if (linkGroup) linkGroup.classList.remove('hidden');
            }
        }

        // 右键目标为链接
        if (target.tagName === 'A' || target.closest('a')) {
            var linkGroup = $menu.querySelector('[data-show="link"]');
            if (linkGroup) linkGroup.classList.remove('hidden');
        }

        // 右键目标为图片
        if (target.tagName === 'IMG') {
            var imgGroup = $menu.querySelector('[data-show="image"]');
            if (imgGroup) imgGroup.classList.remove('hidden');
        }

        // 右键目标为输入框
        if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
            var inputGroup = $menu.querySelector('[data-show="input"]');
            if (inputGroup) inputGroup.classList.remove('hidden');
        }

        // 文章页
        var article = document.querySelector('article') || document.querySelector('.post-content') || document.querySelector('.single-post');
        if (article) {
            var postGroup = $menu.querySelector('[data-show="post"]');
            if (postGroup) postGroup.classList.remove('hidden');
        }

        // 存储当前右键目标
        $menu._contextTarget = target;

        showMenu(e.clientX, e.clientY);
    });

    // 点击其他地方隐藏菜单
    document.addEventListener('click', function (e) {
        if (!$menu.contains(e.target)) {
            hideMenu();
        }
    });

    // 滚动隐藏菜单
    window.addEventListener('scroll', function () {
        if ($menu.style.display === 'block') {
            hideMenu();
        }
    }, { passive: true });

    // ESC 隐藏菜单
    document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape') hideMenu();
    });

    // ==================== 菜单项点击事件 ====================
    $menu.addEventListener('click', function (e) {
        var item = e.target.closest('[data-action]');
        if (!item) return;

        var action = item.getAttribute('data-action');
        var target = $menu._contextTarget;
        var selection = window.getSelection().toString().trim();

        switch (action) {
            case 'back':
                window.history.back();
                break;
            case 'forward':
                window.history.forward();
                break;
            case 'reload':
                window.location.reload();
                break;
            case 'scrollTop':
                scrollToTop();
                break;
            case 'copy':
                if (selection) copyText(selection);
                break;
            case 'searchBaidu':
                if (selection) {
                    window.open('https://www.baidu.com/s?wd=' + encodeURIComponent(selection));
                }
                break;
            case 'openLink':
                if (target && target.closest('a')) {
                    window.location.href = target.closest('a').href;
                } else if (/^https?:\/\//.test(selection)) {
                    window.location.href = selection;
                }
                break;
            case 'openLinkNew':
                if (target && target.closest('a')) {
                    window.open(target.closest('a').href);
                } else if (/^https?:\/\//.test(selection)) {
                    window.open(selection);
                }
                break;
            case 'copyLink':
                if (target && target.closest('a')) {
                    copyText(target.closest('a').href);
                } else if (/^https?:\/\//.test(selection)) {
                    copyText(selection);
                }
                break;
            case 'openImage':
                if (target && target.tagName === 'IMG' && target.src) {
                    window.open(target.src);
                }
                break;
            case 'copyImageLink':
                if (target && target.tagName === 'IMG' && target.src) {
                    copyText(target.src);
                }
                break;
            case 'paste':
                if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable)) {
                    navigator.clipboard.readText().then(function (text) {
                        if (target.isContentEditable) {
                            document.execCommand('insertText', false, text);
                        } else {
                            var start = target.selectionStart;
                            var end = target.selectionEnd;
                            target.value = target.value.substring(0, start) + text + target.value.substring(end);
                            target.selectionStart = target.selectionEnd = start + text.length;
                        }
                        target.focus();
                    }).catch(function () {
                        showToast('请允许读取剪贴板');
                    });
                }
                break;
            case 'copyPageUrl':
                copyText(window.location.href);
                break;
            case 'randomPost':
                // 拉取最新 100 篇文章,随机选一篇跳转
                fetch('/wp-json/wp/v2/posts?per_page=100&_fields=link')
                    .then(function (r) { return r.text(); })
                    .then(function (text) {
                        var start = text.indexOf('[');
                        if (start === -1) { window.location.href = '/'; return; }
                        var posts = JSON.parse(text.substring(start));
                        if (posts && posts.length) {
                            var idx = Math.floor(Math.random() * posts.length);
                            window.location.href = posts[idx].link;
                        } else {
                            window.location.href = '/';
                        }
                    })
                    .catch(function () {
                        window.location.href = '/';
                    });
                break;
            case 'toggleDark':
                toggleDarkMode();
                break;
        }

        hideMenu();
    });
})();

 

 

CSS部分

新建CSS文件(无子主题或者不想修改文件的话可以在主题中添加自定义CSS代码

[blogRoot]/wp-content/themes/AeroCore-Child/css/rightmenu.css

/**
 * 右键菜单 - AeroCore 适配版
 * 使用主题 CSS 变量,自动适配深色模式
 */

/* ==================== 菜单容器 ==================== */
#rightMenu {
    display: none;
    position: fixed;
    z-index: 9999;
    min-width: 160px;
    padding: 6px 0;
    background: var(--bg-primary, #fff);
    border: 1px solid var(--border-primary, #e5e7eb);
    border-radius: 10px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    animation: rmFadeIn 0.15s ease;
}

@keyframes rmFadeIn {
    from { opacity: 0; transform: scale(0.95); }
    to   { opacity: 1; transform: scale(1); }
}

/* 深色模式 */
html[data-theme="dark"] #rightMenu {
    background: var(--bg-primary, #1f2937);
    border-color: var(--border-primary, #374151);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
}

/* ==================== 菜单项通用 ==================== */
#rightMenu .rm-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 16px;
    font-size: 14px;
    color: var(--text-primary, #333);
    text-decoration: none;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
    white-space: nowrap;
    user-select: none;
    -webkit-user-select: none;
}

#rightMenu .rm-item:hover {
    background: var(--bg-hover, #f3f4f6);
    color: var(--theme-color, #3b82f6);
}

html[data-theme="dark"] #rightMenu .rm-item:hover {
    background: var(--bg-hover, #374151);
}

#rightMenu .rm-item svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    opacity: 0.7;
}

#rightMenu .rm-item:hover svg {
    opacity: 1;
}

/* ==================== 分隔线 ==================== */
#rightMenu .rm-divider {
    height: 1px;
    margin: 4px 8px;
    background: var(--border-primary, #e5e7eb);
    opacity: 0.5;
}

/* ==================== 隐藏分组 ==================== */
#rightMenu .rm-group.hidden {
    display: none;
}

/* ==================== 移动端适配 ==================== */
@media (max-width: 768px) {
    #rightMenu {
        min-width: 140px;
        border-radius: 8px;
    }
    #rightMenu .rm-item {
        padding: 10px 14px;
        font-size: 13px;
    }
}

 

 

懒人下载

 

上一篇 华为交换机流策略匹配逻辑
Tree Hole

Tree Hole管理员

何须多虑盈亏事,人生小满胜万全。

本月创作热力图

目录