Open Links

Select links with Z key and open them in new tabs

目前为 2023-07-24 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Open Links
  3. // @namespace https://github.com/mefengl
  4. // @version 0.0.4
  5. // @description Select links with Z key and open them in new tabs
  6. // @author mefengl
  7. // @include *
  8. // @grant GM.openInTab
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13.  
  14. let selectionRectangle = null;
  15. let elementsInsideRectangle = [];
  16. let countLabel = null;
  17. let zKeyPressed = false;
  18. let startX, startY;
  19.  
  20. function createRectangle(x, y) {
  21. let div = document.createElement('div');
  22. div.style.border = '1px dashed red';
  23. div.style.position = 'fixed';
  24. div.style.pointerEvents = 'none';
  25. return div;
  26. }
  27.  
  28. function createCountLabel() {
  29. let div = document.createElement('div');
  30. div.style.position = 'absolute';
  31. div.style.bottom = '0px';
  32. div.style.right = '5px';
  33. div.style.backgroundColor = 'transparent';
  34. return div;
  35. }
  36.  
  37. function detectElementsInRectangle() {
  38. elementsInsideRectangle = Array.from(document.querySelectorAll('a')).filter(el => {
  39. let rect = el.getBoundingClientRect();
  40. return rect.top >= parseInt(selectionRectangle.style.top) && rect.left >= parseInt(selectionRectangle.style.left) && rect.bottom <= (parseInt(selectionRectangle.style.top) + parseInt(selectionRectangle.style.height)) && rect.right <= (parseInt(selectionRectangle.style.left) + parseInt(selectionRectangle.style.width));
  41. });
  42.  
  43. elementsInsideRectangle.forEach(el => el.style.border = '1px solid red');
  44.  
  45. countLabel.innerText = elementsInsideRectangle.length;
  46. }
  47.  
  48. function removeBordersFromLinks() {
  49. document.querySelectorAll('a').forEach(el => el.style.border = '');
  50. }
  51.  
  52. document.addEventListener('keydown', (e) => {
  53. if (e.key.toLowerCase() === 'z') {
  54. zKeyPressed = true;
  55. }
  56. });
  57.  
  58. // Clear selection and open links if 'z' is released before mouse
  59. document.addEventListener('keyup', (e) => {
  60. if (e.key.toLowerCase() === 'z') {
  61. zKeyPressed = false;
  62. openLinksAndClear();
  63. }
  64. });
  65.  
  66. document.addEventListener('mousedown', (e) => {
  67. if (!zKeyPressed || e.buttons === 0) {
  68. clearSelection();
  69. return;
  70. }
  71. e.preventDefault();
  72. removeBordersFromLinks();
  73. startX = e.clientX;
  74. startY = e.clientY;
  75. selectionRectangle = createRectangle(startX, startY);
  76. document.body.appendChild(selectionRectangle);
  77. countLabel = createCountLabel();
  78. selectionRectangle.appendChild(countLabel);
  79. });
  80.  
  81. document.addEventListener('mousemove', (e) => {
  82. if (!zKeyPressed || !selectionRectangle || e.buttons === 0) {
  83. clearSelection();
  84. return;
  85. }
  86. e.preventDefault();
  87. removeBordersFromLinks();
  88. selectionRectangle.style.left = Math.min(e.clientX, startX) + 'px';
  89. selectionRectangle.style.top = Math.min(e.clientY, startY) + 'px';
  90. selectionRectangle.style.width = Math.abs(e.clientX - startX) + 'px';
  91. selectionRectangle.style.height = Math.abs(e.clientY - startY) + 'px';
  92. detectElementsInRectangle();
  93. });
  94.  
  95. function openLinksInBackground(urls) {
  96. urls.forEach((url) => {
  97. GM.openInTab(url, true);
  98. });
  99. }
  100.  
  101. // Clear selection and open links if mouse is released before 'z'
  102. document.addEventListener('mouseup', (e) => {
  103. if (!zKeyPressed || !selectionRectangle || e.buttons !== 0) {
  104. clearSelection();
  105. return;
  106. }
  107. e.preventDefault();
  108. openLinksAndClear();
  109. });
  110.  
  111. function clearSelection() {
  112. if (selectionRectangle) {
  113. document.body.removeChild(selectionRectangle);
  114. selectionRectangle = null;
  115. }
  116. removeBordersFromLinks();
  117. }
  118.  
  119. // To open links and clear selection
  120. function openLinksAndClear() {
  121. if (selectionRectangle) {
  122. let urlsToOpen = elementsInsideRectangle.map(el => el.href);
  123. openLinksInBackground(urlsToOpen);
  124. clearSelection();
  125. }
  126. }
  127. })();