关于javascript:我的代码可在Firefox控制台中使用,但不能在Tampermonkey中使用? (不是时间问题)

My Code works the in Firefox console but not in Tampermonkey? (not a timing issue)

我正在尝试编写使用将图片组合成单个图像的Tampermonkey用户脚本,然后自动下载它。

我的脚本代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// ==UserScript==
// @name         Picture Download
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Picture Download
// @author       Oray
// @match        https://www.example.com/*
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js
// @grant        unsafeWindow
// ==/UserScript==
(function(){
  function GM_wait(){
    if(typeof unsafeWindow.jQuery == 'undefined'){
      window.setTimeout(GM_wait,100);
    }else{
      unsafeWindow.jQuery(function() { letsJQuery(unsafeWindow.jQuery); });
  }}
  GM_wait();

  function letsJQuery($){
$('html[lang] > body').prepend('<canvas id="cve"></canvas>');
      var img1 = new Image();
      var img2 = new Image();
      var combined = new Image();
      var nloaded = 0;
      var combinedx;
      var filename;
      var e;
      function checkload(event){
        nloaded++;
        if (nloaded < 2){
          return;
        }
        var canvas = document.getElementById('cve');
        var context = canvas.getContext('2d');
        canvas.width = img1.width;
        canvas.height = img1.height + img2.height;
        context.drawImage(img1, 0, 0);
        context.drawImage(img2, img1.width / 2 - img2.width / 2 , img1.height);
        combinedx = canvas.toDataURL('data/gif');
        filename = 'myimage.png';
        var lnk = document.createElement('a');
        lnk.download = filename;
        lnk.href = combinedx;
          e = document.createEvent("MouseEvents");
          e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false,false, 0, null);
          lnk.dispatchEvent(e);
      }
      img1.onload = checkload;
      img1.crossOrigin ="Anonymous";
      img1.src ="https://images-na.ssl-images-amazon.com/images/I/81pNr82OTgL._SX679_.jpg";
      img2.onload = checkload;
      img2.crossOrigin ="Anonymous";
      img2.src ="https://images-na.ssl-images-amazon.com/images/I/31W%2BDml7GsL.jpg";
  }
})();

...可在控制台中使用,但不能用作Tampermonkey脚本。

为什么?

编者注:按原始标题,由于AJAX计时,这将是一个非常普遍的问题(示例)。 但是这个问题涵盖了具有相同基本症状的另一种罕见原因。


如果检查浏览器控制台(Ctrl + Shift + J),则应该看到类似以下错误:

Uncaught TypeError: Failed to execute 'initMouseEvent' on 'MouseEvent': parameter 4 is not of type 'Window'.

要么:

TypeError: Argument 4 of MouseEvent.initMouseEvent does not implement interface Window.

这是因为window在此行的用户脚本内具有错误的上下文:

1
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false,false, 0, null);

如果使用unsafeWindow,它将在脚本中运行(但不能在控制台中运行)。

如果使用e.initMouseEvent("click", true, true);,则两者均可使用。

但是,不推荐使用initMouseEvent,最好使用MouseEvent()构造函数; 请参阅下面的代码。

也:

  • (function(){多年来一直是多余的杂物。 默认情况下,用户脚本会被包装,并在所有主要脚本引擎上默认情况下在jQuery准备就绪后触发。
  • 同样,letsJQuery rigmarole也完全没有必要。
  • 在像canvas = document.getElementById('cve');这样的调用之后,需要在使用变量之前确保已定义该变量。 请参见下面的代码。
  • 因此,这是经过这些调整的有效用户脚本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    // ==UserScript==
    // @name        Picture Download
    // @match       *://YOUR_SERVER.COM/YOUR_PATH/*
    // @require     https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js
    // @grant       GM_addStyle
    // @grant       GM.getValue
    // ==/UserScript==
    //- The @grant directives are needed to restore the proper sandbox.
    /* global $ */

    //$('html[lang] > body').prepend ('<canvas id="cve"></canvas>');
    $('html > body').prepend ('<canvas id="cve"></canvas>');
    var img1 = new Image ();
    var img2 = new Image ();
    var combined = new Image ();
    var nloaded = 0;
    var combinedx;
    var filename;
    var e;

    img1.onload = checkload;
    img1.crossOrigin ="Anonymous";
    img1.src ="https://images-na.ssl-images-amazon.com/images/I/81pNr82OTgL._SX679_.jpg";
    img2.onload = checkload;
    img2.crossOrigin ="Anonymous";
    img2.src ="https://images-na.ssl-images-amazon.com/images/I/31W%2BDml7GsL.jpg";

    function checkload (event) {
        nloaded++;
        if (nloaded < 2) {
            return;
        }
        var canvas = document.getElementById ('cve');
        if (!canvas) {
            console.warn ("No canvas.");
            return;
        }
        var context = canvas.getContext ('2d');
        canvas.width = img1.width;
        canvas.height = img1.height + img2.height;
        context.drawImage (img1, 0, 0);
        context.drawImage (img2, img1.width / 2 - img2.width / 2, img1.height);
        combinedx = canvas.toDataURL ('data/gif');
        filename = 'myimage.png';
        var lnk = document.createElement ('a');
        lnk.download = filename;
        lnk.href = combinedx;

        e = new MouseEvent ("click");
        lnk.dispatchEvent (e);
    }