Greasy Fork

Greasy Fork is available in English.

网页拖拽与文本选择增强(优化版)

左键上下滑动拖拽网页,左右滑动自动复制文本,防止意外打开链接

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         网页拖拽与文本选择增强(优化版)
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  左键上下滑动拖拽网页,左右滑动自动复制文本,防止意外打开链接
// @author       deepseek and openai
// @match        *://*/*
// @grant        GM_setClipboard
// @license      MIT
// ==/UserScript==

(function() {
  'use strict';

  let isDragging = false, isSelectingText = false, preventClick = false;
  let startY = 0, startX = 0, startScrollY = 0, startScrollX = 0;
  let moveListenerActive = false, originalUserSelect = '';

  const eventOptions = { passive: false, capture: true };

  function preventAll(e) {
      if (e.cancelable) e.preventDefault();
      e.stopPropagation();
      e.stopImmediatePropagation();
  }

  async function copySelectedText() {
      const selection = window.getSelection()?.toString();
      if (selection) {
          try {
              if (typeof GM_setClipboard !== 'undefined') GM_setClipboard(selection);
              else if (navigator.clipboard?.writeText) await navigator.clipboard.writeText(selection);
              else document.execCommand('copy');
          } catch (err) {
              console.error('复制失败:', err);
          }
      }
  }

  function disableTextSelection() {
      originalUserSelect = document.body.style.userSelect;
      document.body.style.userSelect = 'none';
  }

  function restoreTextSelection() {
      document.body.style.userSelect = originalUserSelect;
  }

  function handleMouseMove(e) {
      if (e.button !== 0) return;

      if (!isDragging && !isSelectingText) {
          const deltaY = Math.abs(e.clientY - startY);
          const deltaX = Math.abs(e.clientX - startX);
          if (deltaY > deltaX * 2) {
              disableTextSelection();
              isDragging = true;
              preventClick = true;
          } else if (deltaX > deltaY * 5) {
              restoreTextSelection();
              isSelectingText = true;
              preventClick = true;
          }
      }

      if (isDragging) {
          window.scrollTo(startScrollX - (e.clientX - startX), startScrollY - (e.clientY - startY));
          preventAll(e);
      }
  }

  function handleMouseUp(e) {
      if (e.button !== 0) return;
      if (isSelectingText) copySelectedText().catch(console.error);
      if (preventClick) preventAll(e);
      restoreTextSelection();
      cleanupListeners();
  }

  function cleanupListeners() {
      if (moveListenerActive) {
          document.removeEventListener('mousemove', handleMouseMove, eventOptions);
          document.removeEventListener('mouseup', handleMouseUp, eventOptions);
          moveListenerActive = false;
      }
      isDragging = isSelectingText = false;
  }

  document.addEventListener('mousedown', (e) => {
      if (e.button !== 0) return;
      isDragging = isSelectingText = preventClick = false;
      startY = e.clientY;
      startX = e.clientX;
      startScrollY = window.scrollY;
      startScrollX = window.scrollX;
      window.getSelection()?.removeAllRanges();
      if (!moveListenerActive) {
          document.addEventListener('mousemove', handleMouseMove, eventOptions);
          document.addEventListener('mouseup', handleMouseUp, eventOptions);
          moveListenerActive = true;
      }
  }, eventOptions);

  document.addEventListener('click', (e) => { if (preventClick) preventAll(e); }, eventOptions);
  document.addEventListener('dragstart', preventAll, eventOptions);
  document.addEventListener('copy', (e) => { if (isSelectingText) e.stopPropagation(); }, eventOptions);
  window.addEventListener('beforeunload', cleanupListeners);
})();