Sometimes, it is useful to gather form data from a webpage en masse.
The quick-script way to do this is to iterate via document.forms
and construct FormData
objects for each form on the page.
// es6 spread converts fancy collection obj into plain array
const allForms = [...document.forms]
allForms.forEach((f) => {
const fd = new FormData(form)
for (const [k, v] of fd.entries()) {
console.log(k, v)
}
})
To take this to the next step, we can construct an object containing all the form data on the page.
For keys like something[nested][deep]
, we can recursively create objects:
const keypairToDict = (k, v) => {
// split key on [ or ], then remove them and empty strings
const keyComponents = k.split(/\s*(\[|\])/).filter((split) => ![']', '[', ''].includes(split))
if (keyComponents.length > 1) {
// no need to completely reassemble, any 1 of the characters we split on above is sufficient
return { [keyComponents[0]]: keypairToDict(keyComponents.slice(1).join(']'), v) }
}
return { [keyComponents[0]]: v }
}
Putting this alllll together (and using _.merge
)
let allFormData = {}
[...document.forms].forEach((form) => {
const fd = new FormData(form)
for (const [k, v] of fd.entries()) {
_.merge(allFormData, keypairToDict(k, v))
}
})
Produces output like:
{
"_method": "patch",
"authenticity_token": "up2UK4xxxY47aSs4OZLow",
"step": "payment_method",
"checkout": {
"client_details": {
"browser_width": "2545",
"browser_height": "939",
"javascript_enabled": "1",
"color_depth": "24",
"java_enabled": "false",
"browser_tz": "300"
},
"reduction_code": "",
"payment_gateway": "00000",
"credit_card": {
"vault": "false"
},
"different_billing_address": "false",
"total_price": "123"
},
"previous_step": "payment_method",
"s": "",
"complete": "1"
}