Firefox: Эмулировать нажатие на кнопку

Изначально передо мной стояла задача «сделать так, чтобы при входе на сайт сразу открывалось окошко с нужной информацией». Поскольку у сайте не предусмотрен поиск по параметрам из адресной строки, мне пришлось завести отдельную переменную serial, которую я указывал в адресе и присваивал ей серийный номер для поиска:

?serial=A01234B5C67890

Т.о. примерный алгоритм был такой:
1. Открываем страницу по ссылке, в конце которой добавлен серийный номер
2. При открытии страницы заполняется поле «Введите серийный номер продукта в поле поиска», при этом данные берутся из адресной строки
3. Нажимается кнопка «Поиск»
Для автоматизации подобных задач прекрасно подошло расширение Tempermonkey.

Проблема в том, что скрипт «не нажимал» кнопку (исправленный скрипт в конце заметки):

SearchSerial.js

// ==UserScript==
// @name         SearchSerial
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       DenTNT
// @match        https://ippon.ru/support/help/?serial=*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

(function ()
{
    'use strict';
    // DOMContentLoaded fires before TamperMonkey starts running on the page
    // fix error "Uncaught TypeError: element is null"
    if (document.readyState == "complete" || document.readyState == "loaded" || document.readyState == "interactive")
    {
        const params = new URLSearchParams(window.location.search);
        const inputField = document.getElementById("searchSerial");
        inputField.value = params.get("serial");
        console.log(`serial = document.getElementById("searchSerial") = `, inputField);
        const check_btn = document.getElementById("searchSerialButton");
        console.log(`check_btn = document.getElementById("searchSerialButton") = `, check_btn);
        check_btn.click(); // НЕ РАБОТАЕТ!

        // Execute a function when the user presses a key on the keyboard
        inputField.addEventListener("keydown", function (event)
        {
            // If the user presses the "Enter" key on the keyboard
            if (event.code === "NumpadEnter" || event.code === "Enter")
            {
                // Cancel the default action, if needed
                event.preventDefault();
                // Trigger the button element with a click
                check_btn.click(); // РАБОТАЕТ!
            }
        });

    }
})();
В заголовке скрипта я добавил @match, чтобы скипт запускался только на нужном мне сайте. При этом в адресной строке должен был присутствовать ключ serial.

 

В логе консоли видно, что кнопка успешно найдена и вроде как нажата, но форма не отправилась, а значит нужного эффекта я не достиг. Причём я ещё добавил событие на поле ввода серийника, оно выполнялось, если я нажимал клавишу Enter. Так вот в этом случае кнопка Поиск нажмалась! Не пойму, почему не срабатывало нажатие, если просто вызвать check_btn.click();.

Как я не пытался, я не смог заставить кнопку нажиматься. Пришлось пойти другим путём — при нажатии на кнопку срабатывает некоторое событие. Его можно увидеть в Инспекторе, если выбрать эту кнопку:
Firefox: Эмулировать нажатие на кнопку
При нажатии данной кнопки будет запущен скрипт js, который отправляет на сервер JSON-запрос, телом которого выступает переменная serial, которой мы должны присвоить значение из поля searchSerial.
Таким образом я изменил скрипт, и теперь он не «нажимал» кнопку, а сразу выполнял и обрабатывал JSON-запрос:

ParseSerial.js
// ==UserScript==
// @name         ParseSerial
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  try to take over the world!
// @author       DenTNT
// @match        https://ippon.ru/support/help/?serial=*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

    const params = new URLSearchParams(window.location.search);
    var inputField = document.querySelector("#searchSerial");
    if (inputField)
    {
        console.log(inputField);
    }
    inputField.value = params.get("serial");

// ***** Код из кнопки ****
//() => {
  var formData = new FormData();
  formData.append('serial', document.getElementById("searchSerial").value);
  $.ajax({
    url: '/support/help/serial.php',
    data: formData,
    processData: false,
    contentType: false,
    type: 'POST',
    success: function(data) {
      console.log(data)
      if (data.ncode == null) {
        $.fancybox.open('<div><div class="clear40"></div><p>По данному номеру определить продукт не удалось. Воспользуйтесь выбором товара из списка</p><div class="clear80"></div></div>');
      } else if (data.brand != 'IPPON') {
        $.fancybox.open('<div><div class="clear40"></div><p>По данному номеру определить продукт не удалось. Воспользуйтесь выбором товара из списка</p><div class="clear80"></div></div>');
      } else {
        let html = '<div><div class="clear20"></div>';
        html += '<h1>' + data.full_name + '</h1><div id="productInfoBySerial"><div class="clear20"></div>';
        html += '<table class="popupTable">';
        html += '<tr><td>Полное наименование</td><td><div class="popupTextareaWrapper"><textarea>' + ((data.merlion_name) ? data.merlion_name : data.full_name) + '</textarea></div></td></tr>';
        html += '<tr><td>Артикул</td><td><input type="text" value="' + data.model + '"></td></tr>';
        html += '<tr><td>Код</td><td><input type="text" value="' + data.id + '"></td></tr>';
        html += '<tr><td>Серийный номер</td><td><input type="text" value="' + data.sn + '"></td></tr>';
        html += '<tr><td>Ревизия</td><td><input type="text" value="' + data.hardware_revision + '"></td></tr>';
        html += '<tr><td>Дата производства</td><td><input type="text" value="' + data.month + ' ' + data.year + '"></td></tr>';
        html += '</table>';
        html += '<div class="clear20"></div>';
        html += '<div id="closePopupTextarea">OK</div>';
        html += '<div class="clear40"></div></div>';
        $.fancybox.open(html, {
          protect: false,
          modal: true
        });
      }
    }
  });
//}

Работающий скрипт для Tampermonkey

Выяснилось, что первоначальный скрипт от Tampermonkey не работал потому, что браузер ещё не успел «отрисовать» кнопку. Т.е. ей уже были присвоены все свойства, но она ещё не была активна. В скрипте ниже, с помощью функции setTimeout(functionRef, delay) мы ждём следующего шага цикла:

delay — If this parameter is omitted, a value of 0 is used, meaning execute «immediately», or more accurately, the next event cycle.

// ==UserScript==
// @name         SearchSerial
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  try to take over the world!
// @author       DenTNT
// @match        https://ippon.ru/support/help/?serial=*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

(function ()
{
    'use strict';
    // DOMContentLoaded fires before TamperMonkey starts running on the page
    // fix error "Uncaught TypeError: element is null"
    if (document.readyState == "complete" || document.readyState == "loaded" || document.readyState == "interactive")
    {
        const params = new URLSearchParams(window.location.search);
        const inputField = document.getElementById("searchSerial");
        inputField.value = params.get("serial");
        const check_btn = document.getElementById("searchSerialButton");
        setTimeout(function() {check_btn.click()}, 0);

        // Execute a function when the user presses a key on the keyboard
        inputField.addEventListener("keydown", function (event)
        {
            // If the user presses the "Enter" key on the keyboard
            if (event.code === "NumpadEnter" || event.code === "Enter")
            {
                // Cancel the default action, if needed
                event.preventDefault();
                // Trigger the button element with a click
                check_btn.click();
            }
        });
    }
})();


Подписаться
Уведомление о
guest
0 Комментарий
Inline Feedbacks
View all comments