您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
安卓浏览器:长按元素弹出菜单(删除/取消),带高亮预览、点击外部关闭、阻止原生长按菜单优先显示。
当前为
// ==UserScript== // @name 长按删除网页元素(v1.2 高亮+外部关闭+拦截原生菜单) // @namespace custom-longpress-delete // @version 1.2 // @description 安卓浏览器:长按元素弹出菜单(删除/取消),带高亮预览、点击外部关闭、阻止原生长按菜单优先显示。 // @match *://*/* // @grant none // ==/UserScript== (function () { 'use strict'; const LONGPRESS_DELAY = 600; // 长按触发时间(ms) const SUPPRESS_MS_AFTER_HIDE = 350; // 菜单被隐藏后短暂禁止再次触发,避免滑动停止后复现 const MAX_Z = 2147483647; let longPressTimer = null; let pressedElement = null; const originalStyles = new WeakMap(); // 保存每个元素的原始样式 let menuVisible = false; let touchMoved = false; let suppressLongPress = false; let overlay = null; let lastTouchX = 0, lastTouchY = 0; // ====== 创建菜单 ====== const menu = document.createElement('div'); menu.id = 'longpress-menu'; Object.assign(menu.style, { position: 'fixed', display: 'none', padding: '10px 14px', borderRadius: '10px', background: 'rgba(0,0,0,0.88)', color: '#fff', fontSize: '16px', zIndex: String(MAX_Z), userSelect: 'none', WebkitUserSelect: 'none', WebkitTouchCallout: 'none', boxShadow: '0 6px 18px rgba(0,0,0,0.35)', minWidth: '130px', textAlign: 'center', transform: 'translate(-50%, -120%)' }); const delBtn = document.createElement('div'); delBtn.innerText = '删除元素'; delBtn.style.padding = '8px 0'; delBtn.style.cursor = 'pointer'; delBtn.addEventListener('click', function (ev) { ev.stopPropagation(); if (pressedElement) { try { pressedElement.remove(); } catch (err) { /* ignore */ } } hideMenu(); }, true); const cancelBtn = document.createElement('div'); cancelBtn.innerText = '取消'; cancelBtn.style.padding = '8px 0'; cancelBtn.style.cursor = 'pointer'; cancelBtn.style.marginTop = '6px'; cancelBtn.style.borderTop = '1px solid rgba(255,255,255,0.08)'; cancelBtn.addEventListener('click', function (ev) { ev.stopPropagation(); hideMenu(); }, true); menu.appendChild(delBtn); menu.appendChild(cancelBtn); document.body.appendChild(menu); // ====== 创建/管理全屏透明 overlay(用于拦截原生菜单 & 点击外部关闭) ====== function ensureOverlay() { if (!overlay) { overlay = document.createElement('div'); overlay.id = 'longpress-overlay'; Object.assign(overlay.style, { position: 'fixed', top: '0', left: '0', width: '100%', height: '100%', background: 'transparent', zIndex: String(MAX_Z - 1), pointerEvents: 'none', // 开始时不拦截事件,只有在菜单显示后启用 WebkitUserSelect: 'none', WebkitTouchCallout: 'none', touchAction: 'none' }); // 点击 overlay 表示点击菜单外,收起菜单 overlay.addEventListener('touchstart', function (e) { if (menuVisible && !e.target.closest('#longpress-menu')) { e.preventDefault(); hideMenu(); } }, { passive: false }); // 阻止 overlay 上的 contextmenu(作为保险) overlay.addEventListener('contextmenu', function (e) { if (menuVisible) e.preventDefault(); }, true); document.body.appendChild(overlay); } return overlay; } function enableOverlay() { const ov = ensureOverlay(); ov.style.pointerEvents = 'auto'; } function disableOverlay() { if (overlay) overlay.style.pointerEvents = 'none'; } // 全局拦截 contextmenu(capture 阶段),当菜单可见时阻止浏览器原生菜单弹出 document.addEventListener('contextmenu', function (e) { if (menuVisible) { e.preventDefault(); e.stopPropagation(); } }, true); // ====== 展示 / 收起 菜单 ====== function showMenuAt(x, y) { // 位置调整:优先显示在触点上方,避免被手指遮挡 let left = x; let top = y; // 初步放在 touch 点上方 menu.style.left = left + 'px'; menu.style.top = top + 'px'; menu.style.display = 'block'; } function showMenu() { if (!pressedElement) return; menuVisible = true; enableOverlay(); menu.style.display = 'block'; } function hideMenu() { if (!menuVisible) { // 也确保恢复样式(以防某些情况下未恢复) if (pressedElement && originalStyles.has(pressedElement)) { const orig = originalStyles.get(pressedElement); pressedElement.style.outline = orig.outline || ''; pressedElement.style.outlineOffset = orig.outlineOffset || ''; originalStyles.delete(pressedElement); } pressedElement = null; return; } menuVisible = false; menu.style.display = 'none'; disableOverlay(); if (pressedElement && originalStyles.has(pressedElement)) { const orig = originalStyles.get(pressedElement); pressedElement.style.outline = orig.outline || ''; pressedElement.style.outlineOffset = orig.outlineOffset || ''; originalStyles.delete(pressedElement); } pressedElement = null; // 短时禁止再次触发,避免滑动停止后又立刻复现 suppressLongPress = true; setTimeout(() => { suppressLongPress = false; }, SUPPRESS_MS_AFTER_HIDE); clearTimeout(longPressTimer); longPressTimer = null; } // ====== 触摸事件监听(核心:长按检测 + 高亮) ====== document.addEventListener('touchstart', function (e) { // 若正在短时禁止触发,则忽略 if (suppressLongPress) return; // 不处理点中菜单本身的触摸(菜单的内部交互交由菜单处理) if (e.target.closest && e.target.closest('#longpress-menu')) return; touchMoved = false; const touch = e.touches && e.touches[0]; if (touch) { lastTouchX = touch.clientX; lastTouchY = touch.clientY; } else { lastTouchX = lastTouchY = 0; } pressedElement = e.target; // 启动长按计时器 longPressTimer = setTimeout(() => { // 当长按真正触发时,保存元素原始样式并高亮 if (!pressedElement) return; // 保存原始 outline,以便恢复 try { originalStyles.set(pressedElement, { outline: pressedElement.style.outline || '', outlineOffset: pressedElement.style.outlineOffset || '' }); pressedElement.style.outline = '3px solid rgba(255,0,0,0.62)'; pressedElement.style.outlineOffset = '-3px'; } catch (err) { // ignore } // 展示菜单并启用 overlay 拦截原生菜单 showMenuAt(lastTouchX || window.innerWidth / 2, lastTouchY || window.innerHeight / 2); enableOverlay(); menuVisible = true; // 阻止浏览器的默认长按行为(尽可能) // 注意:preventDefault 可能影响滚动—这里只在真正触发长按时调用 try { e.preventDefault(); } catch (err) { /* ignore */ } }, LONGPRESS_DELAY); }, { passive: false }); document.addEventListener('touchmove', function (e) { touchMoved = true; // 只要移动就取消未完成的长按 if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = null; } // 如果菜单已经显示,移动时应立即收起并短时禁止再次弹出 if (menuVisible) { hideMenu(); } else { // 更新触点坐标,以便长按触发时菜单能出现在最新位置 const touch = e.touches && e.touches[0]; if (touch) { lastTouchX = touch.clientX; lastTouchY = touch.clientY; } } }, { passive: true }); document.addEventListener('touchend', function (e) { // 手指抬起前清计时器 if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = null; } // 如果菜单已经显示且点击发生在菜单外(overlay 会拦截),overlay 的 touchstart 会触发 hideMenu // 这里额外处理一种情况:touchend 发生在页面(而不是 overlay/menu),也需要收起 if (menuVisible) { const target = e.target; if (!(target && target.closest && target.closest('#longpress-menu'))) { hideMenu(); } } else { // 未显示菜单时,重置 pressedElement pressedElement = null; } }, { passive: true }); // touchcancel 也算是中断,直接收起 document.addEventListener('touchcancel', function () { if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = null; } if (menuVisible) hideMenu(); pressedElement = null; }, { passive: true }); // 滚动时收起菜单,避免停下又复现 window.addEventListener('scroll', function () { if (menuVisible) hideMenu(); }, { passive: true }); // 当页面大小变化时也收起 menu window.addEventListener('resize', function () { if (menuVisible) hideMenu(); }); // 防止菜单自身被网页的 pointer-events:none/transform 等影响(尽量) // (这里不做额外处理,仅作为说明) })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址