Microsoft 365 and Office | Excel | For home | Android
A family of Microsoft spreadsheet software with tools for analyzing, charting, and communicating data.
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
// Queue B - Fill AR details from Prompt (with retry for dropdown/text timing issues)
// Does NOT click Submit/Save/anything.
(function () {
"use strict";
// ---------------------------
// Helpers
// ---------------------------
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
function $(sel) { return document.querySelector(sel); }
function fireAll(el) {
if (!el) return;
el.dispatchEvent(new Event("input", { bubbles: true }));
el.dispatchEvent(new Event("change", { bubbles: true }));
el.dispatchEvent(new Event("blur", { bubbles: true }));
}
function setInputValue(id, val) {
const el = document.getElementById(id);
if (!el) return false;
el.focus();
el.value = val ?? "";
fireAll(el);
return true;
}
function normalize(s) {
return (s ?? "").toString().trim().toLowerCase();
}
function setSelectByText(id, text) {
const el = document.getElementById(id);
if (!el) return { ok: false, reason: "select_not_found" };
const want = normalize(text);
if (!want) return { ok: false, reason: "empty_value" };
const opts = Array.from(el.options || []);
const match = opts.find(o => normalize(o.textContent) === want);
if (!match) return { ok: false, reason: "option_not_found" };
el.focus();
el.value = match.value;
fireAll(el);
return { ok: true };
}
async function setSelectByTextWithRetry(id, text, retries = 4, delays = [0, 250, 700, 1200]) {
for (let i = 0; i < retries; i++) {
const res = setSelectByText(id, text);
if (res.ok) return true;
await sleep(delays[Math.min(i, delays.length - 1)]);
}
return false;
}
// ---------------------------
// Input format (simple, copy/paste)
// ---------------------------
// Paste one person per block, separated by a blank line.
// Each line is: key: value
//
// Keys supported:
// action, firstName, middleName, lastName, suffix,
// jobTitle, country, phoneType, phoneNumber, email
//
// Example block:
// action: Add
// firstName: John
// middleName:
// lastName: Doe
// suffix:
// jobTitle: Manager
// country: US
// phoneType: Mobile
// phoneNumber: 8888888888
// email: ******@email.com
//
function parsePeople(raw) {
const blocks = raw.split(/\n\s*\n+/).map(b => b.trim()).filter(Boolean);
return blocks.map((block) => {
const obj = {};
block.split("\n").forEach((line) => {
const m = line.match(/^\s*([^:]+)\s*:\s*(.*)\s*$/);
if (!m) return;
const k = m[1].trim();
const v = m[2] ?? "";
obj[k] = v;
});
return obj;
});
}
// ---------------------------
// Field ID mapping (Queue B)
// ---------------------------
// For Person N:
// action radio group container: activiti-action{N}B (radio options inside)
// firstName: activiti-firstname{N}B
// middleName: activiti-middlename{N}B
// lastName: activiti-lastname{N}B
// suffix dropdown: activiti-suffix{N}B
// jobTitle: activiti-jobtitle{N}B
// country dropdown: activiti-country{N}B
// phoneType dropdown: activiti-phonetype{N}B
// phoneNumber: activiti-phonenumber{N}B (or phonenumber1Bother etc in some pages)
// email: activiti-email{N}B
//
// NOTE: Your earlier screenshots show both:
// - activiti-phonenumber{N}B
// - activiti-phonenumber{N}Bother (depending on UI)
// We'll try both safely.
//
async function fillOnePersonB(idx1, p) {
const n = idx1; // 1-based
console.log(`Queue B: Filling Person ${n}`, p);
// 1) Action (radio)
// safest: try to click the radio label containing the action text (Add/Update/Delete)
try {
const container = document.getElementById(`activiti-action${n}B`);
if (container && p.action) {
const want = normalize(p.action);
const labels = Array.from(container.querySelectorAll("label"));
const target = labels.find(l => normalize(l.textContent).includes(want));
if (target) target.click();
}
} catch (e) {}
// 2) Names (text)
setInputValue(`activiti-firstname${n}B`, p.firstName);
setInputValue(`activiti-middlename${n}B`, p.middleName);
setInputValue(`activiti-lastname${n}B`, p.lastName);
// 3) Suffix (dropdown) - optional
if (p.suffix) await setSelectByTextWithRetry(`activiti-suffix${n}B`, p.suffix, 4);
// 4) Job Title (text) ✅ FIX: retry because Angular sometimes misses
// We re-apply jobTitle a couple times with short waits.
if (p.jobTitle) {
setInputValue(`activiti-jobtitle${n}B`, p.jobTitle);
await sleep(200);
setInputValue(`activiti-jobtitle${n}B`, p.jobTitle);
await sleep(600);
setInputValue(`activiti-jobtitle${n}B`, p.jobTitle);
}
// 5) Country (dropdown)
if (p.country) await setSelectByTextWithRetry(`activiti-country${n}B`, p.country, 5);
// 6) Phone Type (dropdown) ✅ FIX: retry more aggressively
if (p.phoneType) await setSelectByTextWithRetry(`activiti-phonetype${n}B`, p.phoneType, 6);
// 7) Phone Number (text) - try both possible IDs
if (p.phoneNumber) {
const ok1 = setInputValue(`activiti-phonenumber${n}B`, p.phoneNumber);
if (!ok1) setInputValue(`activiti-phonenumber${n}Bother`, p.phoneNumber);
}
// 8) Email (text)
if (p.email) setInputValue(`activiti-email${n}B`, p.email);
// Small pause between persons to let UI settle
await sleep(120);
}
// ---------------------------
// Main run
// ---------------------------
async function run() {
const raw = prompt(
"Queue B: Paste AR details.\n\n" +
"One person per block, separated by a blank line.\n" +
"Each line like: key: value\n\n" +
"Keys: action, firstName, middleName, lastName, suffix, jobTitle, country, phoneType, phoneNumber, email\n",
""
);
if (!raw || !raw.trim()) {
alert("No input provided.");
return;
}
const people = parsePeople(raw);
if (!people.length) {
alert("Could not parse any people blocks.");
return;
}
// Fill sequentially starting from person 1
for (let i = 0; i < people.length; i++) {
await fillOnePersonB(i + 1, people[i]);
}
alert("Queue B: Filled all provided persons.\nNo submit buttons were clicked.");
}
// Expose a callable function for bookmarklet
window.fillARQueueBFromPrompt = run;
// Auto-run when snippet is executed
run().catch(e => alert("Queue B error: " + (e?.message || e)));
})();