While Autofill can autofill the majority of forms on the internet, there are more and more forms these days that it has a hard time with. These modern forms either use non-standard HTML form tags (e.g., <div>
instead of <select>
) or render forms dynamically via AJAX. Today, we're going to go over how to automate filling out a multi-page form that is powered by AJAX.
Since Autofill is typically triggered on page load, when a form uses the magic of AJAX to "load" the next page without actually loading the web page, Autofill is never triggered again. This is the reason why you might see Autofill working only on the first page and not subsequent pages. In order to properly autofill AJAX forms, we need to use Autofill's powerful JavaScript rules. For this tutorial, we will use Fundrise as a case study.
First, go to the Fundrise link above and enter any email address and password to create a dummy account. The multi-page form should start at the page below, and this is where we'll begin our automation:
For the purpose of this tutorial, let's create a new profile called "Fundrise":
In this new profile, create a JavaScript rule (select Type = "JavaScript") and enter this into the Value field:
const fields = [
{ name: '[data-test="Family or Friend"]' },
{ name: '[data-test="TAXABLE"]' },
{ name: '[data-test="Income"]' },
{ name: '[data-test="$10K - $25K"]' },
{ name: '[data-test="3-5 years"]' },
{ name: '[data-test="I am more hands-on"]' },
{ name: '[data-test="first-name"]', value: 'First' },
{ name: '[data-test="last-name"]', value: 'Last' },
{ name: '[data-test="agreements"]' },
{ name: '[data-test="address-form-address1"]', value: '321 Test Dr' },
{ name: '[data-test="address-form-city"]', value: 'Beverly Hills' },
{ name: '[data-test="address-form-state"]', value: 'CA' },
{ name: '[data-test="address-form-zip"]', value: '90210' },
{ name: '[data-test="phone-number"]', value: '(310) 555-1212' },
{ name: '[data-test="date-input"]', value: '04/01/1984' },
{ name: '[data-test="amount-input"]', value: '10' },
{ name: '[data-test="other-amount-input"]', value: '10' },
{ name: '[data-test="manually-enter-account"]' },
{ name: '[data-test="new-bank-name"]', value: 'Big Bank' },
{ name: '[data-test="new-bank-routing"]', value: '123456789' },
{ name: '[data-test="new-bank-acct-1"]', value: '1234567890' },
{ name: '[data-test="new-bank-acct-2"]', value: '1234567890' },
{ name: '[data-test="acknowledgment-0"]' },
{ name: '[data-test="acknowledgment-1"]' },
{ name: '[data-test="acknowledgment-2"]' },
{ name: '[data-test="acknowledgment-3"]' },
{ name: '[data-test="acknowledgment-4"]' },
{ name: '[data-test="acknowledgment-5"]' },
{ name: '[data-test="acknowledgment-6"]' },
];
setInterval(() => {
for (let i = 0, field; i < fields.length; ++i) {
field = document.querySelector(fields[i].name);
if (field) {
if (fields[i].value) {
field.value = fields[i].value;
field.dispatchEvent(new Event('input'));
field.dispatchEvent(new Event('change'));
} else if (!field.checked) {
field.click();
}
}
}
}, 500);
Whoa, that's quite a handful! Don't worry, I'm going to break it down for you. It's not so intimidating once you break it down into smaller chunks. Let's dive in...
const fields = [ ... ];
Here we are defining all of the form fields that we want to automate. The [ ... ]
contains a list of items, with each item having one or both of these properties:
-
name
- the CSS selector that we will use to identify the fields. -
value
- the text that will be entered in input boxes.
As you'll soon see below, we will assume items that only contain the name
property to be checkbox/radio elements that should be clicked on, and items that also contain the value
property are input boxes that should be autofilled.
NOTE: Throughout this tutorial I will use the terms "field" and "element" to refer to the same thing — the form's <input>
tag.
setInterval(() => { ... }, 500);
We are going to execute everything inside { ... }
every 500 milliseconds (half a second). Since the page never reloads as you move through the steps, what we are essentially doing is polling the page to detect when the form elements we want to fill out or click are added to the page. As with most things in JavaScript, there are other ways of doing this, such as using Mutation Observers, but for our needs good ol' setInterval()
works fine.
for (let i = 0, field; i < fields.length; ++i) { ... }
This loops through each item in the fields
list.
field = document.querySelector(fields[i].name);
Here we are querying the document for the form element we want to automate by using the CSS selector stored in the name
property, and saving the first matching element to a variable called field
for easier reference in the future.
if (field) { ... }
Only proceed if the element actually exists in the document at the time of the polling. If not, then continue to the next item in the fields
list.
if (fields[i].value) { ... }
If the form element does exist, and the fields
list item contains the value
property, then assume the element is an input box that should be autofilled.
field.value = fields[i].value;
Autofill the input box with the text stored in the value
property.
field.dispatchEvent(new Event('input'));
field.dispatchEvent(new Event('change'));
This is required on some forms to simulate a human manually entering the text into the input box. Not having these two lines can make the code break or result in unexpected behaviors.
else if (!field.checked) { ... }
If the fields
list item does not contain the value
property, then we'll assume it's either a checkbox or radio element that needs to be auto-clicked. The !field.checked
condition means we only click it if it's not already checked/ticked; if we leave out this condition, then Autofill would repeatedly click on this element every half second — not good.
field.click();
Click on the checkbox or radio element.
That's pretty much it. I hope it was straight-forward enough. If you wanted even more automation, then there's nothing stopping you from adding a few lines of code to make it also automatically click the Continue button for you. I left that out because there were some sensitive fields that should not be automated by Autofill, such as the Social Security number field.
One thing that may not be obvious is how we came up with the CSS selectors for the form fields. To do this, right-click on a field and select "Inspect"; then look for the <input>
tag closest to the highlighted code. Below I have inspected the "Family or Friend" radio element from our example:
For this part you'll have to look at all of the form elements you want to automate and see which attributes are common among them. In our case, the data-test
attribute was one of the attributes found in all of the fields.
As you proceed through the Fundrise form, it should be autofilled for you even though each page was rendered dynamically via AJAX. Autofill + JavaScript rules can be used like this to open up a world of automation that can significantly reduce your menial workload. Happy autofilling! ⚡
Top comments (0)