InjectJS

Inject Javascript into almost any website.

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

You will need to install an extension such as Tampermonkey to install this script.

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name             InjectJS
// @namespace        http://github.com/YTXaos/InjectJS
// @version          1.30
// @description      Inject Javascript into almost any website.
// @description:es   Inyecte Javascript en casi cualquier sitio web
// @description:fr   Injectez Javascript dans presque tous les sites Web
// @description:de   Fügen Sie Javascript in fast jede Website ein
// @description:ja   ほぼすべてのウェブサイトにジャバスクリとを挿入する
// @description:la   Javascript in inject paene omnem website
// @description:ru   Внедрите Javascript практически в любой веб-сайт
// @author           YTXaos
// @match            *://*/*
// @match            file:///*
// @icon             https://raw.githubusercontent.com/YTXaos/InjectJS/main/assets/logo.png
// @grant            GM_addElement
// @grant            GM_getResourceText
// @grant            GM_getResourceURL
// @license          MIT
// @require          https://code.jquery.com/jquery-3.6.0.min.js
// @resource         MainCSS https://raw.githubusercontent.com/YTXaos/InjectJS/main/assets/main.css
// @resource         OptionsHTML https://raw.githubusercontent.com/YTXaos/InjectJS/main/pages/options.html
// @resource         OptionsJS https://raw.githubusercontent.com/YTXaos/InjectJS/main/options.js
// @resource         Fontawesome https://raw.githubusercontent.com/YTXaos/InjectJS/main/assets/fontawesome.css
// @resource         MainIcon https://raw.githubusercontent.com/YTXaos/InjectJS/main/assets/logov2.png
// ==/UserScript==

