Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript - Click button until element has specific value (without while loop)

Tags:

javascript

I'm currently trying to automate a date picker, using JavaScript. The date picker contains a header element, displaying the current month and year.

Here's a picture of it, for reference.

What I'm trying to achieve is a way to continuously click the date picker's "Back" button until the month and year in the header corresponds to the month and year of the given date value.

At first I thought this could be done with a simple while loop, but because while loops freeze all other JavaScript code execution on the page until the loop is finished (and the back button requires JS for navigation), attempting this will simply freeze the page altogether.

Here's the (non-working) code that I've written:

(function() {

  function checkDatePickerHeader(selector) {
    var date = document.querySelector(selector).innerText;
    date = new Date(date);
    return date;
  }

  var datePickerHeaderSelector = "#body > div.daterangepicker.dropdown-menu.opensleft.show-calendar > div.calendar.left > div > table > thead > tr:nth-child(1) > th.month";
  var datePickerBackButton = document.querySelector("#body > div.daterangepicker.dropdown-menu.opensleft.show-calendar > div.calendar.left > div > table > thead > tr:nth-child(1) > th.prev.available");

  var targetDate = new Date("2016-12-01");

  var datePickerDate;
  datePickerDate = checkDatePickerHeader(datePickerHeaderSelector);

  // click until correct year
  while (targetDate.getFullYear() < datePickerDate.getFullYear()) {
    datePickerBackButton.click();
    // update datePickerDate with new header value
    datePickerDate = checkDatePickerHeader(datePickerHeaderSelector);
  }

  // then click until correct month
  while (targetDate.getMonth() < datePickerDate.getMonth()) {
    datePickerBackButton.click();
    datePickerDate = checkDatePickerHeader(datePickerHeaderSelector);
  }

})();

What I've found after investigating is that re-working the while loop(s) into a function and then calling said function with a timeout may work, but I'm unsure of how to repeatedly call the function until the condition has been met.

like image 417
j-ragnarsson Avatar asked Aug 08 '26 03:08

j-ragnarsson


1 Answers

After some advice from friends and a bit of tinkering, I solved the problem! setInterval was indeed what I needed to use in this case. Here's the working code:

(function() {

function checkDatePickerHeader(selector) {
    var date = document.querySelector(selector).innerText;
    date = new Date(date);
    return date;
}

// clear then set back button again, as it loses it when it's clicked
function resetBackButton() {
  datePickerBackButton = document.querySelector("#body");
  datePickerBackButton = document.querySelector("#body > div.daterangepicker.dropdown-menu.opensleft.show-calendar > div.calendar.left > div > table > thead > tr:nth-child(1) > th.prev.available");
}

function clickIfDatesDoNotMatch() {
  datePickerDate = checkDatePickerHeader(datePickerHeaderSelector);
  if (targetDate.getFullYear() < datePickerDate.getFullYear() || targetDate.getMonth() < datePickerDate.getMonth()) {
    datePickerBackButton.click();
    resetBackButton();
  } else {
    clearInterval(funcInterval);
  }
}

var datePickerHeaderSelector = "#body > div.daterangepicker.dropdown-menu.opensleft.show-calendar > div.calendar.left > div > table > thead > tr:nth-child(1) > th.month";
var datePickerBackButton = document.querySelector("#body > div.daterangepicker.dropdown-menu.opensleft.show-calendar > div.calendar.left > div > table > thead > tr:nth-child(1) > th.prev.available");

var targetDate = new Date("2016-12-01");

var datePickerDate;

var funcInterval = setInterval(clickIfDatesDoNotMatch, 1000);

})();

The above code will run the clickIfDatesDoNotMatch function once per second. If the dates don't match, the function will click the back button (then reassign the back button element to the datePickerBackButton variable, as it seems to lose track of it when elements are changed on the page after the click), repeating this process until the dates match.

like image 84
j-ragnarsson Avatar answered Aug 09 '26 15:08

j-ragnarsson