Мой код работает в консоли Firefox, но не в Tampermonkey? (не проблема времени) - PullRequest
0 голосов
/ 06 января 2019

Я пытаюсь написать пользовательский скрипт Tampermonkey, который использует <canvas> для объединения изображений в одно изображение и затем автоматически загружает его.

Код моего скрипта:

// ==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 ( пример ). Но этот вопрос охватывает другую, более редкую причину с тем же основным симптомом.

1 Ответ

0 голосов
/ 07 января 2019

Если вы проверяете консоль браузера ( Ctrl + Shift + J ), вы должны увидеть такие ошибки, как:

Uncaught TypeError: Не удалось выполнить initMouseEvent для MouseEvent: параметр 4 не относится к типу Window.

Или:

TypeError: Аргумент 4 MouseEvent.initMouseEvent не реализует интерфейс Window.


Это потому, что window имеет неверный контекст внутри вашего usercript в этой строке:

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() конструктор ; см. код ниже.

Также:

  1. То, что (function(){ был лишним беспорядком в течение многих лет. Пользовательские скрипты переносятся по умолчанию и запускаются после готовности jQuery по умолчанию на всех основных скриптовых движках.
  2. Аналогично, ригмароль letsJQuery совершенно не нужна.
  3. После таких вызовов, как canvas = document.getElementById('cve');, вам необходимо убедиться, что переменная определена перед ее использованием. Смотрите код ниже.


Итак, вот рабочий скрипт пользователя с этими настройками:

// ==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);
}
...