How to fix 'addEventListener' not working in Violentmonkey or Tampermonkey Chrome extension?

259 Views Asked by At

I want a button to be automatically clicked after 0.1 seconds after entering 5 characters in a textbox....

This code works correctly in the console(developer.F12) section of the browser. But I want this code to be executed permanently in the browser by Greasemonkey/Tampermonkey extension.

var textbox = document.getElementById("Text");

var button = document.getElementsByClassName("btn")[0];

textbox.addEventListener("input", function() {
  var inputText = textbox.value.trim();
  if (inputText.length === 5) {
    setTimeout(function() {
      button.click();
    }, 100);
  }
});

But This is not working in Greasemonkey/Tampermonkey Chrome extension....

Please see this picture:

enter image description here

How can I run this code in the Greasemonkey/Tampermonkey Chrome extension?


Update:

In response to Alexander Nenashev:

Let me explain what I want to use this code for. For example, I want the login button to be automatically clicked on every website page in the login section after entering a 5-digit password. And also these elements are present on the site I import this code through the browser console of the developer section (F12), it works, but as soon as the page is refreshed, I have to import this code again, and my problem is exactly here. I want this JavaScript code permanently in the background of every site. I want it to be active, and according to my research, the tampermonkey extension seems to do it, but not for me!

enter image description here

I put your code in the Tampermonkey extension, but unfortunately I got the same error as before... And we have the elements available on the desired website

1

There are 1 best solutions below

6
Alexander Nenashev On

Your error's explanation: document.getElementById("Text"); returns null since there's no such textbox on the page yet when you run your monkey script.
When you run your code in the console the elements are present so you have no problems.

I believe a monkey script runs after DOMContentLoaded. But...
The page could create elements after this (for example loading some chunk of HTML from the backend and inserting into the page). So...
You should watch the page for the needed elements. The simple way is to use setTimeout() to run your code a bit later hoping the elements are here. And possible repeat the process, stopping when the elements are found.

But there's a more elegant approach. In my monkey scripts I use MutationObserver:

// emulate code on the page

document.querySelector('button').addEventListener('click', e => {

  e.target.remove();

  document.querySelector('.container').innerHTML = `
    <input id="Text">
    <button class="btn">Auto click me</button>
    <div class="log"></div>
  `;

  const textbox = document.querySelector('#Text');
  textbox.focus();

  document.querySelector('.btn').addEventListener('click', () => {
    document.querySelector('.log').innerHTML += `<div>${textbox.value.trim()}</div>`;
    textbox.value = '';
  });
  
});

// your code, watch for body mutations and add listeners;

let observer = new MutationObserver(addListener);

/*
  if you have more specific container where to look and 
  it's present on DOMContentLoaded - use here.
*/
observer.observe(document.body, {childList: true, subtree: true});

function addListener(){

  const textbox = document.querySelector('#Text');
  const button = document.querySelector('.btn');

  if(!textbox || !button){
    return; // not on the page yet
  }

  textbox.addEventListener('input', () => {
    textbox.value.trim().length === 5 && setTimeout(() => button.click(), 100);
  });
  
  // stop observing since you've attached the listener
  
  observer.disconnect();
  observer = null;

  // stackoverflow's console.log() mutates DOM so use it after disconnecting
  console.log('the listener has been added');

};
<button>Add elements</button>
<div class="container"></div>

UPDATE

If an event bubbles you can catch it at the document:

// emulate code on the page

document.querySelector('button').addEventListener('click', e => {

  e.target.remove();

  document.querySelector('.container').innerHTML = `
    <input id="Text">
    <button class="btn">Auto click me</button>
    <div class="log"></div>
  `;

  const textbox = document.querySelector('#Text');
  textbox.focus();

  document.querySelector('.btn').addEventListener('click', () => {
    document.querySelector('.log').innerHTML += `<div>${textbox.value.trim()}</div>`;
    textbox.value = '';
  });
  
});

// your code, watch for inputs to change

document.addEventListener('input', e => {

  const button = document.querySelector('.btn');

  e.target.value.trim().length === 5 && setTimeout(() => button.click(), 100);

});
<button>Add elements</button>
<div class="container"></div>