tianteng

1. 绅士漫画,下拉浏览页面,由原先的一列模式改为两列模式 2. javbus, 添加 "粘贴并搜索" 按钮; 添加 "打开srbt" 链接; 详情页面添加复制车牌号按钮.

// ==UserScript==
// @name         tianteng
// @namespace    https://greasyfork.org/xmlspy
// @version      0.8.0
// @description  1. 绅士漫画,下拉浏览页面,由原先的一列模式改为两列模式 2. javbus, 添加 "粘贴并搜索" 按钮; 添加 "打开srbt" 链接; 详情页面添加复制车牌号按钮.

// @author       xmlspy
// @license      MIT

// @require      https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js

// @include      *
// @connect      *

// @run-at       document-start

// @grant        GM_xmlhttpRequest
// @grant        GM.setClipboard
// @grant        GM.xmlhttpRequest
// @grant        unsafeWindow
// @grant        GM_log
// @grant        GM_info


// ==/UserScript==

(function () {
  "use strict";
  const enableDebug = true;
  let seq = 0;

  // // 获取 HTMLElement 构造函数
  // const HTMLElementConstructor = HTMLElement;

  // // 创建一个代理对象来拦截 HTMLElement 的构造函数
  // const HTMLElementProxy = new Proxy(HTMLElementConstructor, {
  //   construct(target, args, newTarget) {
  //     console.log("Creating a new HTMLElement instance");
  //     // 创建一个新的 HTMLElement 实例
  //     const instance = new target(...args);
  //     // 返回一个新的代理对象来拦截实例的属性和方法
  //     return new Proxy(instance, {
  //       get(target, prop, receiver) {
  //         console.log(`Accessing property: ${prop}`);
  //         return Reflect.get(target, prop, receiver);
  //       },
  //       set(target, prop, value, receiver) {
  //         console.log(`Setting property: ${prop} to ${value}`);
  //         return Reflect.set(target, prop, value, receiver);
  //       },
  //       has(target, prop) {
  //         console.log(`Checking if property exists: ${prop}`);
  //         return Reflect.has(target, prop);
  //       },
  //       deleteProperty(target, prop) {
  //         console.log(`Deleting property: ${prop}`);
  //         return Reflect.deleteProperty(target, prop);
  //       },
  //       ownKeys(target) {
  //         console.log(`Enumerating properties`);
  //         return Reflect.ownKeys(target);
  //       },
  //       getOwnPropertyDescriptor(target, prop) {
  //         console.log(`Getting property descriptor for: ${prop}`);
  //         return Reflect.getOwnPropertyDescriptor(target, prop);
  //       },
  //       defineProperty(target, prop, descriptor) {
  //         console.log(`Defining property: ${prop}`);
  //         return Reflect.defineProperty(target, prop, descriptor);
  //       },
  //     });
  //   },
  // });

  // // 替换全局的 HTMLElement 构造函数
  // Object.defineProperty(window, "HTMLElement", {
  //   value: HTMLElementProxy,
  //   writable: false,
  //   configurable: false,
  // });

  // // 测试
  // const div = document.createElement("div");
  // div.innerHTML = "Hello, World!";
  // console.log(div.innerHTML);
  // div.innerHTML = "Hello, Proxy!";
  // console.log(div.innerHTML);
  /////////////////////////////////////////////////////////////////////////////
  // 事件拦截
  /////////////////////////////////////////////////////////////////////////////
  debug(document.querySelector("title"));

  //松鼠症倉庫 地址发布页 https://ahrilist.top/

  const ep = EventTarget.prototype;
  // setTimeout(function () {
  //   if (!isNativeCode(ep.addEventListener)) {
  //     debug(`addEventListener 原型被更改为:${ep.addEventListener.toString()}`);
  //   }
  // });
  // if(!ep.constructorOriginal){
  //   ep.constructorOriginal = ep.constructor;
  //   ep.constructor=function(){
  //     debug('构造器');
  //     this.constructorOriginal();
  //   }
  // }
  // function monster1(disposition) {
  //   this.disposition = disposition;
  // }

  // const handler1 = {
  //   construct(target, args) {
  //     console.log(`Creating a ${target.name}`);
  //     // Expected output: "Creating a monster1"

  //     return new target(...args);
  //   },
  // };

  // const proxy1 = new Proxy(monster1, handler1);

  // console.log(new proxy1('fierce').disposition);

  if (!ep.addEventListenerOriginal) {
    ep.addEventListenerOriginal = ep.addEventListener;
    ep.addEventListener = function (type, callback, options) {
      // if (/ahri8\.top/.test(window.location.href)) {
      // debug(`添加事件监听器:target: ${this} type: ${type}  callback: ${callback}  options: ${options}`);
      if (this) {
        /////////////////////////////////////////////////////////////////////////////
        // 松鼠症倉庫
        /////////////////////////////////////////////////////////////////////////////
        if (this.className && this.className.includes("apo")) {
          debug("禁止点击广告", "松鼠症倉庫");
          return;
        }
        // }
        this.allListeners = this.allListeners || [];
        this.allListeners.push({ type, callback, options });
        // this.addEventListenerOriginal(type, callback, options);
        this.addEventListenerOriginal.apply(this, arguments);
      } else {
        debug(
          `[this] is bad. type: ${type}  callback: ${callback}  options: ${options}`,
          "addEventListenerHook"
        );
      }
    };
  }
  if (!ep.removeEventListenerOriginal) {
    ep.removeEventListenerOriginal = ep.removeEventListener;
    ep.removeEventListener = function (type, callback, options) {
      if (this) {
        this.removeEventListenerOriginal.apply(this, arguments);
        this.allListeners = this.allListeners || [];
        const index = this.allListeners.indexOf({ type, callback, options });
        if (index != -1) {
          this.allListeners.splice(index, 1);
        }
      } else {
        debug(
          `[this] is bad. type: ${type}  callback: ${callback}  options: ${options}`,
          "removeEventListenerHook"
        );
      }
    };
  }

  /////////////////////////////////////////////////////////////////////////////
  // 节点变化监控
  /////////////////////////////////////////////////////////////////////////////
  new MutationObserver(function (mutationsList, observer) {
    // Use traditional 'for loops' for IE 11
    // console.log(mutationsList);
    for (let mutation of mutationsList) {
      if (mutation.type === "childList") {
        const target = mutation.target;
        if (target.getAttribute("id") == "magnet-table") {
          debug(mutation.addedNodes);
        }
      } else if (mutation.type === "attributes") {
        if (mutation.attributeName.startsWith("on")) {
          debug(mutation, "MutationObserver");
          // debug(`target: ${mutation.target}`);
        }
      }
    }
  }).observe(document, {
    childList: true,
    subtree: true,
    attributes: true,
    //attributeFilter: [],
    attributeOldValue: true,
    characterData: false,
    characterDataOldValue: false,
  });

  const skrbtDomain = "skrbtqx";
  const skrbtHost = skrbtDomain + ".top";
  const skrbtUrl = "https://" + skrbtHost;

  const javbusDomain = "busfan";
  const javabusUrl = `https://www.${javbusDomain}.shop`;

  // execute(()=>{},()=>{});

  $(function () {
    // execute("松鼠症倉庫", /ahri8\.top/, () => {
    //   removeEvents(document.querySelectorAll("a.apo"), "click");

    //   debug("-------------------------------------------------------xxxx");
    // });
    ///////////////////////////////////////////////////////////////////////////
    // oschina
    ///////////////////////////////////////////////////////////////////////////
    execute("开源中国", /oschina\.net(\/)?$/, () => {
      debug("修改首页头条新闻和在线工具无法中键点击问题.", "开源中国");
      $("div.headline>div.head-news>div").each(function () {
        const $this = $(this);
        const href = $this.attr("data-href");
        const classCss = $this.attr("class");
        const title = $this.attr("title");
        const html = `<a target="_blank" title="${title}" href="${href}" class="${classCss}">${title}</a>`;
        $this.replaceWith(html);
      });
      debug("修改首页在线工具无法中键点击问题.", "开源中国");
      $("div.tool-item>a").each(function () {
        const $this = $(this);
        const href = $this.attr("data-href");
        $this.attr("href", href);
        $this.attr("target", "_blank");
      });
    });
    ///////////////////////////////////////////////////////////////////////////
    // 紳士漫畫永久域名: wnacg.com 紳士漫畫永久地址發佈頁: wnacg.date
    ///////////////////////////////////////////////////////////////////////////
    execute("紳士漫畫", '$head>title:contains("紳士漫畫")', () => {
      if (location.href.includes("photos-index-aid")) {
        debug("明细页面添加搜索框", "紳士漫畫");
        const searchInput = `
          <div class="search" style="float:right;">
            <form id="album_search q-form" action="/search/" method="get" _lpchecked="1">
              <div class="input-append" id="q-input">
                <input type="text" class="search-query ui-autocomplete-input tips" name="q" value="" title="搜索漫畫" autocomplete="off" role="textbox" aria-autocomplete="list" aria-haspopup="true">
                <input style="display:none" type="radio" name="f" value="_all" checked="">
                <input style="display:none" name="s" value="create_time_DESC">
                <input style="display:none" name="syn" value="yes">
                <button type="" name=""></button>
              </div>
            </form>
          </div>
        `;
        $("#bodywrap").prepend(searchInput);
      }

      if (location.href.includes("photos-slide-aid")) {
        debug("下拉阅读页面,图片由一列改为两列", "紳士漫畫");
        const nodeToObserve = document.querySelector("#img_list");
        $(nodeToObserve).css({
          width: "100%",
          display: "flex",
          "flex-wrap": "wrap",
          "justify-content": "flex-start",
          "overflow-x": "hidden",
        });
        const imgWidth = document.documentElement.clientWidth / 2 - 10;
        const imgHeight = document.documentElement.clientHeight - 50;
        new MutationObserver((mutations, observer) => {
          $("#img_list>div").css({
            flex: "1",
            "background-color": "#cacaca",
            margin: "0 5px 5px 0",
            width: "calc((100% - 10px) / 2)",
            "min-width": "calc((100% - 10px) / 2)",
            "max-width": "calc((100% - 10px) / 2)",
          });
          $("#img_list>div>img").on("load", (e) => {
            drawImage(e.target, imgWidth, imgHeight);
          });
        }).observe(nodeToObserve, { childList: true });
      }

      if ($("input.search-query").length > 0) {
        debug("为搜索框后面添加 粘贴&搜索 按钮", "紳士漫畫");
        const $pasteAndSearchButton = $(
          `<button style="float:right;height:30px;">粘贴&amp;搜索</button>`
        );
        $("#bodywrap").prepend($pasteAndSearchButton);
        $pasteAndSearchButton.on("click", () => {
          navigator.clipboard.readText().then((clipText) => {
            if (clipText != null && $.trim(clipText) != "") {
              $("[name=q]").val($.trim(clipText));
              $("#q-input > button").click();
            }
          });
        });
      }
    });

    ///////////////////////////////////////////////////////////////////////////
    // JAVLibrary
    ///////////////////////////////////////////////////////////////////////////
    execute("JAVLibrary", '$head>title:contains("JAVLibrary")', () => {
      // ---- 所有页面

      // 删除广告
      $(".socialmedia,#bottombanner13,#topbanner11,#sidebanner11").remove();
      $("#leftmenu>div>ul:nth-child(2)>li:nth-child(2)").remove();

      // 调节UI
      $("#content").css("padding-top", "10px");
      $("#toplogo").css("height", "50px");
      $("#toplogo").find('img[src*="logo-top"]').attr("height", "40");

      // 添加 打开skrbt 连接
      $(".advsearch").append(
        `&nbsp;&nbsp;<a href="${skrbtUrl}" target="_blank">打开skrbt</a>`
      );

      // 添加 粘贴&搜索 按钮
      const styleMap = {};
      $("#idsearchbutton")[0] &&
        $("#idsearchbutton")[0]
          .computedStyleMap()
          .forEach((value, key) => {
            styleMap[key] = value;
          });
      const $pasteAndSearchButton = $(
        `<input type="button" value="粘贴&搜索" id="pasteAndSearch"></input>`
      );
      $pasteAndSearchButton.css(styleMap);
      $pasteAndSearchButton.click(() => {
        navigator.clipboard.readText().then((clipText) => {
          if (clipText != null && $.trim(clipText) != "") {
            $("#idsearchbox").val(clipText);
            $("#idsearchbutton").click();
          }
        });
      });
      $("#idsearchbutton").parent().append($pasteAndSearchButton);

      // 恢复原始url,删除重定向
      $.each($("a[href^='redirect.php?url']"), function (index, a) {
        var url = getQueryVariable(a, "url");
        a.href = decodeURIComponent(url);
        if (!a.href.startsWith("https")) {
          a.href = a.href.replace("http", "https");
        }
        a.text = a.text + "    " + a.href + "      ";
        if (a.href.includes("yimuhe")) {
          $(a)
            .parentsUntil("tr")
            .closest(".t")
            .css("background-color", "#6B6C83");
          a.style = "font-size:20px;";
        } else {
          a.style = "font-size:20px;";
        }
      });

      // ---- 详情页面

      if (/.*\?v=.*/.test(location.href)) {
        // 添加 复制车牌 按钮
        let chePai = document.querySelector(
          "#video_id > table > tbody > tr > td.text"
        ).innerText;
        let toAppendElement = document.querySelector(
          "#video_id > table > tbody > tr > td.text"
        );
        appendCopyButton(chePai, toAppendElement);

        // 添加 javbus中查询 链接
        let trTag = document.querySelector("#video_id > table > tbody > tr");
        let javdbQueryId = "javdbQueryId";
        trTag.innerHTML = [
          trTag.innerHTML,
          '<td><a id="',
          javdbQueryId,
          '"href="',
          javabusUrl,
          "/",
          chePai,
          '">javbus中查询</a></td>',
        ].join("");

        // 添加 打开SkrBt 链接
        $(trTag).append(
          [
            '<td><a target="_blank" ',
            'href="',
            skrbtUrl,
            "/search?keyword=",
            chePai,
            '">打开SkrBT</a></td>',
          ].join("")
        );

        // 删除名称中的链接,否则很容易误点,又不容易复制文字
        const videoTitleNode = document.querySelector("#video_title > h3 > a");
        if (videoTitleNode) {
          const videoTitle = videoTitleNode.getInnerHTML();
          videoTitleNode.parentNode.innerText = videoTitle;
        }
      }
      1;
      // 用户文章页面
      // if (location.href.includes("userposts.php?u=")) {
      //   debug("1"); //$('div.video a img').
      //   $("div#video_comments a img").each(function (index) {
      //     const times = 1.3; // 倍数
      //     const height = this.height * times;
      //     const width = this.width * times;
      //     this.height = height;
      //     this.width = width;
      //   });
      // }
    });

    ///////////////////////////////////////////////////////////////////////////
    // 永久域名:https://www.javbus.com 防屏蔽地址:https://www.fanbus.help
    // 防屏蔽地址:https://www.javsee.help 防屏蔽地址:https://www.buscdn.help
    ///////////////////////////////////////////////////////////////////////////
    execute(
      "javbus",
      [
        '$head>title:contains("JavBus")',
        // /genre/hd , /genre/sub
        "$body > nav > div > div.navbar-header.mh50 > a > img[alt='JavBus']",
        // 论坛
        "#toptb.jav-nav",
      ],
      () => {
        debug("添加 粘贴&搜索 按钮", "javbus");
        const searchButton = $(
          "button[onclick=\"searchs('search-input')\"]:first"
        );
        const searchInput = $("#search-input:first");
        addPasteAndSearchButton(searchButton, searchInput);

        // 调整样式
        $(".nav>li>a").attr("style", "padding-left:8px;padding-right:8px;");

        debug("添加 打开skrbt 链接", "javbus");
        //添加skrbt链接
        $(".nav-title.nav-inactive:last,ul.nav.navbar-nav:first").append(`
                      <li class="hidden-md hidden-sm">
                          <a href="${skrbtUrl}" target="_blank">打开skrbt</a>
                      </li>
                  `);

        let chePaiNode = document.querySelector(
          "body > div.container > div.row.movie > div.col-md-3.info > p:nth-child(1) > span:nth-child(2)"
        );
        // 明细页面
        if (chePaiNode) {
          debug("删除明细页面磁力链的点击事件", "javbus");
          const chePai = chePaiNode.innerText.trim();
          const toAppendElement = document.querySelector(
            "body > div.container > div.row.movie > div.col-md-3.info > p:nth-child(1)"
          );
          appendCopyButton(chePai, toAppendElement);

          debug("删除磁力链接中的onclick事件", "javbus");
          setInterval(() => $("#magnet-table td").removeAttr("onclick"), 1000);
        }
      }
    );

    ///////////////////////////////////////////////////////////////////////////
    // 添加 粘贴&搜索 按钮
    ///////////////////////////////////////////////////////////////////////////
    [
      // 知乎
      {
        title: "知乎-添加'粘贴&搜索'按钮",
        condition: /zhihu\.com/,
        searchButton: '$button[class*="SearchBar-searchButton"]',
        searchInput: "#Popover1-toggle",
      },
      // skrbt 永 久 地 址 ( 务 必 收 藏 ): skrfabu.top skrso.link
      {
        title: "skrbt-添加'粘贴&搜索'按钮",
        condition: `$head>link[rel='shortcut icon'][href*='skrbt']`,
        searchButton: `$button.search-btn`,
        searchInput: `$input.search-input[name='keyword']`,
        callback: ($searchButton, $searchInput, $pasteAndSearchButton) => {
          // 调整'粘贴&搜索'按钮样式
          $pasteAndSearchButton.removeAttr("style");
          $pasteAndSearchButton.css("margin-left", "3px");
          $pasteAndSearchButton.attr("class", $searchButton.attr("class"));

          function removeAd() {
            const $container = $(".col-md-6:eq(2)");
            $container.remove(".label.label-primary");
            $container
              .find('a.rrt.common-link[href^="http"]')
              .parent()
              .parent()
              .remove();
          }
          removeAd();
          ///搜索结果列表页面
          if (location.href.includes("search")) {
            // 自动分页插件兼容,删除广告
            const nodeToObserve = document.querySelectorAll(".col-md-6")[2];
            new MutationObserver((mutationRecords, observer) => {
              removeAd();
            }).observe(nodeToObserve, { childList: true });
          }
        },
      },
      // 百度
      {
        title: "百度-添加'粘贴&搜索'按钮",
        condition: /baidu\.com/,
        searchButton: `#su`,
        searchInput: `#kw`,
      },
      // 必应
      // {
      //   condition: /bing\.com/,
      //   searchButton: ()=>{
      //     let inputs = document.querySelectorAll('input');
      //     return inputs[1];
      //   },
      //   searchInput: `#sb_form_q`,
      // },
    ].forEach((v, k) => {
      let { title, condition, searchButton, searchInput, callback } = v;
      execute(title, condition, () => {
        searchButton = evalParam(searchButton);
        searchInput = evalParam(searchInput);
        addPasteAndSearchButton(searchButton, searchInput, callback);
      });
    });
  });

  /////////////////////////////////////////////////////////////////////////////
  // 公共方法
  /////////////////////////////////////////////////////////////////////////////

  /**
   *
   * @param {String|Function} param
   * 当类型为String时,
   *  - 如果param是以$开头,则认为这个param为Jquery表达式,会去掉字符$,并返回;
   *  - 否则,认为param为常规css选择符,会返回document.querySelector(param)
   * 当类型为Function时,
   *  直接执行此方法,并使用$()包装并返回
   *
   * @returns {Jquery} 返回Jquery对象
   *
   * @example
   * - evalParam('$div[style="btn"]'); // param为jquery的css selector,返回$('div[style="btn"]')
   * - evalParam('#container'); // param为常规的css selector,返回 $(document.querySelecotr('#container'))
   * - evalParam(()=>{
   *     return document.querySelector('#container');
   *   });  // param为方法,返回$(param())
   *
   */
  function evalParam(param) {
    if ($.type(param) === "string") {
      if (param.startsWith("$")) {
        return $(param.substring(1));
      }
      return $(document.querySelector(param));
    }
    if ($.isFunction(param)) {
      return $(param());
    }
  }

  function execute(title, condition, callback) {
    if (checkCondition(condition) === true) {
      if (callback) {
        debug(condition.toString(), title);
        callback();
      }
    }
    // if ($.isArray(condition)) {
    //   for (let c of condition) {
    //     if (checkCondition(c)) {
    //       debug(condition.toString(), title);
    //       callback && callback();
    //       return;
    //     }
    //   }
    // }
  }

  /**
   *
   * @param {RegExp|Function|Boolean|String} condition
   * @returns {Boolean}
   */
  function checkCondition(condition) {
    if ($.type(condition) === "regexp") {
      const href = window.location.href;
      return condition.test(href);
    }
    if ($.isFunction(condition)) {
      return condition() === true;
    }
    if ($.type(condition) === "boolean") {
      return condition === true;
    }
    if ($.type(condition) === "string") {
      if (condition.startsWith("$")) {
        return $(condition.substring(1)).length > 0;
      }
      return document.querySelector(condition) != null;
    }

    if ($.isArray(condition)) {
      for (let c of condition) {
        if (checkCondition(c)) {
          return true;
        }
      }
    }
    return false;
  }

  function addPasteAndSearchButton($searchButton, $searchInput, callback) {
    const styleMap = { "margin-left": "5px" };
    $searchButton[0].computedStyleMap().forEach((value, key) => {
      styleMap[key] = value;
    });
    const $pasteAndSearchButton = $(
      `<input type="button" value="粘贴&搜索" id="pasteAndSearch"></input>`
    );
    $pasteAndSearchButton.css(styleMap);
    $searchButton.after($pasteAndSearchButton);
    $pasteAndSearchButton.click(() => {
      navigator.clipboard.readText().then((clipText) => {
        if (clipText != null && $.trim(clipText) != "") {
          $searchInput.val($.trim(clipText));
          $searchButton.click();
        }
      });
    });
    callback && callback($searchButton, $searchInput, $pasteAndSearchButton);
  }

  function appendCopyButton(chePai, toAppendElement) {
    var copyButton = document.createElement("button");
    copyButton.innerHTML = "复 制";
    copyButton.setAttribute("id", "copyButton");
    toAppendElement.appendChild(copyButton);
    document.addEventListener("click", (e) => {
      if (e.target.getAttribute("id") === "copyButton") {
        GM.setClipboard(chePai, "text");
      }
    });
  }

  function debug(str, title) {
    if (enableDebug) {
      if (!str) {
        str = "";
      }
      if (!Array.isArray(str)) {
        str = [str];
      }
      seq++;
      console.log(
        `%c【tianteng ${GM_info.script.version}】 ${title ? title : "debug"}:`,
        "color: yellow;font-size: large;font-weight: bold;background-color: darkblue;",
        seq,
        ...str
      );
    }
  }

  function isNativeCode(obj) {
    const nativeCodeTag = "[native code]";
    return obj && obj.toString && obj.toString().includes(nativeCodeTag);
  }

  function getQueryVariable(anchor, variable) {
    var query = anchor.search.substring(1);
    var vars = query.split("&");
    for (var i = 0; i < vars.length; i++) {
      var pair = vars[i].split("=");
      if (pair[0] == variable) {
        return pair[1];
      }
    }
    return false;
  }

  /**
   * 图片按宽高比例进行自动缩放
   * @param ImgObj
   *     缩放图片源对象
   * @param maxWidth
   *     允许缩放的最大宽度
   * @param maxHeight
   *     允许缩放的最大高度
   * @usage
   *     调用:<img src="图片" onload="javascript:drawImage(this,300,200)">
   */
  function drawImage(ImgObj, maxWidth, maxHeight) {
    var image = new Image();
    //原图片原始地址(用于获取原图片的真实宽高,当<img>标签指定了宽、高时不受影响)
    image.src = ImgObj.src;
    // 用于设定图片的宽度和高度
    var tempWidth;
    var tempHeight;

    if (image.width > 0 && image.height > 0) {
      //原图片宽高比例 大于 指定的宽高比例,这就说明了原图片的宽度必然 > 高度
      if (image.width / image.height >= maxWidth / maxHeight) {
        if (image.width > maxWidth) {
          tempWidth = maxWidth;
          // 按原图片的比例进行缩放
          tempHeight = (image.height * maxWidth) / image.width;
        } else {
          // 按原图片的大小进行缩放
          tempWidth = image.width;
          tempHeight = image.height;
        }
      } else {
        // 原图片的高度必然 > 宽度
        if (image.height > maxHeight) {
          tempHeight = maxHeight;
          // 按原图片的比例进行缩放
          tempWidth = (image.width * maxHeight) / image.height;
        } else {
          // 按原图片的大小进行缩放
          tempWidth = image.width;
          tempHeight = image.height;
        }
      }
      // 设置页面图片的宽和高
      ImgObj.height = tempHeight;
      ImgObj.width = tempWidth;
      // 提示图片的原来大小
      ImgObj.alt = image.width + "×" + image.height;
    }
  }

  /**
   *
   * @param {EventTarget|NodeList|Array|jQuery} elements
   * @param {undefined|null|String|Array} events
   */
  function removeEvents(elements, events) {
    if (!elements) return;
    if (elements instanceof EventTarget) {
      elements = [elements];
    }
    if (elements instanceof jQuery) {
      elements = elements.toArray();
    }

    if (!events) {
      elements.forEach((element) => {
        for (let t in element) {
          if (t.startsWith("on") && element[t] != null) {
            element[t] = null;
            console.log("cleanup removed listener from " + element.nodeName, t);
          }
        }
        for (let t of element.allListeners || []) {
          element.removeEventListener(t.type, t.callback, t.options);
          console.log(
            "cleanup removed listener from " + element.nodeName,
            t.type
          );
        }
        element.allListeners = [];
      });
    } else {
      if (typeof events === "string") {
        events = [events];
      }
      if (!Array.isArray(events)) {
        return;
      }
      events.forEach((event) => {
        const onEvent = "on" + event;
        elements.forEach((element) => {
          for (let t in element) {
            if (t.startsWith(onEvent) && element[t] != null) {
              element[t] = null;
              console.log(
                "cleanup removed listener from " + element.nodeName,
                t
              );
            }
          }
          // const toRemoved = [];
          element.allListeners = element.allListeners || [];
          let allListenersNew;
          element.allListeners.forEach((t, i) => {
            if (t.type === event) {
              element.removeEventListener(t.type, t.callback, t.options);
              allListenersNew = element.allListeners.slice(i, 1);
              // toRemoved.push(i);
              console.log(
                "cleanup removed listener from " + element.nodeName,
                t.type
              );
            }
          });
          // toRemoved.forEach((item, index) => {
          //   element.allListeners = element.allListeners.slice(item, 1);
          // });
          if (allListenersNew) {
            element.allListeners = allListenersNew;
          }
        });
      });
    }
  }
})();