Open Links

Select links with Z key and open them in new tabs

当前为 2023-07-26 提交的版本,查看 最新版本

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