2

I am trying to create a script that clicks a button every 31 seconds. That website contains many buttons with the classes reply-markup-button rp tgico. To select the exact button I am looking for, I am looking for the exact text on the button using document.getElementByTagName and a for-loop:

var viewAdsButton = document.getElementsByTagName("button");
var viewAdsButtonText = "View ads";

setInterval(function() {
  for (var i = 0; i < viewAdsButton.length; i++) {
    if (viewAdsButton[i].textContent == viewAdsButtonText) {
      viewAdsButton[i].click()
    }
  }
}, 31000);
<button class='reply-markup-button rp tgico' onclick="console.log('button 1')">View ads</button>
<button class='reply-markup-button rp tgico' onclick="console.log('button 2')">View ads</button>
<button class='reply-markup-button rp tgico' onclick="console.log('button 3')">Don't View ads</button>
<button class='reply-markup-button rp tgico' onclick="console.log('button 4')">View ads</button>

The issue is that there are also many buttons with "View ads" on them, and I only want the script to click the first one instead of all of them.

Michael M.
  • 10,486
  • 9
  • 18
  • 34
Xajov
  • 21
  • 2
  • 1
    Add a `break;` or `return;` after your call to `viewAdsButton[i].click();` so the loop exits after clicking the first button. – kmoser Oct 26 '22 at 03:40
  • Use `break` within the if condition to break out of the for loop once the condition has been satisfied. – dRoyson Oct 26 '22 at 03:40

3 Answers3

0

Add a call to break (or return) after you click the first matching button:

var viewAdsButton = document.getElementsByTagName("button");
var viewAdsButtonText = "View ads";


setInterval(function(){ 
  for (var i = 0; i < viewAdsButton.length; i++) {
    if (viewAdsButton[i].textContent == viewAdsButtonText) {
      viewAdsButton[i].click()
      break // Stop looping
    }
  }
}, 31000);
kmoser
  • 8,780
  • 3
  • 24
  • 40
0

If there are many buttons, don't try to use document.getElementsByTagName or document.getElementsByClassName. They return a collection of elements and it's much harder to find the exact element you want. Also consider this: what if two buttons have the same text, or the website updates and the button text changes?

Here are some better approaches:

First, look at the button in your browser's dev tools. If it has an ID, then use document.getElementsById. Like this:

var viewAdsButton = document.getElementsById("some-button-id");

setInterval(function() { 
    viewAdsButton.click();
}, 31000);

If the button doesn't have an ID, then you should get the element by its XPath. An XPath is just a string that uniquely represents an element in the DOM hierarchy, but this isn't too important. You can copy the elements XPath in the dev tools (Copy -> Copy XPath). Use this code for the XPath:

var viewAdsButton = document.evaluate("some-button-xpath", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

setInterval(function() { 
    viewAdsButton.click();
}, 31000);

(See this answer for more on getting an element by its XPath)

Michael M.
  • 10,486
  • 9
  • 18
  • 34
0

Instead of using getElementsByTagName(), I grabbed the first button with the classes you listed using querySelector(). Then you can just add a click event inside the setInterval() function without looping through anything.

I also used querySelectorAll() and did a forEach() loop to add an onclick event listener to every button with those classes, to show that the setInterval() function was only clicking the first one.

const btn = document.querySelector('button.reply-markup-button.rp.tgico')
const btns = document.querySelectorAll('button.reply-markup-button.rp.tgico')
const btnText = 'View ads'

setInterval(() => {
  btn.click()
}, 500)

btns.forEach(btn => btn.addEventListener('click', (e) => e.target.classList.toggle('red')))
.red {
  color: red;
}
<button class='reply-markup-button rp tgico'>View ads</button>
<button class='reply-markup-button rp tgico'>View ads</button>
<button class='reply-markup-button rp tgico'>Don't View ads</button>
<button class='reply-markup-button rp tgico'>View ads</button>
symlink
  • 11,984
  • 7
  • 29
  • 50