Greasy Fork is available in English.
Multi-profile autofill with draggable panel, collapsible menu, merge import, bulk edit
/* jshint esversion: 8 */
// ==UserScript==
// @name Multi Profile AutoFill Script
// @namespace http://tampermonkey.net/
// @version 6.1
// @description Multi-profile autofill with draggable panel, collapsible menu, merge import, bulk edit
// @match *://*/*
// @grant GM_getValue
// @grant GM_setValue
// @license MIT
// ==/UserScript==
/*
MIT License with No Liability
Copyright (c) 2026 Shariar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The software is provided "as is", without warranty of any kind, express or
implied, including but not limited to the warranties of merchantability,
fitness for a particular purpose, or non-infringement. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability, whether in an action of contract, tort, or otherwise, arising
from, out of, or in connection with the software or the use or other dealings
in the software.
*/
/*
⚠️ DISCLAIMER:
This script is for personal use to automate form-filling.
The author (Shariar) is not responsible for any misuse or damages
resulting from the use of this script.
Do not use for illegal activity.
*/
(async function () {
'use strict';
const STORAGE_KEY = "TM_Global_AutoFill_Profiles";
const defaultProfiles = { "Default": {} };
// ===== Load profiles globally =====
async function loadProfiles() {
const data = await GM_getValue(STORAGE_KEY, "{}");
return Object.keys(JSON.parse(data)).length ? JSON.parse(data) : defaultProfiles;
}
// ===== Save profiles globally =====
function saveProfiles(data) {
GM_setValue(STORAGE_KEY, JSON.stringify(data));
}
// ===== Initialize profiles inside async function =====
let profiles = await loadProfiles();
let currentProfile = Object.keys(profiles)[0];
// ===== Get Unique Key =====
function getKey(el) {
return el.name || el.id || el.placeholder || null;
}
// ===== Fill Form =====
function fillForm() {
const elements = document.querySelectorAll("input, textarea, select");
elements.forEach(el => {
const key = getKey(el);
if (!key) return;
const value = profiles[currentProfile][key];
if (el.type === "checkbox") el.checked = !!value;
else if (el.type === "radio") { if (value === el.value) el.checked = true; }
else { if (value !== undefined) el.value = value; }
el.dispatchEvent(new Event("input", { bubbles: true }));
el.dispatchEvent(new Event("change", { bubbles: true }));
});
}
// ===== Save From Page =====
function saveFromPage() {
const elements = document.querySelectorAll("input, textarea, select");
elements.forEach(el => {
const key = getKey(el);
if (!key) return;
if (el.type === "checkbox") profiles[currentProfile][key] = el.checked;
else if (el.type === "radio") { if (el.checked) profiles[currentProfile][key] = el.value; }
else profiles[currentProfile][key] = el.value;
});
saveProfiles(profiles);
alert(`✅ Data saved to profile: ${currentProfile}`);
}
// ===== UI =====
const panel = document.createElement("div");
panel.style.position = "fixed";
panel.style.bottom = "20px";
panel.style.right = "20px";
panel.style.background = "#222";
panel.style.color = "#fff";
panel.style.padding = "12px";
panel.style.borderRadius = "8px";
panel.style.zIndex = "9999";
panel.style.width = "240px";
panel.style.fontSize = "13px";
panel.innerHTML = `
<b>⚡ AutoFill</b><br><br>
<select id="profileSelect" style="width:100%; margin-bottom:6px;"></select>
<button id="fillBtn" style="width:100%; margin-bottom:5px;">Fill</button>
<button id="saveBtn" style="width:100%; margin-bottom:5px;">Save From Page</button>
<button id="addBtn" style="width:100%; margin-bottom:5px;">Add Profile</button>
<button id="editBtn" style="width:100%; margin-bottom:5px;">Edit Profile</button>
<button id="deleteBtn" style="width:100%; margin-bottom:5px;">Delete</button>
<button id="logBtn" style="width:100%; margin-bottom:5px;">Log Profiles</button>
<button id="exportBtn" style="width:100%; margin-bottom:5px;">Export Profiles</button>
<button id="importBtn" style="width:100%;">Import Profiles</button>
<input type="file" id="importFile" style="display:none;" accept=".json"/>
`;
document.body.appendChild(panel);
// ===== Draggable panel =====
let isDragging = false, offsetX = 0, offsetY = 0;
panel.addEventListener("mousedown", (e) => {
if (!["BUTTON", "SELECT", "INPUT", "TEXTAREA"].includes(e.target.tagName)) {
isDragging = true;
offsetX = e.clientX - panel.offsetLeft;
offsetY = e.clientY - panel.offsetTop;
}
});
document.addEventListener("mousemove", (e) => {
if (isDragging) {
panel.style.left = e.clientX - offsetX + "px";
panel.style.top = e.clientY - offsetY + "px";
panel.style.bottom = "auto";
panel.style.right = "auto";
}
});
document.addEventListener("mouseup", () => { isDragging = false; });
// ===== Toggle collapsed menu button =====
const toggleButton = document.createElement("button");
toggleButton.innerHTML = "⚡ AutoFill";
toggleButton.style.position = "fixed";
toggleButton.style.bottom = "20px";
toggleButton.style.right = "20px";
toggleButton.style.zIndex = "9999";
toggleButton.style.padding = "6px 10px";
toggleButton.style.borderRadius = "6px";
toggleButton.style.background = "#222";
toggleButton.style.color = "#fff";
toggleButton.style.cursor = "pointer";
toggleButton.style.fontSize = "13px";
document.body.appendChild(toggleButton);
panel.style.display = "none"; // hide initially
toggleButton.onclick = () => {
panel.style.display = (panel.style.display === "none") ? "block" : "none";
};
document.addEventListener("click", (e) => {
if (!panel.contains(e.target) && e.target !== toggleButton) {
panel.style.display = "none";
}
});
const profileSelect = document.getElementById("profileSelect");
function refreshDropdown() {
profileSelect.innerHTML = "";
Object.keys(profiles).forEach(name => {
const opt = document.createElement("option");
opt.value = name;
opt.textContent = name;
profileSelect.appendChild(opt);
});
profileSelect.value = currentProfile;
}
refreshDropdown();
profileSelect.onchange = function () { currentProfile = this.value; };
// ===== Button Handlers =====
document.getElementById("fillBtn").onclick = fillForm;
document.getElementById("saveBtn").onclick = saveFromPage;
document.getElementById("addBtn").onclick = () => {
const name = prompt("Profile Name:");
if (!name) return;
profiles[name] = {};
saveProfiles(profiles);
currentProfile = name;
refreshDropdown();
};
// ===== Edit Profile (Bulk Edit + Rename) =====
document.getElementById("editBtn").onclick = () => {
if (!currentProfile) return;
const newName = prompt("Rename profile (leave blank to keep same):", currentProfile);
if (newName && newName !== currentProfile) {
profiles[newName] = profiles[currentProfile];
delete profiles[currentProfile];
currentProfile = newName;
}
const fields = profiles[currentProfile];
let text = Object.entries(fields).map(([k,v]) => `${k}=${v}`).join("\n");
const newText = prompt("Edit all fields (one per line: key=value):", text);
if (newText !== null) {
const newFields = {};
newText.split("\n").forEach(line => {
const [key, ...rest] = line.split("=");
if (key) newFields[key.trim()] = rest.join("=").trim();
});
profiles[currentProfile] = newFields;
}
saveProfiles(profiles);
refreshDropdown();
alert(`✅ Profile "${currentProfile}" updated!`);
};
document.getElementById("deleteBtn").onclick = () => {
if (Object.keys(profiles).length <= 1) {
alert("At least one profile required!");
return;
}
if (confirm("Delete this profile?")) {
delete profiles[currentProfile];
saveProfiles(profiles);
currentProfile = Object.keys(profiles)[0];
refreshDropdown();
}
};
document.getElementById("logBtn").onclick = () => {
console.log("📋 All Saved Profiles:", profiles);
alert("✅ Profiles logged to console!");
};
// ===== Export & Import (Merge Import) =====
const importFile = document.getElementById("importFile");
document.getElementById("exportBtn").onclick = () => {
const blob = new Blob([JSON.stringify(profiles, null, 2)], { type: "application/json" });
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = "autofill_profiles_backup.json";
link.click();
alert("✅ Profiles exported!");
};
document.getElementById("importBtn").onclick = () => { importFile.click(); };
importFile.onchange = function () {
const file = this.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function (e) {
try {
const importedProfiles = JSON.parse(e.target.result);
Object.keys(importedProfiles).forEach(name => { profiles[name] = importedProfiles[name]; });
saveProfiles(profiles);
currentProfile = Object.keys(profiles)[0];
refreshDropdown();
alert("✅ Profiles imported successfully (merged)!");
} catch (err) {
alert("❌ Invalid JSON file!");
}
};
reader.readAsText(file);
};
})();