(function() {
    "use strict";
    const url = location.href,
        origin = location.origin;
    /**
     * @param {string} item Specify what item to look for in the options.
     * @returns {string} True or false if found, false boolean if not.
     */
    function Option(item) {
        if(localStorage.getItem(`inject-js:${item}`)) {
            return localStorage.getItem(`inject-js:${item}`).toString();
        } else {
            return false;
        }
    }
    /**
     * Create a log node.
     * @param {string} type The type of log to create.
     * @param {string} msg The message to output in the logs.
     */
    function createLog(type, msg) {
        const elm = document.querySelector(".js-injector-logs");
        let msg_type;
        type === "warning" && (msg_type = "WARN") || (msg_type = type.toUpperCase());
        elm.innerHTML += `
        <div class="js-log ${type}">
            [InjectJS&nbsp;<span class="time-date"></span>&nbsp;${msg_type}]:&nbsp;
            <span class="js-log-message">
                ${msg}
            </span>
        </div>`;
    }
    const logs = {
        info(msg) { createLog("info", msg); },
        warn(msg) { createLog("warning", msg); },
        error(msg) { createLog("error", msg); }
    }
    /**
     * Check whether the page the user is on is equivalent to param "page".
     * @param {string} page Specify what URL to check for.
     * @param {boolean} exact Whether it should check for the exact URL or relative.
     * @returns {boolean} True or false
     */
    function onURL(page, exact) {
        if(exact) {
            return url === `${origin}${page}`;
        } else {
            return url.includes(page);
        }
    }
    if(Option("disable") == "true") {
        document.addEventListener("keyup", function(e) {
            e.preventDefault();
            if(e.ctrlKey && e.key === ".") {
                localStorage.setItem("inject-js:disable", false);
                location.reload();
            }
        });
        return;
    }
    if(onURL("/inject-js/", true)) {
        location = "https://github.com/YTXaos/InjectJS";
    }
    Option("startup_log") == "true" && (console.info("InjectJS Loaded. Press Ctrl + Q to topen"));
    const popup = document.createElement("div"),
        log = document.createElement("div");
    GM_addElement(document.head, "style", { textContent: GM_getResourceText("MainCSS") });
    log.setAttribute("class", "js-injector-logs");
    log.innerHTML = '<span class="js-logs-close" title="Close" id="js-close">&times;</span>';
    log.style.display = "none";
    popup.setAttribute("class", "js-injector-popup");
    popup.style.display = "none";
    popup.innerHTML = `<label class="js-inject-header">
    <div class="js-logo-needle" style="background-image: url(${GM_getResourceURL("MainIcon")})">.....</div>
    Inject<span class="js-logo">JS</span>
</label>
<textarea placeholder="Your code here" class="js-code-inject" spellcheck="false" data-gramm="false" data-gramm_editor="false" data-enable-grammarly="false" id="js-code-inject"></textarea>
<div class="js-btns-section">
<button class="execute-code" disabled>Execute</button>
<button class="js-options-btn">Options</button>
</div>
<div class="js-btns-column">
<button class="show-js-logs">Logs</button>
</div>`;
    document.body.append(log);
    document.body.prepend(popup);

    function OptionsPage() {
        $("link[rel=stylesheet], style, script").remove();
        document.title = "InjectJS Options";
        document.body.innerHTML = GM_getResourceText("OptionsHTML");
        GM_addElement(document.head, "script", { textContent: GM_getResourceText("OptionsJS") });
    }
    const code = document.querySelector(".js-code-inject"),
        btn = document.querySelector(".execute-code"), option_btn = document.querySelector(".js-options-btn"), log_btn = document.querySelector(".show-js-logs");
    code.addEventListener("input", CheckCode);
    log_btn.addEventListener("click", function() {
        document.querySelector(".js-injector-logs").setAttribute("style", "display: flex !important");
        document.getElementById("js-close").addEventListener("click", function() {
            document.querySelector(".js-injector-logs").setAttribute("style", "");
        });
    });
    if(Option("disable_syntax") != "true") { code.addEventListener("keydown", Syntax); }
    btn.addEventListener("click", InjectCode);
    option_btn.addEventListener("click", () => { location = "/inject-js/options"; });
    /**
     * Syntax properties for autocomplete "(", "{", and strings.
     * @param {event} e Returns an event to handle accordingly.
     */
    function Syntax(e) {
        if(e.key === "{") {
            e.preventDefault();
            const start = code.selectionStart,
              end = code.selectionEnd,
              selection = code.value.substring(start, end),
              replace = `${code.value.substring(0, start)}{\n${selection}\n}${code.value.substring(end)}`;
            code.value = replace;
            code.focus();
            code.selectionEnd = end + 2;
          }
          if(e.key === "(") {
            e.preventDefault();
            const start = code.selectionStart,
              end = code.selectionEnd,
              selection = code.value.substring(start, end),
              replace = `${code.value.substring(0, start)}(${selection})${code.value.substring(end)}`;
            code.value = replace;
            code.focus();
            code.selectionEnd = end + 1;
          }
          if(e.which === 222) {
            e.preventDefault();
            const start = code.selectionStart,
              end = code.selectionEnd,
              selection = code.value.substring(start, end),
              replace = `${code.value.substring(0, start)}${e.key}${selection}${e.key}${code.value.substring(end)}`;
            code.value = replace;
            code.focus();
            code.selectionEnd = end + 1;
          }
    }
    function CheckCode() {
        const code = document.querySelector(".js-code-inject");
        if(code.value.length < 5) {
            btn.setAttribute("disabled", "disabled");
        } else {
            btn.removeAttribute("disabled");
        }
    }

    function InjectCode() {
        try {
            eval(code.value);
        } catch (e) {
            if(Option("alert_errors") == "true") {
                alert(e.message);
            } else {
                logs.error(e);
            }
        }
    }

    function ShowInjector() {
        dragElement(document.querySelector(".js-injector-popup"));
        /**
         * Makes an elemenet draggable around the screen.
         * @param {string} elmnt Select an element from the DOM to become draggable
         */
        function dragElement(elmnt) {
            var pos1 = 0,
                pos2 = 0,
                pos3 = 0,
                pos4 = 0;
            if(document.querySelector(".js-inject-header")) {
                document.querySelector(".js-inject-header").onmousedown = dragMouseDown;
            } else {
                elmnt.onmousedown = dragMouseDown;
            }

            function dragMouseDown(e) {
                e = e || window.event;
                e.preventDefault();
                pos3 = e.clientX;
                pos4 = e.clientY;
                document.onmouseup = closeDragElement;
                document.onmousemove = elementDrag;
            }

            function elementDrag(e) {
                e = e || window.event;
                e.preventDefault();
                pos1 = pos3 - e.clientX;
                pos2 = pos4 - e.clientY;
                pos3 = e.clientX;
                pos4 = e.clientY;
                elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
                elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
            }

            function closeDragElement() {
                document.onmouseup = null;
                document.onmousemove = null;
            }
        }
        popup.classList.toggle("show");
    }
    if(onURL("/inject-js/options", true)) {
        OptionsPage();
    }
    document.addEventListener("keyup", function(e) {
        e.preventDefault();
        if(e.ctrlKey && e.key === "q") {
            ShowInjector();
        }
    });
})();