链接预览助手

功能1:长按链接将打开内置窗口预览。Esc 可以关闭窗口。按住 Shift 或者 Alt 或者 Ctrl 或者 Command 键 或者 鼠标移动,长按时不会打开预览。功能2:鼠标中键 + (Shift 或者 Alt 或者 Ctrl 或者 Command 键),新窗口打开链接。

  1. // ==UserScript==
  2. // @name 链接预览助手
  3. // @namespace https://github.com/CheckCoder
  4. // @version 0.8.0
  5. // @description 功能1:长按链接将打开内置窗口预览。Esc 可以关闭窗口。按住 Shift 或者 Alt 或者 Ctrl 或者 Command 键 或者 鼠标移动,长按时不会打开预览。功能2:鼠标中键 + (Shift 或者 Alt 或者 Ctrl 或者 Command 键),新窗口打开链接。
  6. // @author check
  7. // @match http://*/*
  8. // @match https://*/*
  9. // @grant none
  10. // @license GPL
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // https://www.baidu.com 自动将 http 请求升级为 https
  17. if (window.location.href.indexOf('https://www.baidu.com') === 0) {
  18. const meta = document.createElement('meta');
  19. meta.setAttribute('http-equiv', 'Content-Security-Policy');
  20. meta.setAttribute('content', 'upgrade-insecure-requests');
  21. document.head.appendChild(meta);
  22. }
  23.  
  24. // 界面
  25. const iframeContainer = document.createElement('div');
  26. iframeContainer.setAttribute('style', 'width: 100vw; height: 100vh; position: fixed; z-index: 99999; top: 0; left:0; display:none; background: rgba(0,0,0,0.5); justify-content: center; align-items:center');
  27. const iframe = document.createElement('iframe');
  28. iframe.setAttribute('style', 'width:90vw; height: 80vh; background: white; border: none');
  29.  
  30. // 设置id
  31. const iframeContainerId = '$link-preview-iframeContainer';
  32. const iframeId = '$link-preview-iframe';
  33. iframeContainer.setAttribute('id', iframeContainerId);
  34. iframe.setAttribute('id', iframeId);
  35.  
  36. function getIframeContainer() {
  37. return document.getElementById(iframeContainerId);
  38. }
  39.  
  40. function getIframe() {
  41. return document.getElementById(iframeId);
  42. }
  43.  
  44. iframeContainer.appendChild(iframe);
  45.  
  46. // 显示和隐藏控制
  47. function show() {
  48. if (!getIframeContainer()) document.body.appendChild(iframeContainer);
  49. iframeContainer.style.display = 'flex';
  50. }
  51.  
  52. function hide() {
  53. iframeContainer.style.display = 'none';
  54. iframe.src = '';
  55. }
  56. iframeContainer.addEventListener('click', hide);
  57.  
  58. function getATagByEvent(event) {
  59. for(let i = 0; i < event.path.length; i++) {
  60. const nodeName = event.path[i].nodeName;
  61. if (nodeName && nodeName.toLocaleLowerCase() === 'a') {
  62. return event.path[i];
  63. }
  64. }
  65. }
  66.  
  67. // 长按逻辑
  68. let pressTimer = null;
  69. let hasIntoTimeout = false;
  70. let loogPressThreshold = 350;
  71. let isPressCancelButton = false;
  72. document.body.addEventListener('mousedown', function(event) {
  73. // 按住 Shift 或者 Alt 或者 Ctrl 或者 Command 键,不长按打开预览
  74. if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return;
  75. // 非鼠标左键,不长按打开预览
  76. if (event.button !== 0) return;
  77. const aTag = getATagByEvent(event);
  78. if (!aTag) return;
  79.  
  80. const href = aTag.getAttribute('href');
  81. if (!href || href.indexOf('javascript:') === 0) return;
  82.  
  83. pressTimer = setTimeout(function() {
  84. hasIntoTimeout = true;
  85. iframe.src = href;
  86. show();
  87. }, loogPressThreshold);
  88. });
  89. function cancelTimer() {
  90. if (!pressTimer) return;
  91.  
  92. clearTimeout(pressTimer);
  93. pressTimer = null;
  94. }
  95. document.body.addEventListener('mouseup', cancelTimer);
  96. // 鼠标移动取消
  97. let moveTime = 0;
  98. document.body.addEventListener('mousemove', function() {
  99. if (!pressTimer) return;
  100. if (++moveTime < 2) return;
  101. cancelTimer();
  102. moveTime = 0;
  103. });
  104.  
  105. // document.body.addEventListener('click', function(event) {
  106. // if (hasIntoTimeout) event.preventDefault();
  107. // hasIntoTimeout = false;
  108. // });
  109.  
  110. // esc 关闭
  111. document.body.addEventListener('keydown', function(event) {
  112. if (event.key === 'Escape') {
  113. window.parent.postMessage('$link-preview-hide', '*');
  114. }
  115. });
  116. window.addEventListener('message', function(event){
  117. if (event.data === '$link-preview-hide') {
  118. hide();
  119. window.focus();
  120. }
  121. }, {
  122. capture: true
  123. });
  124.  
  125. // 鼠标中键 + (Shift 或者 Alt 或者 Ctrl 或者 Command 键),新窗口打开链接
  126. document.body.addEventListener('mousedown', function(event) {
  127. if (event.button !== 1 || !(event.shiftKey || event.altKey || event.ctrlKey || event.metaKey)) return;
  128.  
  129. const aTag = getATagByEvent(event);
  130. if (!aTag) return;
  131.  
  132. const href = aTag.getAttribute('href');
  133. if (!href || href.indexOf('javascript:') === 0) return;
  134.  
  135. window.open(href);
  136. });
  137. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址