I'm developing a Chrome extension that uses a CSV file to populate and submit a form on a webpage. The goal is to enter data row-by-row from the CSV file into the form fields, wait for the form to be processed, submit the form, and then move to the next row.
Currently, my script processes all rows at once, causing the fields to be filled and submitted simultaneously. I need help to ensure that the form is filled and submitted sequentially for each row.
Here's my current approach:
a. Reading the CSV file using PapaParse.
b. Iterating over each row of the CSV data.
c. Using chrome.scripting.executeScript to fill the form fields and submit the form.
However, the script still processes all rows at once, instead of waiting for each submission to complete before moving to the next row. This is my first time ever creating an extension, I've used a lot of help from previously Stack Overflow asked questions and Google's extensions samples. Any help would be appreciated, thank you. Here's my code below:
Manifest.json
{
"name": "AutoFiller",
"version": "2.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
"default_title": "Click me"
},
"permissions": ["activeTab", "scripting", "storage"],
"background": {
"service_worker": "background.js"
}
}
popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload CSV</title>
</head>
<body>
<h1>Upload CSV File</h1>
<input type="file" id="csv-file" accept=".csv">
<script src="popup.js"></script>
</body>
</html>
And finally, popup.js
document.addEventListener("DOMContentLoaded", function() {
document.getElementById('csv-file').addEventListener('change', function(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
const contents = e.target.result;
parseCSV(contents);
};
reader.readAsText(file);
}
});
function parseCSV(csv) {
Papa.parse(csv, {
header: true,
complete: function(results) {
const data = results.data;
populateForm(data);
}
});
}
function updateForm(returnObj) {
let pcTextBox = document.getElementById("PCTextBox");
if (returnObj.ndcUpc) {
pcTextBox.value = returnObj.pc;
pcTextBox.dispatchEvent(new Event('change'));
}
let unitCaseDropdown = document.getElementById("OpenCase");
if (returnObj.unitCase) {
unitCaseDropdown.value = returnObj.unitCase
}
let quantityInput = document.getElementById("tbxQuantity");
if (returnObj.quantity) {
quantityInput.value = returnObj.quantity;
quantityInput.dispatchEvent(new Event('change'));
}
let button = document.getElementById('btnSubmitEntries');
button.click();
}
async function populateForm(data) {
if (data.length > 0) {
for (let i = 0; i < data.length; i++) {
let rowData = data[i];
let parsedData = Object.values(rowData);
let returnObj = {
pc: parsedData[0],
unitCase: parsedData[1],
quantity: parsedData[2]
};
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
chrome.scripting.executeScript(
{
target: { tabId: tabs[0].id },
func: updateForm,
args: [returnObj]
}
);
});
}
}
}
});
What I have tried:
I tried using setTimeout(), in between the actual fields and the submit button, but that didn't work, it still processes all rows at once. I also tried converting both updateForm and populateForm to async functions and utilizing await, but that didn't also work, for some reason when I tried that approach, only the PC field was being updated and then the script would stop completely. I just need a way to logically process a row, submit, and then move to the next row and repeat, although I cannot achieve that logic programmatically.