Toolbar (DRAGGABLE Version)

Toolbar + dragabal + Position saving

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Toolbar (DRAGGABLE Version)
// @namespace    https://example.com/
// @version      1.2
// @description  Toolbar + dragabal + Position saving
// @author       ChatGPT&Jérôme
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_setClipboard
// @grant        window.focus
// @run-at       document-idle
// @license MIT
// ==/UserScript==

(function () {
  'use strict';

  // === CSS ===
  const style = document.createElement("style");
  style.textContent = `
  .vm-toolbar {
    position: fixed;
    bottom: 15px;
    right: 15px;
    display: flex;
    gap: 6px;
    padding: 8px;
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.7);
    color: white;
    font-family: sans-serif;
    font-size: 13px;
    z-index: 999999;
    backdrop-filter: blur(6px);
    cursor: move;            /* ← Zeigt: man kann ziehen */
    user-select: none;        /* ← Text lässt sich nicht markieren */
  }
  .vm-btn {
    background: rgba(255, 255, 255, 0.1);
    border: none;
    border-radius: 8px;
    padding: 5px 8px;
    color: white;
    cursor: pointer;
  }
  .vm-btn:hover { background: rgba(255, 255, 255, 0.2); }
  `;
  document.head.appendChild(style);

  // === Toolbar herstellen ===
  const bar = document.createElement("div");
  bar.className = "vm-toolbar";

  // Gespeicherte Position laden (falls vorhanden)
  bar.style.top = GM_getValue("vm_top", "");
  bar.style.left = GM_getValue("vm_left", "");
  if (bar.style.top || bar.style.left) {
    bar.style.bottom = "auto";
    bar.style.right = "auto";
  }

  // Buttons erstellen
  function makeBtn(text, onclick) {
    const btn = document.createElement("button");
    btn.textContent = text;
    btn.className = "vm-btn";
    btn.addEventListener("click", onclick);
    bar.appendChild(btn);
  }

  // === Buttons ===

  // 📋 Titel & URL kopieren
  makeBtn("📋 copy", () => {
    const text = `${document.title} — ${location.href}`;
    if (typeof GM_setClipboard === "function") GM_setClipboard(text);
    else if (navigator.clipboard) navigator.clipboard.writeText(text);
    else {
      const ta = document.createElement("textarea");
      ta.value = text;
      document.body.appendChild(ta);
      ta.select();
      document.execCommand("copy");
      ta.remove();
    }
    alert("✅ Titel & URL copied!");
  });

  // ⬆️ Nach oben scrollen
  makeBtn("⬆️ up", () => {
    window.scrollTo({ top: 0, behavior: "smooth" });
  });

  // 🔗 Externe Links highlighten
  let highlightOn = false;
  let highlightStyle = null;
  makeBtn("🔗 Highlight", () => {
    if (!highlightOn) {
      highlightStyle = document.createElement("style");
      highlightStyle.textContent = `
      a[href^="http"]:not([href*="${location.host}"]) {
        background: rgba(255,255,0,0.15);
        outline: 1px solid rgba(255,255,0,0.5);
      }`;
      document.head.appendChild(highlightStyle);
      highlightOn = true;
      alert("🔗 Extern Links marked");
    } else {
      highlightStyle?.remove();
      highlightOn = false;
    }
  });

  // 🗂 Sichtbare Links öffnen (max 10)
  makeBtn("🗂 open", () => {
    const links = Array.from(document.querySelectorAll('a[href^="http"]'))
      .filter(a => a.offsetParent !== null)
      .map(a => a.href);

    const unique = [...new Set(links)];
    const LIMIT = 10;

    if (unique.length === 0) {
      alert("no links found");
      return;
    }

    if (!confirm(`Es werden ${Math.min(unique.length, LIMIT)} Tabs geöffnet. Fortfahren?`)) return;

    unique.slice(0, LIMIT).forEach(url => window.open(url, "_blank"));
  });

  document.body.appendChild(bar);

  // === DRAGGABLE / Ziehen aktivieren ===
  let dragging = false;
  let offsetX = 0, offsetY = 0;

  bar.addEventListener("mousedown", (e) => {
    dragging = true;

    const rect = bar.getBoundingClientRect();
    offsetX = e.clientX - rect.left;
    offsetY = e.clientY - rect.top;

    // Animation aus
    bar.style.transition = "none";

    e.preventDefault();
  });

  document.addEventListener("mousemove", (e) => {
    if (dragging) {
      bar.style.top = `${e.clientY - offsetY}px`;
      bar.style.left = `${e.clientX - offsetX}px`;
      bar.style.bottom = "auto";
      bar.style.right = "auto";
    }
  });

  document.addEventListener("mouseup", () => {
    if (dragging) {
      dragging = false;

      // Position speichern
      GM_setValue("vm_top", bar.style.top);
      GM_setValue("vm_left", bar.style.left);

      // weiche Rück-Animation
      bar.style.transition = "0.1s ease";
    }
  });
})();