Greasy Fork

来自缓存

Link Selector(同时打开多个网页)

Select and open links within a selected area using Ctrl + mouse selection, even if the area is small and does not completely contain the link element.

目前为 2023-04-08 提交的版本。查看 最新版本

// ==UserScript==
// @name         Link Selector(同时打开多个网页)
// @namespace    http://tampermonkey.net/
// @version      1.51
// @description  Select and open links within a selected area using Ctrl + mouse selection, even if the area is small and does not completely contain the link element. 
//                It selects the links that intersect with the selection rectangle.
// @match        http*://*/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
  let isSelecting = false;
  let startX, startY, currentX, currentY;
  let selectionDiv;

  document.addEventListener("mousedown", (event) => {
    if (event.ctrlKey && event.button === 0) {
      isSelecting = true;
      startX = event.pageX;
      startY = event.pageY;
      currentX = startX;
      currentY = startY;
      selectionDiv = createSelectionDiv(startX, startY);
      document.body.appendChild(selectionDiv);
      event.preventDefault();
    }
  });

  document.addEventListener("mousemove", (event) => {
    if (isSelecting) {
      currentX = event.pageX;
      currentY = event.pageY;
      updateSelectionDiv(startX, startY, currentX, currentY);

      const links = document.getElementsByTagName("a");
      const selectedLinks = [];
      const selectionRect = selectionDiv.getBoundingClientRect();
      for (let i = 0; i < links.length; i++) {
        const linkClientRects = links[i].getClientRects();
        for (let j = 0; j < linkClientRects.length; j++) {
          const linkRect = linkClientRects[j];
          if (
            linkRect.left <= selectionRect.right &&
            linkRect.right >= selectionRect.left &&
            linkRect.top <= selectionRect.bottom &&
            linkRect.bottom >= selectionRect.top
          ) {
            selectedLinks.push(links[i]);
            break;
          }
        }
      }
      highlightSelectedLinks(selectedLinks);
    }
  });

  document.addEventListener("mouseup", (event) => {
    if (isSelecting) {
      isSelecting = false;
      const selectedLinks = getSelectedLinks();
      for (let i = 0; i < selectedLinks.length; i++) {
        const link = selectedLinks[i];
        link.style.outline = "";
        window.open(link.href);
      }
      document.body.removeChild(selectionDiv);
      event.preventDefault();
    }
  });

  window.addEventListener("scroll", () => {
    if (isSelecting) {
      const { top: startTop, left: startLeft } = selectionDiv.getBoundingClientRect();
      const newTop = startTop + window.scrollY;
      const newLeft = startLeft + window.scrollX;
      selectionDiv.style.top = newTop + "px";
      selectionDiv.style.left = newLeft + "px";
    }
  });

  function createSelectionDiv(startX, startY) {
    const div = document.createElement("div");
    div.id = "selection-div";
    div.style.position = "absolute";
    div.style.border = "1px dashed black";
    div.style.background = "rgba(0, 0, 0, 0.1)";
    div.style.left = startX + "px";
    div.style.top = startY + "px";
    return div;
  }

  function updateSelectionDiv(startX, startY, currentX, currentY) {
    const left = Math.min(startX, currentX);
    const top = Math.min(startY, currentY);
    const width = Math.abs(currentX - startX);
    const height = Math.abs(currentY - startY);
    selectionDiv.style.left = left + "px";
    selectionDiv.style.top = top + "px";
    selectionDiv.style.width = width + "px";
    selectionDiv.style.height = height + "px";
  }

  function highlightSelectedLinks(selectedLinks) {
    const allLinks = document.getElementsByTagName("a");
    for (let i = 0; i < allLinks.length; i++) {
      if (selectedLinks.includes(allLinks[i])) {
        allLinks[i].style.outline = "2px solid red";
      } else {
        allLinks[i].style.outline = "";
      }
    }
  }

  function getSelectedLinks() {
    const links = document.getElementsByTagName("a");
    const selectedLinks = [];
    const selectionRect = selectionDiv.getBoundingClientRect();
    for (let i = 0; i < links.length; i++) {
      const linkClientRects = links[i].getClientRects();
      for (let j = 0; j < linkClientRects.length; j++) {
        const linkRect = linkClientRects[j];
        if (
          linkRect.left <= selectionRect.right &&
          linkRect.right >= selectionRect.left &&
          linkRect.top <= selectionRect.bottom &&
          linkRect.bottom >= selectionRect.top
        ) {
          selectedLinks.push(links[i]);
          break;
        }
      }
    }
    return selectedLinks;
  }
})();