I'm having an issue with a click simulation that i'm trying to use in a Chrome Extension I'm building.
This extension is a Components library for framer.com (a nocode CMS). People can paste pre-built component into their framer projects in a few clicks. This part of working well.
I'm also trying to add a feature to enable them to save their own components.
To do this, I've added a Save Component button in the right click contextual menu (see screenshot below):
When clicked this button is doing the following :
- Simulate an hover event on the Copy button to show the contextual menu that contains the actual copy button that I want to click (working fine)
- Simulate a click on the copy button
- Then my extension read the user's clipboard to get the component's data and save it to my DB (this part is working like a charm as well)
Why do I simulate a click on the copy button ? Because this is only way I found to access the component's data.
In short, I'm relying on Framer's copy logic to place the component's data into the clipboard. It's something I'm already doing for Bubble, and it's working like a charm.
The issue is that my Click Simulation doesn't seem to be triggering Framer's copy logic.
The click is dispatched correctly, but Framer's doesn't seem to interpret it like it should, and therefore doesn't place the component's into the clipboard like it should.
The debugging messages I've added that show when using the "Save Component" button
I've tried a bunch of ways to simulate the click, but nothing worked.
I'm pretty sure the issue lies within the Click simulation because if I first copy an element manually (but using Framer's native copy button) and then click on my extension's Save Component button, the component is saved correctly (because correct data is already in the clipboard).
It's a way to make it work, but it would not be a very good experience for my users.
Do you have any idea of workaround that could work ?
Here's the current version of my "Save Component" button logic for reference :
saveButton.addEventListener('click', async function() {
console.log("Save Component button clicked");
// Find and hover over the main Copy button to reveal the submenu
let menuItems = document.querySelectorAll('body > ul > li');
let mainCopyButton = Array.from(menuItems).find(li => li.textContent.includes("Copy"));
if (mainCopyButton) {
console.log("Main Copy button found, dispatching hover event...");
let hoverEvent = new MouseEvent('mouseover', {'bubbles': true, 'cancelable': true});
mainCopyButton.dispatchEvent(hoverEvent);
// Wait for the submenu to appear
setTimeout(function() {
console.log("Submenu should be open now, trying to find and click the actual Copy button...");
// Use querySelector to find the actual Copy button with the specific data-action attribute
let copyButton = document.querySelector('li[data-action="copy"]');
if (copyButton) {
console.log("Actual Copy button found, trying to simulate a detailed click...");
// Create and dispatch a more detailed click event
const clickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
clientX: copyButton.getBoundingClientRect().left + 5, // Example coordinates
clientY: copyButton.getBoundingClientRect().top + 5,
screenX: window.screenX + copyButton.getBoundingClientRect().left + 5,
screenY: window.screenY + copyButton.getBoundingClientRect().top + 5
});
copyButton.dispatchEvent(clickEvent);
console.log("Detailed click event dispatched to the Copy button.");
// Wait for the clipboard action to complete
setTimeout(async function() {
console.log("Attempting to read clipboard...");
try {
const clipboardItems = await navigator.clipboard.read();
for (const clipboardItem of clipboardItems) {
for (const type of clipboardItem.types) {
if (type === "text/html") {
const blob = await clipboardItem.getType(type);
const text = await blob.text();
console.log("Retrieved clipboard data:", text);
let iframe = document.getElementById("bubble-frame");
if (iframe) {
// Send the component data to the iframe
iframe.contentWindow.postMessage({
type: "framerComponentData",
data: text
}, "https://app.nocodable-components.com");
}
toggleSidebar(true);
}
}
}
} catch (err) {
console.error('Failed to read from clipboard:', err);
}
}, 500); // Adjust this delay as necessary
} else {
console.error("Couldn't find the actual 'Copy' button with the specified data-action.");
}
}, 300); // Adjust this delay as necessary
} else {
console.error("Couldn't find Framer's main 'Copy' button.");
}
});
PS : I'm not an expert developer, so I may have missed something stupid, or took a wrong turn ! Feel free to tell me if I did :)
As mentioned above, I've tried a bunch of ways of simulating the click but all resulted in the same issue (i.e not triggering Framer's native copy function).