全局工具箱

添加一个按钮到每个网页左上方的位置,点击后显示工具箱的菜单

// ==UserScript==
// @name         全局工具箱
// @namespace    http://iapp.run
// @version      0.2.1
// @description  添加一个按钮到每个网页左上方的位置,点击后显示工具箱的菜单
// @author       zero-ljz
// @homepage     https://github.com/zero-ljz/scripts/blob/main/greasemonkey/tools.js
// @license MIT
// @match        *://*/*
// @grant        GM_registerMenuCommand
// @grant        GM_info
// @grant        GM_xmlhttpRequest
// @require      https://openuserjs.org/src/libs/sizzle/GM_config.js
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM.getValue
// @grant        GM.setValue
// @grant        GM_addStyle
// ==/UserScript==

(function () {
  "use strict";

  GM_addStyle(`
  .gm-acrylic-box {
    background-color: rgba(255, 255, 255, 0.6);
    color: #333;
    box-shadow: inset 1px 1px rgb(255 255 255 / 20%), inset -1px -1px rgb(255 255 255 / 10%), 1px 3px 24px -1px rgb(0 0 0 / 15%);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    /* box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); */
    }
  
    .gm-glass-box {
    background-image: linear-gradient(125deg, rgba(64, 64, 64, 0.3), rgba(64, 64, 64, 0.2) 70%); 
    /* background-image: linear-gradient(125deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.2) 70%); */
    color: #ADADAD;
    box-shadow: inset 1px 1px rgb(255 255 255 / 20%), inset -1px -1px rgb(255 255 255 / 10%), 1px 3px 24px -1px rgb(0 0 0 / 15%);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    }
  `);


// 使用 <script> 标签加载外部 JavaScript 文件
// var scriptElement = document.createElement('script');
// scriptElement.src = 'https://i.iapp.run/js/utils.js';
// scriptElement.type = 'text/javascript';
// document.head.appendChild(scriptElement);

function showMessageBox(message, title = '提示') {
  var messageBox = document.getElementById("gm-message-box");
  if (!messageBox) {
    messageBox = document.createElement("div");
    messageBox.id = "gm-message-box";
  }
  messageBox.innerHTML = "";

  messageBox.style.all = "initial";
  messageBox.classList.add("gm-acrylic-box");
  messageBox.style.cssText = `
  position: fixed;
  top: 20%;
  left: 50%;
  transform: translate(-50%, -50%);

  /*background: #fff;*/
  padding: 20px;
  /*border: 1px solid #ccc;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);*/

  min-width: 200px;
  max-width: 600px;
  min-height: 100px;
  z-index: 9999;

  border-radius: 10px;
  `;
  messageBox.insertAdjacentHTML('beforeend', `
  <p><b>${title}</b></p>
  <p style="all: initial; whiteSpace: pre-line;" contenteditable="true">${message.replace(/\n/g, "\r\n")}</p>
  `);
  messageBox.insertAdjacentHTML('beforeend', `
  <button id="messageBoxclose" style="all: initial; cursor: pointer; position: absolute; margin-left: 10px; top: 10px; right: 10px;">╳</button>
  `);
  document.body.appendChild(messageBox);
  document.getElementById("messageBoxclose").addEventListener("click", function () {
    document.body.removeChild(messageBox);
  })
  return messageBox;
}

  var menuItems = [
    { name: "隐藏按钮", action: toggleButton },
    {
      name: "脚本设置",
      action: function () {
        gmc.open();
      },
    },

    {
      name: "朗读",
      action: function () {
        let q = window.getSelection().toString();
        if (!q) q = prompt("你没有选中任何文本,请输入:", "");
        if (q != null)
          window.speechSynthesis.speak(new window.SpeechSynthesisUtterance(q));
      },
    },
    {
      name: "翻译",
      action: function () {
        let q = window.getSelection().toString();
        if (q == "") {
          q = prompt("你没有选中任何文本,请输入:", "");
        }
        if (q != null) {
          // 发送翻译请求
          GM_xmlhttpRequest({
            method: "GET",
            url:
              "http://translate.google.com/translate_a/single?client=gtx&dt=t&dj=1&ie=UTF-8&sl=auto&tl=zh&q=" +
              encodeURIComponent(q),
            //data: JSON.stringify({ content: pageContent }),
            //headers: {
            //    'Content-Type': 'application/json'
            //},
            onload: function (response) {
              // 获取翻译结果
              const obj = JSON.parse(response.responseText);
              let res = "";
              for (const [key, value] of Object.entries(obj.sentences)) {
                res += value.trans + "\r\n";
              }
              showMessageBox(res, "翻译结果");
            },
          });
        }
      },
    },
    {
      name: "搜索",
      action: function () {
        let q = window.getSelection().toString();
        if (!q) q = prompt("你没有选中任何文本,请输入:", "");
        if (q != null)
          window.open(
            "https://www.google.com/search?q=" +
              encodeURIComponent(q).replace(/ /g, "+")
          );
      },
    },
    {
      name: "搜索-中文结果",
      action: function () {
        let q = window.getSelection().toString();
        if (!q) q = prompt("你没有选中任何文本,请输入:", "");
        if (q != null)
          window.open(
            "https://www.google.com/search?lr=lang_zh-CN&q=" +
              encodeURIComponent(q).replace(/ /g, "+")
          );
      },
    },
    {
      name: "翻译页面-谷歌",
      action: function () {
        location.href =
          "https://translate.google.com/translate?sl=auto&tl=zh-CN&u=" +
          encodeURIComponent(location.href);
      },
    },

    {
      name: "翻译页面-有道",
      action: function () {
        location.href =
          "http://webtrans.yodao.com/webTransPc/index.html#/?from=auto&to=auto&type=1&url=" +
          encodeURIComponent(location.href);
      },
    },
    {
      name: "词典-谷歌",
      action: function () {
        let q = window.getSelection().toString();
        if (!q) q = prompt("你没有选中任何文本,请输入:", "");
        if (q != null)
          window.open(
            "https://www.google.com/search?q=define:" + encodeURIComponent(q),
            "new",
            "location=no, toolbar=no"
          );
      },
    },

    {
      name: "词典-有道",
      action: function () {
        let q = window.getSelection().toString();
        if (q == "") {
          q = prompt("你没有选中任何文本,请输入:", "");
        }
        if (q != null)
          window.open(
            "http://dict.youdao.com/w/eng/" + encodeURIComponent(q),
            "new",
            "location=no, toolbar=no"
          );
      },
    },


    {
      name: "搜索-维基百科",
      action: function () {
        let q = window.getSelection().toString();
        if (!q) q = prompt("你没有选中任何文本,请输入:", "");
        if (q != null)
          window.open("https://zh.wikipedia.org/wiki/" + encodeURIComponent(q));
      },
    },
    {
      name: "搜索-当前站点",
      action: function () {
        let q = window.getSelection().toString();
        if (!q) q = prompt("你没有选中任何文本,请输入:", "");
        if (q != null)
          location = (
            "http://www.google.com/search?num=100&q=site:" +
            encodeURIComponent(location.hostname) +
            ' "' +
            encodeURIComponent(q.replace(/\"/g, "")) +
            '"'
          ).replace(/ /g, "+");
      },
    },

    {
      name: "显示密码",
      action: function () {
        /*window.top.document.activeElement.type = "text"; */ !(function () {
          for (
            var t = document.getElementsByTagName("input"), e = 0;
            e < t.length;
            e++
          )
            "password" === t[e].getAttribute("type") &&
              t[e].setAttribute("type", "text");
        })();
      },
    },
    {
      name: "屏蔽元素",
      action: function () {
        let selection = window.getSelection();
        if (selection.toString()) {
          var range = selection.getRangeAt(0); // 获取范围内的节点

          // 递归遍历节点,查找最近的元素节点
          function findClosestElement(node) {
            if (node.nodeType === Node.ELEMENT_NODE) {
              return node; // 当前节点是元素节点,返回
            } else if (node.parentNode) {
              return findClosestElement(node.parentNode); // 继续向上查找父节点
            } else {
              return null; // 未找到包含文本的元素节点
            }
          }

          // 查找包含所选文本的最近的元素节点
          findClosestElement(range.commonAncestorContainer).style.display =
            "none";
        } else {
          document.activeElement.style.display = "none";
        }
      },
    },
    {
      name: "解除限制",
      action: function () {
        !(function () {
          function t(e) {
            e.stopPropagation(),
              e.stopImmediatePropagation && e.stopImmediatePropagation();
          }
          document.querySelectorAll("*").forEach((e) => {
            "none" ===
              window
                .getComputedStyle(e, null)
                .getPropertyValue("user-select") &&
              e.style.setProperty("user-select", "text", "important");
          }),
            [
              "copy",
              "cut",
              "contextmenu",
              "selectstart",
              //"mousedown",
              "mouseup",
              "mousemove",
              "keydown",
              "keypress",
              "keyup",
            ].forEach(function (e) {
              document.documentElement.addEventListener(e, t, { capture: !0 });
            }),
            showMessageBox("解除限制成功啦!");
        })();
      },
    },

    {
      name: "编辑网页",
      action: function () {
        !(function () {
          "true" === document.body.getAttribute("contenteditable")
            ? (document.body.setAttribute("contenteditable", !1),
              showMessageBox("网页不能编辑啦!"))
            : (document.body.setAttribute("contenteditable", !0),
              showMessageBox("网页可以编辑啦!"));
        })();
      },
    },
    {
      name: "网页标注",
      action: function () {
        !(function () {
          fetch("https://unpkg.com/spacingjs").then(async (res) =>
            eval(await res.text())
          );
        })();
        showMessageBox("按住Alt即可使用");
      },
    },
    {
      name: "生成二维码",
      action: function () {
        let q = window.getSelection().toString();
        if (!q) q = prompt("你没有选中任何文本,请输入:", "");
        if (q != null)
          window.open(
            "https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=" +
              encodeURIComponent(q),
            "new",
            "location=no, toolbar=no"
          );
      },
    },
    {
      name: "页面快照",
      action: function () {
        document.location.href =
          "http://www.google.com/search?q=cache:" +
          encodeURIComponent(document.location.href);
      },
    },
    {
      name: "网页存档",
      action: function () {
        document.location.href =
          "http://web.archive.org/" +
          encodeURIComponent(document.location.href);
      },
    },
    {
      name: "类似网站",
      action: function () {
        window.open(
          "https://www.similarweb.com/zh-tw/website/" +
            window.location.host +
            "/competitors/",
          "new",
          "location=no, toolbar=no"
        );
      },
    },
    
    {
      name: "类似网站2",
      action: function () {
        const subdomain = window.location.hostname;
        const domainParts = subdomain.split(".");
        const mainDomain = domainParts.slice(-2).join(".");
        window.open(
          "https://www.similarsites.com/site/" + mainDomain + "",
          "new",
          "location=no, toolbar=no"
        );
      },
    },
    {
      name: "类似网站3",
      action: function () {
        window.open(
          "https://www.sitelike.org/similar/" +
            window.location.host +
            "/competitors/",
          "new",
          "location=no, toolbar=no"
        );
      },
    },

    {
      name: "执行JS",
      action: function () {
        let q = window.getSelection().toString();
        if (!q) q = prompt("你没有选中任何文本,请输入:", "alert()");
        if (q != null) eval(q);
      },
    },
    {
      name: "调试信息",
      action: function () {
        console.log(`
          script.name: ${GM_info.script.name}
          script.version: ${GM_info.script.name} ${GM_info.script.version}
          script.description: ${GM_info.script.description}
          script.homepage: ${GM_info.script.homepage}
          script.author: ${GM_info.script.author}

          activeElement: ${document.activeElement}
          activeElement tagName: ${document.activeElement.tagName}
          activeElement type: ${document.activeElement.type}
          activeElement value: ${document.activeElement.value}
          activeElement name: ${document.activeElement.name}
          activeElement id: ${document.activeElement.id}
          activeElement className: ${document.activeElement.className}

          selectedText: ${window.getSelection().toString()}

          URL: ${window.document.URL}
          location.href: ${window.document.location.href}
          location.host: ${window.document.location.host}
          location.pathname: ${window.document.location.pathname}
          location.search: ${window.document.location.search}
          referrer: ${window.document.referrer}
          title: ${window.document.title}
          characterSet: ${window.document.characterSet}
          contentType: ${window.document.contentType}
          doctype: ${window.document.doctype}
          readyState: ${window.document.readyState}
          lastModified: ${window.document.lastModified}
        `);
      },
    },
  ];

  let default_values = {
    btn_top: "15%",
    btn_left: "10px",
    show_button: true,
    btn_text: "◯",
  };

  // 创建脚本设置页面实例
  let gmc = new GM_config({
    id: "MyConfig", // The id used for this instance of GM_config
    title: "脚本设置", // Panel Title
    // Fields object
    fields: {
      btn_top: {
        label: "按钮水平坐标",
        type: "text",
        default: default_values.btn_top,
      },
      btn_left: {
        label: "按钮垂直坐标",
        type: "text",
        default: default_values.btn_left,
      },
      show_button: {
        label: "显示按钮",
        type: "checkbox",
        default: default_values.show_button,
      },
      btn_text: {
        label: "按钮文字",
        type: "select",
        options: ["◯", "🌎", "🌏", "🟢", "🔵", "💧", "🍀", "❄", "〓", "╳"],
        default: default_values.btn_text,
      },
    },
    events: {
      init: function () {
        // runs after initialization completes
        // override saved value
        //this.set('Name', 'Mike Medley');
        // open frame
        //this.open();
      },
      save: function () {
        // Save each setting to GM_setValue
        for (var key in this.fields) {
          if (this.fields.hasOwnProperty(key)) {
            var value = this.get(key);
            GM_setValue(key, value);
          }
        }

        this.close();
      },
    },
  });

  // 注册菜单项
  menuItems.forEach(function (item) {
    GM_registerMenuCommand(item.name, item.action);
  });

  // 创建菜单容器
  var menuContainer = document.createElement("div");
  menuContainer.classList.add("gm-glass-box");
  menuContainer.style.cssText = `
  position: fixed;
  padding: 10px;
  z-index: 9999;
  display: none;
  max-height: 80%; /* 设置最大高度为父元素高度的50% */
  overflow-y: auto; /* 显示滚动条,仅在内容溢出时显示 */
  border-radius: 7px;
`;

  // 创建菜单项
  menuItems.forEach(function (item) {
    var menuItem = document.createElement("div");
    menuItem.innerHTML = item.name;
    menuItem.style.cursor = "pointer";
    menuItem.style.marginBottom = "5px";
    menuItem.style.fontSize = "16px";
    menuItem.style.lineHeight = "1.2";
    menuItem.style.color = "#F2F2F2";
    menuItem.style.textAlign = "left";

    menuItem.addEventListener("mouseenter", function () {
      menuItem.style.color = "white"; // 在鼠标悬停时 0078D7
    });

    menuItem.addEventListener("mouseleave", function () {
      menuItem.style.color = "#F2F2F2"; // 在鼠标离开时
    });

    menuItem.addEventListener("mousedown", function (event) {
      event.preventDefault(); // 阻止获取焦点
      item.action();
      menuContainer.style.display = "none";
    });

    menuContainer.appendChild(menuItem);
  });

  // 创建按钮
  var button = document.createElement("button");
  button.innerHTML = GM_getValue("btn_text", default_values.btn_text);

  Object.assign(button.style, {
    padding: "5px",
    backgroundColor: "grey",
    borderRadius: "0.5rem",
    border: "0",
    color: "white",
    position: "fixed",
    top: GM_getValue("btn_top", default_values.btn_top),
    left: GM_getValue("btn_left", default_values.btn_left),
  });
  button.style.display = GM_getValue("show_button", default_values.show_button)
    ? "block"
    : "none";

  // 添加按钮点击事件
  button.addEventListener("mousedown", function (event) {
    event.preventDefault(); // 阻止获取焦点
    if (menuContainer.style.display === "none") {
      // 获取按钮的相对位置
      var buttonRect = button.getBoundingClientRect();

      // 设置菜单容器的位置
      menuContainer.style.top = buttonRect.top + "px";
      menuContainer.style.left = buttonRect.left + buttonRect.width + 5 + "px";

      menuContainer.style.display = "block";
    } else {
      menuContainer.style.display = "none";
    }
  });

  // 将菜单容器和按钮添加到页面上
  document.body.appendChild(menuContainer);
  document.body.appendChild(button);

  // 切换按钮的显示状态
  function toggleButton() {
    if (button.style.display === "block") {
      button.style.display = "none";
    } else {
      button.style.display = "block";
    }
  }
})();